Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -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 }}
74 changes: 31 additions & 43 deletions .github/workflows/issue-triage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -30,6 +24,9 @@ on:
description: 'Linear API token'
required: true

repository_dispatch:
types: [linear-triage]

permissions:
contents: read
pull-requests: read
Expand All @@ -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: |
Expand All @@ -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) }}
6 changes: 3 additions & 3 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
80 changes: 53 additions & 27 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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

Expand All @@ -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

---

Expand Down Expand Up @@ -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 }}
Expand Down