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 <noreply@anthropic.com>
This commit is contained in:
1 parent
bc063f62f0
commit
88e7747d2f
2 files changed
+29
-14
No files matched your search
+15
-7
@@ -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_branch_ref = h.gha_steps("prepare", "branch")
|
||||||
_merge_behind_ref = h.gha_needs("check-upstream", "behind")
|
_merge_behind_ref = h.gha_needs("check-upstream", "behind")
|
||||||
_merge_ahead_ref = h.gha_needs("check-upstream", "ahead")
|
_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_clean_ref = h.gha_steps("prepare", "merge_clean")
|
||||||
_merge_affected_ref = h.gha_steps("prepare", "affected_files")
|
_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
|
## Current state
|
||||||
- Branch: ${_merge_branch_ref}
|
- Branch: ${_merge_branch_ref}
|
||||||
- ${_merge_behind_ref} commits behind upstream, ${_merge_ahead_ref} commits ahead (our Forgejo changes)
|
- ${_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)
|
- Merge was attempted. Status: ${_merge_clean_ref} (true = clean, false = has conflicts)
|
||||||
|
|
||||||
## Impact analysis
|
## Impact analysis
|
||||||
@@ -276,6 +278,7 @@ The fewer upstream files we modify, the fewer conflicts in the next sync.
|
|||||||
Auth: token ${"$"}GITHUB_TOKEN
|
Auth: token ${"$"}GITHUB_TOKEN
|
||||||
Title: "chore: merge ${_merge_behind_ref} upstream commits from anthropics/claude-code-action"
|
Title: "chore: merge ${_merge_behind_ref} upstream commits from anthropics/claude-code-action"
|
||||||
Body should include:
|
Body should include:
|
||||||
|
- "Closes #${_merge_issue_ref}" on its own line (links PR to the tracking issue)
|
||||||
- Summary of notable upstream changes
|
- Summary of notable upstream changes
|
||||||
- Impact assessment: which fork files (if any) were affected
|
- Impact assessment: which fork files (if any) were affected
|
||||||
- List of conflicts resolved (if any)
|
- List of conflicts resolved (if any)
|
||||||
@@ -301,6 +304,7 @@ _upstream_sync_workflow = {
|
|||||||
needs_sync = h.gha_steps("compare", "needs_sync")
|
needs_sync = h.gha_steps("compare", "needs_sync")
|
||||||
behind = h.gha_steps("compare", "behind")
|
behind = h.gha_steps("compare", "behind")
|
||||||
ahead = h.gha_steps("compare", "ahead")
|
ahead = h.gha_steps("compare", "ahead")
|
||||||
|
issue_number = h.gha_steps("sync-issue", "issue_number")
|
||||||
}
|
}
|
||||||
steps = [
|
steps = [
|
||||||
checkout_mod.checkout() | {"with" = {"fetch-depth" = "0"}}
|
checkout_mod.checkout() | {"with" = {"fetch-depth" = "0"}}
|
||||||
@@ -360,7 +364,7 @@ fi"""
|
|||||||
id = "existing"
|
id = "existing"
|
||||||
run = """\
|
run = """\
|
||||||
RESPONSE=${"$"}(curl -s \\
|
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 "Content-Type: application/json" \\
|
||||||
"${h.gha_env("GITHUB_API_URL")}/repos/${h.gha_github("repository")}/issues?state=open&labels=upstream-sync&limit=1")
|
"${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 = """\
|
run = """\
|
||||||
curl -s -o /dev/null -w "%{http_code}" \\
|
curl -s -o /dev/null -w "%{http_code}" \\
|
||||||
-X POST \\
|
-X POST \\
|
||||||
-H "Authorization: token ${h.gha_github("token")}" \\
|
-H "Authorization: token ${h.gha_secret("CLAUDE_BOT_TOKEN")}" \\
|
||||||
-H "Content-Type: application/json" \\
|
-H "Content-Type: application/json" \\
|
||||||
-d '{"name":"upstream-sync","color":"#0075ca","description":"Upstream sync tracking"}' \\
|
-d '{"name":"upstream-sync","color":"#0075ca","description":"Upstream sync tracking"}' \\
|
||||||
"${h.gha_env("GITHUB_API_URL")}/repos/${h.gha_github("repository")}/labels" || true"""
|
"${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"
|
name = "Create or update sync issue"
|
||||||
"if" = h.gha_steps_eq("compare", "needs_sync", "true")
|
"if" = h.gha_steps_eq("compare", "needs_sync", "true")
|
||||||
|
id = "sync-issue"
|
||||||
run = """\
|
run = """\
|
||||||
BEHIND="${h.gha_steps("compare", "behind")}"
|
BEHIND="${h.gha_steps("compare", "behind")}"
|
||||||
AHEAD="${h.gha_steps("compare", "ahead")}"
|
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")}"
|
ISSUE_NUMBER="${h.gha_steps("existing", "issue_number")}"
|
||||||
curl -s -o /dev/null \\
|
curl -s -o /dev/null \\
|
||||||
-X PATCH \\
|
-X PATCH \\
|
||||||
-H "Authorization: token ${h.gha_github("token")}" \\
|
-H "Authorization: token ${h.gha_secret("CLAUDE_BOT_TOKEN")}" \\
|
||||||
-H "Content-Type: application/json" \\
|
-H "Content-Type: application/json" \\
|
||||||
-d "${"$"}(jq -n --arg title "${"$"}TITLE" --arg body "${"$"}BODY" '{title: ${"$"}title, body: ${"$"}body}')" \\
|
-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}"
|
"${h.gha_env("GITHUB_API_URL")}/repos/${h.gha_github("repository")}/issues/${"$"}{ISSUE_NUMBER}"
|
||||||
echo "Updated existing issue #${"$"}{ISSUE_NUMBER}"
|
echo "Updated existing issue #${"$"}{ISSUE_NUMBER}"
|
||||||
|
echo "issue_number=${"$"}{ISSUE_NUMBER}" >> "${"$"}GITHUB_OUTPUT"
|
||||||
else
|
else
|
||||||
curl -s -o /dev/null \\
|
RESPONSE=${"$"}(curl -s \\
|
||||||
-X POST \\
|
-X POST \\
|
||||||
-H "Authorization: token ${h.gha_github("token")}" \\
|
-H "Authorization: token ${h.gha_secret("CLAUDE_BOT_TOKEN")}" \\
|
||||||
-H "Content-Type: application/json" \\
|
-H "Content-Type: application/json" \\
|
||||||
-d "${"$"}(jq -n --arg title "${"$"}TITLE" --arg body "${"$"}BODY" '{title: ${"$"}title, body: ${"$"}body, labels: [{"name": "upstream-sync"}]}')" \\
|
-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"
|
"${h.gha_env("GITHUB_API_URL")}/repos/${h.gha_github("repository")}/issues")
|
||||||
echo "Created new upstream sync issue"
|
ISSUE_NUMBER=${"$"}(echo "${"$"}RESPONSE" | jq '.number')
|
||||||
|
echo "Created new upstream sync issue #${"$"}{ISSUE_NUMBER}"
|
||||||
|
echo "issue_number=${"$"}{ISSUE_NUMBER}" >> "${"$"}GITHUB_OUTPUT"
|
||||||
fi"""
|
fi"""
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ jobs:
|
|||||||
needs_sync: ${{ steps.compare.outputs.needs_sync }}
|
needs_sync: ${{ steps.compare.outputs.needs_sync }}
|
||||||
behind: ${{ steps.compare.outputs.behind }}
|
behind: ${{ steps.compare.outputs.behind }}
|
||||||
ahead: ${{ steps.compare.outputs.ahead }}
|
ahead: ${{ steps.compare.outputs.ahead }}
|
||||||
|
issue_number: ${{ steps.sync-issue.outputs.issue_number }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: https://${{ secrets.READ_REPO_TOKEN }}@git.wxs.ro/xternal/checkout@v6.0.2
|
uses: https://${{ secrets.READ_REPO_TOKEN }}@git.wxs.ro/xternal/checkout@v6.0.2
|
||||||
@@ -72,7 +73,7 @@ jobs:
|
|||||||
id: existing
|
id: existing
|
||||||
run: |-
|
run: |-
|
||||||
RESPONSE=$(curl -s \
|
RESPONSE=$(curl -s \
|
||||||
-H "Authorization: token ${{ github.token }}" \
|
-H "Authorization: token ${{ secrets.CLAUDE_BOT_TOKEN }}" \
|
||||||
-H "Content-Type: application/json" \
|
-H "Content-Type: application/json" \
|
||||||
"${{ env.GITHUB_API_URL }}/repos/${{ github.repository }}/issues?state=open&labels=upstream-sync&limit=1")
|
"${{ env.GITHUB_API_URL }}/repos/${{ github.repository }}/issues?state=open&labels=upstream-sync&limit=1")
|
||||||
|
|
||||||
@@ -92,12 +93,13 @@ jobs:
|
|||||||
run: |-
|
run: |-
|
||||||
curl -s -o /dev/null -w "%{http_code}" \
|
curl -s -o /dev/null -w "%{http_code}" \
|
||||||
-X POST \
|
-X POST \
|
||||||
-H "Authorization: token ${{ github.token }}" \
|
-H "Authorization: token ${{ secrets.CLAUDE_BOT_TOKEN }}" \
|
||||||
-H "Content-Type: application/json" \
|
-H "Content-Type: application/json" \
|
||||||
-d '{"name":"upstream-sync","color":"#0075ca","description":"Upstream sync tracking"}' \
|
-d '{"name":"upstream-sync","color":"#0075ca","description":"Upstream sync tracking"}' \
|
||||||
"${{ env.GITHUB_API_URL }}/repos/${{ github.repository }}/labels" || true
|
"${{ env.GITHUB_API_URL }}/repos/${{ github.repository }}/labels" || true
|
||||||
- name: Create or update sync issue
|
- name: Create or update sync issue
|
||||||
if: steps.compare.outputs.needs_sync == 'true'
|
if: steps.compare.outputs.needs_sync == 'true'
|
||||||
|
id: sync-issue
|
||||||
run: |-
|
run: |-
|
||||||
BEHIND="${{ steps.compare.outputs.behind }}"
|
BEHIND="${{ steps.compare.outputs.behind }}"
|
||||||
AHEAD="${{ steps.compare.outputs.ahead }}"
|
AHEAD="${{ steps.compare.outputs.ahead }}"
|
||||||
@@ -156,19 +158,22 @@ jobs:
|
|||||||
ISSUE_NUMBER="${{ steps.existing.outputs.issue_number }}"
|
ISSUE_NUMBER="${{ steps.existing.outputs.issue_number }}"
|
||||||
curl -s -o /dev/null \
|
curl -s -o /dev/null \
|
||||||
-X PATCH \
|
-X PATCH \
|
||||||
-H "Authorization: token ${{ github.token }}" \
|
-H "Authorization: token ${{ secrets.CLAUDE_BOT_TOKEN }}" \
|
||||||
-H "Content-Type: application/json" \
|
-H "Content-Type: application/json" \
|
||||||
-d "$(jq -n --arg title "$TITLE" --arg body "$BODY" '{title: $title, body: $body}')" \
|
-d "$(jq -n --arg title "$TITLE" --arg body "$BODY" '{title: $title, body: $body}')" \
|
||||||
"${{ env.GITHUB_API_URL }}/repos/${{ github.repository }}/issues/${ISSUE_NUMBER}"
|
"${{ env.GITHUB_API_URL }}/repos/${{ github.repository }}/issues/${ISSUE_NUMBER}"
|
||||||
echo "Updated existing issue #${ISSUE_NUMBER}"
|
echo "Updated existing issue #${ISSUE_NUMBER}"
|
||||||
|
echo "issue_number=${ISSUE_NUMBER}" >> "$GITHUB_OUTPUT"
|
||||||
else
|
else
|
||||||
curl -s -o /dev/null \
|
RESPONSE=$(curl -s \
|
||||||
-X POST \
|
-X POST \
|
||||||
-H "Authorization: token ${{ github.token }}" \
|
-H "Authorization: token ${{ secrets.CLAUDE_BOT_TOKEN }}" \
|
||||||
-H "Content-Type: application/json" \
|
-H "Content-Type: application/json" \
|
||||||
-d "$(jq -n --arg title "$TITLE" --arg body "$BODY" '{title: $title, body: $body, labels: [{"name": "upstream-sync"}]}')" \
|
-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"
|
"${{ env.GITHUB_API_URL }}/repos/${{ github.repository }}/issues")
|
||||||
echo "Created new upstream sync issue"
|
ISSUE_NUMBER=$(echo "$RESPONSE" | jq '.number')
|
||||||
|
echo "Created new upstream sync issue #${ISSUE_NUMBER}"
|
||||||
|
echo "issue_number=${ISSUE_NUMBER}" >> "$GITHUB_OUTPUT"
|
||||||
fi
|
fi
|
||||||
merge-upstream:
|
merge-upstream:
|
||||||
name: Auto-merge Upstream
|
name: Auto-merge Upstream
|
||||||
@@ -258,6 +263,7 @@ jobs:
|
|||||||
## Current state
|
## Current state
|
||||||
- Branch: ${{ steps.prepare.outputs.branch }}
|
- Branch: ${{ steps.prepare.outputs.branch }}
|
||||||
- ${{ needs.check-upstream.outputs.behind }} commits behind upstream, ${{ needs.check-upstream.outputs.ahead }} commits ahead (our Forgejo changes)
|
- ${{ 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)
|
- Merge was attempted. Status: ${{ steps.prepare.outputs.merge_clean }} (true = clean, false = has conflicts)
|
||||||
|
|
||||||
## Impact analysis
|
## Impact analysis
|
||||||
@@ -293,6 +299,7 @@ jobs:
|
|||||||
Auth: token $GITHUB_TOKEN
|
Auth: token $GITHUB_TOKEN
|
||||||
Title: "chore: merge ${{ needs.check-upstream.outputs.behind }} upstream commits from anthropics/claude-code-action"
|
Title: "chore: merge ${{ needs.check-upstream.outputs.behind }} upstream commits from anthropics/claude-code-action"
|
||||||
Body should include:
|
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
|
- Summary of notable upstream changes
|
||||||
- Impact assessment: which fork files (if any) were affected
|
- Impact assessment: which fork files (if any) were affected
|
||||||
- List of conflicts resolved (if any)
|
- List of conflicts resolved (if any)
|
||||||
|
|||||||
Reference in new issue
Block a user