ARCH-04E1A: bind post-submit routing source evidence #2445
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Backend | |
| on: | |
| pull_request: | |
| push: | |
| branches: | |
| - main | |
| concurrency: | |
| group: backend-${{ github.event.pull_request.number || github.ref }} | |
| cancel-in-progress: true | |
| permissions: | |
| contents: read | |
| pull-requests: read | |
| env: | |
| MINIO_IMAGE: workstream-minio:source | |
| jobs: | |
| minio-image: | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 20 | |
| outputs: | |
| artifact: ${{ steps.identity.outputs.artifact }} | |
| steps: | |
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 | |
| with: | |
| persist-credentials: false | |
| - name: Bind source image to this workflow attempt | |
| id: identity | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| test "$(git rev-parse HEAD)" = "${GITHUB_SHA}" | |
| echo "artifact=minio-source-${GITHUB_SHA}-${GITHUB_RUN_ATTEMPT}" >> "${GITHUB_OUTPUT}" | |
| - name: Cache exact source image | |
| id: cache | |
| uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 | |
| with: | |
| path: ${{ runner.temp }}/minio-image/minio.tar | |
| key: minio-source-v1-${{ github.sha }}-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('docker/minio/**') }} | |
| - name: Build source-pinned MinIO once | |
| if: steps.cache.outputs.cache-hit != 'true' | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| mkdir -p "${RUNNER_TEMP}/minio-image" | |
| docker build --tag "${MINIO_IMAGE}" docker/minio | |
| docker save --output "${RUNNER_TEMP}/minio-image/minio.tar" "${MINIO_IMAGE}" | |
| - name: Verify the cached or freshly built provider | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| docker load --input "${RUNNER_TEMP}/minio-image/minio.tar" | |
| docker run --rm "${MINIO_IMAGE}" --version | |
| docker run --detach --rm --name minio-build-probe \ | |
| --publish 127.0.0.1:9000:9000 \ | |
| --env MINIO_ROOT_USER=workstream-minio \ | |
| --env MINIO_ROOT_PASSWORD=workstream-minio-secret-key \ | |
| "${MINIO_IMAGE}" server /data --address :9000 | |
| trap 'docker logs minio-build-probe; docker stop minio-build-probe' EXIT | |
| for attempt in $(seq 1 60); do | |
| if curl --fail --silent http://127.0.0.1:9000/minio/health/live >/dev/null; then | |
| cd "${RUNNER_TEMP}/minio-image" | |
| sha256sum minio.tar > minio.tar.sha256 | |
| exit 0 | |
| fi | |
| sleep 1 | |
| done | |
| exit 1 | |
| - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 | |
| with: | |
| name: ${{ steps.identity.outputs.artifact }} | |
| path: ${{ runner.temp }}/minio-image/ | |
| compression-level: 0 | |
| if-no-files-found: error | |
| retention-days: 7 | |
| auth-boundary-preflight: | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 10 | |
| steps: | |
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 | |
| with: | |
| persist-credentials: false | |
| fetch-depth: 0 | |
| - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 | |
| with: | |
| python-version: "3.12" | |
| - name: Bind exact checked-out tree | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| test "$(git rev-parse HEAD)" = "${GITHUB_SHA}" | |
| test -z "$(git status --porcelain)" | |
| test "$(git rev-parse "${GITHUB_SHA}^{tree}")" = "$(git rev-parse HEAD^{tree})" | |
| - name: Install backend architecture dependencies | |
| working-directory: backend | |
| run: | | |
| set -euo pipefail | |
| python -m pip install --upgrade pip | |
| python -m pip install -e ".[dev,agents]" | |
| python -m pip install ruff==0.15.22 | |
| test "$(ruff --version)" = "ruff 0.15.22" | |
| - name: Validate module, AUTH, and test boundaries | |
| working-directory: backend | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| ruff check \ | |
| app/modules/authorization/api \ | |
| scripts/authorization_boundary.py \ | |
| scripts/module_boundaries.py \ | |
| scripts/test_structure_boundary.py \ | |
| tests/architecture/test_authorization_boundary.py \ | |
| tests/architecture/test_module_boundaries.py \ | |
| tests/architecture/test_test_structure_boundary.py | |
| python -m scripts.module_boundaries validate \ | |
| --protected-base "${{ github.event.pull_request.base.sha || github.event.before }}" | |
| PYTEST_DISABLE_PLUGIN_AUTOLOAD=1 python -m pytest -q \ | |
| -p pytest_asyncio.plugin \ | |
| tests/architecture/test_module_boundaries.py \ | |
| tests/architecture/test_authorization_boundary.py | |
| python -m scripts.authorization_boundary validate \ | |
| --ledger ../.ci/auth-boundaries/IMPORT_LEDGER.md | |
| python -m scripts.test_structure_boundary validate \ | |
| --policy ../.ci/auth-boundaries/TEST_STRUCTURE_POLICY.md \ | |
| --ledger ../.ci/auth-boundaries/TEST_STRUCTURE_DEBT.json | |
| python -m scripts.behavior_ownership validate | |
| lanes: | |
| needs: minio-image | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 45 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| lane: | |
| - shared_foundations_a | |
| - shared_foundations_b | |
| - schema_contracts | |
| - project_lifecycle_a | |
| - project_lifecycle_b | |
| - project_lifecycle_c | |
| - task_lifecycle_a | |
| - task_lifecycle_b | |
| - task_lifecycle_c | |
| services: | |
| redis: | |
| image: redis:7-alpine@sha256:520775a41a63e77e06c73e35d2fd9cc15921a609516818796b4ecbb813078bc7 | |
| ports: | |
| - 6380:6379 | |
| options: >- | |
| --health-cmd "redis-cli ping" | |
| --health-interval 5s | |
| --health-timeout 5s | |
| --health-retries 10 | |
| postgres: | |
| image: public.ecr.aws/docker/library/postgres:16@sha256:33f923b05f64ca54ac4401c01126a6b92afe839a0aa0a52bc5aeb5cc958e5f20 | |
| env: | |
| POSTGRES_DB: workstream_test | |
| POSTGRES_USER: workstream | |
| POSTGRES_PASSWORD: workstream | |
| ports: | |
| - 5433:5432 | |
| options: >- | |
| ${{ matrix.lane != 'schema_contracts' && '--tmpfs /var/lib/postgresql/data:rw,nosuid,nodev,noexec,size=2147483648' || '' }} | |
| --health-cmd "pg_isready -U workstream -d workstream_test" | |
| --health-interval 5s | |
| --health-timeout 5s | |
| --health-retries 10 | |
| steps: | |
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 | |
| with: | |
| persist-credentials: false | |
| fetch-depth: 0 | |
| - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 | |
| with: | |
| python-version: "3.12" | |
| - id: identity | |
| name: Bind exact checked-out tree | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| job_start_epoch="$(date +%s)" | |
| tree_sha="$(git rev-parse HEAD)" | |
| test "${tree_sha}" = "${GITHUB_SHA}" | |
| test -z "$(git status --porcelain)" | |
| test "$(git rev-parse "${tree_sha}^{tree}")" = "$(git rev-parse HEAD^{tree})" | |
| echo "job_start_epoch=${job_start_epoch}" >> "${GITHUB_OUTPUT}" | |
| echo "tree_sha=${tree_sha}" >> "${GITHUB_OUTPUT}" | |
| - name: Install backend and exact Ruff | |
| working-directory: backend | |
| run: | | |
| set -euo pipefail | |
| python -m pip install --upgrade pip | |
| python -m pip install -e ".[dev,agents]" | |
| python -m pip install ruff==0.15.22 | |
| test "$(ruff --version)" = "ruff 0.15.22" | |
| - name: Lint | |
| working-directory: backend | |
| run: ruff check app tests scripts | |
| - name: Docstring coverage | |
| working-directory: backend | |
| run: docstr-coverage --config .docstr.yaml | |
| - name: Download source-pinned MinIO image | |
| uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 | |
| with: | |
| name: ${{ needs.minio-image.outputs.artifact }} | |
| path: ${{ runner.temp }}/minio-image | |
| - name: Start real MinIO artifact provider | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| (cd "${RUNNER_TEMP}/minio-image" && sha256sum --check minio.tar.sha256) | |
| docker load --input "${RUNNER_TEMP}/minio-image/minio.tar" | |
| docker run --detach --rm --name workstream-minio \ | |
| --publish 127.0.0.1:9000:9000 \ | |
| --env MINIO_ROOT_USER=workstream-minio \ | |
| --env MINIO_ROOT_PASSWORD=workstream-minio-secret-key \ | |
| "${MINIO_IMAGE}" server /data --address :9000 | |
| for attempt in $(seq 1 60); do | |
| if curl --fail --silent http://127.0.0.1:9000/minio/health/live >/dev/null; then | |
| exit 0 | |
| fi | |
| sleep 1 | |
| done | |
| docker logs workstream-minio | |
| exit 1 | |
| - name: Verify PostgreSQL CI storage and write settings | |
| env: | |
| POSTGRES_CONTAINER: ${{ job.services.postgres.id }} | |
| EXPECTED_PG_STORAGE: ${{ matrix.lane == 'schema_contracts' && 'disk' || 'tmpfs' }} | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| storage=$(docker exec "${POSTGRES_CONTAINER}" stat -f -c '%T %b %S' /var/lib/postgresql/data) | |
| read -r filesystem blocks block_size <<< "${storage}" | |
| [[ -n "${filesystem}" && "${blocks}" =~ ^[0-9]+$ && "${block_size}" =~ ^[0-9]+$ ]] | |
| if [[ "${EXPECTED_PG_STORAGE}" == tmpfs ]]; then | |
| [[ "${filesystem}" == tmpfs ]] | |
| (( blocks * block_size == 2147483648 )) | |
| elif [[ "${EXPECTED_PG_STORAGE}" == disk ]]; then | |
| [[ "${filesystem}" != tmpfs ]] | |
| else | |
| exit 1 | |
| fi | |
| settings=$(docker exec "${POSTGRES_CONTAINER}" psql -U workstream -d workstream_test -At -c "SELECT current_setting('fsync'), current_setting('full_page_writes'), current_setting('synchronous_commit'), current_setting('data_directory')") | |
| [[ "${settings}" == 'on|on|on|/var/lib/postgresql/data' ]] | |
| echo "PostgreSQL CI storage: ${filesystem}, bytes=$((blocks * block_size)); write settings: ${settings}" | |
| - name: Execute semantic lane ${{ matrix.lane }} | |
| working-directory: backend | |
| env: | |
| COVERAGE_FILE: .coverage | |
| PYTEST_DISABLE_PLUGIN_AUTOLOAD: "1" | |
| WORKSTREAM_TEST_BROKER_URL: redis://localhost:6380/0 | |
| WORKSTREAM_TEST_ADMIN_DATABASE_URL: postgresql+asyncpg://workstream:workstream@localhost:5433/postgres | |
| WORKSTREAM_TEST_MINIO_ENDPOINT: http://127.0.0.1:9000 | |
| shell: bash | |
| run: | | |
| set -uo pipefail | |
| install -d -m 700 ".ci/lane-bundle/${{ matrix.lane }}" | |
| python scripts/run_test_lanes.py \ | |
| --lane "${{ matrix.lane }}" \ | |
| --metadata-dir ".ci/lane-bundle/${{ matrix.lane }}/metadata" \ | |
| --summary-json ".ci/lane-bundle/${{ matrix.lane }}/summary.json" \ | |
| --timeout-seconds 1200 | |
| - name: Bind lane bundle timing | |
| if: ${{ always() }} | |
| working-directory: backend | |
| shell: bash | |
| run: | | |
| install -d -m 700 '.ci/lane-bundle/${{ matrix.lane }}' | |
| printf '%s\n' '${{ steps.identity.outputs.job_start_epoch }}' \ | |
| > '.ci/lane-bundle/${{ matrix.lane }}/job-start-epoch.txt' | |
| - name: Upload authenticated lane ${{ matrix.lane }} | |
| if: ${{ always() }} | |
| uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 | |
| with: | |
| name: backend-lane-${{ github.sha }}-${{ matrix.lane }}-attempt-${{ github.run_attempt }} | |
| path: | | |
| backend/.ci/lane-bundle/${{ matrix.lane }}/summary.json | |
| backend/.ci/lane-bundle/${{ matrix.lane }}/job-start-epoch.txt | |
| backend/.ci/lane-bundle/${{ matrix.lane }}/metadata/manifest.json | |
| backend/.ci/lane-bundle/${{ matrix.lane }}/metadata/${{ matrix.lane }}.json | |
| backend/.ci/lane-bundle/${{ matrix.lane }}/metadata/${{ matrix.lane }}.database.json | |
| backend/.ci/lane-bundle/${{ matrix.lane }}/metadata/.coverage.${{ matrix.lane }} | |
| backend/.ci/lane-bundle/${{ matrix.lane }}/metadata/${{ matrix.lane }}.log | |
| backend/.ci/lane-bundle/${{ matrix.lane }}/metadata/${{ matrix.lane }}.admin.log | |
| include-hidden-files: true | |
| if-no-files-found: error | |
| retention-days: 7 | |
| test: | |
| if: ${{ always() }} | |
| needs: [auth-boundary-preflight, lanes, minio-image] | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 30 | |
| services: | |
| redis: | |
| image: redis:7-alpine@sha256:520775a41a63e77e06c73e35d2fd9cc15921a609516818796b4ecbb813078bc7 | |
| ports: | |
| - 6380:6379 | |
| options: >- | |
| --health-cmd "redis-cli ping" | |
| --health-interval 5s | |
| --health-timeout 5s | |
| --health-retries 10 | |
| postgres: | |
| image: public.ecr.aws/docker/library/postgres:16@sha256:33f923b05f64ca54ac4401c01126a6b92afe839a0aa0a52bc5aeb5cc958e5f20 | |
| env: | |
| POSTGRES_DB: workstream_test | |
| POSTGRES_USER: workstream | |
| POSTGRES_PASSWORD: workstream | |
| ports: | |
| - 5433:5432 | |
| options: >- | |
| --health-cmd "pg_isready -U workstream -d workstream_test" | |
| --health-interval 5s | |
| --health-timeout 5s | |
| --health-retries 10 | |
| steps: | |
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 | |
| with: | |
| persist-credentials: false | |
| fetch-depth: 0 | |
| - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 | |
| with: | |
| python-version: "3.12" | |
| - id: identity | |
| name: Bind exact checked-out tree | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| job_start_epoch="$(date +%s)" | |
| tree_sha="$(git rev-parse HEAD)" | |
| test "${tree_sha}" = "${GITHUB_SHA}" | |
| test -z "$(git status --porcelain)" | |
| echo "job_start_epoch=${job_start_epoch}" >> "${GITHUB_OUTPUT}" | |
| echo "tree_sha=${tree_sha}" >> "${GITHUB_OUTPUT}" | |
| - name: Install backend | |
| working-directory: backend | |
| run: python -m pip install -e ".[dev,agents]" | |
| - name: Download source-pinned MinIO image | |
| uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 | |
| with: | |
| name: ${{ needs.minio-image.outputs.artifact }} | |
| path: ${{ runner.temp }}/minio-image | |
| - name: Start real MinIO API provider | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| (cd "${RUNNER_TEMP}/minio-image" && sha256sum --check minio.tar.sha256) | |
| docker load --input "${RUNNER_TEMP}/minio-image/minio.tar" | |
| docker run --detach --rm --name workstream-minio \ | |
| --publish 127.0.0.1:9000:9000 \ | |
| --env MINIO_ROOT_USER=workstream-minio \ | |
| --env MINIO_ROOT_PASSWORD=workstream-minio-secret-key \ | |
| "${MINIO_IMAGE}" server /data --address :9000 | |
| for attempt in $(seq 1 60); do | |
| if curl --fail --silent http://127.0.0.1:9000/minio/health/live >/dev/null; then | |
| exit 0 | |
| fi | |
| sleep 1 | |
| done | |
| docker logs workstream-minio | |
| exit 1 | |
| - name: Download separate lane attempts from this run | |
| if: ${{ always() }} | |
| uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 | |
| with: | |
| pattern: backend-lane-${{ github.sha }}-*-attempt-* | |
| path: backend/.ci/download | |
| merge-multiple: false | |
| - name: Require preflight and every semantic lane | |
| if: ${{ always() }} | |
| env: | |
| PREFLIGHT_RESULT: ${{ needs.auth-boundary-preflight.result }} | |
| LANES_RESULT: ${{ needs.lanes.result }} | |
| run: test "${PREFLIGHT_RESULT}" = success && test "${LANES_RESULT}" = success | |
| - name: Merge and independently validate exact lane custody | |
| working-directory: backend | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| install -d -m 700 .ci/test-lanes | |
| python -m scripts.merge_test_lane_evidence \ | |
| --input-root .ci/download \ | |
| --metadata-dir .ci/test-lanes/run \ | |
| --summary-json .ci/test-lanes/run-summary.json \ | |
| --expected-head "${GITHUB_SHA}" \ | |
| --run-attempt "${GITHUB_RUN_ATTEMPT}" | |
| python scripts/validate_test_lane_evidence.py \ | |
| --metadata-dir .ci/test-lanes/run \ | |
| --summary-json .ci/test-lanes/run-summary.json | |
| - name: Combine semantic-lane coverage exactly once | |
| working-directory: backend | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| shopt -s nullglob | |
| coverage_files=(.ci/test-lanes/run/.coverage.*) | |
| test "${#coverage_files[@]}" -eq 9 | |
| for source in "${coverage_files[@]}"; do | |
| destination="$(basename "${source}")" | |
| test -f "${source}" | |
| test ! -L "${source}" | |
| test ! -e "${destination}" | |
| cp -- "${source}" "${destination}" | |
| test "$(sha256sum "${source}" | cut -d' ' -f1)" = \ | |
| "$(sha256sum "${destination}" | cut -d' ' -f1)" | |
| done | |
| coverage combine | |
| - name: API contract real API e2e | |
| working-directory: backend | |
| env: | |
| WORKSTREAM_TEST_BROKER_URL: redis://localhost:6380/0 | |
| WORKSTREAM_TEST_ADMIN_DATABASE_URL: postgresql+asyncpg://workstream:workstream@localhost:5433/postgres | |
| WORKSTREAM_TEST_MINIO_ENDPOINT: http://127.0.0.1:9000 | |
| run: >- | |
| python scripts/run_isolated_tests.py | |
| --metadata-json "${RUNNER_TEMP}/api-database.json" | |
| --timeout-seconds 1500 | |
| -- python scripts/api_contract_e2e.py | |
| - name: Backend coverage diagnostics (no percentage gate) | |
| working-directory: backend | |
| run: coverage report --precision=2 | |
| - name: Record hosted timing, complete execution and diagnostic coverage | |
| working-directory: backend | |
| env: | |
| EXPECTED_HEAD_SHA: ${{ steps.identity.outputs.tree_sha }} | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| coverage json --include='app/*' -o .ci/test-lanes/coverage.json | |
| python - <<'PY' | |
| from __future__ import annotations | |
| from collections import Counter | |
| import hashlib | |
| import json | |
| import math | |
| import os | |
| from pathlib import Path | |
| import subprocess | |
| import time | |
| from scripts.merge_test_lane_evidence import select_lane_bundles | |
| evidence_root = Path(".ci/test-lanes") | |
| run_root = evidence_root / "run" | |
| summary_path = evidence_root / "run-summary.json" | |
| coverage_path = evidence_root / "coverage.json" | |
| output_path = Path(".ci/test-lanes/hosted-evidence.json") | |
| def read_json(path: Path) -> dict[str, object]: | |
| if not path.is_file() or path.is_symlink(): | |
| raise SystemExit(f"invalid hosted evidence input: {path}") | |
| value = json.loads(path.read_text(encoding="utf-8")) | |
| if not isinstance(value, dict): | |
| raise SystemExit(f"invalid hosted evidence object: {path}") | |
| return value | |
| def digest(path: Path) -> str: | |
| if not path.is_file() or path.is_symlink(): | |
| raise SystemExit(f"invalid hosted digest input: {path}") | |
| return hashlib.sha256(path.read_bytes()).hexdigest() | |
| expected_head = os.environ["EXPECTED_HEAD_SHA"] | |
| actual_head = subprocess.check_output( | |
| ["git", "rev-parse", "HEAD"], text=True | |
| ).strip() | |
| summary = read_json(summary_path) | |
| coverage = read_json(coverage_path) | |
| if actual_head != expected_head or summary.get("head_sha") != expected_head: | |
| raise SystemExit("hosted evidence head drift") | |
| lanes = summary.get("lanes") | |
| if not isinstance(lanes, list) or len(lanes) != 9: | |
| raise SystemExit("invalid hosted lane inventory") | |
| collected: list[str] = [] | |
| completed: list[str] = [] | |
| lane_elapsed: list[float] = [] | |
| for lane in lanes: | |
| if not isinstance(lane, dict): | |
| raise SystemExit("invalid hosted lane row") | |
| elapsed = lane.get("elapsed_seconds") | |
| if ( | |
| isinstance(elapsed, bool) | |
| or not isinstance(elapsed, (int, float)) | |
| or not math.isfinite(elapsed) | |
| or elapsed < 0 | |
| ): | |
| raise SystemExit("invalid hosted lane timing") | |
| lane_elapsed.append(float(elapsed)) | |
| for file_key, digest_key in ( | |
| ("evidence_file", "evidence_sha256"), | |
| ("coverage_file", "coverage_sha256"), | |
| ): | |
| name = lane.get(file_key) | |
| expected_digest = lane.get(digest_key) | |
| if not isinstance(name, str) or not isinstance(expected_digest, str): | |
| raise SystemExit("invalid hosted lane digest binding") | |
| path = run_root / name | |
| if path.parent != run_root or digest(path) != expected_digest: | |
| raise SystemExit("hosted lane digest drift") | |
| lane_evidence = read_json(run_root / str(lane["evidence_file"])) | |
| lane_collected = lane_evidence.get("collected_nodes") | |
| lane_completed = lane_evidence.get("completed_nodes") | |
| if not isinstance(lane_collected, list) or not isinstance(lane_completed, list): | |
| raise SystemExit("invalid hosted node custody") | |
| collected.extend(lane_collected) | |
| completed.extend(lane_completed) | |
| canonical_count = summary.get("canonical_node_count") | |
| if ( | |
| isinstance(canonical_count, bool) | |
| or not isinstance(canonical_count, int) | |
| or canonical_count <= 0 | |
| or len(collected) != canonical_count | |
| or len(completed) != canonical_count | |
| or Counter(collected) != Counter(completed) | |
| or len(set(collected)) != canonical_count | |
| ): | |
| raise SystemExit("hosted node count mismatch") | |
| aggregate = summary.get("aggregate_runner_seconds") | |
| slowest = summary.get("slowest_lane_seconds") | |
| for value in (aggregate, slowest): | |
| if ( | |
| isinstance(value, bool) | |
| or not isinstance(value, (int, float)) | |
| or not math.isfinite(value) | |
| or value < 0 | |
| ): | |
| raise SystemExit("invalid hosted summary timing") | |
| if not math.isclose( | |
| float(aggregate), math.fsum(lane_elapsed), rel_tol=0.0, abs_tol=1e-9 | |
| ): | |
| raise SystemExit("aggregate runner timing drift") | |
| if not math.isclose( | |
| float(slowest), max(lane_elapsed), rel_tol=0.0, abs_tol=1e-9 | |
| ): | |
| raise SystemExit("slowest lane timing drift") | |
| start_epochs = [] | |
| selected_bundles = select_lane_bundles( | |
| Path(".ci/download"), expected_head, int(os.environ["GITHUB_RUN_ATTEMPT"]), | |
| ) | |
| for bundle in selected_bundles.values(): | |
| timing_path = bundle / "job-start-epoch.txt" | |
| if timing_path.is_symlink() or not timing_path.is_file(): | |
| raise SystemExit("missing lane start timing") | |
| timing_value = timing_path.read_text(encoding="ascii").strip() | |
| if not timing_value.isdigit(): | |
| raise SystemExit("invalid lane start timing") | |
| start_epochs.append(int(timing_value)) | |
| start_epoch = min(start_epochs) | |
| total_wall = time.time() - start_epoch | |
| if not math.isfinite(total_wall) or total_wall < 0: | |
| raise SystemExit("invalid Backend hosted wall time") | |
| totals = coverage.get("totals") | |
| percent = totals.get("percent_covered") if isinstance(totals, dict) else None | |
| if ( | |
| isinstance(percent, bool) | |
| or not isinstance(percent, (int, float)) | |
| or not math.isfinite(percent) | |
| or percent < 0 | |
| or percent > 100 | |
| ): | |
| raise SystemExit("invalid hosted global coverage") | |
| hosted = { | |
| "aggregate_runner_seconds": float(aggregate), | |
| "canonical_collected_count": len(collected), | |
| "completed_count": len(completed), | |
| "global_coverage_percent": float(percent), | |
| "global_coverage_sha256": digest(coverage_path), | |
| "head_sha": expected_head, | |
| "run_summary_sha256": digest(summary_path), | |
| "slowest_lane_seconds": float(slowest), | |
| "timing_target_met": total_wall <= 480, | |
| "total_backend_wall_seconds": round(total_wall, 3), | |
| } | |
| output_path.write_text( | |
| json.dumps(hosted, indent=2, sort_keys=True) + "\n", encoding="utf-8" | |
| ) | |
| PY | |
| - name: Reassert exact tree custody | |
| if: ${{ always() }} | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| test "$(git rev-parse HEAD)" = "${{ steps.identity.outputs.tree_sha }}" | |
| test "$(git rev-parse HEAD^{tree})" = "$(git rev-parse "${{ steps.identity.outputs.tree_sha }}^{tree}")" | |
| - name: Upload semantic-lane evidence and timing | |
| if: ${{ always() }} | |
| uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 | |
| with: | |
| name: backend-semantic-lane-evidence-${{ steps.identity.outputs.tree_sha }}-attempt-${{ github.run_attempt }} | |
| path: | | |
| backend/.ci/download/** | |
| backend/.ci/test-lanes/** | |
| include-hidden-files: true | |
| if-no-files-found: warn | |
| retention-days: 7 |