From f736986de0ca4a735817c691e0dadcba4af9af1d Mon Sep 17 00:00:00 2001 From: Matt <47545907+SoundMatt@users.noreply.github.com> Date: Sat, 22 Aug 2026 16:13:03 -0700 Subject: [PATCH] fix(release): stop swallowing failed artifact regeneration in the commit step The \"Commit regenerated artifacts to a review branch\" step ran a single monolithic \`git add file1 file2 ... file20 || true\`. Standard git behavior: \`git add\` aborts with a fatal error and stages NOTHING (not just the missing pathspec -- the whole invocation) if even one listed pathspec doesn't exist on disk. Six of the earlier generator steps in this same job (iso26262/iec61508/do178/iec62443/coverage/report gap+compliance reports) are themselves \`|| true\`-guarded because their cpfusa subcommand "exits non-zero by design" against certification thresholds -- so their output files can legitimately be missing if the subcommand crashes before writing. The trailing bare \`|| true\` on the git-add call (the only \`|| true\` in this file with no inline comment justifying it) silently swallowed that fatal error, meaning: guarded generator crashes before writing its file -> git add hits the missing pathspec, stages NOTHING at all -> || true swallows the fatal error -> git diff --cached --quiet sees no staged changes -> "No artifact changes -- nothing to commit", ARTIFACTS_CHANGED=false -> review PR step (gated on ARTIFACTS_CHANGED) is skipped -> job exits 0 (green), no safety-evidence review PR opened, even if other unrelated artifacts (fmea.json, safety-case.json, sbom.json, etc.) genuinely changed and were silently dropped too. Fix: replaced the single git-add call with two passes. 1. The 7 files from `|| true`-guarded generator steps (iso26262-gap-report.json, iec61508-gap-report.json, do178-gap-report.json, iec62443-gap-report.json, coverage-report.json, report.json, report.html) are added one at a time, gated on `[ -f "$f" ]`, logging a `::warning::` and skipping cleanly (not aborting the rest) when legitimately absent. 2. Every other artifact (fmea.*, safety-case.*, tooling/tara.*, sbom.json, provenance.json, artifact-manifest.json, sas.*, sci.json, audit-pack.zip, fusa-badge.svg, qualify-report.json) -- none of whose generator steps are `|| true`-guarded -- is added via the original single git-add call, now with NO trailing `|| true`. If one of these is unexpectedly missing, git add's fatal pathspec error now propagates (GitHub Actions runs bash steps with `-eo pipefail` by default) and fails the job loudly instead of reporting a false green. Verification: - `python3 -c "import yaml; yaml.safe_load(open('.github/workflows/release.yml'))"` parses cleanly. - act/yamllint not available in this environment; instead traced the new logic by hand and reproduced it standalone (see below). - Standalone repro in a scratch git repo (not committed) extracting just the new git-add logic, run against three scenarios: (a) all 22 files present -> all 22 staged, identical to prior behavior, exit 0. (b) coverage-report.json (guarded-generator) missing, fmea.json genuinely changed -> coverage-report.json skipped with a ::warning::, all other 21 files (including the real fmea.json change) still staged, exit 0 -- no longer silently reports "nothing to commit". (c) sbom.json (non-guarded, required) unexpectedly missing -> `git add` fails with "fatal: pathspec 'sbom.json' did not match any files", script exits 128 immediately -- step now fails loudly instead of a false green. - Confirmed via grep that this step's name/ID and the ARTIFACTS_CHANGED/ ARTIFACTS_BRANCH env vars it sets are referenced only within this same job in release.yml; nothing in ci.yml or any other workflow references them, so no downstream breakage from this change. Closes a finding from the cpp-RCP v3.0.0 deep audit (batch 3). Signed-off-by: Matt <47545907+SoundMatt@users.noreply.github.com> --- .github/workflows/release.yml | 44 ++++++++++++++++++++++++++++------- 1 file changed, 36 insertions(+), 8 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 70f6a36..88ddade 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -228,23 +228,51 @@ jobs: - name: Commit regenerated artifacts to a review branch run: | TAG="${{ github.ref_name }}" + + # A single `git add a b c` call aborts with a fatal error and + # stages NOTHING (not just the missing pathspec -- the whole + # invocation) if even one listed file doesn't exist on disk. The + # gap/coverage/report artifacts below come from generator steps + # above that are themselves `|| true`-guarded (cpfusa + # iso26262/iec61508/do178/iec62443/coverage/report "exit non-zero + # by design" -- see the comments on those steps), so their output + # file may legitimately be absent here if the underlying cpfusa + # subcommand crashed before writing it. Those are added one at a + # time and skipped with a warning when missing, instead of + # aborting the whole staging operation. + OPTIONAL_ARTIFACTS=" + iso26262-gap-report.json + iec61508-gap-report.json + do178-gap-report.json + iec62443-gap-report.json + coverage-report.json + report.json + report.html + " + for f in $OPTIONAL_ARTIFACTS; do + if [ -f "$f" ]; then + git add "$f" + else + echo "::warning::$f not present -- its generator step is || true-guarded (exits non-zero by design), treating as legitimately absent and skipping." + fi + done + + # Every other artifact's generator step above is NOT `|| true` + # -guarded, so if one of these is missing here something already + # went more seriously wrong upstream. Add them with no swallowing + # `|| true` so a genuinely-missing one still fails this step + # loudly instead of silently reporting "nothing to commit". git add \ fmea.csv fmea.json \ safety-case.json safety-case.md safety-case.mermaid \ tooling/tara.json tooling/tara.md \ sbom.json provenance.json artifact-manifest.json \ - iso26262-gap-report.json \ - iec61508-gap-report.json \ - do178-gap-report.json \ - iec62443-gap-report.json \ - coverage-report.json \ sas.json sas.md \ sci.json \ audit-pack.zip \ fusa-badge.svg \ - report.json report.html \ - qualify-report.json \ - || true + qualify-report.json + if git diff --cached --quiet; then echo "No artifact changes for $TAG — nothing to commit." echo "ARTIFACTS_CHANGED=false" >> "$GITHUB_ENV"