You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix(ci): drop 3.12-broken argparse sentinel + fix retry Node.js ordering
Two independent fixes from the latest nightly-matrix re-run.
1) tests/test_cli.py::test_discuss_rejects_ack_thread_before_message
started failing on Python 3.12/3.13. The 3.12 argparse refactor
made positional backtracking more aggressive: `discuss WI-test
--ack-thread "Reply text"` now parses as `ack_thread=True,
message="Reply text"` (exit 0) where 3.10/3.11 exited 2 with
"unrecognized arguments". The test was a self-documented sentinel
for exactly this change — its docstring: "If a future Python or
argparse change ever made the broken order work, this test would
fail and we'd revisit the gate-message text." Deleted it in place
with a comment block recording the history and pointing at the
sibling `test_discuss_gate_message_shows_working_arg_order` which
already validates the UX. No cli.py change; gate-message text
still recommends the universally-working `"<msg>" --ack-thread`
order. Tracker package coverage remains 100% in isolation.
2) nightly.yml test-matrix-retry and release.yml post-publish-matrix-
retry both had `actions/download-artifact@v3` (a JS action that
needs Node.js on PATH) running BEFORE `Install Node.js` in a
fresh python:${ver}-bookworm container. download-artifact failed
with `OCI runtime exec failed ... exec: "node": executable file
not found` under continue-on-error, the pass marker never landed,
and the skip-check incorrectly reported "Primary job failed ...
retrying" for already-passing Python versions. Observed 2026-04-21:
3.10/3.11 primary passed but their retry containers still ran the
full ~5-minute retry path. The primary test-matrix jobs solve this
already by installing Node.js as their first step; the retry jobs
just didn't copy that ordering. Moved `Install Node.js for JS-
based actions` to be the first unconditional step of both retry
jobs. Retry containers still spin up for every matrix value when
any primary fails (platform limitation — Forgejo/GitHub Actions
can't express per-matrix-value retry gating), but short-circuit in
~10s via the skip-check once the pass marker is found, down from
the full 5+ minute spurious retry.
Signed-off-by: jgstern-agent <josh-agent@iterabloom.com>
Copy file name to clipboardExpand all lines: CHANGELOG.md
+2Lines changed: 2 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -12,6 +12,8 @@ This changelog tracks the **tool version** (package releases). The **schema vers
12
12
13
13
### Fixed
14
14
15
+
- **Argparse sentinel test dropped + nightly/release retry Node.js chicken-and-egg fixed:** two unrelated nightly-run artifacts from the re-run after the previous CI PR. (1) `packages/hypergumbo-tracker/tests/test_cli.py::TestWriteCommands::test_discuss_rejects_ack_thread_before_message` started failing on the Python 3.12/3.13 slices of the test-matrix. The test was a self-documented sentinel for the argparse behavior change described in CPython's 3.12 argparse refactor: `discuss WI-test --ack-thread "Reply text"` used to hit `exit 2 unrecognized arguments` on 3.10/3.11 but on 3.12+ argparse's more-aggressive positional backtracking consumes `"Reply text"` into the `nargs="?"` positional `message`, producing `ack_thread=True, message="Reply text"` and exit 0. The test's own docstring predicted exactly this: "If a future Python or argparse change ever made the broken order work, this test would fail and we'd revisit the gate-message text." Deleted the test with an in-place comment block documenting the history and pointing at the sibling `test_discuss_gate_message_shows_working_arg_order` which still validates the actual UX. No code change needed — the gate-message text already recommends the universally-working `"<msg>" --ack-thread` order. Coverage stays at 100% (verified via `./scripts/check-package-coverage tracker`). (2) `test-matrix-retry` in `.github/workflows/nightly.yml` was firing the full retry for every Python version when ANY primary matrix slice failed, even the versions whose primary passed. Root cause: `actions/download-artifact@v3` is a JS action that needs Node.js, but the retry job runs in a fresh `python:<ver>-bookworm` container and had `Install Node.js` AFTER `Download pass marker` — so download-artifact failed with `OCI runtime exec failed ... exec: "node": executable file not found` under its `continue-on-error: true` wrapper, the pass marker file never landed, the subsequent `Skip if primary passed` check incorrectly printed `Primary job failed for Python 3.10 — retrying` and ran the full retry. Observed 2026-04-21 — 3.10/3.11 primary passed but their retry containers still spun up and ran tests. The primary `test-matrix` job already solves this correctly by installing Node.js as its first step; the retry job just didn't copy that ordering. Moved `Install Node.js for JS-based actions` to be the first unconditional step in the retry. Same bug present in `.github/workflows/release.yml`'s post-publish-matrix-retry (download-artifact@v3 before Install Node.js) — fixed identically. After the fix the retry containers still spin up when ANY version fails primary (GitHub/Forgejo Actions can't express per-matrix-value retry gating natively — it's a platform constraint), but short-circuit in ~10 seconds once the skip-check sees the pass marker instead of running the full 5+ minute retry. Refactoring out of the matrix pattern into per-version jobs would fix the spin-up overhead entirely at the cost of ~2× the YAML duplication; deferred since the post-fix overhead is well under the nightly's noise floor.
16
+
15
17
- **`hypergumbo-lang-rust-analyzer` wired into nightly.yml / release.yml / full-suite.yml:** only `ci.yml` (per-PR) had the new package in its install lines. Observed failure: `nightly.yml`'s `test-matrix` job collection-errored on every rust-analyzer test file (`ModuleNotFoundError: No module named 'hypergumbo_lang_rust_analyzer'`) because the install block installed five sibling `hypergumbo-lang-*` packages but not this one, while `pytest packages/*/tests/` still tried to collect its tests. Three coordinated edits: (1) `nightly.yml` — added `-e packages/hypergumbo-lang-rust-analyzer` to all three install blocks (lines 49, 168, 245) and `--cov=packages/hypergumbo-lang-rust-analyzer/src` to both COV_PATHS lines (75, 197). (2) `release.yml` — same two kinds of additions at the four install blocks (91, 327, 448, 525) and both COV_PATHS lines (353, 477). Would have failed the same way at the next tag-push; preemptive. (3) `full-suite.yml` — added a dedicated `test-rust-analyzer` job (no retry variant; matches the `test-common` / `test-extended` "small-package" pattern rather than the `test-core` / `test-mainstream` / `test-tracker` retry-eligible pattern since rust-analyzer has ~25 tests across 5 files), and extended the `aggregate` job to include it in the `needs` list, the per-job echo, the success-gate, the coverage roll-up (divisor 5 → 6), the `record-run-result` JSON, and the `all-100%` badge gate. Full-suite was silently not exercising rust-analyzer tests at all before this.
16
18
17
19
- **Nightly coverage gaps closed (scip_pb2 omit + tree-sitter-c-sharp 0.23.5 grammar shift):** two unrelated holes surfaced by the `--cov-config=.coveragerc.no-embeddings` invocation of nightly.yml when `sentence-transformers` is unavailable (the default in the Python-matrix containers). (1) `packages/hypergumbo-core/src/hypergumbo_core/scip/_generated/scip_pb2.py` was reporting 18% coverage because the `*/scip/_generated/scip_pb2.py` omit lived only in `pyproject.toml` under `[tool.coverage.run]`; passing `--cov-config=` makes coverage.py read ONLY that config file, so the pyproject omit list is dropped. Duplicated the entry in `.coveragerc.no-embeddings` so both config paths exclude the auto-generated protobuf binding. (2) `packages/hypergumbo-lang-mainstream/src/hypergumbo_lang_mainstream/csharp.py` was reporting 98% with lines 112-131 (the named-attribute-argument `kwargs` branch) uncovered. Root cause: `tree-sitter-c-sharp~=0.23.1` in mainstream's pyproject.toml resolves to the latest-satisfying 0.23.5, and 0.23.5 flattened the named-argument grammar — `[Route("api", Name="Get")]` now emits `attribute_argument → [identifier, =, string_literal]` directly instead of wrapping those children in an `assignment_expression` node. The code's `find_child_by_type(arg, "assignment_expression")` returned None, the named branch was dead, and the test that should have covered it (`test_annotation_with_named_argument`) started accumulating `"Name"` into the positional `args` list — confirmed by running it under 0.23.5 (`assert ['api/test', 'Name'] == ['api/test']`). Fix: bumped the pin to `tree-sitter-c-sharp~=0.23.5` (matches what pip already resolves) and rewrote the named-arg detection to look for a direct `=` child on `attribute_argument`, then extract the first `identifier` and first `string_literal` children into `kwargs[name] = value`. All 87 `test_csharp.py` cases pass under 0.23.5; full smart-test run: 5201 passed, 0 failed, `csharp.py` at 100% coverage.
0 commit comments