Twice on 5 October 2026 a PowerShell job script carried a bash body inside a string, a quote was lost on the way
through PowerShell, and bash refused the body: pc1-cpu-prove.ps1 (first version) reported exit 0 having done
nothing, the 0.3.10 installer job failed in 4 s. tools/amd-prove/check-job-bash.sh covered only its own here-string.
tools/ci/bash-body-check.sh reads every *.ps1 under relay/playbooks/ and tools/, finds each bash body however it is
handed over (bash -c "...", bash -lc '...', bash -c $var, a + concatenation in parentheses, the Start-Process argument
list, a here-string written to a file that is later run with bash), unescapes it the way PowerShell would (backtick
escapes and "" in double-quoted strings, '' in single-quoted strings, here-strings verbatim; $var left as-is, a $(...)
subexpression replaced by ${PS_SUBEXPR}), and runs bash -n on it. One line per body with the file line of the error.
A body it sees but cannot read is "unextractable body" and fails too: a skip would be a hole in the class check.
bash 3.2 compatible; python3 for the extractor.
--self-test runs three fixtures under tools/ci/fixtures/: the correct shapes (8 bodies, must pass), the lost quotes
(the awk apostrophe, a dropped closing quote in a literal and in a variable; must fail with the line), and three
unreadable bodies (must fail). Wired into ci.yml next to the copied-sources check, self-test first. The current tree:
7 inline bodies in 3 playbooks, all parse. packaging/README-ship.md: the job-script rule (body to a file, bash <file>).
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
88 lines
4.6 KiB
YAML
88 lines
4.6 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), the site build with an internal link check, the gh-free
|
|
# identity grep of the public export list (tools/ci/forbidden-strings.txt), and the no-secrets check of the tree
|
|
# (tools/ci/no-secrets-check.sh: no file named like a key of ~/.config/igneum, no 64-hex value assigned to a
|
|
# token/key/secret name outside tests and the allowlist; docs/security/keys.md).
|
|
#
|
|
# 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: 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: igneum-census build (release)
|
|
working-directory: igneum-census
|
|
run: cargo build --release
|
|
sims:
|
|
name: simulators, quick modes
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
- uses: actions/setup-python@v5
|
|
with:
|
|
python-version: '3.12'
|
|
- run: python3 -m pip install --quiet numpy
|
|
- 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: site build
|
|
run: node site/build.mjs
|
|
- name: internal link check of site/*.html
|
|
run: node tools/ci/link-check.mjs
|
|
- name: identity grep of the public export list
|
|
run: bash tools/ci/identity-check.sh
|
|
- name: no conflict markers in tracked files
|
|
run: bash tools/ci/no-conflict-markers.sh
|
|
- name: copied sources are re-stamped before a build
|
|
run: bash tools/ci/copied-sources-check.sh
|
|
- name: bash bodies in PowerShell job scripts pass bash -n, the lost-quote class (self-test first, then the tree)
|
|
run: bash tools/ci/bash-body-check.sh --self-test && bash tools/ci/bash-body-check.sh
|
|
- name: pinned guest programs match their manifest and are built only by pin-guests.sh
|
|
run: bash tools/ci/pinned-guests-check.sh
|
|
- name: no secret file names and no 64-hex secrets in the tree (self-test first, then the tree)
|
|
run: bash tools/ci/no-secrets-check.sh --self-test && bash tools/ci/no-secrets-check.sh
|
|
- name: faucet unit tests (validation, the daily limits, the signed transaction; keccak, RLP and secp256k1 vectors)
|
|
run: node --test site/api/faucet.test.mjs
|
|
- name: explorer and public stats unit tests (search router, formatters, emission rule against the node's own test values, the documented API fields from a fixture)
|
|
run: node --test site/lib/explorer.test.mjs site/lib/emission.test.mjs site/api/public-stats.test.mjs
|
|
- 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
|
|
- name: ship tool self-test (version bump, the dl-both and public manifest helpers)
|
|
run: node tools/ship-app.mjs --self-test
|
|
- name: relay unit tests (parsers, secret compare, the wake endpoint)
|
|
run: node --test relay/test/parse.test.mjs relay/test/auth.test.mjs relay/test/wake.test.mjs
|
|
- name: miner app notice strip and update card (ordering, keys, wording, timers, when the card shows)
|
|
run: node --test app/igneum-app/ui/notices.test.mjs app/igneum-app/ui/update-card.test.mjs
|