Skip to content

fix(tests): install-journey guard() asserted nothing + CI-config gaps (#310)#311

Merged
saadqbal merged 1 commit into
developfrom
fix/client-310-install-journey-guard
Jul 7, 2026
Merged

fix(tests): install-journey guard() asserted nothing + CI-config gaps (#310)#311
saadqbal merged 1 commit into
developfrom
fix/client-310-install-journey-guard

Conversation

@saadqbal

@saadqbal saadqbal commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Follow-up to #214 (post-merge review by @aptracebloc). Fixes the findings that are solidly correct and locally reasoned; the path-persist signal rework is scoped separately on #310 (needs CI validation across the distro matrix).

🔴 Critical — guard() swallowed every failure (Leg 2 asserted nothing)

scripts/tests/e2e-journey.sh captured local rc=$? inside the then branch of if ! timeout .... In bash, $? there is the negated status — always 0. Since every assertion (cluster info, dataset push --dry-run) runs under guard, set -e never tripped and the job printed E2E JOURNEY PASS even when steps failed or hung.

Reproduced before the fix — a step exiting 3 and a 124 hang both made guard return 0.

  • Rewrote to rc=0; timeout ... || rc=$?; return $rc — a failed step now propagates and a 124 hang is a hard failure.
  • Added a negative-control self-test at startup: guard must return non-zero for a command that exits non-zero, else the script refuses to run. bash -n and shellcheck both passed on the buggy version, so this locks the class.

🟡 Medium — CI config

  • Added timeout-minutes to path-persist (20) and e2e-journey (30). Every other job in the file had one; these two rode to the 6h ceiling on a hang.
  • Added labeled to the pull_request trigger types so adding the e2e label starts an e2e-journey run immediately instead of only on the next push.

Deferred to #310 — 🟠 path-persist has no red/green signal

Not in this PR: it's a real rewrite, not a one-liner. The cli install.sh persists PATH to one rc file keyed off $SHELL (Linux bash→.bashrc, zsh→.zshrc, fish→config.fish, else .profile), and only when the prefix is under $HOME/off-PATH. As root the test installs to /usr/local/bin (already on PATH → persistence never exercised), and the login × nonlogin matrix doesn't match the installer's model (bash -c reads no rc files at all). Making it actually distinguish a pre-fix vs fixed installer means forcing INSTALL_PREFIX=$HOME/.local/bin, installing once per $SHELL, and asserting an interactive shell of that kind — which can only be validated in CI. Tracked on #310.

Test plan

  • Reproduced the guard() bug and verified the fix: self-test detects a non-zero exit; a failing guarded step aborts with its true exit code (SHOULD-NOT-PRINT line absent).
  • bash -n scripts/tests/e2e-journey.sh — parses.
  • shellcheck --severity=error (the CI gate) and --severity=warning (advisory) on the script + libs — both clean.
  • actionlint .github/workflows/installer-tests.yaml — clean.

Refs #310.

🤖 Generated with Claude Code


Note

Medium Risk
The guard fix restores real failure semantics for the labeled e2e journey job; CI-only changes with no production runtime impact, but a previously green e2e job may now correctly fail when steps break.

Overview
Fixes a critical bug in e2e-journey.sh where guard() always returned success: capturing $? inside if ! timeout ... read the negated status, so every guarded step (cluster info, dataset push --dry-run, etc.) could fail or hang while the job still printed E2E JOURNEY PASS. The watchdog now records the real exit via timeout ... || rc=$? and returns it; exit 124 still fails hard on timeout.

Adds a negative-control self-test at startup that refuses to run if guard does not propagate a non-zero exit from a deliberate failure.

In installer-tests.yaml: timeout-minutes for path-persist (20) and e2e-journey (30); pull_request trigger includes labeled so adding the e2e label starts the journey job without waiting for another push.

Reviewed by Cursor Bugbot for commit 1652770. Bugbot is set up for automated code reviews on this repo. Configure here.

… label trigger (#310)

The install-journey harness merged in #214 asserted nothing: guard()
captured `local rc=$?` inside the `then` branch of `if ! timeout ...`,
so rc read the NEGATED status (always 0). Every assertion runs under
guard, so set -e never tripped and the job printed E2E JOURNEY PASS even
when steps failed or hung. Reproduced: a step exiting 3 and a 124 hang
both returned 0.

- guard(): run the command, capture status via `|| rc=$?`, then act on
  it — a failed step now propagates, a 124 hang is treated as a hard
  failure.
- Add a negative-control self-test at startup: guard() must return
  non-zero for a command that exits non-zero, or the script refuses to
  run. Locks the vacuous-pass class so it can't regress silently
  (bash -n and shellcheck both passed on the buggy version).
- installer-tests.yaml: add timeout-minutes to path-persist (20) and
  e2e-journey (30) — every other job already had one; and add `labeled`
  to the pull_request trigger types so adding the `e2e` label starts a
  run immediately instead of on the next push.

Remaining from the #214 review (path-persist has no red/green signal)
is tracked separately on #310 — it's a genuine rewrite that needs CI
validation across the distro matrix.

Refs #310. Follow-up to #214 (review by @aptracebloc).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@saadqbal saadqbal merged commit 698e156 into develop Jul 7, 2026
35 checks passed
@saadqbal saadqbal deleted the fix/client-310-install-journey-guard branch July 7, 2026 11:49
divyasinghds pushed a commit that referenced this pull request Jul 7, 2026
…316)

The guard() watchdog added in #310/#311 wraps steps in `timeout`, which
execs an external command in a fresh process and cannot see shell
functions. create_cluster is a function sourced from cluster.sh, so
`guard 600 "create_cluster" -- create_cluster` failed with
"timeout: failed to run command 'create_cluster': No such file or
directory" (exit 127) before the cluster was ever created — failing the
E2E last-mile journey job.

Run create_cluster inside a real `bash` (which timeout CAN exec) that
re-sources the libs. Exported CLUSTER_NAME / TRACEBLOC_NO_AUTOSTART /
USER carry through the env, and the CLI binaries install_* dropped into
/usr/local/bin are on the inherited PATH.

Refs #310

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants