name: nightly audit # Every vanilla harness, from scratch, on main, at 03:00 Paris time on the Mac mini's runner (it holds the # maintainer's own Minecraft files). The resources are prepared again first when the preparer or its exporters # changed (tools/ci/vanilla-data.sh). A harness that passed in the previous audit and fails now gets an issue # labelled parity-regression (one per harness); its issue closes when it passes again # (tools/ci/parity_issues.py). The bugs session picks those up. See docs/release-flow.md. # gh workflow run "nightly audit" # now # gh workflow run "nightly audit" -f dry_run=true # the audit, without touching issues on: schedule: # GitHub's schedules are in UTC: both, and the first step keeps the one that is 03:07 in Paris today. - cron: '7 1 * * *' - cron: '7 2 * * *' workflow_dispatch: inputs: dry_run: description: Run the audit, but only print what it would do with issues type: boolean default: false permissions: contents: read issues: write concurrency: group: nightly-audit cancel-in-progress: false env: # Test runs never reach the telemetry server: no live-count ping, no uploads (docs/telemetry.md). HORIZON_TELEMETRY_URL: "off" jobs: audit: # The Mac mini's runners only: the audit compares with the previous one, so it stays on one platform. runs-on: [self-hosted, horizon-game, macOS] timeout-minutes: 240 # every harness (~80 min) plus lan_integration (~40 min an attempt under load, retried) steps: - name: 03:07 in Paris id: when env: SCHEDULE: ${{ github.event.schedule }} run: | # Which cron is 03:07 in Paris, from Paris's offset today: GitHub can start a schedule hours late, so the # clock at start time can't tell (on 2026-10-26 both started after 04:00 Paris and both skipped). offset=$(TZ=Europe/Paris date +%z) ours=$([ "$offset" = +0200 ] && echo '7 1 * * *' || echo '7 2 * * *') if [[ "${{ github.event_name }}" == schedule && "$SCHEDULE" != "$ours" ]]; then echo "Paris is at UTC${offset} today: the '$ours' schedule runs the audit." echo "run=false" >> "$GITHUB_OUTPUT" else echo "run=true" >> "$GITHUB_OUTPUT" fi - uses: actions/checkout@v4 if: steps.when.outputs.run == 'true' with: fetch-depth: 0 persist-credentials: false # Keeps .local/ (parity state, probe builds, the previous audit) and target/. clean: false - uses: dtolnay/rust-toolchain@stable if: steps.when.outputs.run == 'true' - name: Tools from the runner if: steps.when.outputs.run == 'true' run: bash tools/ci/runner-env.sh - name: Vanilla data, prepared again if the preparer changed if: steps.when.outputs.run == 'true' run: bash tools/ci/vanilla-data.sh - name: Every harness id: audit if: steps.when.outputs.run == 'true' env: PARITY_HOSTS: '' run: | echo "since=$(date +%Y-%m-%dT%H:%M:%S)" >> "$GITHUB_OUTPUT" set +e # lan_integration (the whole lan_e2e suite) takes ~2,400 s under load, past the usual 1,800. python3 tools/parity.py --all --timeout 3000 2>&1 | tee "$RUNNER_TEMP/audit.log" echo "exit=${PIPESTATUS[0]}" >> "$GITHUB_OUTPUT" { echo '```'; tail -40 "$RUNNER_TEMP/audit.log"; echo '```'; } >> "$GITHUB_STEP_SUMMARY" - name: Issues for the harnesses that regressed if: steps.when.outputs.run == 'true' && always() && steps.audit.outputs.since env: GH_TOKEN: ${{ github.token }} run: python3 tools/ci/parity_issues.py --since "${{ steps.audit.outputs.since }}" ${{ inputs.dry_run && '--dry-run' || '' }} | tee -a "$GITHUB_STEP_SUMMARY" - name: Logs of the failed harnesses if: steps.when.outputs.run == 'true' && steps.audit.outputs.exit != '0' uses: actions/upload-artifact@v4 with: name: nightly-parity-logs path: .local/parity-runner/logs/ if-no-files-found: ignore retention-days: 7