Extend object-reference checks to all versions and add bulk-archive action #13379
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Claude Code | |
| on: | |
| schedule: | |
| - cron: '0 2 * * *' # Daily at 2am UTC — picks up next incremental task | |
| workflow_dispatch: | |
| inputs: | |
| issue_number: | |
| description: 'Specific issue number to work on (optional)' | |
| required: false | |
| type: string | |
| issue_comment: | |
| types: [created] | |
| pull_request_review_comment: | |
| types: [created] | |
| issues: | |
| types: [labeled] | |
| pull_request_review: | |
| types: [submitted] | |
| concurrency: | |
| group: >- | |
| claude-${{ | |
| github.event_name == 'schedule' && 'scheduled' || | |
| github.event_name == 'workflow_dispatch' && format('dispatch-{0}', inputs.issue_number) || | |
| github.event.issue.number || | |
| github.event.pull_request.number || | |
| github.run_id | |
| }} | |
| cancel-in-progress: false | |
| # Restrict default permissions — jobs override as needed | |
| permissions: | |
| contents: read | |
| issues: read | |
| pull-requests: read | |
| jobs: | |
| # ── Scheduled / manual: find the next issue to work on ── | |
| find-work: | |
| if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' | |
| runs-on: ubuntu-latest | |
| outputs: | |
| issue_number: ${{ steps.find.outputs.issue_number }} | |
| issue_body: ${{ steps.find.outputs.issue_body }} | |
| issue_title: ${{ steps.find.outputs.issue_title }} | |
| steps: | |
| - name: Find oldest labeled issue without an open PR | |
| id: find | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| INPUT_ISSUE_NUMBER: ${{ inputs.issue_number }} | |
| run: | | |
| REPO="${{ github.repository }}" | |
| # Get head branch names of all open PRs with the label | |
| OPEN_PR_BRANCHES=$(gh pr list --repo "$REPO" --label "claude" --state open --json headRefName --jq '.[].headRefName') | |
| if [ -n "$INPUT_ISSUE_NUMBER" ]; then | |
| # Manual dispatch: use the specified issue but check for existing PR | |
| ISSUE_NUMBER="$INPUT_ISSUE_NUMBER" | |
| if echo "$OPEN_PR_BRANCHES" | grep -q "^claude/${ISSUE_NUMBER}-"; then | |
| echo "::notice::Issue #$ISSUE_NUMBER already has an open PR, skipping" | |
| exit 0 | |
| fi | |
| else | |
| # Scheduled: find the oldest issue that doesn't already have an open PR | |
| ISSUES=$(gh issue list --repo "$REPO" --label "claude" --state open --json number,createdAt --jq 'sort_by(.createdAt) | .[].number') | |
| ISSUE_NUMBER="" | |
| for CANDIDATE in $ISSUES; do | |
| if ! echo "$OPEN_PR_BRANCHES" | grep -q "^claude/${CANDIDATE}-"; then | |
| ISSUE_NUMBER="$CANDIDATE" | |
| break | |
| fi | |
| echo "::notice::Issue #$CANDIDATE already has an open PR, skipping" | |
| done | |
| fi | |
| if [ -z "$ISSUE_NUMBER" ]; then | |
| echo "::notice::No eligible issues found" | |
| exit 0 | |
| fi | |
| echo "issue_number=$ISSUE_NUMBER" >> $GITHUB_OUTPUT | |
| # Fetch issue details | |
| ISSUE_DATA=$(gh issue view "$ISSUE_NUMBER" --repo "$REPO" --json title,body) | |
| ISSUE_TITLE=$(echo "$ISSUE_DATA" | jq -r '.title') | |
| ISSUE_BODY=$(echo "$ISSUE_DATA" | jq -r '.body') | |
| DELIMITER="ghadelim_$(openssl rand -hex 8)" | |
| echo "issue_title<<$DELIMITER" >> $GITHUB_OUTPUT | |
| echo "$ISSUE_TITLE" >> $GITHUB_OUTPUT | |
| echo "$DELIMITER" >> $GITHUB_OUTPUT | |
| echo "issue_body<<$DELIMITER" >> $GITHUB_OUTPUT | |
| echo "$ISSUE_BODY" >> $GITHUB_OUTPUT | |
| echo "$DELIMITER" >> $GITHUB_OUTPUT | |
| # ── Scheduled / manual: implement the next task on the found issue ── | |
| scheduled: | |
| needs: find-work | |
| if: needs.find-work.outputs.issue_number != '' | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: write | |
| pull-requests: write | |
| issues: write | |
| id-token: write | |
| services: | |
| postgres: | |
| image: pgvector/pgvector:pg16 | |
| env: | |
| POSTGRES_USER: postgres | |
| POSTGRES_PASSWORD: postgres_password | |
| options: >- | |
| --health-cmd pg_isready | |
| --health-interval 10s | |
| --health-timeout 5s | |
| --health-retries 5 | |
| ports: | |
| - 5432:5432 | |
| redis: | |
| image: redis | |
| options: >- | |
| --health-cmd "redis-cli ping" | |
| --health-interval 10s | |
| --health-timeout 5s | |
| --health-retries 5 | |
| ports: | |
| - 6379:6379 | |
| env: | |
| DJANGO_DATABASE_USER: postgres | |
| DJANGO_DATABASE_PASSWORD: postgres_password | |
| SECRET_KEY: secret-test-key | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 0 | |
| token: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Set up Python | |
| uses: actions/setup-python@v6 | |
| with: | |
| python-version: '3.13' | |
| - name: Set up uv | |
| uses: astral-sh/setup-uv@v7 | |
| with: | |
| enable-cache: true | |
| - name: Install Python dependencies | |
| run: | | |
| uv venv | |
| uv sync --locked --dev | |
| echo "$PWD/.venv/bin" >> $GITHUB_PATH | |
| - name: Set up Node.js | |
| uses: actions/setup-node@v6 | |
| with: | |
| node-version: 24.x | |
| - name: Install Node dependencies | |
| run: npm ci | |
| - name: Create branch | |
| id: branch | |
| run: | | |
| BRANCH_NAME="claude/${{ needs.find-work.outputs.issue_number }}-$(date +%Y%m%d-%H%M%S)" | |
| git checkout -b "$BRANCH_NAME" | |
| echo "branch_name=$BRANCH_NAME" >> $GITHUB_OUTPUT | |
| - name: Run Claude Code | |
| id: claude | |
| uses: anthropics/claude-code-action@v1 | |
| with: | |
| anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} | |
| prompt: | | |
| You are working on an incremental project tracked in issue #${{ needs.find-work.outputs.issue_number }}. | |
| ## Issue Title | |
| ${{ needs.find-work.outputs.issue_title }} | |
| ## Issue Content | |
| ${{ needs.find-work.outputs.issue_body }} | |
| ## Instructions | |
| 1. Read the issue and identify the first unchecked task (- [ ]) that is not marked as blocked | |
| 2. Implement that task, making git commits as you go | |
| 3. Run lint, type checks, and tests, fix any issues: | |
| - Python lint: ruff check --fix && ruff format | |
| - Python type check: uv run ty check apps/ | |
| - JS/TS lint: npm run lint | |
| - Python test: pytest path/to/file.py -v | |
| 4. Push the changes you've made to GitHub and create a PR with the 'claude' label. | |
| 5. After completing the task, update the issue using gh issue edit to: | |
| - Check off the completed task (change - [ ] to - [x]) | |
| - Add any learnings to the ## Learnings section (create if needed) | |
| 6. If you cannot complete the task, mark it as blocked (add "blocked:" prefix to the task) | |
| 7. Add a comment to the issue summarizing what you did | |
| If all tasks are complete or blocked, comment on the issue explaining the status. | |
| claude_args: '--allowedTools "Bash(npm run lint:*),Bash(npm run type-check:*),Bash(npm run build:*),Bash(ruff check:*),Bash(ruff format:*),Bash(ty check:*),Bash(uv run ty:*),Bash(uv run ruff:*),Bash(uv run pytest:*),Bash(pytest:*),Bash(uv run --no-project zensical build:*),Bash(git add:*),Bash(git commit:*),Bash(git push:*),Bash(git rm:*),Bash(git checkout:*),Bash(git switch:*),Bash(git status:*),Bash(git diff:*),Bash(gh pr create:*),Bash(gh pr edit:*),Bash(gh api:*),Bash(gh issue edit:*),Bash(gh issue comment:*),Bash(ls:*),Bash(grep:*),Bash(sort:*),Bash(tail:*),Grep,Glob,Read,Write,Edit"' | |
| # ── Event-driven: respond to @claude mentions, issue label ── | |
| claude: | |
| if: | | |
| github.event_name != 'schedule' && github.event_name != 'workflow_dispatch' && ( | |
| (github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) || | |
| (github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude')) || | |
| (github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude')) || | |
| (github.event_name == 'issues' && github.event.action == 'labeled' && github.event.label.name == 'claude') | |
| ) | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: write | |
| pull-requests: write | |
| issues: write | |
| id-token: write | |
| services: | |
| postgres: | |
| image: pgvector/pgvector:pg16 | |
| env: | |
| POSTGRES_USER: postgres | |
| POSTGRES_PASSWORD: postgres_password | |
| options: >- | |
| --health-cmd pg_isready | |
| --health-interval 10s | |
| --health-timeout 5s | |
| --health-retries 5 | |
| ports: | |
| - 5432:5432 | |
| redis: | |
| image: redis | |
| options: >- | |
| --health-cmd "redis-cli ping" | |
| --health-interval 10s | |
| --health-timeout 5s | |
| --health-retries 5 | |
| ports: | |
| - 6379:6379 | |
| env: | |
| DJANGO_DATABASE_USER: postgres | |
| DJANGO_DATABASE_PASSWORD: postgres_password | |
| SECRET_KEY: secret-test-key | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 0 | |
| token: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Set up Python | |
| uses: actions/setup-python@v6 | |
| with: | |
| python-version: '3.13' | |
| - name: Set up uv | |
| uses: astral-sh/setup-uv@v7 | |
| with: | |
| enable-cache: true | |
| - name: Install Python dependencies | |
| run: | | |
| uv venv | |
| uv sync --locked --dev | |
| echo "$PWD/.venv/bin" >> $GITHUB_PATH | |
| - name: Set up Node.js | |
| uses: actions/setup-node@v6 | |
| with: | |
| node-version: 24.x | |
| - name: Install Node dependencies | |
| run: npm ci | |
| - name: Run Claude Code | |
| id: claude | |
| uses: anthropics/claude-code-action@v1 | |
| with: | |
| anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} | |
| branch_prefix: "claude/" | |
| claude_args: | | |
| --allowedTools "mcp__github_inline_comment__create_inline_comment,Bash(npm run lint:*),Bash(npm run type-check:*),Bash(npm run build:*),Bash(ruff check:*),Bash(ruff format:*),Bash(ty check:*),Bash(uv run ty:*),Bash(uv run ruff:*),Bash(uv run pytest:*),Bash(pytest:*),Bash(git add:*),Bash(git commit:*),Bash(git push:*),Bash(git checkout:*),Bash(git switch:*),Bash(git status:*),Bash(git diff:*),Bash(git branch:*),Bash(gh pr create:*),Bash(gh pr edit:*),Bash(gh pr comment:*),Bash(gh pr diff:*),Bash(gh pr view:*),Bash(gh api:*),Bash(gh issue comment:*),Bash(gh issue edit:*),Read,Write,Edit" |