name: Release Verify on: workflow_call: inputs: ref: description: Commit SHA, branch, or tag to verify required: true type: string # Caller-provided refs may name unmerged PR code. AWS is eligible only when # the caller runs on canonical master and verifies that event's exact SHA. # The organization group also restricts these workflow files to master. jobs: runner_chaos_evals: name: Pre-release Runner chaos evals uses: ./.github/workflows/runner-chaos-evals.yml with: ref: ${{ inputs.ref }} typecheck: name: Typecheck runs-on: ${{ vars.AWS_POST_MERGE_CI_ENABLED == 'true' && github.repository == 'paperclipai/paperclip' && github.repository_id == '1170821064' && github.ref == 'refs/heads/master' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch') && github.sha != '' && inputs.ref == github.sha && 'runs-on/fleet=paperclip-post-merge-x64/env=public-ci' || 'ubuntu-latest' }} timeout-minutes: 20 permissions: contents: read steps: - name: Checkout repository uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 with: ref: ${{ inputs.ref }} - name: Setup pnpm uses: pnpm/action-setup@0977fd99725f1db4007ccb2928dbb4e90d06cc86 # v6 with: version: 9.15.4 - name: Setup Node.js uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7 with: node-version: 24 cache: pnpm - name: Select the pinned Runner Rust toolchain working-directory: packages/paperclip-runner run: | set -euo pipefail rustup show toolchain="$(rustup show active-toolchain | awk '{print $1}')" echo "RUSTUP_TOOLCHAIN=$toolchain" >> "$GITHUB_ENV" - name: Cache typecheck Rust dependencies # Restore and save only within trusted master-push verification. GitHub # isolates branch/PR caches from master; other callers compile afresh. if: ${{ github.repository == 'paperclipai/paperclip' && github.event_name == 'push' && github.ref == 'refs/heads/master' && inputs.ref == github.sha }} uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2 with: workspaces: packages/paperclip-runner/runner -> target shared-key: release-typecheck-v1 # Rebuild workspace code and rerun every check. Cache only compiled # dependencies; never restore installed executables from cargo/bin. cache-workspace-crates: false cache-bin: false # The step guard also restricts restores. Save only after a successful # master-push verification of that push's exact commit. save-if: ${{ github.repository == 'paperclipai/paperclip' && github.event_name == 'push' && github.ref == 'refs/heads/master' && inputs.ref == github.sha }} - name: Validate release package manifest run: node ./scripts/release-package-map.mjs check - name: Install dependencies run: pnpm install --no-frozen-lockfile - name: Typecheck run: pnpm -r typecheck general_tests: name: General tests (${{ matrix.group_label }}) runs-on: ${{ vars.AWS_POST_MERGE_CI_ENABLED == 'true' && github.repository == 'paperclipai/paperclip' && github.repository_id == '1170821064' && github.ref == 'refs/heads/master' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch') && github.sha != '' && inputs.ref == github.sha && 'runs-on/fleet=paperclip-post-merge-x64/env=public-ci' || 'ubuntu-latest' }} timeout-minutes: 20 permissions: contents: read strategy: fail-fast: false matrix: include: # Split the long chat file by collected test locations, and balance # the remaining server files across ten runners. Normal PR/local # invocations retain their complete general-server group. - group: general-server-without-chat group_label: server (1/10) shard_index: 0 shard_count: 10 - group: general-server-without-chat group_label: server (2/10) shard_index: 1 shard_count: 10 - group: general-server-without-chat group_label: server (3/10) shard_index: 2 shard_count: 10 - group: general-server-without-chat group_label: server (4/10) shard_index: 3 shard_count: 10 - group: general-server-without-chat group_label: server (5/10) shard_index: 4 shard_count: 10 - group: general-server-without-chat group_label: server (6/10) shard_index: 5 shard_count: 10 - group: general-server-without-chat group_label: server (7/10) shard_index: 6 shard_count: 10 - group: general-server-without-chat group_label: server (8/10) shard_index: 7 shard_count: 10 - group: general-server-without-chat group_label: server (9/10) shard_index: 8 shard_count: 10 - group: general-server-without-chat group_label: server (10/10) shard_index: 9 shard_count: 10 - group: general-chat group_label: chat (1/3) shard_index: 0 shard_count: 3 - group: general-chat group_label: chat (2/3) shard_index: 1 shard_count: 3 - group: general-chat group_label: chat (3/3) shard_index: 2 shard_count: 3 # Keep parity with pr.yml: workspaces-a is split with Vitest's # native --shard because the ui project dominates the lane. - group: general-workspaces-a group_label: workspaces-a (1/2) shard_index: 0 shard_count: 2 - group: general-workspaces-a group_label: workspaces-a (2/2) shard_index: 1 shard_count: 2 - group: general-workspaces-b group_label: workspaces-b steps: - name: Checkout repository uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 with: ref: ${{ inputs.ref }} - name: Setup pnpm uses: pnpm/action-setup@0977fd99725f1db4007ccb2928dbb4e90d06cc86 # v6 with: version: 9.15.4 - name: Setup Node.js uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7 with: node-version: 24 cache: pnpm - name: Install dependencies run: pnpm install --no-frozen-lockfile - name: Run grouped general test suites run: | if [ -n "${{ matrix.shard_count }}" ]; then pnpm test:run:general -- --group '${{ matrix.group }}' \ --shard-index ${{ matrix.shard_index }} --shard-count ${{ matrix.shard_count }} else pnpm test:run:general -- --group '${{ matrix.group }}' fi serialized_tests: name: Serialized tests (${{ matrix.shard_label }}) runs-on: ${{ vars.AWS_POST_MERGE_CI_ENABLED == 'true' && github.repository == 'paperclipai/paperclip' && github.repository_id == '1170821064' && github.ref == 'refs/heads/master' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch') && github.sha != '' && inputs.ref == github.sha && 'runs-on/fleet=paperclip-post-merge-x64/env=public-ci' || 'ubuntu-latest' }} timeout-minutes: 20 permissions: contents: read strategy: fail-fast: false matrix: include: - shard_index: 0 shard_count: 5 shard_label: 1/5 - shard_index: 1 shard_count: 5 shard_label: 2/5 - shard_index: 2 shard_count: 5 shard_label: 3/5 - shard_index: 3 shard_count: 5 shard_label: 4/5 - shard_index: 4 shard_count: 5 shard_label: 5/5 steps: - name: Checkout repository uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 with: ref: ${{ inputs.ref }} - name: Setup pnpm uses: pnpm/action-setup@0977fd99725f1db4007ccb2928dbb4e90d06cc86 # v6 with: version: 9.15.4 - name: Setup Node.js uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7 with: node-version: 24 cache: pnpm - name: Install dependencies run: pnpm install --no-frozen-lockfile - name: Run serialized server test shard run: pnpm test:run:serialized -- --shard-index ${{ matrix.shard_index }} --shard-count ${{ matrix.shard_count }} runner_workflow_evals: name: Runner workflow eval scorer contract runs-on: ${{ vars.AWS_POST_MERGE_CI_ENABLED == 'true' && github.repository == 'paperclipai/paperclip' && github.repository_id == '1170821064' && github.ref == 'refs/heads/master' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch') && github.sha != '' && inputs.ref == github.sha && 'runs-on/fleet=paperclip-post-merge-x64/env=public-ci' || 'ubuntu-latest' }} timeout-minutes: 10 permissions: contents: read steps: - name: Checkout repository uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 with: ref: ${{ inputs.ref }} - name: Setup pnpm uses: pnpm/action-setup@0977fd99725f1db4007ccb2928dbb4e90d06cc86 # v6 with: version: 9.15.4 - name: Setup Node.js uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7 with: node-version: 24 cache: pnpm - name: Install dependencies run: pnpm install --no-frozen-lockfile - name: Run deterministic Runner workflow scorer tests run: pnpm test:runner-workflow-evals verify_paperclip_runner: name: Verify Paperclip Runner (${{ matrix.lane }}) runs-on: ${{ vars.AWS_POST_MERGE_CI_ENABLED == 'true' && github.repository == 'paperclipai/paperclip' && github.repository_id == '1170821064' && github.ref == 'refs/heads/master' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch') && github.sha != '' && inputs.ref == github.sha && 'runs-on/fleet=paperclip-post-merge-x64/env=public-ci' || 'ubuntu-latest' }} timeout-minutes: 20 permissions: contents: read strategy: fail-fast: false matrix: include: - lane: protocol checks: check:eval-kernel check:protocol - lane: rust checks: check:runner check:api-authority steps: - name: Checkout repository uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 with: ref: ${{ inputs.ref }} - name: Setup pnpm uses: pnpm/action-setup@0977fd99725f1db4007ccb2928dbb4e90d06cc86 # v6 with: version: 9.15.4 - name: Setup Node.js uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7 with: node-version: 24 cache: pnpm - name: Select the pinned Runner Rust toolchain working-directory: packages/paperclip-runner run: | set -euo pipefail rustup show toolchain="$(rustup show active-toolchain | awk '{print $1}')" echo "RUSTUP_TOOLCHAIN=$toolchain" >> "$GITHUB_ENV" - name: Cache Runner Rust dependencies # Restore and save only within trusted master-push verification. GitHub # isolates branch/PR caches from master; other callers compile afresh. if: ${{ github.repository == 'paperclipai/paperclip' && github.event_name == 'push' && github.ref == 'refs/heads/master' && inputs.ref == github.sha }} uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2 with: workspaces: packages/paperclip-runner/runner -> target shared-key: release-runner-v1 # Rebuild workspace code and rerun every check. Cache only compiled # dependencies; never restore installed executables from cargo/bin. cache-workspace-crates: false cache-bin: false # Both lanes restore the existing dependency cache. Only the Rust # lane saves it, after warming both release and debug dependencies. save-if: ${{ matrix.lane == 'rust' && github.repository == 'paperclipai/paperclip' && github.event_name == 'push' && github.ref == 'refs/heads/master' && inputs.ref == github.sha }} - name: Install dependencies run: pnpm install --no-frozen-lockfile - name: Verify Paperclip Runner env: RUNNER_CHECKS: ${{ matrix.checks }} run: | set -euo pipefail for check in $RUNNER_CHECKS; do pnpm --filter @paperclipai/paperclip-runner "$check" done - name: Warm debug dependencies for the shared Runner cache # Protocol tests need debug binaries. Populate their dependencies in # the sole cache writer, so a cold save also serves the protocol lane. if: ${{ matrix.lane == 'rust' && github.repository == 'paperclipai/paperclip' && github.event_name == 'push' && github.ref == 'refs/heads/master' && inputs.ref == github.sha }} run: pnpm --filter @paperclipai/paperclip-runner build:rust build: name: Build runs-on: ${{ vars.AWS_POST_MERGE_CI_ENABLED == 'true' && github.repository == 'paperclipai/paperclip' && github.repository_id == '1170821064' && github.ref == 'refs/heads/master' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch') && github.sha != '' && inputs.ref == github.sha && 'runs-on/fleet=paperclip-post-merge-x64/env=public-ci' || 'ubuntu-latest' }} timeout-minutes: 20 permissions: contents: read steps: - name: Checkout repository uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 with: ref: ${{ inputs.ref }} persist-credentials: false - name: Setup pnpm uses: pnpm/action-setup@0977fd99725f1db4007ccb2928dbb4e90d06cc86 # v6 with: version: 9.15.4 - name: Setup Node.js uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7 with: node-version: 24 - name: Install dependencies run: pnpm install --no-frozen-lockfile - name: Build run: pnpm build