From 8ff9dc699b1cee59eda7e15c3263d5f951f2aea1 Mon Sep 17 00:00:00 2001 From: Leo Fang Date: Tue, 7 Apr 2026 12:22:40 -0400 Subject: [PATCH 1/3] Fix race condition in PR metadata check workflow The workflow reads assignees, labels, and milestone from the event payload, which is a snapshot taken at trigger time. When a PR is opened, the `opened` event fires before labels/milestone/assignee are fully applied, causing the check to fail with stale data. Fix by fetching live PR data via `gh api` instead of relying on the event payload. The downstream validation logic is unchanged. --- .github/workflows/pr-metadata-check.yml | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/.github/workflows/pr-metadata-check.yml b/.github/workflows/pr-metadata-check.yml index d8cf91579d..733e39242c 100644 --- a/.github/workflows/pr-metadata-check.yml +++ b/.github/workflows/pr-metadata-check.yml @@ -25,10 +25,10 @@ jobs: steps: - name: Check for assignee, labels, and milestone env: - ASSIGNEES: ${{ toJson(github.event.pull_request.assignees) }} - LABELS: ${{ toJson(github.event.pull_request.labels) }} - MILESTONE: ${{ github.event.pull_request.milestone && github.event.pull_request.milestone.title || '' }} PR_URL: ${{ github.event.pull_request.html_url }} + PR_NUMBER: ${{ github.event.pull_request.number }} + GH_REPO: ${{ github.repository }} + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} IS_BOT: ${{ github.actor == 'dependabot[bot]' || github.actor == 'pre-commit-ci[bot]' || github.actor == 'copy-pr-bot[bot]' }} IS_DRAFT: ${{ github.event.pull_request.draft }} run: | @@ -37,6 +37,13 @@ jobs: exit 0 fi + # Fetch live PR data to avoid stale event payload (race condition + # when labels/milestone are added shortly after PR creation). + PR_JSON=$(gh api "repos/${GH_REPO}/pulls/${PR_NUMBER}") + ASSIGNEES=$(echo "$PR_JSON" | jq '.assignees') + LABELS=$(echo "$PR_JSON" | jq '.labels') + MILESTONE=$(echo "$PR_JSON" | jq -r '.milestone.title // empty') + ERRORS="" ASSIGNEE_COUNT=$(echo "$ASSIGNEES" | jq 'length') From ee3e7a8bc8959291124afce074a78fd0595fbb11 Mon Sep 17 00:00:00 2001 From: Leo Fang Date: Tue, 7 Apr 2026 13:09:14 -0400 Subject: [PATCH 2/3] Use --jq to filter gh api response to only needed fields Address review feedback: use gh's built-in --jq flag to extract only assignees, labels, and milestone from the API response, avoiding unnecessary processing of the full PR payload. --- .github/workflows/pr-metadata-check.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pr-metadata-check.yml b/.github/workflows/pr-metadata-check.yml index 733e39242c..15e4924383 100644 --- a/.github/workflows/pr-metadata-check.yml +++ b/.github/workflows/pr-metadata-check.yml @@ -39,10 +39,11 @@ jobs: # Fetch live PR data to avoid stale event payload (race condition # when labels/milestone are added shortly after PR creation). - PR_JSON=$(gh api "repos/${GH_REPO}/pulls/${PR_NUMBER}") + PR_JSON=$(gh api "repos/${GH_REPO}/pulls/${PR_NUMBER}" \ + --jq '{assignees: .assignees, labels: .labels, milestone: (.milestone.title // empty)}') ASSIGNEES=$(echo "$PR_JSON" | jq '.assignees') LABELS=$(echo "$PR_JSON" | jq '.labels') - MILESTONE=$(echo "$PR_JSON" | jq -r '.milestone.title // empty') + MILESTONE=$(echo "$PR_JSON" | jq -r '.milestone') ERRORS="" From f1850e071d59aaef42bfd6ed9094e4113992eacc Mon Sep 17 00:00:00 2001 From: Leo Fang Date: Tue, 7 Apr 2026 13:28:07 -0400 Subject: [PATCH 3/3] Use gh pr view instead of gh api for cleaner PR data fetch Address review feedback: use the higher-level `gh pr view` command with --json and --jq instead of constructing the raw API URL. --- .github/workflows/pr-metadata-check.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/pr-metadata-check.yml b/.github/workflows/pr-metadata-check.yml index 15e4924383..6f60ec45bf 100644 --- a/.github/workflows/pr-metadata-check.yml +++ b/.github/workflows/pr-metadata-check.yml @@ -39,7 +39,8 @@ jobs: # Fetch live PR data to avoid stale event payload (race condition # when labels/milestone are added shortly after PR creation). - PR_JSON=$(gh api "repos/${GH_REPO}/pulls/${PR_NUMBER}" \ + PR_JSON=$(gh pr view "${PR_NUMBER}" --repo "${GH_REPO}" \ + --json assignees,labels,milestone \ --jq '{assignees: .assignees, labels: .labels, milestone: (.milestone.title // empty)}') ASSIGNEES=$(echo "$PR_JSON" | jq '.assignees') LABELS=$(echo "$PR_JSON" | jq '.labels')