From 4c8902d608f0515b635c6d9a5abb5b6062d151a8 Mon Sep 17 00:00:00 2001 From: MichaelFisher1997 Date: Sat, 11 Apr 2026 15:09:50 +0100 Subject: [PATCH 1/4] fix(ci): find PR by author instead of branch name for downstream triggers The opencode action auto-creates branches with names like opencode/schedule-XXX, not test/MODULE. The old trigger step searched for PRs by branch name which never matched. Now finds the PR by PAT author, labels it, then triggers build and review workflows. --- .github/workflows/opencode-test-writer.yml | 34 ++++++++++++++++------ 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/.github/workflows/opencode-test-writer.yml b/.github/workflows/opencode-test-writer.yml index 46be2cf0..3e528282 100644 --- a/.github/workflows/opencode-test-writer.yml +++ b/.github/workflows/opencode-test-writer.yml @@ -226,20 +226,36 @@ jobs: 5. Commit your changes: `git add` and `git commit` with message `test: add {area} tests for ${{ steps.select-module.outputs.module }}` 6. STOP. Do not push or create a PR. - - name: Trigger downstream workflows + - name: Find and label created PR if: steps.check-existing.outputs.skip != 'true' + id: find-pr run: | sleep 5 - BRANCH="${{ steps.select-module.outputs.branch }}" - PR_NUM=$(gh pr list --base dev --head "$BRANCH" --label automated-test --state open --json number --jq '.[0].number') + PAT_USER=$(gh api user --jq '.login') + PR_NUM=$(gh pr list \ + --base dev \ + --state open \ + --limit 10 \ + --json number,createdAt,author \ + --jq "[.[] | select(.author.login == \"${PAT_USER}\")] | sort_by(.createdAt) | reverse | .[0].number") if [ -n "$PR_NUM" ]; then - echo "Triggering Build and opencode review for PR #$PR_NUM" - SHA=$(gh api repos/OpenStaticFish/ZigCraft/pulls/$PR_NUM --jq '.head.sha') - BRANCH=$(gh api repos/OpenStaticFish/ZigCraft/pulls/$PR_NUM --jq '.head.ref') - gh workflow run build.yml --field ref="$BRANCH" || echo "Build trigger attempted" - gh workflow run opencode-pr.yml --field pr_number="$PR_NUM" --field head_sha="$SHA" + echo "Found newly created PR #$PR_NUM (author: ${PAT_USER})" + gh pr edit "$PR_NUM" --add-label "automated-test" + echo "pr_number=${PR_NUM}" >> "$GITHUB_OUTPUT" else - echo "No PR found to trigger workflows" + echo "No PR found authored by ${PAT_USER}" fi env: GH_TOKEN: ${{ secrets.OPENCODE_PAT }} + + - name: Trigger downstream workflows + if: steps.find-pr.outputs.pr_number != '' + run: | + PR_NUM="${{ steps.find-pr.outputs.pr_number }}" + echo "Triggering Build and opencode review for PR #$PR_NUM" + SHA=$(gh api repos/OpenStaticFish/ZigCraft/pulls/$PR_NUM --jq '.head.sha') + BRANCH=$(gh api repos/OpenStaticFish/ZigCraft/pulls/$PR_NUM --jq '.head.ref') + gh workflow run build.yml --field ref="$BRANCH" || echo "Build trigger attempted" + gh workflow run opencode-pr.yml --field pr_number="$PR_NUM" --field head_sha="$SHA" + env: + GH_TOKEN: ${{ secrets.OPENCODE_PAT }} From 1faf6954320b8fc104cf7a07db169f8578a173ea Mon Sep 17 00:00:00 2001 From: MichaelFisher1997 Date: Sat, 11 Apr 2026 15:33:20 +0100 Subject: [PATCH 2/4] fix(ci): add retry loop with backoff for PR discovery Replace fragile sleep 5 with up to 5 retries at increasing intervals (3s, 6s, 9s, 12s, 15s) to handle GitHub API latency. --- .github/workflows/opencode-test-writer.yml | 23 ++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/.github/workflows/opencode-test-writer.yml b/.github/workflows/opencode-test-writer.yml index 3e528282..7f83b78d 100644 --- a/.github/workflows/opencode-test-writer.yml +++ b/.github/workflows/opencode-test-writer.yml @@ -230,20 +230,27 @@ jobs: if: steps.check-existing.outputs.skip != 'true' id: find-pr run: | - sleep 5 PAT_USER=$(gh api user --jq '.login') - PR_NUM=$(gh pr list \ - --base dev \ - --state open \ - --limit 10 \ - --json number,createdAt,author \ - --jq "[.[] | select(.author.login == \"${PAT_USER}\")] | sort_by(.createdAt) | reverse | .[0].number") + PR_NUM="" + for i in 1 2 3 4 5; do + sleep $((i * 3)) + echo "Attempt $i: searching for PR by ${PAT_USER}..." + PR_NUM=$(gh pr list \ + --base dev \ + --state open \ + --limit 10 \ + --json number,createdAt,author \ + --jq "[.[] | select(.author.login == \"${PAT_USER}\")] | sort_by(.createdAt) | reverse | .[0].number") + if [ -n "$PR_NUM" ]; then + break + fi + done if [ -n "$PR_NUM" ]; then echo "Found newly created PR #$PR_NUM (author: ${PAT_USER})" gh pr edit "$PR_NUM" --add-label "automated-test" echo "pr_number=${PR_NUM}" >> "$GITHUB_OUTPUT" else - echo "No PR found authored by ${PAT_USER}" + echo "No PR found authored by ${PAT_USER} after 5 attempts" fi env: GH_TOKEN: ${{ secrets.OPENCODE_PAT }} From d31a00353f5f66aa4f3fe14d4726f59efc6c3b8e Mon Sep 17 00:00:00 2001 From: MichaelFisher1997 Date: Sat, 11 Apr 2026 15:39:26 +0100 Subject: [PATCH 3/4] fix(ci): extend PR discovery retry budget to 8 attempts (~108s max) --- .github/workflows/opencode-test-writer.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/opencode-test-writer.yml b/.github/workflows/opencode-test-writer.yml index 7f83b78d..b3501319 100644 --- a/.github/workflows/opencode-test-writer.yml +++ b/.github/workflows/opencode-test-writer.yml @@ -230,9 +230,11 @@ jobs: if: steps.check-existing.outputs.skip != 'true' id: find-pr run: | + # Retry budget: 8 attempts, 3s/6s/9s/12s/15s/18s/21s/24s = ~108s max wait. + # Increase max attempts if GitHub API latency during incidents exceeds this window. PAT_USER=$(gh api user --jq '.login') PR_NUM="" - for i in 1 2 3 4 5; do + for i in 1 2 3 4 5 6 7 8; do sleep $((i * 3)) echo "Attempt $i: searching for PR by ${PAT_USER}..." PR_NUM=$(gh pr list \ @@ -250,7 +252,7 @@ jobs: gh pr edit "$PR_NUM" --add-label "automated-test" echo "pr_number=${PR_NUM}" >> "$GITHUB_OUTPUT" else - echo "No PR found authored by ${PAT_USER} after 5 attempts" + echo "No PR found authored by ${PAT_USER} after 8 attempts" fi env: GH_TOKEN: ${{ secrets.OPENCODE_PAT }} From f7a8eba3d6231004466554e659cfd8c07e9e53d5 Mon Sep 17 00:00:00 2001 From: MichaelFisher1997 Date: Sat, 11 Apr 2026 15:57:04 +0100 Subject: [PATCH 4/4] fix(ci): extract base_branch output, guard label failure, configurable retries - Add base_branch output to select-module step, replace all hardcoded dev and github.event.repository.default_branch references - Extract MAX_RETRIES variable for single-point adjustment - Guard gh pr edit failure with warning annotation --- .github/workflows/opencode-test-writer.yml | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/.github/workflows/opencode-test-writer.yml b/.github/workflows/opencode-test-writer.yml index b3501319..ed8124e4 100644 --- a/.github/workflows/opencode-test-writer.yml +++ b/.github/workflows/opencode-test-writer.yml @@ -77,6 +77,7 @@ jobs: BRANCH_NAME="test/$(echo "${SELECTED}" | tr '/' '-')" echo "module=${SELECTED}" >> "$GITHUB_OUTPUT" echo "branch=${BRANCH_NAME}" >> "$GITHUB_OUTPUT" + echo "base_branch=${{ github.event.repository.default_branch }}" >> "$GITHUB_OUTPUT" case "$SELECTED" in graphics/vulkan-device) @@ -135,7 +136,7 @@ jobs: - name: Checkout repository uses: actions/checkout@v4 with: - ref: ${{ github.event.repository.default_branch }} + ref: ${{ steps.select-module.outputs.base_branch }} fetch-depth: 0 token: ${{ secrets.OPENCODE_PAT }} @@ -154,7 +155,7 @@ jobs: run: | MODULE="${{ steps.select-module.outputs.module }}" EXISTING=$(gh pr list \ - --base ${{ github.event.repository.default_branch }} \ + --base ${{ steps.select-module.outputs.base_branch }} \ --label "automated-test" \ --state open \ --limit 20 \ @@ -230,15 +231,15 @@ jobs: if: steps.check-existing.outputs.skip != 'true' id: find-pr run: | - # Retry budget: 8 attempts, 3s/6s/9s/12s/15s/18s/21s/24s = ~108s max wait. - # Increase max attempts if GitHub API latency during incidents exceeds this window. + BASE="${{ steps.select-module.outputs.base_branch }}" + MAX_RETRIES=8 PAT_USER=$(gh api user --jq '.login') PR_NUM="" - for i in 1 2 3 4 5 6 7 8; do + for i in $(seq 1 "$MAX_RETRIES"); do sleep $((i * 3)) - echo "Attempt $i: searching for PR by ${PAT_USER}..." + echo "Attempt $i/$MAX_RETRIES: searching for PR by ${PAT_USER} targeting ${BASE}..." PR_NUM=$(gh pr list \ - --base dev \ + --base "$BASE" \ --state open \ --limit 10 \ --json number,createdAt,author \ @@ -249,10 +250,12 @@ jobs: done if [ -n "$PR_NUM" ]; then echo "Found newly created PR #$PR_NUM (author: ${PAT_USER})" - gh pr edit "$PR_NUM" --add-label "automated-test" + if ! gh pr edit "$PR_NUM" --add-label "automated-test" 2>/dev/null; then + echo "::warning::Failed to add automated-test label to PR #$PR_NUM" + fi echo "pr_number=${PR_NUM}" >> "$GITHUB_OUTPUT" else - echo "No PR found authored by ${PAT_USER} after 8 attempts" + echo "No PR found authored by ${PAT_USER} after $MAX_RETRIES attempts" fi env: GH_TOKEN: ${{ secrets.OPENCODE_PAT }}