diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fe2e9bf..d854c71 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -4,6 +4,16 @@ on: push: branches: [main] pull_request: + types: [opened, ready_for_review] + issue_comment: + types: [created] + +permissions: + contents: read + pull-requests: write + checks: write + id-token: write + actions: read jobs: pre-commit: @@ -20,3 +30,27 @@ jobs: - name: Run pre-commit uses: pre-commit/action@v3.0.1 + + code-review-auto: + name: Code Review (Auto) + needs: [pre-commit] + if: | + github.event_name == 'pull_request' && + github.event.pull_request.draft == false + uses: ./.github/workflows/code-review.yml + with: + trigger_type: auto + secrets: + claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} + + code-review-manual: + name: Code Review (Manual) + if: | + github.event_name == 'issue_comment' && + github.event.issue.pull_request && + contains(github.event.comment.body, '/review') + uses: ./.github/workflows/code-review.yml + with: + trigger_type: comment + secrets: + claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} diff --git a/.github/workflows/issue-triage.yml b/.github/workflows/issue-triage.yml index 647d526..a8bf281 100644 --- a/.github/workflows/issue-triage.yml +++ b/.github/workflows/issue-triage.yml @@ -3,12 +3,6 @@ name: Issue Triage on: workflow_call: inputs: - linear_team_prefix: - description: - 'Linear team prefix for ticket references (e.g., "PROJ" for PROJ-123)' - type: string - required: false - default: '' allowed_tools: description: 'Comma-separated list of allowed tools for Claude' type: string @@ -30,6 +24,9 @@ on: description: 'Linear API token' required: true + repository_dispatch: + types: [linear-triage] + permissions: contents: read pull-requests: read @@ -48,9 +45,12 @@ jobs: - name: Triage Issue uses: anthropics/claude-code-action@v1 env: - LINEAR_API_TOKEN: ${{ secrets.linear_api_token }} + LINEAR_API_TOKEN: + ${{ secrets.linear_api_token || secrets.LINEAR_API_TOKEN }} with: - claude_code_oauth_token: ${{ secrets.claude_code_oauth_token }} + claude_code_oauth_token: + ${{ secrets.claude_code_oauth_token || + secrets.CLAUDE_CODE_OAUTH_TOKEN }} github_token: ${{ secrets.GITHUB_TOKEN }} track_progress: true settings: | @@ -62,53 +62,41 @@ jobs: } } } - claude_args: --allowedTools "${{ inputs.allowed_tools }}" + claude_args: + --allowedTools "${{ inputs.allowed_tools || + github.event.client_payload.allowed_tools || + 'Read,Grep,Glob,LS,Bash(gh issue:*),Bash(gh label:*),mcp__linear__*' + }}" prompt: | - ${{ inputs.prompt || format('**Issue Triage Task** + ${{ inputs.prompt || github.event.client_payload.prompt || format('**Linear Issue Triage Task** - A new GitHub issue has been created. Linear is the source of truth for all tickets. + A Linear issue needs triage: {0} + Issue ID: {1} + Title: {2} ## Your Tasks - ### 1. Understand the Request - - Read the issue title and description - - Identify type: bug, feature, enhancement, or question - - Determine scope and complexity + ### 1. Fetch Issue Details + - Use Linear MCP to fetch the full issue details for {1} + - Review the issue description, labels, and current status ### 2. Research the Codebase - Search for related code, components, or existing implementations - Identify files that would likely need changes - Check for similar functionality - ### 3. Ask Clarifying Questions (if needed) - - If vague or missing key info, ask specific questions - - For bugs: request reproduction steps, expected vs actual behavior - - For features: clarify acceptance criteria - - ### 4. Apply Labels - Use `gh label list` to see available labels, then apply appropriate ones: - ```bash - gh issue edit $ISSUE_NUMBER --add-label "bug" --add-label "priority:high" - ``` - - ### 5. Linear Integration - Check if this issue is already linked to a Linear ticket (look for {0}-XXX in the issue body or comments). - - **If NO Linear ticket exists:** - - Use the Linear MCP tools to create a new ticket - - Link it back to this GitHub issue - - Add a comment with the Linear ticket ID (e.g., "Created Linear ticket: {0}-123") - - **If a Linear ticket already exists:** - - Fetch the ticket details using Linear MCP - - Update the GitHub issue with any additional context from Linear - - ### 6. Provide Analysis Summary - Comment with: - - Your understanding of the request + ### 3. Update Linear Ticket + Update the Linear ticket with your analysis: - Files/components likely involved - Complexity estimate (small/medium/large) - Any dependencies or blockers - - Linear ticket reference + - Implementation suggestions or approach + + ### 4. Update Ticket Status + - Move the ticket from Triage to the appropriate next status + - Add any relevant labels if needed - Be concise and actionable.', inputs.linear_team_prefix) }} + Be concise and actionable.', + github.event.client_payload.url, + github.event.client_payload.issue_id, + github.event.client_payload.title) }} diff --git a/CLAUDE.md b/CLAUDE.md index 39b9dd1..51aa4a5 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -49,9 +49,9 @@ Each workflow defines: for triage) - `permissions` - GitHub token scopes needed -The `issue-triage.yml` workflow has conditional steps based on `enable_linear` -and `prompt` inputs to handle four combinations: with/without Linear, -with/without custom prompt. +The `issue-triage.yml` workflow is triggered via `repository_dispatch` (type: +`linear-triage`) for Linear webhook integration. It uses the `format()` function +to inject `client_payload` fields (issue_id, url, title) into the prompt. The `code-review.yml` workflow includes additional `actions/github-script` steps for check run management and emoji reactions. diff --git a/README.md b/README.md index 011db3e..a95c2ad 100644 --- a/README.md +++ b/README.md @@ -60,25 +60,42 @@ jobs: claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} ``` -### With Issue Triage +### With Linear Issue Triage (Repository Dispatch) + +Trigger issue triage from Linear webhooks via repository dispatch: ```yaml -name: Claude Code +name: Linear Issue Triage on: - issues: - types: [opened] + repository_dispatch: + types: [linear-triage] jobs: triage: uses: zaks-io/claude-code-action/.github/workflows/issue-triage.yml@main - with: - linear_team_prefix: 'PROJ' secrets: claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} linear_api_token: ${{ secrets.LINEAR_API_KEY }} ``` +To trigger, send a POST request to GitHub's repository dispatch API: + +```bash +curl -X POST \ + -H "Authorization: token $GITHUB_TOKEN" \ + -H "Accept: application/vnd.github.v3+json" \ + https://api.github.com/repos/OWNER/REPO/dispatches \ + -d '{ + "event_type": "linear-triage", + "client_payload": { + "issue_id": "PROJ-123", + "url": "https://linear.app/team/issue/PROJ-123", + "title": "Issue title" + } + }' +``` + ### With Manual Code Review Triggered by `/review` comment on a PR: @@ -160,15 +177,28 @@ permissions: ### issue-triage.yml -Automated issue triage with Linear integration. +Automated Linear issue triage via repository dispatch. + +#### Triggers + +- `repository_dispatch` with type `linear-triage` +- `workflow_call` for reusable workflow usage #### Inputs -| Input | Type | Default | Description | -| -------------------- | ------ | -------------------------------------------------------------------- | ------------------------------------------------ | -| `linear_team_prefix` | string | `''` | Linear team prefix (e.g., `PROJ` for `PROJ-123`) | -| `allowed_tools` | string | `Read,Grep,Glob,LS,Bash(gh issue:*),Bash(gh label:*),mcp__linear__*` | Comma-separated list of allowed tools | -| `prompt` | string | `''` | Custom prompt (overrides default) | +| Input | Type | Default | Description | +| --------------- | ------ | -------------------------------------------------------------------- | --------------------------------- | +| `allowed_tools` | string | `Read,Grep,Glob,LS,Bash(gh issue:*),Bash(gh label:*),mcp__linear__*` | Comma-separated list of tools | +| `prompt` | string | `''` | Custom prompt (overrides default) | + +#### Repository Dispatch Payload + +| Field | Required | Description | +| ---------- | -------- | ---------------------------------- | +| `issue_id` | Yes | Linear issue ID (e.g., `PROJ-123`) | +| `url` | Yes | Linear issue URL | +| `title` | Yes | Linear issue title | +| `prompt` | No | Custom prompt override | #### Secrets @@ -191,13 +221,11 @@ permissions: When no custom `prompt` is provided, the workflow: -1. Analyzes the issue title and description -2. Identifies the issue type (bug, feature, enhancement, question) -3. Researches related code in the repository -4. Asks clarifying questions if needed -5. Applies appropriate labels -6. Creates/links Linear tickets -7. Posts an analysis summary +1. Fetches full issue details from Linear via MCP +2. Researches related code in the repository +3. Updates the Linear ticket with analysis (files involved, complexity, + implementation suggestions) +4. Moves the ticket from Triage to the appropriate status --- @@ -264,27 +292,25 @@ on: types: [created] pull_request_review_comment: types: [created] - issues: - types: [opened, labeled] pull_request_review: types: [submitted] + repository_dispatch: + types: [linear-triage] jobs: # General Claude agent for comments claude: if: | - !contains(github.event.comment.body, '/review') && - github.event_name != 'issues' + github.event_name != 'repository_dispatch' && + !contains(github.event.comment.body, '/review') uses: zaks-io/claude-code-action/.github/workflows/claude.yml@main secrets: claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} - # Issue triage on new issues + # Issue triage via repository dispatch (triggered by Linear webhook) triage: - if: github.event_name == 'issues' && github.event.action == 'opened' + if: github.event_name == 'repository_dispatch' uses: zaks-io/claude-code-action/.github/workflows/issue-triage.yml@main - with: - linear_team_prefix: 'PROJ' secrets: claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} linear_api_token: ${{ secrets.LINEAR_API_KEY }}