From ed4d899deaa036024bea8b7c49bfc16c1638463b Mon Sep 17 00:00:00 2001 From: Richie McIlroy <33632126+richiemcilroy@users.noreply.github.com> Date: Sat, 17 Oct 2026 12:07:00 +0900 Subject: [PATCH 1/9] ci(verify): diff main's nightly verification against the cap-v0.6.0 baseline --- .github/workflows/baseline-diff.yml | 115 ++++++++++++++++++++++++++++ scripts/verify/baseline-na.tsv | 2 + scripts/verify/diff.py | 14 +++- 3 files changed, 130 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/baseline-diff.yml create mode 100644 scripts/verify/baseline-na.tsv diff --git a/.github/workflows/baseline-diff.yml b/.github/workflows/baseline-diff.yml new file mode 100644 index 00000000000..141153a3d69 --- /dev/null +++ b/.github/workflows/baseline-diff.yml @@ -0,0 +1,115 @@ +name: Baseline diff + +# Compares main's nightly Engine verify and real-capture runs with the latest +# run of the same workflow on the production baseline branch +# (scratch/prod-baseline: cap-v0.6.0 plus the suite), case by case +# (scripts/verify/diff.py). Fails when main is worse than 0.6.0 anywhere. The +# baseline is re-run weekly so its report artifacts never expire. + +on: + workflow_run: + workflows: ["Engine verify", "Verify recording (real capture)"] + types: [completed] + branches: [main] + schedule: + - cron: "17 2 * * 1" + workflow_dispatch: + inputs: + main-run: + description: "Run id on main to compare (Engine verify or real capture)" + required: true + baseline-run: + description: "Baseline run id (default: the latest of the same workflow on scratch/prod-baseline)" + default: "" + +permissions: + contents: read + actions: write + +concurrency: + group: baseline-diff-${{ github.event.workflow_run.id || inputs.main-run || 'refresh' }} + cancel-in-progress: false + +env: + BASELINE_BRANCH: scratch/prod-baseline + +jobs: + refresh: + if: github.event_name == 'schedule' + runs-on: blacksmith-2vcpu-ubuntu-2404 + steps: + - name: Re-run the baseline + env: + GH_TOKEN: ${{ github.token }} + run: | + gh workflow run engine-verify.yml --repo "$GITHUB_REPOSITORY" --ref "$BASELINE_BRANCH" --raw-field tier=full + gh workflow run verify-recording.yml --repo "$GITHUB_REPOSITORY" --ref "$BASELINE_BRANCH" + + diff: + if: >- + github.event_name == 'workflow_dispatch' || + (github.event_name == 'workflow_run' && github.event.workflow_run.event == 'schedule') + runs-on: blacksmith-2vcpu-ubuntu-2404 + steps: + - uses: actions/checkout@v4 + with: + persist-credentials: false + + - name: Runs + id: runs + env: + GH_TOKEN: ${{ github.token }} + MAIN_RUN: ${{ github.event.workflow_run.id || inputs.main-run }} + BASELINE_INPUT: ${{ inputs.baseline-run }} + run: | + set -euo pipefail + workflow=$(gh run view "$MAIN_RUN" --repo "$GITHUB_REPOSITORY" --json workflowDatabaseId --jq .workflowDatabaseId) + baseline="$BASELINE_INPUT" + if [[ -z "$baseline" ]]; then + baseline=$(gh run list --repo "$GITHUB_REPOSITORY" --workflow "$workflow" --branch "$BASELINE_BRANCH" \ + --status completed --limit 1 --json databaseId --jq '.[0].databaseId // empty') + fi + if [[ -z "$baseline" ]]; then + echo "::error::no completed baseline run of workflow $workflow on $BASELINE_BRANCH" + exit 1 + fi + echo "main=$MAIN_RUN" >> "$GITHUB_OUTPUT" + echo "baseline=$baseline" >> "$GITHUB_OUTPUT" + echo "Comparing main run $MAIN_RUN with baseline run $baseline" | tee -a "$GITHUB_STEP_SUMMARY" + + - name: Download reports + env: + GH_TOKEN: ${{ github.token }} + MAIN_RUN: ${{ steps.runs.outputs.main }} + BASELINE_RUN: ${{ steps.runs.outputs.baseline }} + run: | + set -euo pipefail + for side in main baseline; do + run=$([[ $side == main ]] && echo "$MAIN_RUN" || echo "$BASELINE_RUN") + dest="$RUNNER_TEMP/reports/$side" + mkdir -p "$dest" + gh run download "$run" --repo "$GITHUB_REPOSITORY" --dir "$dest" \ + --pattern 'verify-report-*' --pattern 'verify-recording-*' + # Recordings are large and not read by the diff. + find "$dest" -type d -name verify-scratch -prune -exec rm -r {} + + echo "$side: $(find "$dest" -name '*.jsonl' | wc -l) report files" + done + + - name: Diff + run: | + python3 scripts/verify/diff.py \ + "$RUNNER_TEMP/reports/baseline" "$RUNNER_TEMP/reports/main" \ + --na scripts/verify/baseline-na.tsv \ + --title "cap-v0.6.0 baseline vs main" \ + --fail-on-worse > "$RUNNER_TEMP/baseline-diff.md" + status=$? + cat "$RUNNER_TEMP/baseline-diff.md" >> "$GITHUB_STEP_SUMMARY" + exit "$status" + shell: bash {0} + + - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 + if: always() + with: + name: baseline-diff + path: ${{ runner.temp }}/baseline-diff.md + if-no-files-found: ignore diff --git a/scripts/verify/baseline-na.tsv b/scripts/verify/baseline-na.tsv new file mode 100644 index 00000000000..877252ee91c --- /dev/null +++ b/scripts/verify/baseline-na.tsv @@ -0,0 +1,2 @@ +# globreason (cases n/a on the cap-v0.6.0 production baseline) +captions/* caption projection model (synchronize_captions) and transcription audio assembly did not exist in cap-v0.6.0; captions suite not run diff --git a/scripts/verify/diff.py b/scripts/verify/diff.py index d9332ad199c..29ab169bf67 100644 --- a/scripts/verify/diff.py +++ b/scripts/verify/diff.py @@ -326,6 +326,7 @@ def main(): ap.add_argument("--json") ap.add_argument("--title", default="baseline vs main") ap.add_argument("--na", help="file of 'case-globreason' lines: cases n/a on the baseline") + ap.add_argument("--fail-on-worse", action="store_true", help="exit 1 when any lane has WORSE or junit WORSE rows") args = ap.parse_args() na = load_na(args.na) @@ -400,7 +401,18 @@ def main(): if args.json: with open(args.json, "w") as fh: json.dump(out, fh, indent=1, default=list) + if args.fail_on_worse: + # A unit test that main no longer has was renamed or removed with the + # code it tested; the case-level rows cover the product. + def counted(items): + return [item for item in items or [] if not any(r.startswith("missing on main (baseline") for r in item[1])] + + worse = sum(len(counted(lane.get("WORSE"))) + len(counted(lane.get("JUNIT-WORSE"))) for lane in out.values()) + if worse: + print(f"\n{worse} row(s) worse than the baseline", file=sys.stderr) + return 1 + return 0 if __name__ == "__main__": - main() + sys.exit(main()) From 6d549aef9afdcfe135d0c420d896aff8b74ec798 Mon Sep 17 00:00:00 2001 From: Richie McIlroy <33632126+richiemcilroy@users.noreply.github.com> Date: Sat, 17 Oct 2026 12:22:11 +0900 Subject: [PATCH 2/9] ci(verify): baseline refresh matches main's nightly shape, skip cancelled baselines, fail on missing lanes --- .github/workflows/baseline-diff.yml | 15 ++++++++------- scripts/verify/diff.py | 5 +++++ 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/.github/workflows/baseline-diff.yml b/.github/workflows/baseline-diff.yml index 141153a3d69..265573004c7 100644 --- a/.github/workflows/baseline-diff.yml +++ b/.github/workflows/baseline-diff.yml @@ -1,10 +1,8 @@ name: Baseline diff -# Compares main's nightly Engine verify and real-capture runs with the latest -# run of the same workflow on the production baseline branch -# (scratch/prod-baseline: cap-v0.6.0 plus the suite), case by case -# (scripts/verify/diff.py). Fails when main is worse than 0.6.0 anywhere. The -# baseline is re-run weekly so its report artifacts never expire. +# Report artifacts expire after 90 days and the baseline branch never +# changes, so a weekly cron re-runs the baseline in the same shape as main's +# nightly runs (FULL, three repeats of real capture on both runner pools). on: workflow_run: @@ -43,7 +41,8 @@ jobs: GH_TOKEN: ${{ github.token }} run: | gh workflow run engine-verify.yml --repo "$GITHUB_REPOSITORY" --ref "$BASELINE_BRANCH" --raw-field tier=full - gh workflow run verify-recording.yml --repo "$GITHUB_REPOSITORY" --ref "$BASELINE_BRANCH" + gh workflow run verify-recording.yml --repo "$GITHUB_REPOSITORY" --ref "$BASELINE_BRANCH" \ + --raw-field tier=full --raw-field repeat=3 --raw-field runners=both diff: if: >- @@ -66,8 +65,10 @@ jobs: workflow=$(gh run view "$MAIN_RUN" --repo "$GITHUB_REPOSITORY" --json workflowDatabaseId --jq .workflowDatabaseId) baseline="$BASELINE_INPUT" if [[ -z "$baseline" ]]; then + # Baseline runs fail (0.6.0 has known bugs) but must not be cancelled. baseline=$(gh run list --repo "$GITHUB_REPOSITORY" --workflow "$workflow" --branch "$BASELINE_BRANCH" \ - --status completed --limit 1 --json databaseId --jq '.[0].databaseId // empty') + --status completed --limit 20 --json databaseId,conclusion \ + --jq '[.[] | select(.conclusion != "cancelled")][0].databaseId // empty') fi if [[ -z "$baseline" ]]; then echo "::error::no completed baseline run of workflow $workflow on $BASELINE_BRANCH" diff --git a/scripts/verify/diff.py b/scripts/verify/diff.py index 29ab169bf67..bab9950ceba 100644 --- a/scripts/verify/diff.py +++ b/scripts/verify/diff.py @@ -408,6 +408,11 @@ def counted(items): return [item for item in items or [] if not any(r.startswith("missing on main (baseline") for r in item[1])] worse = sum(len(counted(lane.get("WORSE"))) + len(counted(lane.get("JUNIT-WORSE"))) for lane in out.values()) + # A baseline run that stopped early leaves main's cases unmatched. + unmatched = [lane for lane in lanes if mrec.get(lane) and not brec.get(lane)] + for lane in unmatched: + print(f"lane {lane}: no baseline records", file=sys.stderr) + worse += len(unmatched) if worse: print(f"\n{worse} row(s) worse than the baseline", file=sys.stderr) return 1 From 64f98b3f7c2f9eb70dd9ee1107e4febb8b90effa Mon Sep 17 00:00:00 2001 From: Richie McIlroy <33632126+richiemcilroy@users.noreply.github.com> Date: Sat, 17 Oct 2026 12:39:42 +0900 Subject: [PATCH 3/9] ci(verify): fail the baseline diff when a tenth of a lane's main cases have no baseline record --- scripts/verify/diff.py | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/scripts/verify/diff.py b/scripts/verify/diff.py index bab9950ceba..f112a873937 100644 --- a/scripts/verify/diff.py +++ b/scripts/verify/diff.py @@ -408,11 +408,19 @@ def counted(items): return [item for item in items or [] if not any(r.startswith("missing on main (baseline") for r in item[1])] worse = sum(len(counted(lane.get("WORSE"))) + len(counted(lane.get("JUNIT-WORSE"))) for lane in out.values()) - # A baseline run that stopped early leaves main's cases unmatched. - unmatched = [lane for lane in lanes if mrec.get(lane) and not brec.get(lane)] - for lane in unmatched: - print(f"lane {lane}: no baseline records", file=sys.stderr) - worse += len(unmatched) + # A baseline run that stopped early, or a baseline suite that fell + # behind main's, leaves main's cases unmatched. Cases new on main are + # expected, a tenth of a lane is not. + for lane in lanes: + main_cases = len(mrec.get(lane) or {}) + only_main = len(out.get(lane, {}).get("ONLY-MAIN") or []) + if main_cases and (not brec.get(lane) or only_main * 10 > main_cases): + print( + f"lane {lane}: {only_main} of {main_cases} main cases have no baseline record " + "(re-run the baseline, or refresh its suite)", + file=sys.stderr, + ) + worse += 1 if worse: print(f"\n{worse} row(s) worse than the baseline", file=sys.stderr) return 1 From 0d7f07b5761e2d49634ec824ca96ffd458393afb Mon Sep 17 00:00:00 2001 From: Richie McIlroy <33632126+richiemcilroy@users.noreply.github.com> Date: Sat, 17 Oct 2026 12:50:35 +0900 Subject: [PATCH 4/9] ci(verify): use the latest baseline run with no cancelled or timed-out job --- .github/workflows/baseline-diff.yml | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/.github/workflows/baseline-diff.yml b/.github/workflows/baseline-diff.yml index 265573004c7..86077dbe919 100644 --- a/.github/workflows/baseline-diff.yml +++ b/.github/workflows/baseline-diff.yml @@ -65,10 +65,17 @@ jobs: workflow=$(gh run view "$MAIN_RUN" --repo "$GITHUB_REPOSITORY" --json workflowDatabaseId --jq .workflowDatabaseId) baseline="$BASELINE_INPUT" if [[ -z "$baseline" ]]; then - # Baseline runs fail (0.6.0 has known bugs) but must not be cancelled. - baseline=$(gh run list --repo "$GITHUB_REPOSITORY" --workflow "$workflow" --branch "$BASELINE_BRANCH" \ - --status completed --limit 20 --json databaseId,conclusion \ - --jq '[.[] | select(.conclusion != "cancelled")][0].databaseId // empty') + # Baseline runs fail (0.6.0 has known bugs), but a run with a + # cancelled or timed-out job stopped before reporting every case. + for candidate in $(gh run list --repo "$GITHUB_REPOSITORY" --workflow "$workflow" --branch "$BASELINE_BRANCH" \ + --status completed --limit 20 --json databaseId --jq '.[].databaseId'); do + stopped=$(gh run view "$candidate" --repo "$GITHUB_REPOSITORY" --json conclusion,jobs \ + --jq '[.conclusion, .jobs[].conclusion] | map(select(. == "cancelled" or . == "timed_out")) | length') + if [[ "$stopped" == 0 ]]; then + baseline="$candidate" + break + fi + done fi if [[ -z "$baseline" ]]; then echo "::error::no completed baseline run of workflow $workflow on $BASELINE_BRANCH" From c2d41ba3ed37df0887d8426cf9e63b5a4c3c66d6 Mon Sep 17 00:00:00 2001 From: Richie McIlroy <33632126+richiemcilroy@users.noreply.github.com> Date: Sat, 17 Oct 2026 13:21:46 +0900 Subject: [PATCH 5/9] ci(verify): report-only real-capture artifacts for the baseline diff, baselines from runs that succeeded or failed --- .github/workflows/baseline-diff.yml | 13 +++++++++---- .github/workflows/verify-recording.yml | 8 ++++++++ scripts/verify/diff.py | 2 +- 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/.github/workflows/baseline-diff.yml b/.github/workflows/baseline-diff.yml index 86077dbe919..f89b935e1c6 100644 --- a/.github/workflows/baseline-diff.yml +++ b/.github/workflows/baseline-diff.yml @@ -68,7 +68,8 @@ jobs: # Baseline runs fail (0.6.0 has known bugs), but a run with a # cancelled or timed-out job stopped before reporting every case. for candidate in $(gh run list --repo "$GITHUB_REPOSITORY" --workflow "$workflow" --branch "$BASELINE_BRANCH" \ - --status completed --limit 20 --json databaseId --jq '.[].databaseId'); do + --limit 20 --json databaseId,conclusion \ + --jq '.[] | select(.conclusion == "success" or .conclusion == "failure") | .databaseId'); do stopped=$(gh run view "$candidate" --repo "$GITHUB_REPOSITORY" --json conclusion,jobs \ --jq '[.conclusion, .jobs[].conclusion] | map(select(. == "cancelled" or . == "timed_out")) | length') if [[ "$stopped" == 0 ]]; then @@ -96,10 +97,14 @@ jobs: run=$([[ $side == main ]] && echo "$MAIN_RUN" || echo "$BASELINE_RUN") dest="$RUNNER_TEMP/reports/$side" mkdir -p "$dest" + # Real capture also uploads its reports alone; runs from before + # that only have the artifact with the recordings. gh run download "$run" --repo "$GITHUB_REPOSITORY" --dir "$dest" \ - --pattern 'verify-report-*' --pattern 'verify-recording-*' - # Recordings are large and not read by the diff. - find "$dest" -type d -name verify-scratch -prune -exec rm -r {} + + --pattern 'verify-report-*' --pattern 'verify-recording-report-*' || true + if [[ -z "$(find "$dest" -maxdepth 1 -name 'verify-*' -print -quit)" ]]; then + gh run download "$run" --repo "$GITHUB_REPOSITORY" --dir "$dest" --pattern 'verify-recording-*' + find "$dest" -type d -name verify-scratch -prune -exec rm -r {} + + fi echo "$side: $(find "$dest" -name '*.jsonl' | wc -l) report files" done diff --git a/.github/workflows/verify-recording.yml b/.github/workflows/verify-recording.yml index 28a0af88722..41ef09139cd 100644 --- a/.github/workflows/verify-recording.yml +++ b/.github/workflows/verify-recording.yml @@ -317,6 +317,14 @@ jobs: run: | python3 scripts/verify/summary.py --title "real capture ${{ matrix.runner }} ${{ needs.scope.outputs.tier }}" "$CAP_VERIFY_REPORT_DIR" >> "$GITHUB_STEP_SUMMARY" || true + - name: Upload reports + if: always() + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 + with: + name: verify-recording-report-${{ matrix.runner }} + path: ${{ github.workspace }}/verify-report + if-no-files-found: ignore + - name: Upload artifacts if: always() uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 diff --git a/scripts/verify/diff.py b/scripts/verify/diff.py index f112a873937..3beb84d7cf8 100644 --- a/scripts/verify/diff.py +++ b/scripts/verify/diff.py @@ -34,7 +34,7 @@ def lane_of(artifact): m = re.match(r"verify-report-(.+?)-(fast|full)(-\d+)?$", artifact) if m: return m.group(1) - m = re.match(r"verify-recording-(.+)$", artifact) + m = re.match(r"verify-recording-(?:report-)?(.+)$", artifact) if m: return "recording-" + m.group(1) return artifact From 78d57207521ebdd75361715716605a6edfaa8d06 Mon Sep 17 00:00:00 2001 From: Richie McIlroy <33632126+richiemcilroy@users.noreply.github.com> Date: Sat, 17 Oct 2026 13:39:41 +0900 Subject: [PATCH 6/9] ci(verify): pick the baseline diff's artifact pattern from the run's artifacts and fail on any download error --- .github/workflows/baseline-diff.yml | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/.github/workflows/baseline-diff.yml b/.github/workflows/baseline-diff.yml index f89b935e1c6..bdb98adec95 100644 --- a/.github/workflows/baseline-diff.yml +++ b/.github/workflows/baseline-diff.yml @@ -99,12 +99,19 @@ jobs: mkdir -p "$dest" # Real capture also uploads its reports alone; runs from before # that only have the artifact with the recordings. - gh run download "$run" --repo "$GITHUB_REPOSITORY" --dir "$dest" \ - --pattern 'verify-report-*' --pattern 'verify-recording-report-*' || true - if [[ -z "$(find "$dest" -maxdepth 1 -name 'verify-*' -print -quit)" ]]; then - gh run download "$run" --repo "$GITHUB_REPOSITORY" --dir "$dest" --pattern 'verify-recording-*' - find "$dest" -type d -name verify-scratch -prune -exec rm -r {} + + names=$(gh api "repos/$GITHUB_REPOSITORY/actions/runs/$run/artifacts" --paginate --jq '.artifacts[].name') + if grep -q '^verify-report-' <<< "$names"; then + pattern='verify-report-*' + elif grep -q '^verify-recording-report-' <<< "$names"; then + pattern='verify-recording-report-*' + elif grep -q '^verify-recording-' <<< "$names"; then + pattern='verify-recording-*' + else + echo "::error::run $run has no verification reports" + exit 1 fi + gh run download "$run" --repo "$GITHUB_REPOSITORY" --dir "$dest" --pattern "$pattern" + find "$dest" -type d -name verify-scratch -prune -exec rm -r {} + echo "$side: $(find "$dest" -name '*.jsonl' | wc -l) report files" done From da45510607d3238d9f4f31616cff2d516f923d42 Mon Sep 17 00:00:00 2001 From: Richie McIlroy <33632126+richiemcilroy@users.noreply.github.com> Date: Sat, 17 Oct 2026 14:26:48 +0900 Subject: [PATCH 7/9] ci(verify): fail the baseline diff when the baseline lacks one of main's lanes --- .github/workflows/baseline-diff.yml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/.github/workflows/baseline-diff.yml b/.github/workflows/baseline-diff.yml index bdb98adec95..2432915a85a 100644 --- a/.github/workflows/baseline-diff.yml +++ b/.github/workflows/baseline-diff.yml @@ -115,6 +115,21 @@ jobs: echo "$side: $(find "$dest" -name '*.jsonl' | wc -l) report files" done + - name: Baseline covers main's runners + shell: bash + run: | + set -euo pipefail + # Lanes as diff.py names them: shard numbers and tiers dropped. + lanes() { + find "$1" -mindepth 1 -maxdepth 1 -type d -name 'verify-*' -printf '%f\n' \ + | sed -E 's/^verify-recording-report-/verify-recording-/; s/-(fast|full)(-[0-9]+)?$//' | sort -u + } + missing=$(comm -23 <(lanes "$RUNNER_TEMP/reports/main") <(lanes "$RUNNER_TEMP/reports/baseline")) + if [[ -n "$missing" ]]; then + echo "::error::the baseline run has no reports for: $(echo $missing)" + exit 1 + fi + - name: Diff run: | python3 scripts/verify/diff.py \ From 99036640bfdbe01626a3ef99988a7db28f42e5bd Mon Sep 17 00:00:00 2001 From: Richie McIlroy <33632126+richiemcilroy@users.noreply.github.com> Date: Sun, 18 Oct 2026 07:46:12 +0900 Subject: [PATCH 8/9] ci(verify): baseline diff pins checkout and grants actions write only to the refresh job --- .github/workflows/baseline-diff.yml | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/.github/workflows/baseline-diff.yml b/.github/workflows/baseline-diff.yml index 2432915a85a..ef0ca0a435d 100644 --- a/.github/workflows/baseline-diff.yml +++ b/.github/workflows/baseline-diff.yml @@ -1,8 +1,7 @@ name: Baseline diff # Report artifacts expire after 90 days and the baseline branch never -# changes, so a weekly cron re-runs the baseline in the same shape as main's -# nightly runs (FULL, three repeats of real capture on both runner pools). +# changes, so the baseline is re-run weekly. on: workflow_run: @@ -22,7 +21,6 @@ on: permissions: contents: read - actions: write concurrency: group: baseline-diff-${{ github.event.workflow_run.id || inputs.main-run || 'refresh' }} @@ -35,6 +33,8 @@ jobs: refresh: if: github.event_name == 'schedule' runs-on: blacksmith-2vcpu-ubuntu-2404 + permissions: + actions: write steps: - name: Re-run the baseline env: @@ -45,12 +45,15 @@ jobs: --raw-field tier=full --raw-field repeat=3 --raw-field runners=both diff: + permissions: + contents: read + actions: read if: >- github.event_name == 'workflow_dispatch' || (github.event_name == 'workflow_run' && github.event.workflow_run.event == 'schedule') runs-on: blacksmith-2vcpu-ubuntu-2404 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 with: persist-credentials: false From 6d4c54c58b0a1affa83516149c82f06b00ead504 Mon Sep 17 00:00:00 2001 From: Richie McIlroy <33632126+richiemcilroy@users.noreply.github.com> Date: Sun, 18 Oct 2026 08:52:07 +0900 Subject: [PATCH 9/9] ci(verify): baseline lane check lists directories portably and fails when main has none --- .github/workflows/baseline-diff.yml | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/.github/workflows/baseline-diff.yml b/.github/workflows/baseline-diff.yml index ef0ca0a435d..2a71f59ec40 100644 --- a/.github/workflows/baseline-diff.yml +++ b/.github/workflows/baseline-diff.yml @@ -124,10 +124,18 @@ jobs: set -euo pipefail # Lanes as diff.py names them: shard numbers and tiers dropped. lanes() { - find "$1" -mindepth 1 -maxdepth 1 -type d -name 'verify-*' -printf '%f\n' \ - | sed -E 's/^verify-recording-report-/verify-recording-/; s/-(fast|full)(-[0-9]+)?$//' | sort -u + local dir + for dir in "$1"/verify-*/; do + if [[ -d "$dir" ]]; then basename "$dir"; fi + done | sed -E 's/^verify-recording-report-/verify-recording-/; s/-(fast|full)(-[0-9]+)?$//' | sort -u } - missing=$(comm -23 <(lanes "$RUNNER_TEMP/reports/main") <(lanes "$RUNNER_TEMP/reports/baseline")) + main_lanes=$(lanes "$RUNNER_TEMP/reports/main") + baseline_lanes=$(lanes "$RUNNER_TEMP/reports/baseline") + if [[ -z "$main_lanes" ]]; then + echo "::error::main's run has no report directories" + exit 1 + fi + missing=$(comm -23 <(echo "$main_lanes") <(echo "$baseline_lanes")) if [[ -n "$missing" ]]; then echo "::error::the baseline run has no reports for: $(echo $missing)" exit 1