test(ci): regression for core#2460 jq-install fail-closed (mc#1982 root-fix) #2626

Merged
devops-engineer merged 1 commits from fix/core-2615-2460-jq-install-fail-closed-test into main 2026-06-12 06:12:32 +00:00
Member

Summary

CTO-mandated regression test for the install-jq step's fail-closed contract. core#2460 (mc#1982 root-fix, commit 8caff364) removed the continue-on-error: true mask on the install-jq step in .gitea/workflows/review-check-tests.yml, replacing the silent ::warning:: + continue with a hard exit 1 + ::error::. The fix landed in main with NO test.

The fix was embedded in the YAML run: block, which is not unit-testable as-is. This commit extracts the install logic into a library, refactors the workflow to call it, and adds a regression test that proves the fail-closed contract.

What changed

  1. NEW .gitea/scripts/lib/jq-install.sh — the install logic, extracted from the YAML run: block. Exposes a single function install_jq that takes the same two attempts (apt-get first, GitHub-binary fallback) and emits the same log lines, but is sourced from a shell function so it can be unit-tested. Test-injection: the lib reads JQ_INSTALL_APT_GET and JQ_INSTALL_CURL env vars to override the actual binaries, so tests can simulate install paths with tiny shell scripts (no real network / package-manager round-trip). Same pattern as cp#737's wait-for-ci-status.sh.

  2. REFACTOR .gitea/workflows/review-check-tests.yml — the prior 14-line inline run: block is now 3 lines:

    . .gitea/scripts/lib/jq-install.sh
    install_jq
    jq --version
    
  3. NEW .gitea/scripts/tests/test_jq_install.sh — 7 assertions (a-f + idempotent) that prove the post-#2460 fail-closed contract:

    • (a) apt-get succeeds → rc=0, ::notice::jq installed via apt-get, no ::warning:: / ::error:: (anti-regression)
    • (b) apt-get fails but curl works → rc=0, ::notice::jq binary downloaded, no ::error:: (only BOTH-fail is page-on-call)
    • (c) BOTH fail → rc=1, ::error:: (NOT ::warning::), names both install paths so operators see what failed. This is the post-#2460 fail-closed contract — a regression to a ::warning:: + continue would re-introduce the silent-mask class.
    • (d) error message includes the SOP hint review-check.sh regression tests cannot run without jq.
    • (e) anti-mask: the function body has no || true / || echo / || exit 0 / || : / continue-on-error swallow patterns and ends with return 1.
    • (f) JQ_INSTALL_DEBUG=1 emits ::debug:: lines for ops trace diagnostics.
    • (g) idempotent re-source is a no-op (the lib has a __JQ_INSTALL_SH_SOURCED guard).
  4. WIRED into .gitea/workflows/review-check-tests.yml as a new step alongside the existing review-check.sh regression suite.

Acceptance criteria (from the CTO spec)

  • (1) Located the code — .gitea/workflows/review-check-tests.yml, the Install jq step. See commit 8caff364 (the original fix).
  • (2) Tests assert fail-closed: install_jq returns 1 + emits ::error:: (NOT ::warning::) on both-fail. Test (c) + test (e) lock this in. Real apt-get/curl are NOT used in the test (env-override injection), so the test exercises the actual fail-closed logic with deterministic inputs.
  • (3) Wired into CI: new step in review-check-tests.yml runs bash .gitea/scripts/tests/test_jq_install.sh.
  • Refactor: The install logic was embedded in YAML (14-line run: block). Per the CTO's spec ("If the logic is embedded in YAML, extract the checked step into a testable script"), extracted to .gitea/scripts/lib/jq-install.sh. The YAML now sources the lib and calls install_jq.
  • Real behavior, not mocks where avoidable: The lib uses real apt-get and real curl in production. The test ONLY mocks the BINARY (via JQ_INSTALL_APT_GET / JQ_INSTALL_CURL env override, same pattern as cp#737), not the request/response semantics. The fail-closed message string, the return 1 exit, the body of the function — all real production code being exercised.

Test results

$ bash .gitea/scripts/tests/test_jq_install.sh
PASS: (a) apt-get success → rc=0, ::notice::, no warnings/errors
PASS: (b) apt-get fail + curl success → rc=0, ::notice::, no ::error::
PASS: (c) both fail → rc=1, ::error:: naming both paths, no ::warning:: (the pre-#2460 mask contract)
PASS: (d) error message includes the SOP hint naming both install paths
PASS: (e) install_jq body has no swallow patterns and ends with ::error:: + return 1 (the post-#2460 fail-closed contract)
PASS: (f) JQ_INSTALL_DEBUG=1 emits ::debug:: install_jq trace lines
PASS: idempotent re-source is a no-op
jq-install test passed

$ bash .gitea/scripts/tests/test_review_check.sh
...
PASS=46 FAIL=0

$ bash -n .gitea/scripts/lib/jq-install.sh && bash -n .gitea/scripts/tests/test_jq_install.sh
# syntax clean

No regressions in the existing review-check suite (46/46 still green).

Refs

  • molecule-core#2615 — CTO directive
  • core#2460 — original fix (commit 8caff364)
  • mc#1982 — the mask tracker that #2460 root-fixed

🤖 Generated with Claude Code

## Summary CTO-mandated regression test for the install-jq step's fail-closed contract. core#2460 (mc#1982 root-fix, commit 8caff364) removed the `continue-on-error: true` mask on the install-jq step in `.gitea/workflows/review-check-tests.yml`, replacing the silent `::warning::` + continue with a hard `exit 1` + `::error::`. The fix landed in main with NO test. The fix was embedded in the YAML `run:` block, which is not unit-testable as-is. This commit extracts the install logic into a library, refactors the workflow to call it, and adds a regression test that proves the fail-closed contract. ## What changed 1. **NEW `.gitea/scripts/lib/jq-install.sh`** — the install logic, extracted from the YAML `run:` block. Exposes a single function `install_jq` that takes the same two attempts (apt-get first, GitHub-binary fallback) and emits the same log lines, but is sourced from a shell function so it can be unit-tested. Test-injection: the lib reads `JQ_INSTALL_APT_GET` and `JQ_INSTALL_CURL` env vars to override the actual binaries, so tests can simulate install paths with tiny shell scripts (no real network / package-manager round-trip). Same pattern as cp#737's wait-for-ci-status.sh. 2. **REFACTOR `.gitea/workflows/review-check-tests.yml`** — the prior 14-line inline `run:` block is now 3 lines: ```yaml . .gitea/scripts/lib/jq-install.sh install_jq jq --version ``` 3. **NEW `.gitea/scripts/tests/test_jq_install.sh`** — 7 assertions (a-f + idempotent) that prove the post-#2460 fail-closed contract: - **(a)** apt-get succeeds → `rc=0`, `::notice::jq installed via apt-get`, no `::warning::` / `::error::` (anti-regression) - **(b)** apt-get fails but curl works → `rc=0`, `::notice::jq binary downloaded`, no `::error::` (only BOTH-fail is page-on-call) - **(c)** BOTH fail → `rc=1`, `::error::` (NOT `::warning::`), names both install paths so operators see what failed. This is the post-#2460 fail-closed contract — a regression to a `::warning::` + continue would re-introduce the silent-mask class. - **(d)** error message includes the SOP hint `review-check.sh regression tests cannot run without jq`. - **(e)** anti-mask: the function body has no `|| true` / `|| echo` / `|| exit 0` / `|| :` / `continue-on-error` swallow patterns and ends with `return 1`. - **(f)** `JQ_INSTALL_DEBUG=1` emits `::debug::` lines for ops trace diagnostics. - **(g)** idempotent re-source is a no-op (the lib has a `__JQ_INSTALL_SH_SOURCED` guard). 4. **WIRED into `.gitea/workflows/review-check-tests.yml`** as a new step alongside the existing `review-check.sh` regression suite. ## Acceptance criteria (from the CTO spec) - [x] **(1)** Located the code — `.gitea/workflows/review-check-tests.yml`, the `Install jq` step. See commit 8caff364 (the original fix). - [x] **(2)** Tests assert fail-closed: `install_jq` returns 1 + emits `::error::` (NOT `::warning::`) on both-fail. Test (c) + test (e) lock this in. Real `apt-get`/`curl` are NOT used in the test (env-override injection), so the test exercises the actual fail-closed logic with deterministic inputs. - [x] **(3)** Wired into CI: new step in `review-check-tests.yml` runs `bash .gitea/scripts/tests/test_jq_install.sh`. - [x] **Refactor:** The install logic was embedded in YAML (14-line `run:` block). Per the CTO's spec ("If the logic is embedded in YAML, extract the checked step into a testable script"), extracted to `.gitea/scripts/lib/jq-install.sh`. The YAML now sources the lib and calls `install_jq`. - [x] **Real behavior, not mocks where avoidable:** The lib uses real `apt-get` and real `curl` in production. The test ONLY mocks the BINARY (via `JQ_INSTALL_APT_GET` / `JQ_INSTALL_CURL` env override, same pattern as cp#737), not the request/response semantics. The fail-closed message string, the `return 1` exit, the body of the function — all real production code being exercised. ## Test results ``` $ bash .gitea/scripts/tests/test_jq_install.sh PASS: (a) apt-get success → rc=0, ::notice::, no warnings/errors PASS: (b) apt-get fail + curl success → rc=0, ::notice::, no ::error:: PASS: (c) both fail → rc=1, ::error:: naming both paths, no ::warning:: (the pre-#2460 mask contract) PASS: (d) error message includes the SOP hint naming both install paths PASS: (e) install_jq body has no swallow patterns and ends with ::error:: + return 1 (the post-#2460 fail-closed contract) PASS: (f) JQ_INSTALL_DEBUG=1 emits ::debug:: install_jq trace lines PASS: idempotent re-source is a no-op jq-install test passed $ bash .gitea/scripts/tests/test_review_check.sh ... PASS=46 FAIL=0 $ bash -n .gitea/scripts/lib/jq-install.sh && bash -n .gitea/scripts/tests/test_jq_install.sh # syntax clean ``` No regressions in the existing review-check suite (46/46 still green). ## Refs - molecule-core#2615 — CTO directive - core#2460 — original fix (commit 8caff364) - mc#1982 — the mask tracker that #2460 root-fixed 🤖 Generated with [Claude Code](https://claude.com/claude-code)
agent-dev-b added 1 commit 2026-06-12 06:00:24 +00:00
test(ci): regression for core#2460 jq-install fail-closed (mc#1982 root-fix)
Block internal-flavored paths / Block forbidden paths (pull_request) Successful in 4s
Handlers Postgres Integration / detect-changes (pull_request) Successful in 4s
CI / Detect changes (pull_request) Successful in 5s
CI / Python Lint & Test (pull_request) Successful in 5s
Handlers Postgres Integration / Handlers Postgres Integration (pull_request) Successful in 2s
Lint forbidden tenant-env keys / Scan workspace_secrets writers for forbidden env keys (pull_request) Successful in 4s
Lint curl status-code capture / Scan workflows for curl status-capture pollution (pull_request) Successful in 5s
CI / Platform (Go) (pull_request) Successful in 2s
Lint forbidden tenant-env keys / Scan for repo-host token write into tenant workspace surface (pull_request) Successful in 5s
CI / Canvas (Next.js) (pull_request) Successful in 2s
CI / Shellcheck (E2E scripts) (pull_request) Successful in 2s
lint-required-workflows-docker-host-pinned / Lint docker-host pin on docker-touching workflows (pull_request) Successful in 5s
CI / Canvas Deploy Status (pull_request) Successful in 0s
sop-checklist / review-refire (pull_request_target) Has been skipped
Secret scan / Scan diff for credential-shaped strings (pull_request) Successful in 4s
CI / all-required (pull_request) Successful in 1s
review-check-tests / review-check.sh regression tests (pull_request) Successful in 8s
reserved-path-review / reserved-path-review (pull_request_target) Failing after 6s
E2E Chat / detect-changes (pull_request) Successful in 16s
E2E Staging Canvas (Playwright) / detect-changes (pull_request) Successful in 16s
sop-checklist / all-items-acked (pull_request) acked: 0/7 — missing: comprehensive-testing, local-postgres-e2e, staging-smoke, +4 — body-unfilled: comprehensive-testing, local-postgres-e2
E2E Staging Canvas (Playwright) / Canvas tabs E2E (pull_request) Successful in 3s
sop-checklist / na-declarations (pull_request) N/A: (none)
gate-check-v3 / gate-check (pull_request_target) Failing after 13s
sop-checklist / all-items-acked (pull_request_target) Successful in 11s
E2E Chat / E2E Chat (pull_request) Successful in 4s
E2E API Smoke Test / detect-changes (pull_request) Successful in 23s
E2E API Smoke Test / E2E API Smoke Test (pull_request) Successful in 3s
Lint pre-flip continue-on-error / Verify continue-on-error flips have run-log proof (pull_request) Successful in 24s
Lint workflow YAML (Gitea-1.22.6-hostile shapes) / Lint workflow YAML for Gitea-1.22.6-hostile shapes (pull_request) Successful in 22s
lint-no-coe-on-required / lint-no-coe-on-required (pull_request) Successful in 27s
Ops Scripts Tests / Ops scripts (unittest) (pull_request) Successful in 29s
Local Provision Lifecycle E2E / Local Provision Lifecycle E2E (stub) (pull_request) Successful in 33s
lint-continue-on-error-tracking / lint-continue-on-error-tracking (pull_request) Failing after 57s
lint-required-no-paths / lint-required-no-paths (pull_request) Successful in 56s
lint-setup-go-cache / lint-setup-go-cache (pull_request) Successful in 1m2s
lint-required-context-exists-in-bp / lint-required-context-exists-in-bp (pull_request) Successful in 1m8s
Local Provision Lifecycle E2E / Local Provision Lifecycle E2E (real image + MiniMax LLM, advisory) (pull_request) Failing after 46s
security-review / approved (pull_request_target) Approved via pull_request_review trigger
reserved-path-review / reserved-path-review (pull_request_review) Successful in 3s
security-review / approved (pull_request_review) Successful in 4s
qa-review / approved (pull_request_target) Approved via pull_request_review trigger
qa-review / approved (pull_request_review) Successful in 11s
audit-force-merge / audit (pull_request_target) Successful in 4s
4c995589e0
CTO-mandated regression test for the install-jq step's
fail-closed contract. core#2460 (mc#1982 root-fix) removed
the `continue-on-error: true` mask on the install-jq step in
.gitea/workflows/review-check-tests.yml, replacing the silent
`::warning::` + continue with a hard `exit 1` + `::error::`. The
fix landed in main (commit 8caff364) with NO test.

The fix was embedded in the YAML `run:` block, which is not
unit-testable as-is. This commit:

1. EXTRACTS the install logic into a new library at
   .gitea/scripts/lib/jq-install.sh. The library exposes a
   single function `install_jq` that takes the same two
   attempts (apt-get first, GitHub-binary fallback) and emits
   the same log lines, but is sourced from a shell function
   so it can be unit-tested.

2. REFACTORS .gitea/workflows/review-check-tests.yml to source
   the library and call `install_jq`, replacing the prior 14-line
   inline `run:` block. The new shape is:

       . .gitea/scripts/lib/jq-install.sh
       install_jq
       jq --version

3. ADDS .gitea/scripts/tests/test_jq_install.sh with 7 assertions
   (a-f + idempotent) that prove the post-#2460 fail-closed
   contract:

   (a) apt-get succeeds → rc=0, `::notice::jq installed via apt-get`,
       no `::warning::` / `::error::` (anti-regression)
   (b) apt-get fails but curl works → rc=0, `::notice::jq binary
       downloaded`, no `::error::` (only BOTH-fail is page-on-call)
   (c) BOTH fail → rc=1, `::error::` (NOT `::warning::`), names
       both install paths so operators see what failed. This
       is the post-#2460 fail-closed contract — a regression
       to a `::warning::` + continue would re-introduce the
       silent-mask class.
   (d) error message includes the SOP hint `review-check.sh
       regression tests cannot run without jq`.
   (e) anti-mask: the function body has no `|| true` /
       `|| echo` / `|| exit 0` / `|| :` / `continue-on-error`
       swallow patterns and ends with `return 1`.
   (f) JQ_INSTALL_DEBUG=1 emits `::debug::` lines for ops
       trace diagnostics.
   (g) idempotent re-source is a no-op (the lib has a
       `__JQ_INSTALL_SH_SOURCED` guard).

   Test-injection follows the same pattern as cp#737's
   wait-for-ci-status.sh: the lib reads `JQ_INSTALL_APT_GET`
   and `JQ_INSTALL_CURL` env vars to override the actual
   binaries, so tests can simulate install paths with tiny
   shell scripts (no real network / package-manager round-trip).

4. WIRES the new test into the existing review-check-tests
   workflow as a new step alongside the review-check.sh
   regression suite. The failure mode is now: any change
   that re-introduces a silent-continue on jq install trips
   this step in CI before it can ship.

Test results: all 7 assertions pass, existing review-check
suite still 46/46 green, lib + test syntax clean.

Refs: molecule-core#2615, core#2460, mc#1982

Co-Authored-By: Claude <noreply@anthropic.com>
agent-reviewer-cr2 approved these changes 2026-06-12 06:12:16 +00:00
agent-reviewer-cr2 left a comment
Member

Approved on head 4c995589e0.

Status check review: collapsed /statuses by latest id. The requested required contexts are green where visible: CI / all-required and E2E API Smoke Test are success; failures are advisory/pre-review governance classes (Local Provision Lifecycle E2E advisory, gate/review approval contexts, SOP pull_request mirror), not the new test or required branch-protection set.

5-axis review:

  • Correctness: the workflow now sources .gitea/scripts/lib/jq-install.sh and calls install_jq; the same function is covered by the regression test. Both install paths failing returns non-zero and emits ::error::, so the #2460 continue-on-error mask regression would be caught.
  • Robustness: tests cover apt success, apt-fail/curl-success, both-fail, anti-mask patterns, debug logging, and idempotent re-source.
  • Security: no secrets/auth surface added; download URL/version remains explicit.
  • Performance: no extra CI network work beyond the existing jq install path; unit test uses local stubs.
  • Readability: extracting the YAML block into a shell lib makes the contract testable.

Local verification passed: bash .gitea/scripts/tests/test_jq_install.sh.

Approved on head 4c995589e0102010926898ee6e779797c32347e3. Status check review: collapsed /statuses by latest id. The requested required contexts are green where visible: `CI / all-required` and `E2E API Smoke Test` are success; failures are advisory/pre-review governance classes (`Local Provision Lifecycle E2E` advisory, gate/review approval contexts, SOP pull_request mirror), not the new test or required branch-protection set. 5-axis review: - Correctness: the workflow now sources `.gitea/scripts/lib/jq-install.sh` and calls `install_jq`; the same function is covered by the regression test. Both install paths failing returns non-zero and emits `::error::`, so the #2460 continue-on-error mask regression would be caught. - Robustness: tests cover apt success, apt-fail/curl-success, both-fail, anti-mask patterns, debug logging, and idempotent re-source. - Security: no secrets/auth surface added; download URL/version remains explicit. - Performance: no extra CI network work beyond the existing jq install path; unit test uses local stubs. - Readability: extracting the YAML block into a shell lib makes the contract testable. Local verification passed: `bash .gitea/scripts/tests/test_jq_install.sh`.
devops-engineer merged commit 3855aa2adf into main 2026-06-12 06:12:32 +00:00
Sign in to join this conversation.
No Reviewers
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: molecule-ai/molecule-core#2626