Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 10 additions & 5 deletions .github/workflows/copilot-review-refresh.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,13 @@ jobs:
github.event.pull_request.draft == false &&
github.event.pull_request.head.repo.full_name == github.repository &&
(
github.actor == 'copilot-pull-request-reviewer' ||
github.actor == 'copilot-pull-request-reviewer[bot]' ||
(
contains(fromJSON('["Copilot","copilot-pull-request-reviewer","copilot-pull-request-reviewer[bot]"]'), github.actor) &&
(
github.event.review.user.login == 'copilot-pull-request-reviewer[bot]' ||
github.event.comment.user.login == 'copilot-pull-request-reviewer[bot]'
)
) ||
contains(fromJSON('["COLLABORATOR","MEMBER","OWNER"]'), github.event.review.author_association) ||
contains(fromJSON('["COLLABORATOR","MEMBER","OWNER"]'), github.event.comment.author_association)
)
Expand All @@ -40,7 +45,7 @@ jobs:
timeout-minutes: 5

steps:
- name: Rerun the canonical pull request gate when needed
- name: Rerun the canonical protected gate when needed
env:
GH_TOKEN: ${{ github.token }}
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
Expand All @@ -51,7 +56,7 @@ jobs:
runs_url="repos/${REPOSITORY}/actions/runs"

for attempt in $(seq 1 10); do
response="$(gh api "${runs_url}?event=pull_request&head_sha=${HEAD_SHA}&per_page=100")"
response="$(gh api "${runs_url}?event=pull_request_target&head_sha=${HEAD_SHA}&per_page=100")"
run="$(
jq -c --arg head_sha "${HEAD_SHA}" --argjson pr "${PR_NUMBER}" '
[
Expand Down Expand Up @@ -82,5 +87,5 @@ jobs:
sleep 6
done

echo "No canonical pull_request gate found for PR #${PR_NUMBER} at ${HEAD_SHA}." >&2
echo "No canonical pull_request_target gate found for PR #${PR_NUMBER} at ${HEAD_SHA}." >&2
exit 1
776 changes: 458 additions & 318 deletions .github/workflows/copilot-review.yml

Large diffs are not rendered by default.

202 changes: 202 additions & 0 deletions .github/workflows/current-revision-rerun.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,202 @@
# Protected helper: it can rerun only the single verifier reservation bound to
# the exact live PR head, and only once after a neutral PASS exists.
# yamllint disable rule:truthy rule:line-length
---
name: Re-evaluate protected current-revision evidence

on:
workflow_dispatch:
inputs:
pr_number:
description: Pull request whose protected verifier must be re-evaluated
required: true
type: number
expected_base:
description: Frozen pull-request base SHA
required: true
type: string
expected_head:
description: Frozen pull-request head SHA
required: true
type: string

permissions:
contents: read

jobs:
rerun-protected-verifier:
name: Re-run the one protected verifier attempt
permissions:
actions: write
checks: read
contents: read
pull-requests: read
runs-on: ubuntu-latest
timeout-minutes: 5

steps:
- name: Validate the live binding and rerun exactly once
env:
EXPECTED_BASE: ${{ inputs.expected_base }}
EXPECTED_HEAD: ${{ inputs.expected_head }}
GH_TOKEN: ${{ github.token }}
PR_NUMBER: ${{ inputs.pr_number }}
REPOSITORY: ${{ github.repository }}
run: |
set -euo pipefail
test "${GITHUB_REF}" = refs/heads/develop
[[ "${EXPECTED_BASE}" =~ ^[0-9a-f]{40}$ ]]
[[ "${EXPECTED_HEAD}" =~ ^[0-9a-f]{40}$ ]]
[[ "${PR_NUMBER}" =~ ^[1-9][0-9]*$ ]]
pr="$(gh api "repos/${REPOSITORY}/pulls/${PR_NUMBER}")"
jq -e \
--arg base "${EXPECTED_BASE}" \
--arg head "${EXPECTED_HEAD}" \
--arg repository "${REPOSITORY}" '
.state == "open"
and .draft == false
and .base.sha == $base
and .head.sha == $head
and .base.repo.full_name == $repository
and .head.repo.full_name == $repository
and (.base.ref == "develop" or .base.ref == "main")
' <<<"${pr}" >/dev/null

neutral_pages="$(gh api --paginate --slurp \
"repos/${REPOSITORY}/commits/${EXPECTED_HEAD}/check-runs?check_name=Current%20revision%20review&per_page=100")"
neutral="$(jq -c '
[.[].check_runs[]? |
select(.name == "Current revision review") |
select(.app.id == 15368 and .app.slug == "github-actions") |
select(.status == "completed" and .conclusion == "success")]
' <<<"${neutral_pages}")"
test "$(jq 'length' <<<"${neutral}")" -eq 1
neutral_check_id="$(jq -er '.[0].id | select(type == "number" and . > 0)' <<<"${neutral}")"
neutral_details_url="$(jq -r '.[0].details_url // empty' <<<"${neutral}")"
test "${neutral_details_url}" = "${GITHUB_SERVER_URL}/${REPOSITORY}/runs/${neutral_check_id}"
neutral_external_id="$(jq -er '.[0].external_id | select(type == "string" and length > 0)' <<<"${neutral}")"
neutral_summary="$(jq -er '.[0].output.summary | fromjson | select(type == "object")' <<<"${neutral}")"
producer_id="$(jq -er '.producer_run_id | select(type == "number" and . > 0)' <<<"${neutral_summary}")"
producer_url="$(jq -er '.run_url | select(type == "string" and length > 0)' <<<"${neutral_summary}")"
producer_prefix="${GITHUB_SERVER_URL}/${REPOSITORY}/actions/runs/"
test "${producer_url}" = "${producer_prefix}${producer_id}"
author="$(jq -er '.user.login | select(type == "string" and length > 0)' <<<"${pr}")"
base_ref="$(jq -er '.base.ref | select(. == "develop" or . == "main")' <<<"${pr}")"
head_ref="$(jq -er '.head.ref | select(type == "string" and length > 0)' <<<"${pr}")"
jq -e \
--arg base "${EXPECTED_BASE}" \
--arg head "${EXPECTED_HEAD}" \
--arg run_url "${producer_url}" \
--argjson run_id "${producer_id}" '
.schema == 4
and .base_sha == $base
and .head_sha == $head
and .producer_run_id == $run_id
and .run_url == $run_url
' <<<"${neutral_summary}" >/dev/null
for attempt in 1 2 3 4 5 6 7 8 9 10; do
producer="$(gh api "repos/${REPOSITORY}/actions/runs/${producer_id}")"
if [ "$(jq -r .status <<<"${producer}")" = completed ]; then
test "$(jq -r .conclusion <<<"${producer}")" = success
break
fi
test "${attempt}" -lt 10
sleep 2
done
if [ "${author}" = 'lightning-it-release-automation[bot]' ]; then
[[ "${neutral_external_id}" =~ ^mlx90-current-revision:v4:${producer_id}:[0-9a-f]{64}$ ]]
expected_title="Exact-Revision Codex PR #${PR_NUMBER} ${EXPECTED_BASE}..${EXPECTED_HEAD}"
jq -e \
--arg actor "${author}" \
--arg base_ref "${base_ref}" \
--arg base_sha "${EXPECTED_BASE}" \
--arg run_url "${producer_url}" \
--arg title "${expected_title}" '
.event == "workflow_dispatch"
and .path == ".github/workflows/release-bot-exact-head-review.yml"
and .display_title == $title
and .head_branch == $base_ref
and .head_sha == $base_sha
and .html_url == $run_url
and .actor.login == $actor
and .triggering_actor.login == $actor
' <<<"${producer}" >/dev/null
else
test "${neutral_external_id}" = "mlx90-current-revision:copilot:v5:${producer_id}:${EXPECTED_BASE}:${EXPECTED_HEAD}"
controller_sha="$(jq -er '.controller_sha | select(type == "string" and test("^[0-9a-f]{40}$"))' \
<<<"${neutral_summary}")"
default_branch="$(gh api "repos/${REPOSITORY}" --jq .default_branch)"
test "${default_branch}" = develop
default_head="$(gh api "repos/${REPOSITORY}/branches/${default_branch}" --jq .commit.sha)"
controller_ancestry="$(gh api \
"repos/${REPOSITORY}/compare/${controller_sha}...${default_head}")"
jq -e \
--arg controller "${controller_sha}" '
.status == "identical"
or (.status == "ahead" and .behind_by == 0
and .merge_base_commit.sha == $controller)
' <<<"${controller_ancestry}" >/dev/null
jq -e \
--arg actor "${author}" \
--arg head_ref "${head_ref}" \
--arg head_sha "${EXPECTED_HEAD}" \
--arg run_url "${producer_url}" '
.event == "pull_request_target"
and .path == ".github/workflows/copilot-review.yml"
and .name == "Current revision review gate"
and .head_branch == $head_ref
and .head_sha == $head_sha
and .html_url == $run_url
and .actor.login == $actor
and .triggering_actor.login == $actor
' <<<"${producer}" >/dev/null
fi

reservations_pages="$(gh api --paginate --slurp \
"repos/${REPOSITORY}/commits/${EXPECTED_HEAD}/check-runs?check_name=Protected%20current-revision%20verifier&per_page=100")"
reservations="$(jq -c \
--arg head "${EXPECTED_HEAD}" \
--arg prefix "rep60-required-workflow:v2:" \
--arg suffix ":${PR_NUMBER}:${EXPECTED_HEAD}" '
[.[].check_runs[]? |
select(.name == "Protected current-revision verifier") |
select(.app.id == 15368 and .app.slug == "github-actions") |
select(.head_sha == $head) |
select((.external_id | type) == "string") |
select(.external_id | startswith($prefix) and endswith($suffix))]
' <<<"${reservations_pages}")"
test "$(jq 'length' <<<"${reservations}")" -eq 1
reservation_id="$(jq -er '.[0].id | select(type == "number" and . > 0)' <<<"${reservations}")"
reservation_url="$(jq -r '.[0].details_url // empty' <<<"${reservations}")"
test "${reservation_url}" = "${GITHUB_SERVER_URL}/${REPOSITORY}/runs/${reservation_id}"
reservation_external_id="$(jq -er '.[0].external_id | select(type == "string" and length > 0)' <<<"${reservations}")"
[[ "${reservation_external_id}" =~ ^rep60-required-workflow:v2:([1-9][0-9]*):${PR_NUMBER}:${EXPECTED_HEAD}$ ]]
run_id="${BASH_REMATCH[1]}"
verifier_run_url="${GITHUB_SERVER_URL}/${REPOSITORY}/actions/runs/${run_id}"
run="$(gh api "repos/${REPOSITORY}/actions/runs/${run_id}")"
jq -e \
--arg api_url "${GITHUB_API_URL}" \
--arg actor "${author}" \
--arg head_ref "${head_ref}" \
--arg head_sha "${EXPECTED_HEAD}" \
--arg repository "${REPOSITORY}" \
--arg run_url "${verifier_run_url}" '
.event == "pull_request_target"
and .path == ".github/workflows/supplementary-current-revision-required.yml"
and (.workflow_id | type == "number" and . > 0)
and .workflow_url == ($api_url + "/repos/" + $repository
+ "/actions/required_workflows/" + (.workflow_id | tostring))
and .head_branch == $head_ref
and .head_sha == $head_sha
and .html_url == $run_url
and .actor.login == $actor
and .triggering_actor.login == $actor
and .status == "completed"
' <<<"${run}" >/dev/null
if [ "$(jq -r .conclusion <<<"${run}")" = success ]; then
echo "Protected verifier already passed; no rerun is needed."
exit 0
fi
test "$(jq -r .conclusion <<<"${run}")" = failure
test "$(jq -r .run_attempt <<<"${run}")" -eq 1
gh api --method POST "repos/${REPOSITORY}/actions/runs/${run_id}/rerun" >/dev/null
26 changes: 3 additions & 23 deletions .github/workflows/release-bot-exact-head-review.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ concurrency:
# the full binary diff, protected prompt, and protected schema.
jobs:
exact-revision-codex-review:
name: Protected Exact-Revision Codex review
name: Current revision review
if: >-
github.event_name == 'workflow_dispatch' &&
github.actor == 'lightning-it-release-automation[bot]'
Expand Down Expand Up @@ -371,19 +371,15 @@ jobs:
named="$(jq -c \
--arg name "${check_name}" \
'[.[].check_runs[]? |
select(.name == $name)]' \
select(.name == $name) |
select(.app.id == 15368 and .app.slug == "github-actions")]' \
<<<"${checks}")"
count="$(jq 'length' <<<"${named}")"
if [ "${count}" -gt 1 ]; then
echo "Multiple ${check_name} checks exist for this head." >&2
exit 1
fi
if [ "${count}" -eq 1 ]; then
if ! jq -e '.[0].app.id == 15368 and .[0].app.slug == "github-actions"' \
<<<"${named}" >/dev/null; then
echo "${check_name} exists under an unauthorized GitHub App." >&2
exit 1
fi
check_id="$(jq -er '.[0].id | select(type == "number" and . > 0)' <<<"${named}")"
check_url="${GITHUB_SERVER_URL}/${REPOSITORY}/runs/${check_id}"
current_external_id="$(jq -r '.[0].external_id // empty' <<<"${named}")"
Expand Down Expand Up @@ -416,14 +412,12 @@ jobs:
return
fi
jq -e \
--arg check_name "${check_name}" \
--arg evidence "${evidence}" \
--arg external_id "${external_id}" \
--arg head "${EXPECTED_HEAD}" \
--arg url "${check_url}" \
--argjson check_id "${check_id}" '
.[0].id == $check_id
and .[0].name == $check_name
and .[0].app.id == 15368
and .[0].app.slug == "github-actions"
and .[0].head_sha == $head
Expand All @@ -448,14 +442,12 @@ jobs:
created="$(gh api --method PATCH "repos/${REPOSITORY}/check-runs/${check_id}" \
-f "details_url=${check_url}")"
jq -e \
--arg check_name "${check_name}" \
--arg evidence "${evidence}" \
--arg external_id "${external_id}" \
--arg head "${EXPECTED_HEAD}" \
--arg url "${check_url}" \
--argjson check_id "${check_id}" '
.id == $check_id
and .name == $check_name
and .app.id == 15368
and .app.slug == "github-actions"
and .head_sha == $head
Expand All @@ -470,18 +462,6 @@ jobs:
'Current revision review' \
"mlx90-current-revision:v4:${producer_run_id}:${input_sha256}" \
'Protected Exact-Revision Codex review passed'
# One-time compatibility alias for protected Shared Assets promotion
# PR #1047. It is derived from this same Codex PASS and never starts a
# second reviewer. The develop version replaces this bootstrap file
# during the promotion, removing the legacy Copilot-named context.
if [ "${REPOSITORY}" = lightning-it/shared-assets-lit ] \
&& [ "${PR_NUMBER}" = 1047 ] \
&& [ "${BASE_REF}" = main ]; then
publish_once \
'Successful Copilot review' \
"mlx90-legacy-transition:v4:${producer_run_id}:${input_sha256}" \
'Exact-Revision Codex PASS (temporary legacy context; no Copilot)'
fi

request-protected-verifier-reevaluation:
name: Request protected verifier re-evaluation
Expand Down
10 changes: 5 additions & 5 deletions .lit/push-ready.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
{
"id": "copilot-current-head-review",
"workflow": ".github/workflows/copilot-review.yml",
"job": "current-revision-reviewed",
"job": "verify-current-revision-policy",
"reason": "The authoritative Copilot pull-request review is produced and bound to the current head SHA by GitHub.",
"owner": "Lightning IT Application Platform Maintainers"
}
Expand All @@ -31,14 +31,14 @@
},
"agents": {
"copilot": {
"enabled": true,
"required": true,
"enabled": false,
"required": false,
"command": ["copilot"],
"timeout_seconds": 600
},
"codex": {
"enabled": true,
"required": true,
"enabled": false,
"required": false,
"command": ["codex"],
"timeout_seconds": 900
}
Expand Down
Loading
Loading