Skip to content

Commit 2b6add5

Browse files
committed
Fix tests on Linux, allow to run Linux CI locally using act
1 parent a3c7fb3 commit 2b6add5

4 files changed

Lines changed: 44 additions & 13 deletions

File tree

.github/workflows/ci.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ jobs:
1212
runs-on: ubuntu-latest
1313
steps:
1414
- uses: actions/checkout@v5
15+
- name: Install shellcheck
16+
run: command -v shellcheck || sudo apt-get update -qq && sudo apt-get install -qq -y shellcheck
1517
- name: Run shellcheck
1618
run: shellcheck hdi
1719

README.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,17 @@ shellcheck hdi
101101
bats test/hdi.bats
102102
```
103103

104+
### Running Linux tests locally with Act
105+
106+
This assumes that the host system is macOS.
107+
108+
CI runs tests on both macOS and Ubuntu. To run the Ubuntu job locally using [Act](https://github.com/nektos/act) (requires Docker / Docker Desktop):
109+
110+
```bash
111+
brew install act
112+
act -j test --matrix os:ubuntu-latest --container-architecture linux/amd64
113+
```
114+
104115
## Demo
105116

106117
The demo GIF is generated with [VHS](https://github.com/charmbracelet/vhs). To regenerate it:

hdi

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -384,7 +384,7 @@ draw_picker() {
384384
all) printf " %s[all]%s" "$DIM" "$RESET" ;;
385385
esac
386386
printf "\n"
387-
(( count++ ))
387+
(( count += 1 ))
388388

389389
for idx in "${!DISPLAY_LINES[@]}"; do
390390
local line="${DISPLAY_LINES[$idx]}"
@@ -403,15 +403,15 @@ draw_picker() {
403403
else
404404
printf " %s %s%s\n" "$GREEN" "$line" "$RESET"
405405
fi
406-
(( count++ ))
406+
(( count += 1 ))
407407
;;
408408
empty)
409409
if [[ -n "$line" ]]; then
410410
printf " %s %s%s\n" "$DIM" "$line" "$RESET"
411411
else
412412
printf "\n"
413413
fi
414-
(( count++ ))
414+
(( count += 1 ))
415415
;;
416416
esac
417417
done
@@ -510,14 +510,14 @@ run_interactive() {
510510
case "$KEY" in
511511
up|k)
512512
if (( cursor > 0 )); then
513-
(( cursor-- ))
513+
(( cursor -= 1 ))
514514
selected="${CMD_INDICES[$cursor]}"
515515
fi
516516
;;
517517

518518
down|j)
519519
if (( cursor < num_cmds - 1 )); then
520-
(( cursor++ ))
520+
(( cursor += 1 ))
521521
selected="${CMD_INDICES[$cursor]}"
522522
fi
523523
;;

test/hdi.bats

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -633,15 +633,33 @@ setup() {
633633
# Keys: ↓ c q (navigate down one, copy, quit)
634634
local keys=$'\x1b[Bcq'
635635

636-
# Run interactively in a pseudo-TTY via Python pty module.
637-
# (script(1) does not reliably forward stdin to the PTY on Linux.)
638-
# The sleep ensures hdi has time to draw the picker and set raw mode
639-
# before keystrokes arrive — otherwise Linux buffers them in canonical
640-
# mode and they never reach the application.
641-
{ sleep 0.5; printf '%s' "$keys"; } | python3 -c "
642-
import pty, os, sys
636+
# Run interactively in a pseudo-TTY.
637+
# We use pty.fork() rather than pty.spawn() because spawn's _copy loop
638+
# crashes on Linux (EIO when slave closes) in older Python versions.
639+
python3 -c "
640+
import pty, os, sys, time, select, errno
641+
643642
os.environ['PATH'] = sys.argv[1] + ':' + os.environ['PATH']
644-
pty.spawn(sys.argv[2:])" "$fake_bin" "$HDI" "$FIXTURES/node-express" >/dev/null 2>&1 || true
643+
keys = sys.argv[2].encode()
644+
645+
pid, fd = pty.fork()
646+
if pid == 0:
647+
os.execvp(sys.argv[3], sys.argv[3:])
648+
else:
649+
# Wait for hdi to draw picker and enter raw mode
650+
time.sleep(0.5)
651+
os.write(fd, keys)
652+
# Wait for hdi to process keystrokes and exit
653+
time.sleep(0.5)
654+
# Drain any remaining output
655+
try:
656+
while select.select([fd], [], [], 0.5)[0]:
657+
if not os.read(fd, 4096):
658+
break
659+
except OSError:
660+
pass
661+
os.waitpid(pid, 0)
662+
" "$fake_bin" "$keys" "$HDI" "$FIXTURES/node-express" >/dev/null 2>&1 || true
645663

646664
# Second command in node-express default mode is "nvm use 20"
647665
[ -f "$clip_file" ]

0 commit comments

Comments
 (0)