Skip to content

Commit 665ad0e

Browse files
fix(workflows): add integrity heuristic and per-file compile loop to recompile-safe-output-fixtures (#868)
The previous iteration of the workflow silently no-op'd on release v0.31.1 because `ado-aw compile tests/safe-outputs/` exits 0 with "0 compiled, N skipped" when given a directory argument (issue #867). It also did not catch the case where the on-disk lock files were stamped by a non-release build, which is what triggered the manual recompile in the first place. This change: - Replaces `ado-aw compile tests/safe-outputs/` with a per-file loop `for md in tests/safe-outputs/*.md; do ado-aw compile --force "$md"; done` run from the repo root. `--force` is required to bypass the GitHub-remote guard inside this repo. - Adds Step 2.5 (pre-flight `ado-aw check`) to detect drift between the released binary and the committed lock files independent of any version string comparison. - Adds Step 3.5 (post-compile sanity) that re-runs `ado-aw check` against every recompiled lock file and hard-fails with `report-incomplete` if any still report drift. - Updates the no-op decision logic so the agent only emits `noop` when both the git diff is empty AND pre-flight integrity passed for every file. An empty diff plus failed integrity now emits `report-incomplete`. - Updates the PR body and "When NOT to open a PR" guidance to reference the new integrity signals. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent abc4959 commit 665ad0e

2 files changed

Lines changed: 66 additions & 6 deletions

File tree

.github/workflows/recompile-safe-output-fixtures.lock.yml

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.github/workflows/recompile-safe-output-fixtures.md

Lines changed: 65 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -125,17 +125,63 @@ chmod +x ado-aw
125125

126126
If the version printed by `./ado-aw --version` does not contain `BARE`, abort with `missing-data` describing the mismatch — you have downloaded the wrong asset.
127127

128+
## Step 2.5 — Pre-flight integrity check on the existing lock files
129+
130+
Before recompiling, run `ado-aw check` against every existing `tests/safe-outputs/*.lock.yml` using the **released** binary. The `check` subcommand recompiles each pipeline from its source `.md` and compares against the committed lock file; a non-zero exit means the on-disk lock file does **not** match what the released compiler would produce — i.e. it drifted (for example because someone recompiled with a dev build off `main` and merged that, or because a release shipped output changes that were never propagated). This is a primary signal that we need to recompile, independent of whether the source `.md` changed.
131+
132+
```bash
133+
set -euo pipefail
134+
cd "$GITHUB_WORKSPACE"
135+
mkdir -p /tmp/gh-aw/agent
136+
: > /tmp/gh-aw/agent/integrity-failures.txt
137+
INTEGRITY_FAIL_COUNT=0
138+
for lock in tests/safe-outputs/*.lock.yml; do
139+
if /tmp/gh-aw/agent/ado-aw-bin/ado-aw check "$lock" \
140+
> "/tmp/gh-aw/agent/check-$(basename "$lock").log" 2>&1; then
141+
echo "PASS $lock"
142+
else
143+
echo "FAIL $lock (exit $?)"
144+
echo "$lock" >> /tmp/gh-aw/agent/integrity-failures.txt
145+
INTEGRITY_FAIL_COUNT=$((INTEGRITY_FAIL_COUNT + 1))
146+
fi
147+
done
148+
echo "integrity_failures=$INTEGRITY_FAIL_COUNT"
149+
```
150+
151+
Record the failure count and the failing-file list — both go in the PR body (Step 6) when a PR is opened. Do **not** abort on integrity failure here; this step is diagnostic only. Recompilation in Step 3 is what fixes the drift. If a single per-file check log shows an error other than a content mismatch (for example a missing source file, a codemod-required source, or an internal compiler error), include the relevant log excerpt in the PR body or — if recompile in Step 3 cannot succeed either — fall back to `report-incomplete` from Step 3.
152+
128153
## Step 3 — Recompile every fixture in `tests/safe-outputs/`
129154

130-
The `tests/safe-outputs/README.md` documents the idempotent recompile command. Run it under strict shell mode so a single fixture failure aborts the whole run instead of leaving partial output on disk:
155+
`ado-aw compile` accepts a single `.md` path or no arguments (cwd autodiscovery). It does **not** accept a directory argument — passing one silently produces `0 compiled, N skipped`, which is exactly the failure mode that took down [run 27020309715](https://github.com/githubnext/ado-aw/actions/runs/27020309715) and is tracked in [issue #867](https://github.com/githubnext/ado-aw/issues/867). Loop per-file from the repo root instead, and pass `--force` to bypass the GitHub-remote guard (required when running inside `githubnext/ado-aw` itself):
131156

132157
```bash
133158
set -euo pipefail
134159
cd "$GITHUB_WORKSPACE"
135-
/tmp/gh-aw/agent/ado-aw-bin/ado-aw compile tests/safe-outputs/ 2>&1 | tee /tmp/gh-aw/agent/recompile.log
160+
: > /tmp/gh-aw/agent/recompile.log
161+
for md in tests/safe-outputs/*.md; do
162+
echo ">>> compiling $md" | tee -a /tmp/gh-aw/agent/recompile.log
163+
/tmp/gh-aw/agent/ado-aw-bin/ado-aw compile --force "$md" 2>&1 | tee -a /tmp/gh-aw/agent/recompile.log
164+
done
136165
```
137166

138-
If the compile exits non-zero, do **not** open a PR with partial output. Emit `report-incomplete` with the last ~80 lines of `/tmp/gh-aw/agent/recompile.log` so a maintainer can investigate. Stop.
167+
If any per-file compile exits non-zero, the script aborts via `set -euo pipefail` and partial output is left on disk. Do **not** open a PR in that state — emit `report-incomplete` with the last ~80 lines of `/tmp/gh-aw/agent/recompile.log` so a maintainer can investigate. Stop.
168+
169+
## Step 3.5 — Post-compile sanity check
170+
171+
After recompiling, re-run `ado-aw check` against every lock file using the same released binary. Every check **must** now pass — if any still fails, our just-produced output disagrees with itself, which means the compile silently mis-handled something. That is a hard failure:
172+
173+
```bash
174+
set -euo pipefail
175+
cd "$GITHUB_WORKSPACE"
176+
for lock in tests/safe-outputs/*.lock.yml; do
177+
/tmp/gh-aw/agent/ado-aw-bin/ado-aw check "$lock" \
178+
> "/tmp/gh-aw/agent/postcheck-$(basename "$lock").log" 2>&1 \
179+
|| { echo "post-compile integrity STILL failing for $lock"; cat "/tmp/gh-aw/agent/postcheck-$(basename "$lock").log"; exit 1; }
180+
done
181+
echo "all lock files pass integrity check against ado-aw ${TAG}"
182+
```
183+
184+
If this step fails, emit `report-incomplete` with the offending file name and the tail of its postcheck log; do **not** open a PR with broken integrity.
139185

140186
## Step 4 — Detect actual changes
141187

@@ -146,7 +192,9 @@ git status --porcelain -- tests/safe-outputs/ > /tmp/gh-aw/agent/recompile-statu
146192
cat /tmp/gh-aw/agent/recompile-status.txt
147193
```
148194

149-
If `/tmp/gh-aw/agent/recompile-status.txt` is empty, the fixtures already match the released version — emit `noop` with the message `"tests/safe-outputs/ already compiled against ado-aw ${TAG}"` and stop. Do **not** open an empty PR.
195+
If `/tmp/gh-aw/agent/recompile-status.txt` is empty **and** `INTEGRITY_FAIL_COUNT` from Step 2.5 was `0`, the fixtures already match the released version — emit `noop` with the message `"tests/safe-outputs/ already compiled against ado-aw ${TAG} and all integrity checks pass"` and stop. Do **not** open an empty PR.
196+
197+
If `/tmp/gh-aw/agent/recompile-status.txt` is empty **but** `INTEGRITY_FAIL_COUNT > 0`, this is contradictory — recompile produced no diff yet `check` reported drift. That should not happen in practice (a passing `check` and a no-op `compile` against the same source and binary must agree). Emit `report-incomplete` with the contents of `/tmp/gh-aw/agent/integrity-failures.txt` and the relevant `check-*.log` files so a maintainer can investigate. Stop.
150198

151199
If non-empty, inspect the diff briefly to make sure only `.lock.yml` files under `tests/safe-outputs/` changed:
152200

@@ -183,14 +231,24 @@ The `safe-outputs.create-pull-request.title-prefix` is configured to `chore(work
183231

184232
Bumps the `version` field in every `tests/safe-outputs/*.lock.yml` metadata marker from `${OLD_VER}` to `${NEW_VER}`, picking up any compile-output changes shipped in [`ado-aw ${TAG}`](https://github.com/githubnext/ado-aw/releases/tag/${TAG}).
185233

234+
### Pre-flight integrity check
235+
236+
Before recompiling, `ado-aw check` was run against every existing lock file using the released `${TAG}` binary:
237+
238+
- **Integrity failures**: `${INTEGRITY_FAIL_COUNT}` of N files
239+
240+
<if INTEGRITY_FAIL_COUNT > 0, include a fenced block listing the contents of `/tmp/gh-aw/agent/integrity-failures.txt`>
241+
186242
### Files updated
187243

188244
<list of files from `git diff --name-only -- tests/safe-outputs/`, one per line in a fenced block>
189245

190246
### How this was produced
191247

192248
- Downloaded `ado-aw-linux-x64` from the `${TAG}` release and verified its SHA256 against `checksums.txt`.
249+
- Ran `ado-aw check tests/safe-outputs/*.lock.yml` against the released binary to detect drift (see counts above).
193250
- Ran `ado-aw compile tests/safe-outputs/` from the repo root.
251+
- Re-ran `ado-aw check` against every regenerated lock file; all passed.
194252
- The `allowed-files` glob in this workflow restricts the diff to `tests/safe-outputs/**/*.lock.yml`.
195253

196254
### Reviewer checklist
@@ -212,7 +270,9 @@ The `safe-outputs.close-pull-request` configuration on this workflow targets any
212270
- Release assets never appear within the bounded retry window (Step 2) — emit `report-incomplete`.
213271
- `ado-aw --version` does not contain `BARE` (Step 2) — emit `missing-data`.
214272
- `ado-aw compile` fails (Step 3) — emit `report-incomplete`.
215-
- `tests/safe-outputs/` is already at `BARE` (Step 4) — emit `noop`.
273+
- Post-compile `ado-aw check` still fails for any lock file (Step 3.5) — emit `report-incomplete`.
274+
- `tests/safe-outputs/` is already at `BARE` **and** pre-flight integrity reported zero failures (Step 4) — emit `noop`.
275+
- Recompile produced no diff but pre-flight integrity reported failures (Step 4) — emit `report-incomplete`.
216276
- Compile output touched paths outside `tests/safe-outputs/*.lock.yml` (Step 4) — emit `report-incomplete`.
217277

218278
Keep the PR small, mechanical, and reviewable. One release, one PR.

0 commit comments

Comments
 (0)