Skip to content

Commit 58fbedb

Browse files
authored
[codex] add test impact plan workflow (#794)
* add test impact plan workflow * Harden test impact plan comments * Use two-workflow test impact comments
1 parent b226396 commit 58fbedb

4 files changed

Lines changed: 753 additions & 0 deletions

File tree

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
name: test-impact-plan-comment
2+
3+
on:
4+
workflow_run:
5+
workflows: ["test-impact-plan"]
6+
types: [completed]
7+
8+
permissions:
9+
contents: read
10+
issues: write
11+
pull-requests: read
12+
13+
concurrency:
14+
group: test-impact-plan-comment-${{ github.event.workflow_run.head_repository.full_name }}-${{ github.event.workflow_run.head_branch }}
15+
cancel-in-progress: true
16+
17+
jobs:
18+
comment:
19+
if: github.event.workflow_run.event == 'pull_request' && github.event.workflow_run.conclusion == 'success'
20+
runs-on: ubuntu-24.04-arm
21+
timeout-minutes: 5
22+
steps:
23+
- name: Checkout trusted default branch
24+
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
25+
with:
26+
ref: ${{ github.event.repository.default_branch }}
27+
fetch-depth: 1
28+
persist-credentials: false
29+
30+
- name: Resolve pull request context
31+
id: context
32+
env:
33+
GH_TOKEN: ${{ github.token }}
34+
REPOSITORY: ${{ github.repository }}
35+
RUN_HEAD_SHA: ${{ github.event.workflow_run.head_sha }}
36+
TARGET_BRANCH: ${{ github.event.repository.default_branch }}
37+
run: |
38+
set -euo pipefail
39+
pr_count="$(jq -r '.workflow_run.pull_requests | length' "$GITHUB_EVENT_PATH")"
40+
if [ "$pr_count" != "1" ]; then
41+
echo "Expected one pull request context, found $pr_count."
42+
echo "current=false" >> "$GITHUB_OUTPUT"
43+
exit 0
44+
fi
45+
46+
pr_number="$(jq -r '.workflow_run.pull_requests[0].number // empty' "$GITHUB_EVENT_PATH")"
47+
if [ -z "$pr_number" ]; then
48+
echo "No pull request context found for workflow run."
49+
echo "current=false" >> "$GITHUB_OUTPUT"
50+
exit 0
51+
fi
52+
53+
pr_json=/tmp/test-impact-pr.json
54+
gh api "repos/$REPOSITORY/pulls/$pr_number" > "$pr_json"
55+
head_sha="$(jq -r '.head.sha' "$pr_json")"
56+
state="$(jq -r '.state' "$pr_json")"
57+
base_repo="$(jq -r '.base.repo.full_name' "$pr_json")"
58+
base_ref="$(jq -r '.base.ref' "$pr_json")"
59+
changed_files="$(jq -r '.changed_files' "$pr_json")"
60+
61+
if [ "$state" != "open" ]; then
62+
echo "Skipping PR #$pr_number because it is $state."
63+
echo "current=false" >> "$GITHUB_OUTPUT"
64+
exit 0
65+
fi
66+
67+
if [ "$base_repo" != "$REPOSITORY" ] || [ "$base_ref" != "$TARGET_BRANCH" ]; then
68+
echo "Skipping PR #$pr_number targeting $base_repo:$base_ref."
69+
echo "current=false" >> "$GITHUB_OUTPUT"
70+
exit 0
71+
fi
72+
73+
if [ "$head_sha" != "$RUN_HEAD_SHA" ]; then
74+
echo "Skipping stale workflow run for $RUN_HEAD_SHA; current PR head is $head_sha."
75+
echo "current=false" >> "$GITHUB_OUTPUT"
76+
exit 0
77+
fi
78+
79+
echo "current=true" >> "$GITHUB_OUTPUT"
80+
echo "pr_number=$pr_number" >> "$GITHUB_OUTPUT"
81+
echo "changed_files=$changed_files" >> "$GITHUB_OUTPUT"
82+
83+
- name: Generate test impact plan
84+
if: steps.context.outputs.current == 'true'
85+
env:
86+
GH_TOKEN: ${{ github.token }}
87+
PR_NUMBER: ${{ steps.context.outputs.pr_number }}
88+
REPOSITORY: ${{ github.repository }}
89+
CHANGED_FILES: ${{ steps.context.outputs.changed_files }}
90+
run: |
91+
set -euo pipefail
92+
gh api "repos/$REPOSITORY/pulls/$PR_NUMBER/files?per_page=100" \
93+
--paginate \
94+
--slurp \
95+
> /tmp/test-impact-pr-files.json
96+
97+
python3 scripts/test_impact_plan.py \
98+
--github-pr-files-json /tmp/test-impact-pr-files.json \
99+
--expected-file-count "$CHANGED_FILES" \
100+
--markdown-output /tmp/test-impact-plan.md \
101+
--json-output /tmp/test-impact-plan.json
102+
103+
cat /tmp/test-impact-plan.md >> "$GITHUB_STEP_SUMMARY"
104+
105+
- name: Comment on pull request
106+
if: steps.context.outputs.current == 'true'
107+
env:
108+
GH_TOKEN: ${{ github.token }}
109+
PR_NUMBER: ${{ steps.context.outputs.pr_number }}
110+
REPOSITORY: ${{ github.repository }}
111+
run: |
112+
set -euo pipefail
113+
marker="<!-- test-impact-plan -->"
114+
body_file=/tmp/test-impact-plan-comment.md
115+
{
116+
echo "$marker"
117+
cat /tmp/test-impact-plan.md
118+
} > "$body_file"
119+
120+
existing_id="$(
121+
gh api "repos/$REPOSITORY/issues/$PR_NUMBER/comments" --paginate \
122+
--jq '.[] | select(.user.login == "github-actions[bot]" and (.body | startswith("<!-- test-impact-plan -->"))) | .id' \
123+
| tail -n 1
124+
)"
125+
126+
if [ -n "$existing_id" ]; then
127+
gh api "repos/$REPOSITORY/issues/comments/$existing_id" \
128+
-X PATCH \
129+
-F "body=@$body_file" >/dev/null
130+
else
131+
gh api "repos/$REPOSITORY/issues/$PR_NUMBER/comments" \
132+
-F "body=@$body_file" >/dev/null
133+
fi
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
name: test-impact-plan
2+
3+
on:
4+
pull_request:
5+
branches: [main]
6+
types: [opened, synchronize, reopened, ready_for_review]
7+
8+
permissions:
9+
contents: read
10+
11+
concurrency:
12+
group: test-impact-plan-${{ github.event.pull_request.number }}
13+
cancel-in-progress: true
14+
15+
jobs:
16+
trigger:
17+
runs-on: ubuntu-24.04-arm
18+
timeout-minutes: 5
19+
steps:
20+
- name: Record trigger
21+
run: |
22+
{
23+
echo "## Test Impact Plan"
24+
echo
25+
echo "A follow-up workflow posts the sticky PR comment after this run completes."
26+
} >> "$GITHUB_STEP_SUMMARY"

justfile

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,11 @@ test-configstore-integration:
288288
test-controlplane-k8s:
289289
go test -v -count=1 -tags kubernetes ./controlplane ./controlplane/admin ./controlplane/provisioner
290290

291+
# Print the test impact plan for the current branch
292+
[group('test')]
293+
test-impact-plan base="origin/main" head="HEAD":
294+
python3 scripts/test_impact_plan.py --base {{base}} --head {{head}}
295+
291296
# Run Kubernetes integration tests against the default kind-backed multitenant setup
292297
[group('test')]
293298
test-k8s-integration:

0 commit comments

Comments
 (0)