Repository navigation
ci: run bootstrap for real, and fix the two bugs it found - #1
Chikimuras wants to merge 4 commits into
Conversation
glab publishes its tarballs as glab_<ver>_linux_amd64 / _arm64, but 10-packages.sh translated dpkg's amd64 to x86_64 before building the URL. The download therefore 404'd on every 64-bit Intel machine — only arm64 happened to line up. curl exited 22 and, under `set -e`, took the whole bootstrap with it. lazygit and jira-cli further down do use x86_64, hence the (wrong) symmetry; a comment now records the difference. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
stow folds trees: after a first run, ~/.zsh is a single symlink to dotfiles/zsh/.zsh. backup_conflicts() then walked the package files and tested ~/.zsh/rc.d/10-aliases.zsh, which resolves *through* that symlink to the repo's own file — it exists, and it is not itself a symlink, so backup_path() moved it. Every re-run of bootstrap.sh renamed a large part of dotfiles/ to *.forge-backup.<ts> inside the repo, and the shell config then failed to load (~/.zshrc: no matches found: ~/.zsh/rc.d/*.zsh). Skip any target that already resolves into dotfiles/ — it is stow's own work, not a user file to preserve. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The smoke job only ever ran bootstrap.sh --dry-run, which installs nothing. Anything that depends on a binary actually being present was therefore untested, and broke in CI twice (require_cmd zsh, then command -v zsh under set -e). Two changes: - smoke now pre-installs zsh, so 20-shell.sh traverses its real branches ([dry-run] sudo chsh -s /usr/bin/zsh) instead of bailing out early. - bootstrap-real runs the thing for real in ubuntu:24.04, asserts the post-conditions (ci/assert-bootstrap.sh: tools on PATH, omz plugins and tpm checked out, dotfiles resolving into the repo, `zsh -i` starting), then re-runs bootstrap and re-asserts — the repo claims to be safe to re-run, so CI checks it. It is slow and depends on third-party endpoints, but it is the only job that proves the install works rather than that the scripts merely parse: it found both bugs fixed in the two preceding commits on its first run. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
🟡 Changes recommended
ci/assert-bootstrap.sh currently mixes logical $FORGE_DIR paths with readlink -f physical paths, which can make link assertions fail incorrectly on symlinked checkouts.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
This PR strengthens CI coverage for bootstrap.sh by running both an end-to-end dry-run (with prerequisites that make more branches execute) and a new full “real bootstrap” job that asserts post-conditions and idempotency. It also fixes two bootstrap issues uncovered by exercising the real installation path (glab arch download URL and stow re-run behavior).
Changes:
- Update
smokeCI to preinstallzshso--dry-runtraverses relevant branches. - Add
bootstrap-realCI job plusci/assert-bootstrap.shto validate a real bootstrap run and re-run idempotency. - Fix glab asset arch selection and prevent
stowconflict backup from renaming files inside the repo on re-runs.
File summaries
| File | Description |
|---|---|
install/50-stow.sh |
Avoids backing up files that resolve into the repo through folded stow symlinks. |
install/10-packages.sh |
Fixes glab download URL to use dpkg/Go arch strings (e.g., amd64). |
ci/assert-bootstrap.sh |
Adds post-install assertions for PATH tools, plugin checkouts, stowed dotfiles, and zsh -i startup. |
.github/workflows/ci.yml |
Adds manual trigger, improves smoke, and introduces bootstrap-real job. |
Review details
- Files reviewed: 4/4 changed files
- Comments generated: 1
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| # run, not just the first failure. | ||
| set -uo pipefail | ||
|
|
||
| FORGE_DIR="${FORGE_DIR:-$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)}" |
The bootstrap-real job reported, on every run: fzf_setup_using_debian:source:40: no such file or directory: /usr/share/doc/fzf/examples/key-bindings.zsh Not a dotfiles bug. The ubuntu image ships /etc/dpkg/dpkg.cfg.d/excludes with path-exclude=/usr/share/doc/*, so dpkg drops fzf's shell integration at install time while leaving the examples/ directory behind — enough for oh-my-zsh's fzf plugin to pass its `-d` check and then source a file that was never unpacked. A real Ubuntu desktop has it. The container was lying, so drop the exclusion in both container jobs. While here, make that class of defect fail the build instead of scrolling past: the assertion now starts the shell under a pty (script -qec, so fzf's key-bindings.zsh does not warn `can't change option: zle`) and requires startup to print *nothing*. Checking the exit status alone was not enough — a failed `source` inside a plugin leaves it at 0, which is exactly why this went unnoticed. Verified both ways in a local amd64 container: with the exclusion left in place the assertion captures the 107-byte fzf warning and fails; with it removed, startup is silent. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Suite : le point fzf signalé plus haut est traité dans Ce n'était pas un bug des dotfiles. L'image Au passage, cette classe de défaut fait maintenant échouer le build au lieu de défiler : l'assertion démarre le shell sous un pty ( Vérifié dans les deux sens en container amd64 local : exclusion laissée en place → l'assertion capture les 107 octets d'avertissement fzf et échoue ; exclusion retirée → démarrage silencieux. Run complet (bootstrap réel + assertions + re-run + re-assertions) : exit 0, aucun |
Pourquoi
Le job
smokene lançait quebootstrap.sh --dry-run, qui n'installe rien. Il ne pouvait donc valider que le parsing des scripts, jamais l'installation. C'est ce qui avait fait échouer la CI deux fois de suite sur20-shell.sh(require_cmd zsh, puiscommand -v zshsousset -e).Ce que fait la PR
smokepré-installezsh— le dry-run traverse enfin les vraies branches de20-shell.sh([dry-run] sudo chsh -s /usr/bin/zsh tester) au lieu de s'arrêter avant.bootstrap-real— lance le bootstrap pour de vrai dansubuntu:24.04, vérifie les post-conditions (ci/assert-bootstrap.sh), puis relance le bootstrap et re-vérifie : le repo se documente comme ré-exécutable, la CI le contrôle.ci/assert-bootstrap.shvérifie : les binaires installés sans condition sont sur le PATH,~/.oh-my-zsh+ les deux plugins +tpmsont clonés, les dotfiles résolvent bien dans le repo, etzsh -idémarre. Les outils optionnels (aerc,tealdeer,jira-cli) ne sont pas assertés : leur absence est tolérée par conception.Les deux bugs trouvés par le nouveau job, dès son premier run
glab: 404 sur toute machine amd64 (fix: use Go arch names…)10-packages.shtraduisaitamd64→x86_64, alors que glab nomme ses assets avec les noms d'arch Go (glab_1.50.0_linux_amd64.tar.gz). L'install n'a jamais fonctionné sur Intel 64 bits ; seul arm64 tombait juste par coïncidence.curlsortait en 22 et emportait tout le bootstrap avec lui.50-stow.shrenommait les dotfiles dans le repo à chaque ré-exécution (fix: never back up a file reached through a folded stow symlink)stow plie les arbres : après un premier passage,
~/.zshest un symlink versdotfiles/zsh/.zsh.backup_conflicts()testait ensuite~/.zsh/rc.d/10-aliases.zsh, qui résout à travers ce symlink vers le fichier source du repo — présent, et pas lui-même un symlink — doncbackup_path()le déplaçait. Reproduit :Après quoi
~/.zshrccassait :no matches found: ~/.zsh/rc.d/*.zsh. Ça touchait aussigit,kitty,aerc,jiraetnvim— tous les paquets dont stow avait plié un répertoire.Vérification locale
Tout a été rejoué en container
ubuntu:24.04amd64 (comme les runners), pas seulement lu :shellcheck -S warning -xsur tous les scripts : OKsmoke: exit 0bootstrap-real: exit 0 — run réel + assertions + re-run + re-assertions, et aucun*.forge-backup.*dansdotfiles/après le second passagePoint relevé, non corrigé ici
zsh -idémarre proprement mais affichefzf_setup_using_debian: no such file or directory: /usr/share/doc/fzf/examples/key-bindings.zsh: le plugin fzf d'oh-my-zsh cherche les key-bindings à l'ancien emplacement Debian. Préexistant, sans effet sur le démarrage — à traiter séparément si tu veux.🤖 Generated with Claude Code