Files
pezkuwi-subquery/.github/workflows/ci.yml
T
Satoshi Qazi Muhammed 7a51810333 Re-confirm unchanged stake, and never submit a partial total
People Chain now counts a staking duration only up to the last confirmation
of the stake plus MaxDataAge (fourteen days), so a stopped noter cannot leave
scores climbing on unchecked data. The bot submitted only on change, which
under that rule would freeze every account whose stake stays put.

confirm.js decides when unchanged stake is sent again: not while a
submission is pending (each one restarts the dispute window), not on
half-read data, and only once the last confirmation is CONFIRM_EVERY_BLOCKS
old (default three days). On a runtime without stakingScore.lastConfirmed
the bot behaves as before.

The direct-staking query failed silently into zeros, and a zero that lands
clears the account's stake clock on chain. It now reports the failure, and a
failure in either half skips the account for that scan.
2026-10-18 20:56:46 +04:00

127 lines
4.7 KiB
YAML

name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
- name: Setup Node.js
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version: '20'
- name: Enable Corepack
run: corepack enable
- name: Install dependencies
run: yarn install --immutable
- name: Generate types
run: ./node_modules/.bin/subql codegen pezkuwi.yaml
- name: Build
run: ./node_modules/.bin/subql build pezkuwi.yaml
# Dependency Review allows the @subql packages because the mapping imports
# only their types; this is the check that keeps it true. A type-only
# import is erased on emit, a value import survives as a require.
- name: The mapping imports no @subql code
run: |
out=$(mktemp -d)
./node_modules/.bin/tsc -p tsconfig.json --outDir "$out" --declaration false
! grep -rn 'require("@subql/' "$out" || {
echo "the mapping imports @subql code; import its types with 'import type' or drop it"; exit 1; }
# The noter and payout bots ship as their own images (docker-compose.prod.yml)
# and nothing else here builds or runs them. Build each image as production
# does, then run inside it: the crypto stack must be the locked one and sign
# with every key type, and the bot must load its whole module graph and stop
# only where it reads the mnemonic that CI does not have.
bots:
name: bots (${{ matrix.bot }})
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
include:
- bot: noter
mode: esm
expect: 'No noter mnemonic found'
- bot: payout-bot
mode: cjs
expect: "ENOENT: no such file or directory, open '/run/secrets/payout_mnemonic'"
steps:
- name: Checkout
uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
- name: Build the image
run: docker build -t bot ${{ matrix.bot }}
# Dependency Review allows these GPL-3.0 packages in the lockfiles only
# because no image installs them; this is the check that keeps it true.
- name: No light client in the image
run: |
docker run --rm bot sh -c '! [ -e node_modules/@bizinikiwi ] && ! [ -e node_modules/smoldot ]' || {
echo "the image installs the light client; it must be built with --omit=optional"; exit 1; }
- name: Crypto stack
run: docker run --rm -v "$PWD/scripts/bot-smoke.mjs:/app/bot-smoke.mjs:ro" bot node bot-smoke.mjs ${{ matrix.mode }}
# Run inside the image, so the modules under test are the ones the image ships.
- name: Unit tests
if: matrix.bot == 'noter'
run: docker run --rm -v "$PWD/noter/test:/app/test:ro" bot node --test test/submit.test.mjs test/confirm.test.mjs
- name: The bot loads and stops at its missing mnemonic
env:
EXPECT: ${{ matrix.expect }}
run: |
set +e
out=$(timeout 60 docker run --rm bot 2>&1)
code=$?
set -e
echo "$out"
[ "$code" -ne 0 ] && [ "$code" -ne 124 ] || { echo "expected the bot to exit with an error, got $code"; exit 1; }
grep -qF "$EXPECT" <<<"$out" || { echo "expected: $EXPECT"; exit 1; }
# The indexers run docker/Dockerfile.node (docker-compose.prod.yml). Build it
# as production does: the patch step fails the build if a pattern no longer
# matches. Then the aliased crypto stack must be the locked one and sign with
# every key type, and subql-node must load.
indexer:
name: Indexer image
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
- name: Build the image
run: docker build -f docker/Dockerfile.node -t indexer .
- name: Crypto stack
run: docker run --rm --entrypoint node -v "$PWD/scripts/bot-smoke.mjs:/app/bot-smoke.mjs:ro" indexer /app/bot-smoke.mjs indexer
- name: subql-node loads
run: docker run --rm indexer --help >/dev/null
# The scripts the deploy key is pinned to are the whole of what CI can do on
# the host, so they are checked with every change.
host-scripts:
name: Host deploy scripts
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
- run: |
shellcheck -S warning ops/host/subquery-deploy ops/host/subquery-deploy-ssh ops/host/test-deploy.sh
bash ops/host/test-deploy.sh