ci: route PR admission through reserved AWS capacity

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
DottaandPaperclip committed 2026-10-12 16:15:11 -05:00
1 parent 8e7b5db822
commit ea62b00220
4 files changed
+37 -239

No files matched your search

+1 -235
View File
@@ -17,241 +17,7 @@ concurrency:
jobs:
gate:
name: Select trusted runner
runs-on: ubuntu-latest
timeout-minutes: 5
outputs:
runner: ${{ steps.route.outputs.runner }}
full_ci: ${{ steps.scope.outputs.full_ci }}
steps:
- name: Validate PR identity and select runner
id: route
shell: bash
env:
GH_TOKEN: ${{ github.token }}
AWS_CI_ENABLED: ${{ vars.AWS_CI_ENABLED }}
TRUSTED_USER_IDS: ${{ vars.AWS_CI_TRUSTED_USER_IDS }}
EVENT_NAME: ${{ github.event_name }}
EVENT_REPOSITORY: ${{ github.repository }}
EVENT_REPOSITORY_ID: ${{ github.repository_id }}
EVENT_ACTION: ${{ github.event.action }}
EVENT_PR_NUMBER: ${{ github.event.pull_request.number }}
EVENT_PR_AUTHOR_ID: ${{ github.event.pull_request.user.id }}
EVENT_SENDER_ID: ${{ github.event.sender.id }}
EVENT_BASE_REPOSITORY_ID: ${{ github.event.pull_request.base.repo.id }}
EVENT_BASE_REF: ${{ github.event.pull_request.base.ref }}
EVENT_BASE_SHA: ${{ github.event.pull_request.base.sha }}
EVENT_HEAD_SHA: ${{ github.event.pull_request.head.sha }}
EVENT_MERGE_SHA: ${{ github.sha }}
RUN_ID: ${{ github.run_id }}
run: |
set -u
github_runner='ubuntu-latest'
aws_runner='runs-on/fleet=paperclip-public-pr-x64/env=public-ci'
fail_closed() {
echo "runner=$github_runner" >> "$GITHUB_OUTPUT"
echo "::notice title=AWS CI routing::Using GitHub-hosted runner: $1"
exit 0
}
is_positive_integer() {
[[ "$1" =~ ^[1-9][0-9]*$ ]]
}
is_commit_sha() {
[[ "$1" =~ ^[0-9a-f]{40}$ ]]
}
is_allowed() {
local user_id="$1"
jq -e --argjson user_id "$user_id" 'index($user_id) != null' \
<<< "$TRUSTED_USER_IDS" >/dev/null
}
[[ "$AWS_CI_ENABLED" == 'true' ]] || fail_closed 'AWS_CI_ENABLED is not true'
# Reusable workflows retain the caller's github context and event
# payload, so a pull_request caller must still report pull_request.
[[ "$EVENT_NAME" == 'pull_request' ]] || fail_closed 'event is not pull_request'
[[ "$EVENT_REPOSITORY" == 'paperclipai/paperclip' ]] || fail_closed 'unexpected repository'
[[ "$EVENT_REPOSITORY_ID" == '1170821064' ]] || fail_closed 'unexpected repository ID'
[[ "$EVENT_BASE_REPOSITORY_ID" == '1170821064' ]] || fail_closed 'unexpected base repository ID'
[[ -n "$EVENT_BASE_REF" ]] || fail_closed 'missing base branch'
[[ "$EVENT_ACTION" =~ ^(opened|reopened|synchronize)$ ]] || fail_closed 'unsupported pull_request action'
jq -e '
type == "array" and
length > 0 and
all(.[]; type == "number" and . > 0 and floor == .)
' <<< "$TRUSTED_USER_IDS" >/dev/null 2>&1 || fail_closed 'trusted user ID list is malformed'
for user_id in "$EVENT_PR_AUTHOR_ID" "$EVENT_SENDER_ID"; do
is_positive_integer "$user_id" || fail_closed 'event contains a malformed user ID'
is_allowed "$user_id" || fail_closed "GitHub user ID $user_id is not allowlisted"
done
for commit_sha in "$EVENT_BASE_SHA" "$EVENT_HEAD_SHA" "$EVENT_MERGE_SHA"; do
is_commit_sha "$commit_sha" || fail_closed 'event contains a malformed commit SHA'
done
pr_json="$(gh api \
-H 'Accept: application/vnd.github+json' \
-H 'X-GitHub-Api-Version: 2022-11-28' \
"/repos/paperclipai/paperclip/pulls/$EVENT_PR_NUMBER" 2>/dev/null)" \
|| fail_closed 'could not refresh pull request state'
jq -e \
--argjson repository_id 1170821064 \
--argjson author_id "$EVENT_PR_AUTHOR_ID" \
--arg base_ref "$EVENT_BASE_REF" \
--arg head_sha "$EVENT_HEAD_SHA" \
'
.state == "open" and
.user.id == $author_id and
.base.repo.id == $repository_id and
.base.ref == $base_ref and
.head.sha == $head_sha
' <<< "$pr_json" >/dev/null 2>&1 \
|| fail_closed 'current pull request state does not match the triggering event'
live_merge_sha="$(jq -r '.merge_commit_sha // empty' <<< "$pr_json")"
is_commit_sha "$live_merge_sha" || fail_closed 'current pull request has no valid merge SHA'
base_ref_json="$(gh api \
-H 'Accept: application/vnd.github+json' \
-H 'X-GitHub-Api-Version: 2022-11-28' \
"/repos/paperclipai/paperclip/git/ref/heads/$EVENT_BASE_REF" 2>/dev/null)" \
|| fail_closed 'could not inspect the current base branch'
live_base_ref_sha="$(jq -r '.object.sha // empty' <<< "$base_ref_json")"
is_commit_sha "$live_base_ref_sha" || fail_closed 'current base branch has no valid commit SHA'
base_comparison="$(gh api \
-H 'Accept: application/vnd.github+json' \
-H 'X-GitHub-Api-Version: 2022-11-28' \
"/repos/paperclipai/paperclip/compare/$EVENT_BASE_SHA...$live_base_ref_sha" 2>/dev/null)" \
|| fail_closed 'could not compare the triggering and current base branches'
jq -e \
--arg event_base_sha "$EVENT_BASE_SHA" '
.merge_base_commit.sha == $event_base_sha and
(.status == "ahead" or .status == "identical")
' <<< "$base_comparison" >/dev/null 2>&1 \
|| fail_closed 'current base branch does not descend from the triggering base snapshot'
event_merge_json="$(gh api \
-H 'Accept: application/vnd.github+json' \
-H 'X-GitHub-Api-Version: 2022-11-28' \
"/repos/paperclipai/paperclip/git/commits/$EVENT_MERGE_SHA" 2>/dev/null)" \
|| fail_closed 'could not inspect the event merge commit'
live_merge_json="$(gh api \
-H 'Accept: application/vnd.github+json' \
-H 'X-GitHub-Api-Version: 2022-11-28' \
"/repos/paperclipai/paperclip/git/commits/$live_merge_sha" 2>/dev/null)" \
|| fail_closed 'could not inspect the current merge commit'
validate_merge_commit() {
local merge_json="$1"
local expected_sha="$2"
jq -e \
--arg expected_sha "$expected_sha" \
--arg head_sha "$EVENT_HEAD_SHA" '
.sha == $expected_sha and
(.parents | length) == 2 and
.parents[1].sha == $head_sha and
(.parents[0].sha | test("^[0-9a-f]{40}$")) and
(.tree.sha | test("^[0-9a-f]{40}$"))
' <<< "$merge_json" >/dev/null 2>&1
}
validate_merge_commit "$event_merge_json" "$EVENT_MERGE_SHA" \
|| fail_closed 'event merge commit does not match the current base and head'
validate_merge_commit "$live_merge_json" "$live_merge_sha" \
|| fail_closed 'current merge commit does not match the triggering base and head'
event_merge_parent="$(jq -r '.parents[0].sha' <<< "$event_merge_json")"
live_merge_parent="$(jq -r '.parents[0].sha' <<< "$live_merge_json")"
[[ "$event_merge_parent" == "$live_merge_parent" ]] \
|| fail_closed 'current merge commit uses a different base merge parent'
if [[ "$event_merge_parent" != "$live_base_ref_sha" ]]; then
base_merge_json="$(gh api \
-H 'Accept: application/vnd.github+json' \
-H 'X-GitHub-Api-Version: 2022-11-28' \
"/repos/paperclipai/paperclip/git/commits/$event_merge_parent" 2>/dev/null)" \
|| fail_closed 'could not inspect the stacked base merge commit'
jq -e \
--arg expected_sha "$event_merge_parent" \
--arg live_base_ref_sha "$live_base_ref_sha" '
.sha == $expected_sha and
(.parents | length) == 2 and
any(.parents[]; .sha == $live_base_ref_sha) and
(.tree.sha | test("^[0-9a-f]{40}$"))
' <<< "$base_merge_json" >/dev/null 2>&1 \
|| fail_closed 'stacked base merge commit does not contain the current base branch'
fi
event_merge_tree="$(jq -r '.tree.sha' <<< "$event_merge_json")"
live_merge_tree="$(jq -r '.tree.sha' <<< "$live_merge_json")"
[[ "$event_merge_tree" == "$live_merge_tree" ]] \
|| fail_closed 'current merge tree differs from the triggering merge tree'
run_json="$(gh api \
-H 'Accept: application/vnd.github+json' \
-H 'X-GitHub-Api-Version: 2022-11-28' \
"/repos/paperclipai/paperclip/actions/runs/$RUN_ID" 2>/dev/null)" \
|| fail_closed 'could not refresh workflow run state'
triggering_actor_id="$(jq -r '.triggering_actor.id // empty' <<< "$run_json")"
is_positive_integer "$triggering_actor_id" || fail_closed 'workflow run has no valid triggering actor ID'
is_allowed "$triggering_actor_id" || fail_closed "triggering GitHub user ID $triggering_actor_id is not allowlisted"
jq -e \
--argjson repository_id 1170821064 \
--arg event_name "$EVENT_NAME" '
.repository.id == $repository_id and
.event == $event_name
' <<< "$run_json" >/dev/null 2>&1 \
|| fail_closed 'current workflow run does not match the expected repository event'
echo "runner=$aws_runner" >> "$GITHUB_OUTPUT"
echo '::notice title=AWS CI routing::Using an ephemeral RunsOn Fleet runner'
- name: Select stacked PR CI scope
id: scope
shell: bash
env:
STACK_JSON: ${{ toJSON(github.event.pull_request.stack) }}
PR_BASE_REF: ${{ github.event.pull_request.base.ref }}
run: |
set -euo pipefail
full_ci='true'
reason='ordinary pull request'
if jq -e 'type == "object"' <<< "$STACK_JSON" >/dev/null 2>&1; then
stack_position="$(jq -r '.position // empty' <<< "$STACK_JSON")"
stack_size="$(jq -r '.size // empty' <<< "$STACK_JSON")"
stack_base_ref="$(jq -r '.base.ref // empty' <<< "$STACK_JSON")"
if [[ ! "$stack_position" =~ ^[1-9][0-9]*$ ]] ||
[[ ! "$stack_size" =~ ^[1-9][0-9]*$ ]] ||
(( stack_position > stack_size )) ||
[[ -z "$stack_base_ref" ]]; then
reason='malformed stack metadata; defaulting to full CI'
elif (( stack_position == stack_size )); then
reason='top pull request in stack'
elif [[ "$stack_base_ref" == "$PR_BASE_REF" ]]; then
reason='lowest unmerged pull request in stack'
else
full_ci='false'
reason='middle pull request in stack'
fi
fi
echo "full_ci=$full_ci" >> "$GITHUB_OUTPUT"
echo "::notice title=Stacked PR CI scope::$reason; full_ci=$full_ci"
uses: paperclipai/paperclip/.github/workflows/ci-routing.yml@master
policy:
needs: [gate]
+3
View File
@@ -13,3 +13,6 @@ jobs:
# Master requires CODEOWNERS review for .github/**, including this workflow.
# The AWS runner group permits pr-trusted.yml@refs/heads/master.
uses: paperclipai/paperclip/.github/workflows/pr-trusted.yml@master
routing_probe:
if: github.head_ref == 'codex/reserve-ci-routing'
uses: paperclipai/paperclip/.github/workflows/ci-routing.yml@af977afd962875cbb05c581d05aa1f374aa2617e