Skip to content

Merge pull request #2083 from valory-xyz/release/v1.8.7 #558

Merge pull request #2083 from valory-xyz/release/v1.8.7

Merge pull request #2083 from valory-xyz/release/v1.8.7 #558

Workflow file for this run

name: CI
on:
pull_request:
push:
branches: [main, staging]
permissions:
contents: read
concurrency:
group: ci-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
jobs:
backend:
name: Backend
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: "22.18"
- name: Activate pinned Yarn via Corepack
run: |
corepack enable
# Read the full integrity-verified spec from package.json so corepack
# checks the sha512 hash. Plain `corepack prepare yarn@1.22.22 --activate`
# downloads from npm without verifying against the hash.
PM_SPEC=$(node -p "require('./package.json').packageManager")
corepack prepare "$PM_SPEC" --activate
- name: Verify Yarn version
run: |
yarn --version
test "$(yarn --version)" = "1.22.22" || (echo "::error::Yarn version mismatch" && exit 1)
- name: Configure Yarn network settings
run: |
yarn config set network-timeout 60000
yarn config set network-retries 10
yarn config set network-concurrency 2
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with:
python-version: "3.14"
- uses: astral-sh/setup-uv@d0cc045d04ccac9d8b7881df0226f9e82c39688e # v6.8.0
with:
version: "0.11.15"
enable-cache: true
cache-dependency-glob: "uv.lock"
- run: yarn install:backend
frontend:
name: Frontend
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: "22.18"
- name: Activate pinned Yarn via Corepack
run: |
corepack enable
# Read the full integrity-verified spec from package.json so corepack
# checks the sha512 hash. Plain `corepack prepare yarn@1.22.22 --activate`
# downloads from npm without verifying against the hash.
PM_SPEC=$(node -p "require('./package.json').packageManager")
corepack prepare "$PM_SPEC" --activate
- name: Verify Yarn version
run: |
yarn --version
test "$(yarn --version)" = "1.22.22" || (echo "::error::Yarn version mismatch" && exit 1)
- name: Configure Yarn network settings
run: |
yarn config set network-timeout 60000
yarn config set network-retries 10
yarn config set network-concurrency 2
- name: Ensure root yarn.lock exists and is valid
run: |
if [ ! -f "yarn.lock" ]; then
echo "Error: Missing root yarn.lock."
echo "Run 'yarn install' and commit the generated lockfile."
exit 1
fi
if [ ! -s "yarn.lock" ]; then
echo "Error: Root yarn.lock exists but is empty."
exit 1
fi
yarn install --frozen-lockfile
- name: Ensure frontend yarn.lock exists and is valid
run: |
if [ ! -f "frontend/yarn.lock" ]; then
echo "Error: Missing frontend/yarn.lock."
echo "Run 'cd frontend && yarn install' and commit the generated lockfile."
exit 1
fi
if [ ! -s "frontend/yarn.lock" ]; then
echo "Error: frontend/yarn.lock exists but is empty."
exit 1
fi
cd frontend
yarn install --frozen-lockfile
- name: Lint & Typecheck
run: yarn quality-check:frontend
- name: Check service templates
run: cd frontend && npx tsx ../scripts/js/check_service_templates.ts
frontend-tests:
name: Frontend Tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: "22.18"
- name: Activate pinned Yarn via Corepack
run: |
corepack enable
# Read the full integrity-verified spec from package.json so corepack
# checks the sha512 hash. Plain `corepack prepare yarn@1.22.22 --activate`
# downloads from npm without verifying against the hash.
PM_SPEC=$(node -p "require('./package.json').packageManager")
corepack prepare "$PM_SPEC" --activate
- name: Verify Yarn version
run: |
yarn --version
test "$(yarn --version)" = "1.22.22" || (echo "::error::Yarn version mismatch" && exit 1)
- name: Install dependencies
run: yarn install:frontend
- name: Run tests
run: yarn test:frontend
gitleaks:
name: Gitleaks
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 0
- name: Install and run gitleaks
env:
GITLEAKS_VERSION: 8.30.1
# Verify against the published sha256 on the release page so a swapped
# tarball is rejected. Update both fields together when bumping.
GITLEAKS_LINUX_X64_SHA256: 551f6fc83ea457d62a0d98237cbad105af8d557003051f41f3e7ca7b3f2470eb
run: |
set -euo pipefail
TARBALL="gitleaks_${GITLEAKS_VERSION}_linux_x64.tar.gz"
wget --quiet "https://github.com/gitleaks/gitleaks/releases/download/v${GITLEAKS_VERSION}/${TARBALL}"
echo "${GITLEAKS_LINUX_X64_SHA256} ${TARBALL}" | sha256sum -c -
tar -xzf "${TARBALL}"
sudo install gitleaks /usr/bin
gitleaks detect --report-format json --report-path leak_report -v
deps-check-pinned:
name: Deps pinned (both trees)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version-file: .nvmrc
- name: Activate pinned Yarn via Corepack
run: |
corepack enable
# Read the full integrity-verified spec from package.json so corepack
# checks the sha512 hash. Plain `corepack prepare yarn@1.22.22 --activate`
# downloads from npm without verifying against the hash.
PM_SPEC=$(node -p "require('./package.json').packageManager")
corepack prepare "$PM_SPEC" --activate
- name: Verify Yarn version
run: |
yarn --version
test "$(yarn --version)" = "1.22.22" || (echo "::error::Yarn version mismatch" && exit 1)
- name: Check root deps are exact-pinned
run: yarn deps:check-pinned
- name: Check frontend deps are exact-pinned
run: cd frontend && yarn deps:check-pinned
audit:
name: yarn audit (both trees)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version-file: .nvmrc
- name: Activate pinned Yarn via Corepack
run: |
corepack enable
# Read the full integrity-verified spec from package.json so corepack
# checks the sha512 hash. Plain `corepack prepare yarn@1.22.22 --activate`
# downloads from npm without verifying against the hash.
PM_SPEC=$(node -p "require('./package.json').packageManager")
corepack prepare "$PM_SPEC" --activate
- name: Verify Yarn version
run: |
yarn --version
test "$(yarn --version)" = "1.22.22" || (echo "::error::Yarn version mismatch" && exit 1)
# No `yarn install` — `yarn audit` reads yarn.lock directly. Skipping
# install means a compromised `postinstall` script cannot execute inside
# the audit job. Defense in depth at the workflow level.
- name: Audit root tree
run: yarn audit:prod
- name: Audit frontend tree
run: cd frontend && yarn audit:prod
install-hooks-root:
name: install-hooks (root tree)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version-file: .nvmrc
- name: Activate pinned Yarn via Corepack
run: |
corepack enable
# Read the full integrity-verified spec from package.json so corepack
# checks the sha512 hash. Plain `corepack prepare yarn@1.22.22 --activate`
# downloads from npm without verifying against the hash.
PM_SPEC=$(node -p "require('./package.json').packageManager")
corepack prepare "$PM_SPEC" --activate
- name: Verify Yarn version
run: |
yarn --version
test "$(yarn --version)" = "1.22.22" || (echo "::error::Yarn version mismatch" && exit 1)
# Install with --ignore-scripts so the gate fires before any postinstall
# executes on the runner. The wrapper reads node_modules/*/package.json
# to detect declared hooks; it does NOT need them to have run.
- name: Install root (lifecycle scripts skipped)
run: yarn install --frozen-lockfile --ignore-scripts
- name: Diff install-hook surface against allowlist
run: yarn audit:install-hooks
install-hooks-frontend:
name: install-hooks (frontend tree)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version-file: .nvmrc
- name: Activate pinned Yarn via Corepack
run: |
corepack enable
PM_SPEC=$(node -p "require('./package.json').packageManager")
corepack prepare "$PM_SPEC" --activate
- name: Verify Yarn version
run: |
yarn --version
test "$(yarn --version)" = "1.22.22" || (echo "::error::Yarn version mismatch" && exit 1)
- name: Install frontend (lifecycle scripts skipped)
run: cd frontend && yarn install --frozen-lockfile --ignore-scripts
- name: Diff install-hook surface against allowlist
run: cd frontend && yarn audit:install-hooks
lockfile-lint:
name: lockfile-lint (both trees)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version-file: .nvmrc
# Pin lockfile-lint version explicitly so a compromise of the npm-published
# tool can't silently land via `npx @latest`. Bump together with any
# deps-check-pinned coverage updates.
- name: Lint root yarn.lock
run: npx -y lockfile-lint@5.0.0 --path yarn.lock --type yarn --validate-https --allowed-hosts yarn npm --empty-hostname false
- name: Lint frontend yarn.lock
run: npx -y lockfile-lint@5.0.0 --path frontend/yarn.lock --type yarn --validate-https --allowed-hosts yarn npm --empty-hostname false
license-check:
# License allowlist gate, mirroring the backend's tomte [Licenses]
# under liccheck PARANOID. Unlike `audit` (which reads yarn.lock
# directly and skips install for defense-in-depth), this job MUST
# install — license-checker-rseidelsohn walks node_modules and
# reads LICENSE files. We pass --ignore-scripts so postinstall
# hooks still cannot execute during the gate; LICENSE files are
# unpacked from tarballs regardless of script execution.
#
# Rollout: NOT in `all-checks-passed.needs` — this job reports,
# it does not block merges. Flipping to required is a maintainer's
# later action (add to `needs:` here + branch protection).
name: License allowlist gate (both trees)
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version-file: .nvmrc
- name: Activate pinned Yarn via Corepack
run: |
corepack enable
# Read the full integrity-verified spec from package.json so corepack
# checks the sha512 hash. Plain `corepack prepare yarn@1.22.22 --activate`
# downloads from npm without verifying against the hash.
PM_SPEC=$(node -p "require('./package.json').packageManager")
corepack prepare "$PM_SPEC" --activate
- name: Verify Yarn version
run: |
yarn --version
test "$(yarn --version)" = "1.22.22" || (echo "::error::Yarn version mismatch" && exit 1)
- name: Configure Yarn network settings
run: |
yarn config set network-timeout 60000
yarn config set network-retries 10
yarn config set network-concurrency 2
- name: Install root (lifecycle scripts skipped)
run: yarn install --frozen-lockfile --ignore-scripts
- name: Unit tests for license-check helpers
# Pure-function tests for normalize() / evalExpr() in
# scripts/license-check.lib.mjs. No deps beyond node:test (built-in
# since Node 18). Runs once; the script is shared across both trees
# so testing once is sufficient.
run: yarn test:license-check
- name: License check (root tree)
run: yarn license-check
- name: Install frontend (lifecycle scripts skipped)
run: cd frontend && yarn install --frozen-lockfile --ignore-scripts
- name: License check (frontend tree)
run: cd frontend && yarn license-check
all-checks-passed:
name: All checks passed
needs: [backend, frontend, frontend-tests, gitleaks, deps-check-pinned, lockfile-lint, audit, install-hooks-root, install-hooks-frontend]
if: always()
runs-on: ubuntu-latest
steps:
- name: Verify all required checks succeeded
run: |
if [[ "${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') || contains(needs.*.result, 'skipped') }}" == "true" ]]; then
echo "One or more required checks did not succeed."
echo "Results: ${{ toJson(needs) }}"
exit 1
fi