name: T3MP3ST CI on: pull_request: branches: [main] push: branches: - main tags: - "v*" permissions: contents: read concurrency: group: t3mp3st-ci-${{ github.workflow }}-${{ github.ref }} cancel-in-progress: ${{ github.event_name == 'pull_request' }} jobs: test: name: Pull request gate if: github.event_name == 'pull_request' || (github.event_name == 'push' && github.ref == 'refs/heads/main') runs-on: ubuntu-latest timeout-minutes: 20 steps: - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 with: fetch-depth: 0 - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 with: node-version: 22 cache: npm - run: npm ci - name: Run PR correctness gate run: npm run test:pr - name: Resolve comparison base env: EVENT_BASE: ${{ github.event.pull_request.base.sha || github.event.before }} run: | coverage_base="$EVENT_BASE" if ! git rev-parse --verify "${coverage_base}^{commit}" >/dev/null 2>&1; then coverage_base="$(git rev-parse HEAD^)" fi echo "COVERAGE_BASE=$coverage_base" >> "$GITHUB_ENV" - name: Enforce 50% changed-line coverage floor env: PR_CHANGED_LINE_COVERAGE: "50" run: npm run test:pr-coverage - name: Verify changed-line coverage policy tool run: npm run test:changed-coverage-script release: name: Release certification and ZIP archive if: startsWith(github.ref, 'refs/tags/v') runs-on: ubuntu-latest timeout-minutes: 30 permissions: artifact-metadata: write attestations: write contents: read id-token: write steps: - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 with: ref: ${{ github.sha }} - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 with: node-version: 22 cache: npm - run: npm ci - name: Run release-grade test and evidence gates run: npm run test:release - name: Reject high-severity dependency vulnerabilities run: npm audit --audit-level=high - name: Build deterministic source ZIP from tested tag run: | mkdir -p release release-evidence archive="release/T3MP3ST-${GITHUB_SHA}.zip" git archive --format=zip --prefix="T3MP3ST-${GITHUB_SHA}/" --output="$archive" "$GITHUB_SHA" unzip -t "$archive" | tee release-evidence/source-zip-check.txt sha256sum "$archive" | tee release-evidence/SHA256SUMS - name: Verify a clean user build from the ZIP run: | install_root="$RUNNER_TEMP/t3mp3st-release-smoke" mkdir -p "$install_root" unzip -q "release/T3MP3ST-${GITHUB_SHA}.zip" -d "$install_root" cd "$install_root/T3MP3ST-${GITHUB_SHA}" npm ci npm run build node dist/cli.js --help > /dev/null - name: Attest tested ZIP provenance id: provenance uses: actions/attest@1e69f48acb82d1966a394da916b4c1698aa569d6 # v4.2.2 with: subject-checksums: release-evidence/SHA256SUMS - name: Retain provenance bundle and verify archive checksum run: | cp "${{ steps.provenance.outputs.bundle-path }}" release-evidence/slsa-provenance.sigstore.json sha256sum -c release-evidence/SHA256SUMS - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: tested-source-zip-${{ github.sha }} path: | release/ release-evidence/ if-no-files-found: error retention-days: 14