mirror of
https://github.com/coder/coder.git
synced 2026-06-02 20:48:20 +00:00
193 lines
8.2 KiB
YAML
193 lines
8.2 KiB
YAML
name: AI Triage Automation
|
||
|
||
on:
|
||
issues:
|
||
types:
|
||
- labeled
|
||
workflow_dispatch:
|
||
inputs:
|
||
issue_url:
|
||
description: "GitHub Issue URL to process"
|
||
required: true
|
||
type: string
|
||
template_name:
|
||
description: "Coder template to use for workspace"
|
||
required: true
|
||
default: "coder"
|
||
type: string
|
||
template_preset:
|
||
description: "Template preset to use"
|
||
required: false
|
||
default: ""
|
||
type: string
|
||
prefix:
|
||
description: "Prefix for workspace name"
|
||
required: false
|
||
default: "traiage"
|
||
type: string
|
||
|
||
permissions:
|
||
contents: read
|
||
|
||
jobs:
|
||
traiage:
|
||
name: Triage GitHub Issue with Claude Code
|
||
runs-on: ubuntu-latest
|
||
if: github.event.label.name == 'traiage' || github.event_name == 'workflow_dispatch'
|
||
timeout-minutes: 30
|
||
env:
|
||
CODER_URL: ${{ secrets.TRAIAGE_CODER_URL }}
|
||
CODER_SESSION_TOKEN: ${{ secrets.TRAIAGE_CODER_SESSION_TOKEN }}
|
||
permissions:
|
||
contents: read
|
||
issues: write
|
||
|
||
steps:
|
||
# This is only required for testing locally using nektos/act, so leaving commented out.
|
||
# An alternative is to use a larger or custom image.
|
||
# - name: Install Github CLI
|
||
# id: install-gh
|
||
# run: |
|
||
# (type -p wget >/dev/null || (sudo apt update && sudo apt install wget -y)) \
|
||
# && sudo mkdir -p -m 755 /etc/apt/keyrings \
|
||
# && out=$(mktemp) && wget -nv -O$out https://cli.github.com/packages/githubcli-archive-keyring.gpg \
|
||
# && cat $out | sudo tee /etc/apt/keyrings/githubcli-archive-keyring.gpg > /dev/null \
|
||
# && sudo chmod go+r /etc/apt/keyrings/githubcli-archive-keyring.gpg \
|
||
# && sudo mkdir -p -m 755 /etc/apt/sources.list.d \
|
||
# && echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | sudo tee /etc/apt/sources.list.d/github-cli.list > /dev/null \
|
||
# && sudo apt update \
|
||
# && sudo apt install gh -y
|
||
|
||
- name: Determine Inputs
|
||
id: determine-inputs
|
||
if: always()
|
||
env:
|
||
GITHUB_ACTOR: ${{ github.actor }}
|
||
GITHUB_EVENT_ISSUE_HTML_URL: ${{ github.event.issue.html_url }}
|
||
GITHUB_EVENT_NAME: ${{ github.event_name }}
|
||
GITHUB_EVENT_USER_ID: ${{ github.event.sender.id }}
|
||
GITHUB_EVENT_USER_LOGIN: ${{ github.event.sender.login }}
|
||
INPUTS_ISSUE_URL: ${{ inputs.issue_url }}
|
||
INPUTS_TEMPLATE_NAME: ${{ inputs.template_name || 'coder' }}
|
||
INPUTS_TEMPLATE_PRESET: ${{ inputs.template_preset || ''}}
|
||
INPUTS_PREFIX: ${{ inputs.prefix || 'traiage' }}
|
||
GH_TOKEN: ${{ github.token }}
|
||
run: |
|
||
echo "Using template name: ${INPUTS_TEMPLATE_NAME}"
|
||
echo "template_name=${INPUTS_TEMPLATE_NAME}" >> "${GITHUB_OUTPUT}"
|
||
|
||
echo "Using template preset: ${INPUTS_TEMPLATE_PRESET}"
|
||
echo "template_preset=${INPUTS_TEMPLATE_PRESET}" >> "${GITHUB_OUTPUT}"
|
||
|
||
echo "Using prefix: ${INPUTS_PREFIX}"
|
||
echo "prefix=${INPUTS_PREFIX}" >> "${GITHUB_OUTPUT}"
|
||
|
||
# For workflow_dispatch, use the actor who triggered it
|
||
# For issues events, use the issue author.
|
||
if [[ "${GITHUB_EVENT_NAME}" == "workflow_dispatch" ]]; then
|
||
if ! GITHUB_USER_ID=$(gh api "users/${GITHUB_ACTOR}" --jq '.id'); then
|
||
echo "::error::Failed to get GitHub user ID for actor ${GITHUB_ACTOR}"
|
||
exit 1
|
||
fi
|
||
echo "Using workflow_dispatch actor: ${GITHUB_ACTOR} (ID: ${GITHUB_USER_ID})"
|
||
echo "github_user_id=${GITHUB_USER_ID}" >> "${GITHUB_OUTPUT}"
|
||
echo "github_username=${GITHUB_ACTOR}" >> "${GITHUB_OUTPUT}"
|
||
|
||
echo "Using issue URL: ${INPUTS_ISSUE_URL}"
|
||
echo "issue_url=${INPUTS_ISSUE_URL}" >> "${GITHUB_OUTPUT}"
|
||
|
||
exit 0
|
||
elif [[ "${GITHUB_EVENT_NAME}" == "issues" ]]; then
|
||
GITHUB_USER_ID=${GITHUB_EVENT_USER_ID}
|
||
echo "Using issue author: ${GITHUB_EVENT_USER_LOGIN} (ID: ${GITHUB_USER_ID})"
|
||
echo "github_user_id=${GITHUB_USER_ID}" >> "${GITHUB_OUTPUT}"
|
||
echo "github_username=${GITHUB_EVENT_USER_LOGIN}" >> "${GITHUB_OUTPUT}"
|
||
|
||
echo "Using issue URL: ${GITHUB_EVENT_ISSUE_HTML_URL}"
|
||
echo "issue_url=${GITHUB_EVENT_ISSUE_HTML_URL}" >> "${GITHUB_OUTPUT}"
|
||
|
||
exit 0
|
||
else
|
||
echo "::error::Unsupported event type: ${GITHUB_EVENT_NAME}"
|
||
exit 1
|
||
fi
|
||
|
||
- name: Verify push access
|
||
env:
|
||
GITHUB_REPOSITORY: ${{ github.repository }}
|
||
GH_TOKEN: ${{ github.token }}
|
||
GITHUB_USERNAME: ${{ steps.determine-inputs.outputs.github_username }}
|
||
GITHUB_USER_ID: ${{ steps.determine-inputs.outputs.github_user_id }}
|
||
run: |
|
||
# Query the actor’s permission on this repo
|
||
can_push="$(gh api "/repos/${GITHUB_REPOSITORY}/collaborators/${GITHUB_USERNAME}/permission" --jq '.user.permissions.push')"
|
||
if [[ "${can_push}" != "true" ]]; then
|
||
echo "::error title=Access Denied::${GITHUB_USERNAME} does not have push access to ${GITHUB_REPOSITORY}"
|
||
exit 1
|
||
fi
|
||
|
||
- name: Extract context key and description from issue
|
||
id: extract-context
|
||
env:
|
||
ISSUE_URL: ${{ steps.determine-inputs.outputs.issue_url }}
|
||
GH_TOKEN: ${{ github.token }}
|
||
run: |
|
||
issue_number="$(gh issue view "${ISSUE_URL}" --json number --jq '.number')"
|
||
context_key="gh-${issue_number}"
|
||
|
||
TASK_PROMPT=$(cat <<EOF
|
||
Fix ${ISSUE_URL}
|
||
|
||
1. Use the gh CLI to read the issue description and comments.
|
||
2. Think carefully and try to understand the root cause. If the issue is unclear or not well defined, ask me to clarify and provide more information.
|
||
3. Write a proposed implementation plan to PLAN.md for me to review before starting implementation. Your plan should use TDD and only make the minimal changes necessary to fix the root cause.
|
||
4. When I approve your plan, start working on it. If you encounter issues with the plan, ask me for clarification and update the plan as required.
|
||
5. When you have finished implementation according to the plan, commit and push your changes, and create a PR using the gh CLI for me to review.
|
||
|
||
EOF
|
||
)
|
||
|
||
echo "context_key=${context_key}" >> "${GITHUB_OUTPUT}"
|
||
{
|
||
echo "TASK_PROMPT<<EOF"
|
||
echo "${TASK_PROMPT}"
|
||
echo "EOF"
|
||
} >> "${GITHUB_OUTPUT}"
|
||
|
||
- name: Checkout repository
|
||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||
with:
|
||
fetch-depth: 1
|
||
path: ./.github/actions/create-task-action
|
||
persist-credentials: false
|
||
ref: main
|
||
repository: coder/create-task-action
|
||
|
||
- name: Create Coder Task
|
||
id: create_task
|
||
uses: ./.github/actions/create-task-action
|
||
with:
|
||
coder-url: ${{ secrets.TRAIAGE_CODER_URL }}
|
||
coder-token: ${{ secrets.TRAIAGE_CODER_SESSION_TOKEN }}
|
||
coder-organization: "default"
|
||
coder-template-name: coder
|
||
coder-template-preset: ${{ steps.determine-inputs.outputs.template_preset }}
|
||
coder-task-name-prefix: gh-coder
|
||
coder-task-prompt: ${{ steps.extract-context.outputs.task_prompt }}
|
||
github-user-id: ${{ steps.determine-inputs.outputs.github_user_id }}
|
||
github-token: ${{ github.token }}
|
||
github-issue-url: ${{ steps.determine-inputs.outputs.issue_url }}
|
||
comment-on-issue: ${{ startsWith(steps.determine-inputs.outputs.issue_url, format('{0}/{1}', github.server_url, github.repository)) }}
|
||
|
||
- name: Write outputs
|
||
env:
|
||
TASK_CREATED: ${{ steps.create_task.outputs.task-created }}
|
||
TASK_NAME: ${{ steps.create_task.outputs.task-name }}
|
||
TASK_URL: ${{ steps.create_task.outputs.task-url }}
|
||
run: |
|
||
{
|
||
echo "**Task created:** ${TASK_CREATED}"
|
||
echo "**Task name:** ${TASK_NAME}"
|
||
echo "**Task URL**: ${TASK_URL}"
|
||
} >> "${GITHUB_STEP_SUMMARY}"
|