Update Claude workflow: add cost controls and model selection

This commit is contained in:
2026-03-09 22:17:33 +00:00
parent 0a7d81d79c
commit 13ef58f08a

View File

@@ -14,6 +14,7 @@ jobs:
(github.event_name == 'issue_comment' && (github.event_name == 'issue_comment' &&
contains(github.event.comment.body, '@claude')) contains(github.event.comment.body, '@claude'))
runs-on: ubuntu-latest runs-on: ubuntu-latest
timeout-minutes: 15
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@v4
@@ -23,21 +24,39 @@ jobs:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
GIT_TOKEN: ${{ secrets.GIT_TOKEN }} GIT_TOKEN: ${{ secrets.GIT_TOKEN }}
run: | run: |
# Configure git for Claude to use set +e
# Configure git
git config user.name "Claude Bot" git config user.name "Claude Bot"
git config user.email "claude@localhost" git config user.email "claude@localhost"
git remote set-url origin "http://admin:${GIT_TOKEN}@localhost:3000/${{ github.repository }}.git" git remote set-url origin "http://admin:${GIT_TOKEN}@localhost:3000/${{ github.repository }}.git"
# Extract issue info
ISSUE_NUMBER="${{ github.event.issue.number }}" ISSUE_NUMBER="${{ github.event.issue.number }}"
ISSUE_TITLE="${{ github.event.issue.title }}" ISSUE_TITLE="${{ github.event.issue.title }}"
REPO="${{ github.repository }}" REPO="${{ github.repository }}"
LABELS_JSON='${{ toJSON(github.event.issue.labels) }}'
# Determine model + cost limits from issue labels
# Default: haiku (cheap). Add claude:sonnet or claude:opus for harder tasks.
CLAUDE_MODEL="haiku"
MAX_TURNS=15
MAX_BUDGET="0.50"
EFFORT="low"
if echo "$LABELS_JSON" | grep -q '"claude:opus"'; then
CLAUDE_MODEL="claude-opus-4-6"
MAX_TURNS=40
MAX_BUDGET="5.00"
EFFORT="high"
elif echo "$LABELS_JSON" | grep -q '"claude:sonnet"'; then
CLAUDE_MODEL="claude-sonnet-4-6"
MAX_TURNS=25
MAX_BUDGET="2.00"
EFFORT="medium"
fi
# Fetch issue body via API
ISSUE_BODY=$(curl -s "http://localhost:3000/api/v1/repos/${REPO}/issues/${ISSUE_NUMBER}" \ ISSUE_BODY=$(curl -s "http://localhost:3000/api/v1/repos/${REPO}/issues/${ISSUE_NUMBER}" \
-H "Authorization: token ${GIT_TOKEN}" | python3 -c "import sys,json; print(json.load(sys.stdin).get('body',''))") -H "Authorization: token ${GIT_TOKEN}" | python3 -c "import sys,json; print(json.load(sys.stdin).get('body',''))")
# Get comment body if triggered by comment
COMMENT_BODY="" COMMENT_BODY=""
if [ "${{ github.event_name }}" = "issue_comment" ]; then if [ "${{ github.event_name }}" = "issue_comment" ]; then
COMMENT_ID="${{ github.event.comment.id }}" COMMENT_ID="${{ github.event.comment.id }}"
@@ -45,17 +64,10 @@ jobs:
-H "Authorization: token ${GIT_TOKEN}" | python3 -c "import sys,json; print(json.load(sys.stdin).get('body',''))") -H "Authorization: token ${GIT_TOKEN}" | python3 -c "import sys,json; print(json.load(sys.stdin).get('body',''))")
fi fi
# Create working branch
BRANCH="claude/issue-${ISSUE_NUMBER}" BRANCH="claude/issue-${ISSUE_NUMBER}"
git checkout -b "${BRANCH}" git checkout -b "${BRANCH}"
# Post status comment # Run Claude Code with cost controls
curl -s -X POST "http://localhost:3000/api/v1/repos/${REPO}/issues/${ISSUE_NUMBER}/comments" \
-H "Authorization: token ${GIT_TOKEN}" \
-H "Content-Type: application/json" \
-d "{\"body\": \"Claude is working on this issue...\"}"
# Run Claude Code - it handles everything: code changes, commits, push, and PR creation
claude -p "You are working on the repository ${REPO} (Gitea instance at http://localhost:3000). claude -p "You are working on the repository ${REPO} (Gitea instance at http://localhost:3000).
A Gitea issue needs your attention: A Gitea issue needs your attention:
@@ -63,19 +75,55 @@ jobs:
Description: ${ISSUE_BODY} Description: ${ISSUE_BODY}
Additional context: ${COMMENT_BODY} Additional context: ${COMMENT_BODY}
Instructions: IMPORTANT RULES:
1. Read and understand the codebase - Do NOT retry failed commands more than once. If something fails twice, stop and report the error.
- Do NOT loop on failing tests. Fix the obvious issue or report it. Never run the same failing command 3+ times.
- If you cannot complete the task, push what you have, create the PR as draft, and explain what is blocked.
- Be efficient: read only files you need, make targeted edits, avoid unnecessary exploration.
Steps:
1. Read and understand the relevant parts of the codebase
2. Implement the requested changes 2. Implement the requested changes
3. Commit your changes with a descriptive message 3. Commit your changes with a descriptive message
4. Push branch ${BRANCH} to origin 4. Push branch ${BRANCH} to origin
5. Create a pull request targeting main that references issue #${ISSUE_NUMBER} 5. Create a pull request targeting main that references issue #${ISSUE_NUMBER}
6. Comment on issue #${ISSUE_NUMBER} with a link to the PR 6. Post a comment on issue #${ISSUE_NUMBER} summarizing what you did
Git is configured. You are on branch ${BRANCH}. Work in the current directory. Git is configured. You are on branch ${BRANCH}. Work in the current directory.
Use git commands to push, and curl to the Gitea API for PR creation. Use git commands to push, and curl to the Gitea API for PR creation and comments.
Gitea API token is available as env var GIT_TOKEN." \ Gitea API token is available as env var GIT_TOKEN." \
--allowedTools "Bash,Read,Edit,Write,Glob,Grep" \ --allowedTools "Bash,Read,Edit,Write,Glob,Grep" \
--mcp-config /home/claude-runner/.claude/mcp-gitea.json \ --model "${CLAUDE_MODEL}" \
--max-turns 50 \ --max-turns "${MAX_TURNS}" \
--max-budget-usd "${MAX_BUDGET}" \
--effort "${EFFORT}" \
--permission-mode bypassPermissions \ --permission-mode bypassPermissions \
--output-format text 2>&1 | tee /home/claude-runner/last-claude-output.txt --output-format json 2>&1 > /tmp/claude-result.json
CLAUDE_EXIT=$?
# Extract cost from JSON output
COST=$(python3 -c "
import json
with open('/tmp/claude-result.json') as f:
data = json.load(f)
cost = data.get('total_cost_usd', 0)
print(f'\${cost:.4f}')
" 2>/dev/null || echo "unknown")
# Amend the last commit to include cost and model
if git log --oneline main..HEAD 2>/dev/null | head -1 | grep -q .; then
LAST_MSG=$(git log -1 --format=%B)
git commit --amend -m "${LAST_MSG}
Claude model: ${CLAUDE_MODEL} | API cost: ${COST}" --no-verify
git push origin "${BRANCH}" --force
fi
# Post cost as comment
curl -s -X POST "http://localhost:3000/api/v1/repos/${REPO}/issues/${ISSUE_NUMBER}/comments" \
-H "Authorization: token ${GIT_TOKEN}" \
-H "Content-Type: application/json" \
-d "{\"body\": \"Done (model: **${CLAUDE_MODEL}**, effort: ${EFFORT}, budget cap: \$${MAX_BUDGET}). API cost: **${COST}**\"}" > /dev/null
exit ${CLAUDE_EXIT}