igneum/.github/workflows/ci.yml

101 lines
5.7 KiB
YAML

# CI on every push and pull request (private repository, free runner minutes).
#
# What runs: the lottery-hash crate's tests (igneum-pow, release profile), the census tool's build, the two Python
# simulators' --quick modes (each under two minutes), and the tree gate: every fast check in ONE script,
# tools/ci/pre-push.sh (site build and link check, the ledger sentences, the identity grep of the public export list
# and the served site, Windows-valid paths, workflow shell syntax, the copied-sources and playbook classes, the unit
# tests, the no-secrets check). The pre-push hook runs the SAME script before a push to master or release-*, so the
# local gate and CI cannot drift (6 October 2026: 131 red `ci` runs in three days, 92 of them on master, every one a
# tree check that would have failed on the pushing machine in under 25 s; docs/analysis/ci-failures-2026-10-06.md).
#
# Where it runs: `pow` and `sims` go to the box's runner (igneum-build-1, rustc pinned, sccache read-only, 48 jobs)
# when the repository variable IGNEUM_CI_RUNNER is `box`, else to ubuntu-latest (docs/plans/ci-self-hosted.md; GitHub
# has no fallback in runs-on, the variable is the switch). The `site` job stays on GitHub's machines. The `red` job
# runs on the box after any failed master or release-* run and records the failure for the watcher
# (tools/ci/red-watch.mjs; infra/build-server/ci-red): one line per run to the hidden updates channel and to
# /srv/ci-red/red.jsonl, so nobody opens the Actions page to learn master is red.
#
# What does not run, on purpose: the node fork (vendor/igneum-node*, a rusty-kaspa fork of about 500 crates with
# rocksdb, blst and the execution layer) is gitignored here and too big for the free runners today (a cold build is
# 20 to 55 minutes on 2 to 8 vCPU, docs/bench-log.md). The workflow builds igneum-pow only; the fork's own tests run
# on the Mac and the seed node (infra/seed-nodes, infra/fast-time).
name: ci
on:
push:
pull_request:
jobs:
pow:
name: igneum-pow tests, igneum-census build
runs-on: ${{ vars.IGNEUM_CI_RUNNER == 'box' && fromJSON('["self-hosted", "linux", "x64", "igneum-build-1"]') || 'ubuntu-latest' }}
steps:
- uses: actions/checkout@v4
- name: toolchain
run: rustc --version && cargo --version
- name: igneum-pow tests (release)
working-directory: igneum-pow
run: cargo test --release
- name: pack loader seed rule (packfile.h on a known-good and a known-mismatched pack)
run: bash proto-cuda/nvrtc/emu/packfile-test.sh
- name: igneum-census build (release)
working-directory: igneum-census
run: cargo build --release
sims:
name: simulators, quick modes
runs-on: ${{ vars.IGNEUM_CI_RUNNER == 'box' && fromJSON('["self-hosted", "linux", "x64", "igneum-build-1"]') || 'ubuntu-latest' }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
if: vars.IGNEUM_CI_RUNNER != 'box' # the box has python3 and numpy from provision.sh
with:
python-version: '3.12'
- run: python3 -m pip install --quiet numpy
if: vars.IGNEUM_CI_RUNNER != 'box'
- name: finality_v2.py --quick (under two minutes)
working-directory: sim
run: time timeout 120 python3 finality_v2.py --quick > finality_quick.md
- name: difficulty/sim.py --quick (under two minutes)
working-directory: sim/difficulty
run: time timeout 120 python3 sim.py --quick > difficulty_quick.md
- uses: actions/upload-artifact@v4
with:
name: sim-quick-output
path: |
sim/finality_quick.md
sim/difficulty/difficulty_quick.md
site:
name: site build, link check, identity grep
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '22'
- name: the tree gate, tools/ci/pre-push.sh --ci (the same script the pre-push hook runs; one line per check, a red check prints its output)
run: bash tools/ci/pre-push.sh --ci
- name: public stats API answers with the documented fields (the live site; master only, the endpoints exist there after the merge)
if: github.ref == 'refs/heads/master'
run: node tools/ci/public-api-check.mjs https://igneum.network
red:
# Runs only when a master or release-* run has a failed job, on the box's own runner (not a GitHub-hosted machine:
# the billing block of 6 October 2026, 18:37Z to 20:10Z, failed every hosted job at start and nobody was told).
# tools/ci/red-watch.mjs record appends ONE line for this run to /srv/ci-red/red.jsonl (idempotent per run attempt);
# the box's igneum-ci-red.timer posts each new line once to the hidden updates channel. Never blocks a release:
# it reads the run, writes one line, and ends.
name: red watcher (master and release-* only; one line per failed run to the updates channel and the box file)
needs: [pow, sims, site]
if: ${{ failure() && (github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/heads/release-')) }}
runs-on: [self-hosted, linux, x64, igneum-build-1]
timeout-minutes: 5
permissions:
actions: read # the run's jobs API (the first real red run, 21:19Z: the default token answered 403 and the line carried no step)
contents: read
steps:
- uses: actions/checkout@v4
with:
sparse-checkout: tools/ci
- name: record this run (one line, the failed jobs and their first failed step, from the run's own API)
env:
GITHUB_TOKEN: ${{ github.token }}
RED_WATCH_TITLE: ${{ github.event.head_commit.message }}
run: node tools/ci/red-watch.mjs record --file /srv/ci-red/red.jsonl