name: Trusted engineering checks on: push: branches: [feat/single-node-delivery] permissions: contents: read concurrency: group: kf-onlinejudge-trusted-engineering cancel-in-progress: false jobs: check: if: github.server_url == 'https://github.com' && github.repository == 'KiriAky107/KF-OnlineJudge' runs-on: ubuntu-24.04 timeout-minutes: 30 defaults: run: shell: bash --noprofile --norc -euo pipefail {0} env: CI: "true" RUSTUP_TOOLCHAIN: 1.99.0 CARGO_BUILD_JOBS: "2" CARGO_NET_RETRY: "2" UV_PYTHON: 3.13.16 UV_NO_PROGRESS: "1" UV_HTTP_TIMEOUT: "30" UV_HTTP_RETRIES: "2" steps: - name: Check out the pushed commit uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6 timeout-minutes: 2 with: persist-credentials: false fetch-depth: 1 fetch-tags: false submodules: false lfs: false - name: Set up Node.js uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6 timeout-minutes: 3 with: node-version: 26.11.1 check-latest: false package-manager-cache: false - name: Set up uv uses: astral-sh/setup-uv@94527f2e458b27549849d47d273a16bec83a01e9 # v7 timeout-minutes: 3 with: version: 0.12.24 python-version: 3.13.16 enable-cache: false - name: Install locked toolchains and dependencies timeout-minutes: 10 run: | test "$GITHUB_SERVER_URL" = https://github.com test "$GITHUB_REPOSITORY" = KiriAky107/KF-OnlineJudge test "$GITHUB_EVENT_NAME" = push test "$GITHUB_REF" = refs/heads/feat/single-node-delivery test "$(git rev-parse HEAD)" = "$GITHUB_SHA" uv python install 3.13.16 rustup toolchain install 1.99.0 --profile minimal --component rustfmt --component clippy npm install --global --ignore-scripts pnpm@11.28.4 make install - name: Check toolchain versions and CI inputs timeout-minutes: 1 run: | test "$(node --version)" = v26.11.1 test "$(pnpm --version)" = 11.28.4 test "$(rustc --version | cut -d ' ' -f 2)" = 1.99.0 test "$(uv --version | cut -d ' ' -f 2)" = 0.12.24 backend/.venv/bin/python - <<'PYCODE' import os import subprocess import sys assert sys.version_info[:3] == (3, 13, 16) assert not any(name.startswith(('KF_', 'PGPASSWORD', 'PGSERVICE', 'DATABASE_URL', 'AMQP_URL')) for name in os.environ), 'CI must not carry node credentials or VM flags' assert not subprocess.check_output(['git', 'ls-files', '--', 'docs/', '.localplan/']) PYCODE - name: Check architecture and generated contracts timeout-minutes: 3 run: | uv run --project backend --locked python scripts/check_architecture.py make contracts git diff --exit-code -- contracts frontend/src/api/generated/schema.d.ts - name: Check Backend and run ordinary tests timeout-minutes: 5 working-directory: backend run: | uv run --locked ruff check . ../scripts uv run --locked ruff format --check . ../scripts uv run --locked pytest \ tests/test_contracts.py \ tests/test_judging_contracts.py \ tests/test_judging_v2_contracts.py \ tests/test_submission_performance_contract.py \ tests/test_admin_import_contracts.py \ tests/test_availability.py \ tests/test_dependency_errors.py \ tests/test_production_logging.py \ tests/test_delivery.py \ tests/test_delivery_io.py \ tests/test_delivery_backup.py \ tests/test_delivery_restore_io.py \ tests/test_operator_imports.py \ tests/test_health.py \ tests/test_identity.py \ tests/test_coordinator_control.py \ --junitxml="$RUNNER_TEMP/kf-engineering-backend.xml" uv run --locked python -m kf_oj.contracts.export --check - name: Check Rust and run library and contract tests timeout-minutes: 8 working-directory: judge run: | cargo fmt --all -- --check cargo clippy --workspace --all-targets --locked -- -D warnings cargo test --workspace --lib --locked cargo test --package kf-contracts --locked - name: Check and build Frontend timeout-minutes: 5 run: make check-frontend - name: Parse development Compose configuration timeout-minutes: 1 run: make infra-config - name: Collect public contracts and engineering report timeout-minutes: 1 run: | backend/.venv/bin/python - <<'PYCODE' import hashlib import json import os import subprocess import xml.etree.ElementTree as ET from pathlib import Path source = subprocess.check_output(['git', 'rev-parse', 'HEAD'], text=True).strip() assert source == os.environ['GITHUB_SHA'] destination = Path(os.environ['RUNNER_TEMP']) / 'kf-engineering-artifacts' destination.mkdir(mode=0o700) names = subprocess.check_output(['git', 'ls-files', '-z', '--', 'contracts/openapi/platform.v1.json', 'contracts/schemas/*.json']).decode().split('\0')[:-1] assert 1 <= len(names) <= 64 files, total = [], 0 for name in names: path = Path(name) assert not any(part.is_symlink() for part in (path, *path.parents)) assert path.is_file() and path.stat().st_size <= 2 * 1024**2 data = path.read_bytes() json.loads(data) total += len(data) assert total <= 8 * 1024**2 output = destination / name output.parent.mkdir(parents=True, exist_ok=True) output.write_bytes(data) files.append({'path': name, 'bytes': len(data), 'sha256': hashlib.sha256(data).hexdigest()}) junit = ET.parse(Path(os.environ['RUNNER_TEMP']) / 'kf-engineering-backend.xml') suites = list(junit.getroot().iter('testsuite')) backend = {name: sum(int(suite.attrib.get(name, 0)) for suite in suites) for name in ('tests', 'failures', 'errors', 'skipped')} assert backend['failures'] == backend['errors'] == 0 report = {'schema_version': 1, 'source_sha': source, 'scope': 'Trusted engineering checks only', 'backend': backend, 'toolchains': {'python': '3.13.16', 'rust': '1.99.0', 'node': '26.11.1', 'pnpm': '11.28.4', 'uv': '0.12.24'}, 'files': files, 'not_run': ['real PostgreSQL acceptance', 'independent VM cases', 'user source execution', 'adverse archives and filesystem acceptance', 'Linux isolation acceptance', 'deployment']} (destination / 'engineering-report.json').write_text(json.dumps(report, indent=2)+'\n') PYCODE - name: Upload public contracts and engineering report uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 timeout-minutes: 2 with: name: engineering-checks-${{ github.sha }} path: ${{ runner.temp }}/kf-engineering-artifacts if-no-files-found: error include-hidden-files: false overwrite: false retention-days: 1 compression-level: 6