Nightly Mainnet Smoke #63
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Nightly Mainnet Smoke | |
| on: | |
| schedule: | |
| # 06:00 UTC every day. | |
| - cron: "0 6 * * *" | |
| workflow_dispatch: {} | |
| permissions: | |
| contents: read | |
| # PR comments live on the issues API (`github.rest.issues.createComment`), | |
| # so the failure-notification step needs `issues: write`. Granting only | |
| # `pull-requests: write` would let the workflow load but the createComment | |
| # call would 403 at runtime. | |
| issues: write | |
| concurrency: | |
| group: nightly-mainnet-smoke | |
| cancel-in-progress: false | |
| env: | |
| CARGO_TERM_COLOR: always | |
| RUST_BACKTRACE: 1 | |
| jobs: | |
| mainnet-smoke: | |
| name: mainnet smoke (devnet pipeline → mainnet reads) | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 30 | |
| # NOTE: `continue-on-error` is set on the test STEP below (not on the job) | |
| # so the job's overall status reflects the test failure and the | |
| # `if: failure()` notification step actually fires. Setting it at the job | |
| # level forces job status to success and silently kills the notification | |
| # path. | |
| # | |
| # The `Verify mainnet-smoke cargo feature exists` step below gates all | |
| # subsequent steps — if the cargo feature is absent it short-circuits | |
| # cleanly without failing the workflow. | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 1 | |
| - name: Verify mainnet-smoke cargo feature exists | |
| id: feature_check | |
| # `tests/mainnet_smoke.rs` and `[features] mainnet-smoke = []` may | |
| # land in separate PRs. We set an output rather than failing the step | |
| # so the rest of the job can short-circuit cleanly via `if:` (GitHub | |
| # Actions has no native "skip" exit code). | |
| run: | | |
| if grep -q '^mainnet-smoke\b' Cargo.toml; then | |
| echo "feature_present=true" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "feature_present=false" >> "$GITHUB_OUTPUT" | |
| echo "::warning::tests/mainnet_smoke.rs exists but [features] mainnet-smoke is not declared in Cargo.toml — skipping rest of job" | |
| fi | |
| - name: Install pinned MSRV toolchain | |
| if: steps.feature_check.outputs.feature_present == 'true' | |
| uses: dtolnay/rust-toolchain@1.88.0 | |
| - name: Cache cargo registry + target (separate from per-PR cache) | |
| if: steps.feature_check.outputs.feature_present == 'true' | |
| uses: Swatinem/rust-cache@v2 | |
| with: | |
| # Deliberately separate from `solarix-ci` so the cron run does not | |
| # pollute the per-PR cache. | |
| shared-key: "solarix-nightly" | |
| - name: Run mainnet smoke | |
| if: steps.feature_check.outputs.feature_present == 'true' | |
| id: run_smoke | |
| # `continue-on-error` lives on the STEP, not the job, so the workflow | |
| # job status correctly reflects the failure and the notification step | |
| # below actually runs. | |
| continue-on-error: true | |
| env: | |
| # Devnet for the pipeline, mainnet only for the specific reads the | |
| # smoke test needs. Story 6.5 owns the exact test surface. | |
| SOLANA_RPC_URL: https://api.mainnet-beta.solana.com | |
| run: cargo test --release --features mainnet-smoke -- mainnet_smoke | |
| - name: Comment on most recent merged PR on failure | |
| # The test step uses `continue-on-error: true`, which makes its | |
| # `outcome` reflect the real exit code while `conclusion` is forced | |
| # to success. We branch on `steps.run_smoke.outcome == 'failure'` | |
| # rather than `if: failure()` because the latter would never trigger | |
| # when continue-on-error is in play. | |
| if: steps.run_smoke.outcome == 'failure' | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| const runUrl = `${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`; | |
| // Walk git log for the latest merge commit and post a comment to | |
| // the associated PR. Falls back to logging if no PR is found. | |
| const { data: commits } = await github.rest.repos.listCommits({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| sha: 'main', | |
| per_page: 20, | |
| }); | |
| for (const commit of commits) { | |
| const { data: prs } = await github.rest.repos.listPullRequestsAssociatedWithCommit({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| commit_sha: commit.sha, | |
| }); | |
| const merged = prs.find((pr) => pr.merged_at); | |
| if (merged) { | |
| await github.rest.issues.createComment({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: merged.number, | |
| body: `:rotating_light: Nightly mainnet smoke failed on \`main\`: ${runUrl}`, | |
| }); | |
| core.info(`Posted failure comment to PR #${merged.number}`); | |
| return; | |
| } | |
| } | |
| core.warning(`No recent merged PR found to notify; run: ${runUrl}`); |