From 2cc0e080fc785c0919bd914a5da3087e5030345e Mon Sep 17 00:00:00 2001 From: David Spencer <1526975+DecisionNerd@users.noreply.github.com> Date: Thu, 20 Aug 2026 15:56:40 -0600 Subject: [PATCH 1/4] ci(perf): gate Macro walltime by changed paths --- .github/workflows/codspeed.yml | 31 ++++++++++++ .github/workflows/test.yml | 3 ++ scripts/ci/classify-codspeed-macro.py | 55 ++++++++++++++++++++++ scripts/ci/test-classify-codspeed-macro.py | 42 +++++++++++++++++ 4 files changed, 131 insertions(+) create mode 100644 scripts/ci/classify-codspeed-macro.py create mode 100644 scripts/ci/test-classify-codspeed-macro.py diff --git a/.github/workflows/codspeed.yml b/.github/workflows/codspeed.yml index dc6d23d76..e10b8c99a 100644 --- a/.github/workflows/codspeed.yml +++ b/.github/workflows/codspeed.yml @@ -25,6 +25,33 @@ concurrency: cancel-in-progress: ${{ github.event_name == 'pull_request' }} jobs: + macro-changes: + name: Classify Macro Changes + runs-on: blacksmith-4vcpu-ubuntu-2404 + timeout-minutes: 10 + outputs: + required: ${{ steps.classify.outputs.required }} + steps: + - name: Checkout code + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + fetch-depth: 0 + - name: Classify durable walltime paths + id: classify + shell: bash + run: | + set -euo pipefail + if [[ "${{ github.event_name }}" != "pull_request" ]]; then + echo "required=true" >> "$GITHUB_OUTPUT" + exit 0 + fi + BASE="${{ github.event.pull_request.base.sha }}" + required="$( + git diff --name-only "$BASE" "${{ github.event.pull_request.head.sha }}" | + python3 scripts/ci/classify-codspeed-macro.py + )" + echo "required=$required" >> "$GITHUB_OUTPUT" + benchmarks: name: Rust Benchmarks runs-on: blacksmith-4vcpu-ubuntu-2404 @@ -59,6 +86,10 @@ jobs: m6-walltime: name: M6 Durable Walltime (CodSpeed Macro ARM64) + needs: macro-changes + if: >- + github.event_name != 'pull_request' || + needs.macro-changes.outputs.required == 'true' # Walltime comparisons require CodSpeed's isolated bare-metal runner. # Shared hosted runners are intentionally not a fallback. runs-on: codspeed-macro diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 451611e32..55b34b1b6 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -74,6 +74,9 @@ jobs: - name: Test changed-path classifier run: scripts/ci/test-classify-changes.sh + - name: Test CodSpeed Macro path classifier + run: python3 scripts/ci/test-classify-codspeed-macro.py + - name: Test Repository Policy suite classifier run: scripts/ci/test-classify-policy-suites.sh diff --git a/scripts/ci/classify-codspeed-macro.py b/scripts/ci/classify-codspeed-macro.py new file mode 100644 index 000000000..d23b00879 --- /dev/null +++ b/scripts/ci/classify-codspeed-macro.py @@ -0,0 +1,55 @@ +#!/usr/bin/env python3 +"""Classify whether changed paths can affect M6 durable walltime.""" + +from __future__ import annotations + +from pathlib import PurePosixPath +import sys + +RELEVANT_PREFIXES = ( + "crates/graphforge-core/", + "crates/graphforge-filesystem/", + "crates/graphforge-storage/", + ".cargo/", +) +RELEVANT_FILES = { + "Cargo.lock", + "Cargo.toml", + "rust-toolchain.toml", +} +KNOWN_IRRELEVANT_PREFIXES = ( + ".github/", + "docs/", + "docs-site/", + "legal/", + "packages/", + "scripts/", + "tests/", + "tools/", +) + + +def requires_macro(path: str) -> bool: + """Return true for relevant or unknown paths; unknowns fail closed.""" + path = path.strip().removeprefix("./") + if not path: + return False + if path in RELEVANT_FILES or path.startswith(RELEVANT_PREFIXES): + return True + if path.startswith("crates/"): + return False + if path.startswith(KNOWN_IRRELEVANT_PREFIXES): + return False + if PurePosixPath(path).suffix.lower() == ".md": + return False + return True + + +def main() -> int: + paths = [line.strip() for line in sys.stdin if line.strip()] + print("true" if any(requires_macro(path) for path in paths) else "false") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/scripts/ci/test-classify-codspeed-macro.py b/scripts/ci/test-classify-codspeed-macro.py new file mode 100644 index 000000000..72f8eaa38 --- /dev/null +++ b/scripts/ci/test-classify-codspeed-macro.py @@ -0,0 +1,42 @@ +#!/usr/bin/env python3 +"""Regression tests for CodSpeed Macro changed-path classification.""" + +from __future__ import annotations + +from pathlib import Path +import subprocess + +ROOT = Path(__file__).resolve().parents[2] +CLASSIFIER = ROOT / "scripts/ci/classify-codspeed-macro.py" +WORKFLOW = ROOT / ".github/workflows/codspeed.yml" + + +def classify(*paths: str) -> str: + result = subprocess.run( + ["python3", str(CLASSIFIER)], + input="\n".join(paths), + check=True, + capture_output=True, + text=True, + ) + return result.stdout.strip() + + +assert classify("crates/graphforge-storage/src/project.rs") == "true" +assert classify("crates/graphforge-filesystem/src/lib.rs") == "true" +assert classify("Cargo.lock") == "true" +assert classify("docs/reference/storage.md") == "false" +assert classify(".github/workflows/codspeed.yml") == "false" +assert classify("scripts/ci/classify-codspeed-macro.py") == "false" +assert classify("crates/graphforge-ontology/src/lib.rs") == "false" +assert classify("docs/guide.md", "crates/graphforge-storage/src/lib.rs") == "true" +assert classify() == "false" +assert classify("new-runtime-surface/config.bin") == "true" + +workflow = WORKFLOW.read_text(encoding="utf-8") +assert "macro-changes:" in workflow +assert "needs: macro-changes" in workflow +assert "github.event_name != 'pull_request'" in workflow +assert "needs.macro-changes.outputs.required == 'true'" in workflow + +print("CodSpeed Macro path classification verified") From 6fdb01bf8a27dd1d6feb9aaf557013a7ed1a0e18 Mon Sep 17 00:00:00 2001 From: David Spencer <1526975+DecisionNerd@users.noreply.github.com> Date: Thu, 20 Aug 2026 17:24:13 -0600 Subject: [PATCH 2/4] test(ci): harden Macro path policy regressions --- scripts/ci/classify-codspeed-macro.py | 4 ++-- scripts/ci/test-classify-codspeed-macro.py | 26 +++++++++++++++++----- 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/scripts/ci/classify-codspeed-macro.py b/scripts/ci/classify-codspeed-macro.py index d23b00879..3f27281fb 100644 --- a/scripts/ci/classify-codspeed-macro.py +++ b/scripts/ci/classify-codspeed-macro.py @@ -31,7 +31,7 @@ def requires_macro(path: str) -> bool: """Return true for relevant or unknown paths; unknowns fail closed.""" - path = path.strip().removeprefix("./") + path = path.removeprefix("./") if not path: return False if path in RELEVANT_FILES or path.startswith(RELEVANT_PREFIXES): @@ -46,7 +46,7 @@ def requires_macro(path: str) -> bool: def main() -> int: - paths = [line.strip() for line in sys.stdin if line.strip()] + paths = [line.removesuffix("\n").removesuffix("\r") for line in sys.stdin] print("true" if any(requires_macro(path) for path in paths) else "false") return 0 diff --git a/scripts/ci/test-classify-codspeed-macro.py b/scripts/ci/test-classify-codspeed-macro.py index 72f8eaa38..9a9e46aff 100644 --- a/scripts/ci/test-classify-codspeed-macro.py +++ b/scripts/ci/test-classify-codspeed-macro.py @@ -6,6 +6,8 @@ from pathlib import Path import subprocess +import yaml + ROOT = Path(__file__).resolve().parents[2] CLASSIFIER = ROOT / "scripts/ci/classify-codspeed-macro.py" WORKFLOW = ROOT / ".github/workflows/codspeed.yml" @@ -24,7 +26,11 @@ def classify(*paths: str) -> str: assert classify("crates/graphforge-storage/src/project.rs") == "true" assert classify("crates/graphforge-filesystem/src/lib.rs") == "true" +assert classify("crates/graphforge-core/src/lib.rs") == "true" +assert classify(".cargo/config.toml") == "true" assert classify("Cargo.lock") == "true" +assert classify("Cargo.toml") == "true" +assert classify("rust-toolchain.toml") == "true" assert classify("docs/reference/storage.md") == "false" assert classify(".github/workflows/codspeed.yml") == "false" assert classify("scripts/ci/classify-codspeed-macro.py") == "false" @@ -32,11 +38,19 @@ def classify(*paths: str) -> str: assert classify("docs/guide.md", "crates/graphforge-storage/src/lib.rs") == "true" assert classify() == "false" assert classify("new-runtime-surface/config.bin") == "true" - -workflow = WORKFLOW.read_text(encoding="utf-8") -assert "macro-changes:" in workflow -assert "needs: macro-changes" in workflow -assert "github.event_name != 'pull_request'" in workflow -assert "needs.macro-changes.outputs.required == 'true'" in workflow +assert classify(" docs/change.rs") == "true" +assert classify("unknown.md ") == "true" + +workflow = yaml.safe_load(WORKFLOW.read_text(encoding="utf-8")) +jobs = workflow["jobs"] +macro_changes = jobs["macro-changes"] +assert macro_changes["outputs"]["required"] == "${{ steps.classify.outputs.required }}" +assert any(step.get("id") == "classify" for step in macro_changes["steps"]) + +walltime = jobs["m6-walltime"] +assert walltime["needs"] == "macro-changes" +assert walltime["if"] == ( + "github.event_name != 'pull_request' || needs.macro-changes.outputs.required == 'true'" +) print("CodSpeed Macro path classification verified") From 8d4f59e1aac5f2e2c430a4cb1bdf5b037094bde9 Mon Sep 17 00:00:00 2001 From: David Spencer <1526975+DecisionNerd@users.noreply.github.com> Date: Thu, 20 Aug 2026 17:36:45 -0600 Subject: [PATCH 3/4] ci(perf): run CodSpeed nightly on changed main --- .github/workflows/README.md | 20 +++--- .github/workflows/codspeed.yml | 79 ++++++++++++++-------- .github/workflows/test.yml | 4 +- scripts/ci/classify-codspeed-macro.py | 55 --------------- scripts/ci/test-classify-codspeed-macro.py | 56 --------------- scripts/ci/test-codspeed-nightly.py | 50 ++++++++++++++ 6 files changed, 111 insertions(+), 153 deletions(-) delete mode 100644 scripts/ci/classify-codspeed-macro.py delete mode 100644 scripts/ci/test-classify-codspeed-macro.py create mode 100644 scripts/ci/test-codspeed-nightly.py diff --git a/.github/workflows/README.md b/.github/workflows/README.md index 8d395343a..d731ede62 100644 --- a/.github/workflows/README.md +++ b/.github/workflows/README.md @@ -121,19 +121,19 @@ deployments remain serialized to GitHub Pages. ### `codspeed.yml` — CodSpeed -Builds the divan benchmark targets with `cargo codspeed` and measures them -under CodSpeed's CPU simulation instrument on pull requests to `main`, pushes -to `main`, and manual dispatch. It reports performance deltas against the base -commit as evidence. It is not part of the `CI Gate` aggregate, but its external -check must still be resolved for the PR to reach the required `CLEAN` state. -Its Cargo build stays a diagnostic path next to authoritative Bazel -compilation. Comparable-run and measurement-floor triage is documented in +Runs once nightly against the exact latest `main` SHA, plus explicit manual +dispatch. Pull requests and pushes do not trigger CodSpeed. The latest +successful scheduled workflow SHA skips all nightly benchmark runners when +`main` has not changed; missing or unsuccessful prior evidence fails closed to +running the suite. Its Cargo +build stays a diagnostic path next to authoritative Bazel compilation. +Comparable-run and measurement-floor triage is documented in [`docs/development/benchmarking.md`](../../docs/development/benchmarking.md). M6 pure kernels use simulation on the ordinary pinned CI runner; durable open/recovery/commit/GC/compaction use CodSpeed's isolated bare-metal -`codspeed-macro` ARM64 runner. Weekly/manual runs -also retain exact-SHA replay and compaction peak-RSS artifacts while CodSpeed -memory mode is unavailable for this project. +`codspeed-macro` ARM64 runner. Manual runs also retain exact-SHA replay and +compaction peak-RSS artifacts while CodSpeed memory mode is unavailable for +this project. ### `binding-release-candidate.yml` diff --git a/.github/workflows/codspeed.yml b/.github/workflows/codspeed.yml index e10b8c99a..09be7da83 100644 --- a/.github/workflows/codspeed.yml +++ b/.github/workflows/codspeed.yml @@ -1,64 +1,80 @@ name: CodSpeed -# Continuous performance measurement for the Rust surface. Benchmarks are +# Nightly performance measurement for the Rust surface. Benchmarks are # divan targets built through `cargo codspeed` and measured with CodSpeed's # CPU simulation instrument for pure kernels and CodSpeed Macro Runners for # durable I/O walltime. Cargo builds here are diagnostics-only: Bazel remains # the authoritative compile/test surface (see .github/workflows/README.md). on: - push: - branches: ["main"] - pull_request: - branches: ["main"] - # Lets CodSpeed trigger a backtest run to seed the baseline. workflow_dispatch: schedule: - - cron: "17 7 * * 1" + - cron: "17 7 * * *" permissions: + actions: read contents: read # OpenID Connect authentication with CodSpeed (no long-lived token). id-token: write concurrency: - group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} - cancel-in-progress: ${{ github.event_name == 'pull_request' }} + group: ${{ github.workflow }}-main + cancel-in-progress: false jobs: - macro-changes: - name: Classify Macro Changes + nightly: + name: Check Latest Main runs-on: blacksmith-4vcpu-ubuntu-2404 timeout-minutes: 10 outputs: - required: ${{ steps.classify.outputs.required }} + sha: ${{ steps.main.outputs.sha }} + should-run: ${{ steps.decision.outputs.should-run }} steps: - - name: Checkout code + - name: Checkout latest main uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: - fetch-depth: 0 - - name: Classify durable walltime paths - id: classify + ref: main + - name: Resolve latest main SHA + id: main + shell: bash + run: echo "sha=$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT" + - name: Find latest successful nightly SHA + id: previous shell: bash + env: + GH_TOKEN: ${{ github.token }} run: | set -euo pipefail - if [[ "${{ github.event_name }}" != "pull_request" ]]; then - echo "required=true" >> "$GITHUB_OUTPUT" - exit 0 + previous="" + if curl --fail --silent --show-error \ + --header "Authorization: Bearer $GH_TOKEN" \ + --header "X-GitHub-Api-Version: 2022-11-28" \ + "https://api.github.com/repos/$GITHUB_REPOSITORY/actions/workflows/codspeed.yml/runs?branch=main&event=schedule&status=success&per_page=1" \ + --output nightly-runs.json; then + previous="$(python3 -c 'import json; data=json.load(open("nightly-runs.json", encoding="utf-8")); runs=data.get("workflow_runs", []); print(runs[0]["head_sha"] if runs else "")')" fi - BASE="${{ github.event.pull_request.base.sha }}" - required="$( - git diff --name-only "$BASE" "${{ github.event.pull_request.head.sha }}" | - python3 scripts/ci/classify-codspeed-macro.py - )" - echo "required=$required" >> "$GITHUB_OUTPUT" + echo "sha=$previous" >> "$GITHUB_OUTPUT" + - name: Decide whether benchmarks are needed + id: decision + shell: bash + run: | + set -euo pipefail + should_run=true + if [[ "${{ github.event_name }}" == "schedule" && "${{ steps.previous.outputs.sha }}" == "${{ steps.main.outputs.sha }}" ]]; then + should_run=false + fi + echo "should-run=$should_run" >> "$GITHUB_OUTPUT" benchmarks: name: Rust Benchmarks + needs: nightly + if: needs.nightly.outputs.should-run == 'true' runs-on: blacksmith-4vcpu-ubuntu-2404 timeout-minutes: 60 steps: - name: Checkout code uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + ref: ${{ needs.nightly.outputs.sha }} - name: Install Rust toolchain uses: dtolnay/rust-toolchain@6c977a6ca4077a0ceb28ffbe03f59d46e9ac8772 # master as of 2026-08-05 @@ -86,16 +102,16 @@ jobs: m6-walltime: name: M6 Durable Walltime (CodSpeed Macro ARM64) - needs: macro-changes - if: >- - github.event_name != 'pull_request' || - needs.macro-changes.outputs.required == 'true' + needs: nightly + if: needs.nightly.outputs.should-run == 'true' # Walltime comparisons require CodSpeed's isolated bare-metal runner. # Shared hosted runners are intentionally not a fallback. runs-on: codspeed-macro timeout-minutes: 60 steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + ref: ${{ needs.nightly.outputs.sha }} - uses: dtolnay/rust-toolchain@6c977a6ca4077a0ceb28ffbe03f59d46e9ac8772 # master as of 2026-08-05 with: toolchain: "1.96.0" @@ -111,11 +127,14 @@ jobs: m6-memory-fallback: name: M6 Scheduled Peak Memory Artifact - if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' + needs: nightly + if: github.event_name == 'workflow_dispatch' && needs.nightly.outputs.should-run == 'true' runs-on: blacksmith-4vcpu-ubuntu-2404 timeout-minutes: 60 steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + ref: ${{ needs.nightly.outputs.sha }} - uses: dtolnay/rust-toolchain@6c977a6ca4077a0ceb28ffbe03f59d46e9ac8772 # master as of 2026-08-05 with: toolchain: "1.96.0" diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 55b34b1b6..91c6fdb57 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -74,8 +74,8 @@ jobs: - name: Test changed-path classifier run: scripts/ci/test-classify-changes.sh - - name: Test CodSpeed Macro path classifier - run: python3 scripts/ci/test-classify-codspeed-macro.py + - name: Test CodSpeed nightly policy + run: python3 scripts/ci/test-codspeed-nightly.py - name: Test Repository Policy suite classifier run: scripts/ci/test-classify-policy-suites.sh diff --git a/scripts/ci/classify-codspeed-macro.py b/scripts/ci/classify-codspeed-macro.py deleted file mode 100644 index 3f27281fb..000000000 --- a/scripts/ci/classify-codspeed-macro.py +++ /dev/null @@ -1,55 +0,0 @@ -#!/usr/bin/env python3 -"""Classify whether changed paths can affect M6 durable walltime.""" - -from __future__ import annotations - -from pathlib import PurePosixPath -import sys - -RELEVANT_PREFIXES = ( - "crates/graphforge-core/", - "crates/graphforge-filesystem/", - "crates/graphforge-storage/", - ".cargo/", -) -RELEVANT_FILES = { - "Cargo.lock", - "Cargo.toml", - "rust-toolchain.toml", -} -KNOWN_IRRELEVANT_PREFIXES = ( - ".github/", - "docs/", - "docs-site/", - "legal/", - "packages/", - "scripts/", - "tests/", - "tools/", -) - - -def requires_macro(path: str) -> bool: - """Return true for relevant or unknown paths; unknowns fail closed.""" - path = path.removeprefix("./") - if not path: - return False - if path in RELEVANT_FILES or path.startswith(RELEVANT_PREFIXES): - return True - if path.startswith("crates/"): - return False - if path.startswith(KNOWN_IRRELEVANT_PREFIXES): - return False - if PurePosixPath(path).suffix.lower() == ".md": - return False - return True - - -def main() -> int: - paths = [line.removesuffix("\n").removesuffix("\r") for line in sys.stdin] - print("true" if any(requires_macro(path) for path in paths) else "false") - return 0 - - -if __name__ == "__main__": - raise SystemExit(main()) diff --git a/scripts/ci/test-classify-codspeed-macro.py b/scripts/ci/test-classify-codspeed-macro.py deleted file mode 100644 index 9a9e46aff..000000000 --- a/scripts/ci/test-classify-codspeed-macro.py +++ /dev/null @@ -1,56 +0,0 @@ -#!/usr/bin/env python3 -"""Regression tests for CodSpeed Macro changed-path classification.""" - -from __future__ import annotations - -from pathlib import Path -import subprocess - -import yaml - -ROOT = Path(__file__).resolve().parents[2] -CLASSIFIER = ROOT / "scripts/ci/classify-codspeed-macro.py" -WORKFLOW = ROOT / ".github/workflows/codspeed.yml" - - -def classify(*paths: str) -> str: - result = subprocess.run( - ["python3", str(CLASSIFIER)], - input="\n".join(paths), - check=True, - capture_output=True, - text=True, - ) - return result.stdout.strip() - - -assert classify("crates/graphforge-storage/src/project.rs") == "true" -assert classify("crates/graphforge-filesystem/src/lib.rs") == "true" -assert classify("crates/graphforge-core/src/lib.rs") == "true" -assert classify(".cargo/config.toml") == "true" -assert classify("Cargo.lock") == "true" -assert classify("Cargo.toml") == "true" -assert classify("rust-toolchain.toml") == "true" -assert classify("docs/reference/storage.md") == "false" -assert classify(".github/workflows/codspeed.yml") == "false" -assert classify("scripts/ci/classify-codspeed-macro.py") == "false" -assert classify("crates/graphforge-ontology/src/lib.rs") == "false" -assert classify("docs/guide.md", "crates/graphforge-storage/src/lib.rs") == "true" -assert classify() == "false" -assert classify("new-runtime-surface/config.bin") == "true" -assert classify(" docs/change.rs") == "true" -assert classify("unknown.md ") == "true" - -workflow = yaml.safe_load(WORKFLOW.read_text(encoding="utf-8")) -jobs = workflow["jobs"] -macro_changes = jobs["macro-changes"] -assert macro_changes["outputs"]["required"] == "${{ steps.classify.outputs.required }}" -assert any(step.get("id") == "classify" for step in macro_changes["steps"]) - -walltime = jobs["m6-walltime"] -assert walltime["needs"] == "macro-changes" -assert walltime["if"] == ( - "github.event_name != 'pull_request' || needs.macro-changes.outputs.required == 'true'" -) - -print("CodSpeed Macro path classification verified") diff --git a/scripts/ci/test-codspeed-nightly.py b/scripts/ci/test-codspeed-nightly.py new file mode 100644 index 000000000..f7e0dfd33 --- /dev/null +++ b/scripts/ci/test-codspeed-nightly.py @@ -0,0 +1,50 @@ +#!/usr/bin/env python3 +"""Regression tests for the nightly-only CodSpeed workflow.""" + +from pathlib import Path + +import yaml + +ROOT = Path(__file__).resolve().parents[2] +WORKFLOW = ROOT / ".github/workflows/codspeed.yml" + +workflow = yaml.load(WORKFLOW.read_text(encoding="utf-8"), Loader=yaml.BaseLoader) +triggers = workflow["on"] +assert "pull_request" not in triggers +assert "push" not in triggers +assert "workflow_dispatch" in triggers +assert triggers["schedule"] == [{"cron": "17 7 * * *"}] + +jobs = workflow["jobs"] +assert workflow["permissions"]["actions"] == "read" +nightly = jobs["nightly"] +assert nightly["outputs"]["sha"] == "${{ steps.main.outputs.sha }}" +assert nightly["outputs"]["should-run"] == "${{ steps.decision.outputs.should-run }}" +checkout = nightly["steps"][0] +assert checkout["with"]["ref"] == "main" +previous = next(step for step in nightly["steps"] if step.get("id") == "previous")["run"] +assert "actions/workflows/codspeed.yml/runs" in previous +assert "event=schedule" in previous +assert "status=success" in previous +assert 'previous=""' in previous +decision = next(step for step in nightly["steps"] if step.get("id") == "decision")["run"] +assert 'github.event_name }}" == "schedule"' in decision +assert "steps.previous.outputs.sha" in decision +assert "steps.main.outputs.sha" in decision +assert "should_run=true" in decision +assert "should_run=false" in decision + +for job_name in ("benchmarks", "m6-walltime"): + job = jobs[job_name] + assert job["needs"] == "nightly" + assert job["if"] == "needs.nightly.outputs.should-run == 'true'" + checkout = next(step for step in job["steps"] if "actions/checkout@" in step.get("uses", "")) + assert checkout["with"]["ref"] == "${{ needs.nightly.outputs.sha }}" + +memory = jobs["m6-memory-fallback"] +assert memory["if"] == ( + "github.event_name == 'workflow_dispatch' && " + "needs.nightly.outputs.should-run == 'true'" +) + +print("CodSpeed nightly-only policy verified") From d5b3db8679d43d95b949da328b12c29e76235231 Mon Sep 17 00:00:00 2001 From: David Spencer <1526975+DecisionNerd@users.noreply.github.com> Date: Thu, 20 Aug 2026 17:39:03 -0600 Subject: [PATCH 4/4] style(ci): format CodSpeed nightly policy test --- scripts/ci/test-codspeed-nightly.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/scripts/ci/test-codspeed-nightly.py b/scripts/ci/test-codspeed-nightly.py index f7e0dfd33..2b4d9cc2e 100644 --- a/scripts/ci/test-codspeed-nightly.py +++ b/scripts/ci/test-codspeed-nightly.py @@ -43,8 +43,7 @@ memory = jobs["m6-memory-fallback"] assert memory["if"] == ( - "github.event_name == 'workflow_dispatch' && " - "needs.nightly.outputs.should-run == 'true'" + "github.event_name == 'workflow_dispatch' && needs.nightly.outputs.should-run == 'true'" ) print("CodSpeed nightly-only policy verified")