From 88e7747d2f84d05dc97db7600db5c130935731ba Mon Sep 17 00:00:00 2001 From: Vlad Mocanu Date: Fri, 27 Feb 2026 13:12:35 +0200 Subject: [PATCH] fix: use bot token for issue creation and link PRs to tracking issues Three fixes in the upstream-sync workflow: 1. Replace github.token with CLAUDE_BOT_TOKEN in the check-upstream job. The default runner token on Forgejo doesn't have issue-write permissions, so issues were silently failing to create. 2. Output the tracking issue number from check-upstream and pass it to the merge-upstream job. Claude's prompt now includes the issue reference and instructs it to add "Closes #N" in the PR body. 3. Capture the issue number from both create and update paths so the merge job always has it available. Also cleaned up 6 duplicate upstream-sync labels created by previous runs that used the unprivileged token. Co-Authored-By: Claude Opus 4.6 --- .forgejo/kcl-ci/main.k | 22 +++++++++++++++------- .forgejo/workflows/upstream-sync.yml | 21 ++++++++++++++------- 2 files changed, 29 insertions(+), 14 deletions(-) diff --git a/.forgejo/kcl-ci/main.k b/.forgejo/kcl-ci/main.k index 8c0f217..dd02c93 100644 --- a/.forgejo/kcl-ci/main.k +++ b/.forgejo/kcl-ci/main.k @@ -232,6 +232,7 @@ _claude_action_url = h.gha_action_url("actions", "claude-code-action", versions. _merge_branch_ref = h.gha_steps("prepare", "branch") _merge_behind_ref = h.gha_needs("check-upstream", "behind") _merge_ahead_ref = h.gha_needs("check-upstream", "ahead") +_merge_issue_ref = h.gha_needs("check-upstream", "issue_number") _merge_clean_ref = h.gha_steps("prepare", "merge_clean") _merge_affected_ref = h.gha_steps("prepare", "affected_files") @@ -241,6 +242,7 @@ You are automating an upstream sync for our Forgejo fork of anthropics/claude-co ## Current state - Branch: ${_merge_branch_ref} - ${_merge_behind_ref} commits behind upstream, ${_merge_ahead_ref} commits ahead (our Forgejo changes) +- Tracking issue: #${_merge_issue_ref} - Merge was attempted. Status: ${_merge_clean_ref} (true = clean, false = has conflicts) ## Impact analysis @@ -276,6 +278,7 @@ The fewer upstream files we modify, the fewer conflicts in the next sync. Auth: token ${"$"}GITHUB_TOKEN Title: "chore: merge ${_merge_behind_ref} upstream commits from anthropics/claude-code-action" Body should include: + - "Closes #${_merge_issue_ref}" on its own line (links PR to the tracking issue) - Summary of notable upstream changes - Impact assessment: which fork files (if any) were affected - List of conflicts resolved (if any) @@ -301,6 +304,7 @@ _upstream_sync_workflow = { needs_sync = h.gha_steps("compare", "needs_sync") behind = h.gha_steps("compare", "behind") ahead = h.gha_steps("compare", "ahead") + issue_number = h.gha_steps("sync-issue", "issue_number") } steps = [ checkout_mod.checkout() | {"with" = {"fetch-depth" = "0"}} @@ -360,7 +364,7 @@ fi""" id = "existing" run = """\ RESPONSE=${"$"}(curl -s \\ - -H "Authorization: token ${h.gha_github("token")}" \\ + -H "Authorization: token ${h.gha_secret("CLAUDE_BOT_TOKEN")}" \\ -H "Content-Type: application/json" \\ "${h.gha_env("GITHUB_API_URL")}/repos/${h.gha_github("repository")}/issues?state=open&labels=upstream-sync&limit=1") @@ -382,7 +386,7 @@ fi""" run = """\ curl -s -o /dev/null -w "%{http_code}" \\ -X POST \\ - -H "Authorization: token ${h.gha_github("token")}" \\ + -H "Authorization: token ${h.gha_secret("CLAUDE_BOT_TOKEN")}" \\ -H "Content-Type: application/json" \\ -d '{"name":"upstream-sync","color":"#0075ca","description":"Upstream sync tracking"}' \\ "${h.gha_env("GITHUB_API_URL")}/repos/${h.gha_github("repository")}/labels" || true""" @@ -390,6 +394,7 @@ curl -s -o /dev/null -w "%{http_code}" \\ { name = "Create or update sync issue" "if" = h.gha_steps_eq("compare", "needs_sync", "true") + id = "sync-issue" run = """\ BEHIND="${h.gha_steps("compare", "behind")}" AHEAD="${h.gha_steps("compare", "ahead")}" @@ -448,19 +453,22 @@ if [ "${h.gha_steps("existing", "issue_exists")}" = "true" ]; then ISSUE_NUMBER="${h.gha_steps("existing", "issue_number")}" curl -s -o /dev/null \\ -X PATCH \\ - -H "Authorization: token ${h.gha_github("token")}" \\ + -H "Authorization: token ${h.gha_secret("CLAUDE_BOT_TOKEN")}" \\ -H "Content-Type: application/json" \\ -d "${"$"}(jq -n --arg title "${"$"}TITLE" --arg body "${"$"}BODY" '{title: ${"$"}title, body: ${"$"}body}')" \\ "${h.gha_env("GITHUB_API_URL")}/repos/${h.gha_github("repository")}/issues/${"$"}{ISSUE_NUMBER}" echo "Updated existing issue #${"$"}{ISSUE_NUMBER}" + echo "issue_number=${"$"}{ISSUE_NUMBER}" >> "${"$"}GITHUB_OUTPUT" else - curl -s -o /dev/null \\ + RESPONSE=${"$"}(curl -s \\ -X POST \\ - -H "Authorization: token ${h.gha_github("token")}" \\ + -H "Authorization: token ${h.gha_secret("CLAUDE_BOT_TOKEN")}" \\ -H "Content-Type: application/json" \\ -d "${"$"}(jq -n --arg title "${"$"}TITLE" --arg body "${"$"}BODY" '{title: ${"$"}title, body: ${"$"}body, labels: [{"name": "upstream-sync"}]}')" \\ - "${h.gha_env("GITHUB_API_URL")}/repos/${h.gha_github("repository")}/issues" - echo "Created new upstream sync issue" + "${h.gha_env("GITHUB_API_URL")}/repos/${h.gha_github("repository")}/issues") + ISSUE_NUMBER=${"$"}(echo "${"$"}RESPONSE" | jq '.number') + echo "Created new upstream sync issue #${"$"}{ISSUE_NUMBER}" + echo "issue_number=${"$"}{ISSUE_NUMBER}" >> "${"$"}GITHUB_OUTPUT" fi""" } ] diff --git a/.forgejo/workflows/upstream-sync.yml b/.forgejo/workflows/upstream-sync.yml index 2d60ec5..7d04b0d 100644 --- a/.forgejo/workflows/upstream-sync.yml +++ b/.forgejo/workflows/upstream-sync.yml @@ -18,6 +18,7 @@ jobs: needs_sync: ${{ steps.compare.outputs.needs_sync }} behind: ${{ steps.compare.outputs.behind }} ahead: ${{ steps.compare.outputs.ahead }} + issue_number: ${{ steps.sync-issue.outputs.issue_number }} steps: - name: Checkout uses: https://${{ secrets.READ_REPO_TOKEN }}@git.wxs.ro/xternal/checkout@v6.0.2 @@ -72,7 +73,7 @@ jobs: id: existing run: |- RESPONSE=$(curl -s \ - -H "Authorization: token ${{ github.token }}" \ + -H "Authorization: token ${{ secrets.CLAUDE_BOT_TOKEN }}" \ -H "Content-Type: application/json" \ "${{ env.GITHUB_API_URL }}/repos/${{ github.repository }}/issues?state=open&labels=upstream-sync&limit=1") @@ -92,12 +93,13 @@ jobs: run: |- curl -s -o /dev/null -w "%{http_code}" \ -X POST \ - -H "Authorization: token ${{ github.token }}" \ + -H "Authorization: token ${{ secrets.CLAUDE_BOT_TOKEN }}" \ -H "Content-Type: application/json" \ -d '{"name":"upstream-sync","color":"#0075ca","description":"Upstream sync tracking"}' \ "${{ env.GITHUB_API_URL }}/repos/${{ github.repository }}/labels" || true - name: Create or update sync issue if: steps.compare.outputs.needs_sync == 'true' + id: sync-issue run: |- BEHIND="${{ steps.compare.outputs.behind }}" AHEAD="${{ steps.compare.outputs.ahead }}" @@ -156,19 +158,22 @@ jobs: ISSUE_NUMBER="${{ steps.existing.outputs.issue_number }}" curl -s -o /dev/null \ -X PATCH \ - -H "Authorization: token ${{ github.token }}" \ + -H "Authorization: token ${{ secrets.CLAUDE_BOT_TOKEN }}" \ -H "Content-Type: application/json" \ -d "$(jq -n --arg title "$TITLE" --arg body "$BODY" '{title: $title, body: $body}')" \ "${{ env.GITHUB_API_URL }}/repos/${{ github.repository }}/issues/${ISSUE_NUMBER}" echo "Updated existing issue #${ISSUE_NUMBER}" + echo "issue_number=${ISSUE_NUMBER}" >> "$GITHUB_OUTPUT" else - curl -s -o /dev/null \ + RESPONSE=$(curl -s \ -X POST \ - -H "Authorization: token ${{ github.token }}" \ + -H "Authorization: token ${{ secrets.CLAUDE_BOT_TOKEN }}" \ -H "Content-Type: application/json" \ -d "$(jq -n --arg title "$TITLE" --arg body "$BODY" '{title: $title, body: $body, labels: [{"name": "upstream-sync"}]}')" \ - "${{ env.GITHUB_API_URL }}/repos/${{ github.repository }}/issues" - echo "Created new upstream sync issue" + "${{ env.GITHUB_API_URL }}/repos/${{ github.repository }}/issues") + ISSUE_NUMBER=$(echo "$RESPONSE" | jq '.number') + echo "Created new upstream sync issue #${ISSUE_NUMBER}" + echo "issue_number=${ISSUE_NUMBER}" >> "$GITHUB_OUTPUT" fi merge-upstream: name: Auto-merge Upstream @@ -258,6 +263,7 @@ jobs: ## Current state - Branch: ${{ steps.prepare.outputs.branch }} - ${{ needs.check-upstream.outputs.behind }} commits behind upstream, ${{ needs.check-upstream.outputs.ahead }} commits ahead (our Forgejo changes) + - Tracking issue: #${{ needs.check-upstream.outputs.issue_number }} - Merge was attempted. Status: ${{ steps.prepare.outputs.merge_clean }} (true = clean, false = has conflicts) ## Impact analysis @@ -293,6 +299,7 @@ jobs: Auth: token $GITHUB_TOKEN Title: "chore: merge ${{ needs.check-upstream.outputs.behind }} upstream commits from anthropics/claude-code-action" Body should include: + - "Closes #${{ needs.check-upstream.outputs.issue_number }}" on its own line (links PR to the tracking issue) - Summary of notable upstream changes - Impact assessment: which fork files (if any) were affected - List of conflicts resolved (if any)