Files
vac-optimizer/.gitea/workflows/ci.yml
T
nessarandClaude Opus 5.5 676ea24410 test(benchmark): tighten the relative gate to the measured speed
After #302, the development machine's protocol takes about 41 seconds
instead of 232. The budget multipliers now add about 1.5 times headroom
to the new ratios (0.1 for typed obligations, which leaves room for
runner jitter), and the hang guard drops from 600 to 240 seconds, with
a 210-second test timeout: about three times the expected run on
srvhome, which is about 1.9 times slower than nessar-desktop.

Part of #286 and #302. The gate still needs a passing CI benchmark on
two runners.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 21:36:37 +02:00

238 lines
9.4 KiB
YAML

name: CI
on:
push:
pull_request:
types: [opened, reopened, synchronize, edited]
workflow_dispatch:
permissions:
contents: read
# Gitea's checkout and upload-artifact actions are JavaScript actions that the runner
# executes with the job container's own `node`, so those containers keep Node. Project
# commands never use it: the jobs that run them install the pinned Bun with
# scripts/install-bun.sh and run `run:` steps under a shell whose PATH has Bun but no Node.
concurrency:
group: ci-${{ github.event_name }}-${{ github.ref }}
cancel-in-progress: ${{ !startsWith(github.ref, 'refs/tags/') }}
jobs:
policy:
name: policy
runs-on: ubuntu-latest
container: node:24.22.0
defaults:
run:
shell: env PATH=/opt/bun/bin:/usr/bin:/bin bash -e {0}
outputs:
slug: ${{ steps.policy.outputs.slug }}
tag: ${{ steps.policy.outputs.tag }}
steps:
- uses: https://gitea.com/actions/checkout@v7
with:
fetch-depth: 0
persist-credentials: false
- name: Install Bun
run: sh scripts/install-bun.sh
- name: Policy regression tests
run: bun scripts/ci-policy.test.mjs && bun scripts/ci-image.test.mjs
- name: Validate event and commit
id: policy
run: bun scripts/ci-policy.mjs
validate:
name: validate
runs-on: ubuntu-latest
container: node:24.22.0
defaults:
run:
shell: env PATH=/opt/bun/bin:/usr/bin:/bin bash -e {0}
steps:
- uses: https://gitea.com/actions/checkout@v7
with:
persist-credentials: false
- name: Install Bun
run: sh scripts/install-bun.sh
- run: bun install --frozen-lockfile
- run: bun run lint
- run: bun run format:check
- run: bun run typecheck
test:
name: test
runs-on: ubuntu-latest
container: node:24.22.0
defaults:
run:
shell: env PATH=/opt/bun/bin:/usr/bin:/bin bash -e {0}
steps:
- uses: https://gitea.com/actions/checkout@v7
with:
persist-credentials: false
- name: Install Bun
run: sh scripts/install-bun.sh
- run: bun install --frozen-lockfile
- run: bun scripts/generate-langs.js
- name: Functional coverage
run: bun test --config=bunfig.coverage.toml --isolate --path-ignore-patterns='**/benchmark/**'
- name: Coverage report
if: ${{ always() }}
run: bun scripts/coverage-reports.mjs
- name: Upload coverage
if: ${{ always() }}
uses: https://gitea.com/actions/upload-artifact@v7
with:
name: coverage
path: coverage/
retention-days: 7
if-no-files-found: error
benchmark:
name: benchmark
runs-on: ubuntu-latest
container:
image: node:24.22.0
options: --memory=3g
defaults:
run:
shell: env PATH=/opt/bun/bin:/usr/bin:/bin bash -e {0}
steps:
- uses: https://gitea.com/actions/checkout@v7
with:
persist-credentials: false
- name: Install Bun
run: sh scripts/install-bun.sh
- run: bun install --frozen-lockfile
- run: bun scripts/generate-langs.js
- name: Benchmark protocol with relative gate
run: timeout 240s bun test src/app/benchmark --timeout=240000
build:
name: build
runs-on: ubuntu-latest
container: node:24.22.0
defaults:
run:
shell: env PATH=/opt/bun/bin:/usr/bin:/bin bash -e {0}
steps:
- uses: https://gitea.com/actions/checkout@v7
with:
persist-credentials: false
- name: Install Bun
run: sh scripts/install-bun.sh
- run: bun install --frozen-lockfile
- run: bun run build -- --configuration production
- uses: https://gitea.com/actions/upload-artifact@v7
with:
name: dist
path: dist/
retention-days: 7
if-no-files-found: error
security:
name: security
runs-on: ubuntu-latest
container: node:24.22.0
steps:
- uses: https://gitea.com/actions/checkout@v7
with:
persist-credentials: false
- name: Install scanners
run: |
apt-get update
apt-get install --yes --no-install-recommends python3-venv
python3 -m venv /tmp/semgrep
/tmp/semgrep/bin/pip install semgrep==1.180.0
case "$(uname -m)" in
x86_64) trivy_arch=64bit ;;
aarch64) trivy_arch=ARM64 ;;
*) echo 'Unsupported Trivy architecture' >&2; exit 1 ;;
esac
archive="trivy_0.75.0_Linux-${trivy_arch}.tar.gz"
curl --fail --location --silent --show-error "https://github.com/aquasecurity/trivy/releases/download/v0.75.0/${archive}" --output "/tmp/${archive}"
curl --fail --location --silent --show-error https://github.com/aquasecurity/trivy/releases/download/v0.75.0/trivy_0.75.0_checksums.txt --output /tmp/trivy-checksums.txt
(cd /tmp && sha256sum --check --ignore-missing trivy-checksums.txt)
tar -xzf "/tmp/${archive}" -C /usr/local/bin trivy
- name: JavaScript and TypeScript SAST
run: /tmp/semgrep/bin/semgrep scan --config p/javascript --config p/typescript --metrics off --sarif --output semgrep-results.sarif src scripts
- name: Dependency and secret scan
if: ${{ !cancelled() }}
run: trivy fs --db-repository public.ecr.aws/aquasecurity/trivy-db:2 --format sarif --output trivy-results.sarif --skip-dirs node_modules,dist,coverage .
- name: Security reports
if: ${{ always() }}
uses: https://gitea.com/actions/upload-artifact@v7
with:
name: security
path: '*-results.sarif'
retention-days: 7
if-no-files-found: error
images:
name: images
needs: [policy, validate, test, benchmark, build, security]
if: >-
success() &&
(github.event_name == 'push' ||
(github.event_name == 'pull_request' &&
github.event.pull_request.head.repo.full_name == github.repository))
runs-on: ubuntu-latest
container: docker:29.9.1
concurrency:
group: image-${{ needs.policy.outputs.tag != '' && 'stable' || needs.policy.outputs.slug }}
cancel-in-progress: false
services:
docker:
image: docker:29.9.1-dind
env:
DOCKER_TLS_CERTDIR: ''
options: >-
--privileged
--health-cmd "docker info"
--health-interval 5s
--health-timeout 5s
--health-retries 12
env:
DOCKER_HOST: tcp://docker:2375
DOCKER_TLS_CERTDIR: ''
defaults:
run:
shell: sh
steps:
# Alpine's nodejs package is for the checkout action only (it shares /usr/bin
# with git); Bun needs libgcc and libstdc++ and the installer needs curl.
- name: Install checkout runtime and tools
run: apk add --no-cache nodejs git curl libgcc libstdc++
- uses: https://gitea.com/actions/checkout@v7
with:
fetch-depth: 0
persist-credentials: false
- name: Install Bun
run: sh scripts/install-bun.sh
- name: Build branch images or promote a release
env:
REGISTRY_USERNAME: ${{ secrets.REGISTRY_USERNAME }}
REGISTRY_PASSWORD: ${{ secrets.REGISTRY_PASSWORD }}
run: /opt/bun/bin/bun scripts/ci-image.mjs
required:
name: required
if: ${{ always() }}
needs: [policy, validate, test, benchmark, build, security, images]
runs-on: ubuntu-latest
container: node:24.22.0
env:
CHECK_RESULTS: ${{ needs.policy.result }} ${{ needs.validate.result }} ${{ needs.test.result }} ${{ needs.benchmark.result }} ${{ needs.build.result }} ${{ needs.security.result }}
IMAGE_RESULT: ${{ needs.images.result }}
IMAGE_EXPECTED: ${{ github.event_name == 'push' || (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository) }}
steps:
- name: Require successful validation and expected publication
run: |
test "$CHECK_RESULTS" = 'success success success success success success' || exit 1
if [ "$IMAGE_EXPECTED" = 'true' ]; then
test "$IMAGE_RESULT" = 'success'
else
test "$IMAGE_RESULT" = 'skipped'
fi