Skip to content

Commit 1249683

Browse files
johnstcnmafredri
andauthored
ci: add workflow for agentic issue triage (#19839)
Adds a GH workflow to start a workspace with a pre-determined template, perform a first pass over a given GitHub issue, and persist the changes in a GCS bucket for later refining. Tested locally with `nektos/act`. Co-authored-by: Mathias Fredriksson <mafredri@gmail.com>
1 parent 5c2b9a5 commit 1249683

2 files changed

Lines changed: 406 additions & 0 deletions

File tree

.github/workflows/traiage.yaml

Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
name: AI Triage Automation
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
issue_url:
7+
description: 'GitHub Issue URL to process'
8+
required: true
9+
type: string
10+
template_name:
11+
description: 'Coder template to use for workspace'
12+
required: true
13+
default: 'ai-workspace'
14+
type: string
15+
prefix:
16+
description: 'Prefix for workspace name'
17+
required: false
18+
default: 'traiage'
19+
type: string
20+
persistence_mode:
21+
description: 'Persistence mode (push or archive)'
22+
required: false
23+
type: choice
24+
options:
25+
- push
26+
- archive
27+
default: 'archive'
28+
29+
jobs:
30+
traiage:
31+
name: Triage GitHub Issue with Claude Code
32+
runs-on: ubuntu-latest
33+
timeout-minutes: 30
34+
env:
35+
CODER_URL: ${{ secrets.TRAIAGE_CODER_URL }}
36+
CODER_SESSION_TOKEN: ${{ secrets.TRAIAGE_CODER_SESSION_TOKEN }}
37+
TEMPLATE_NAME: ${{ inputs.template_name }}
38+
permissions:
39+
contents: read
40+
issues: write
41+
actions: write
42+
43+
steps:
44+
- name: Checkout repository
45+
uses: actions/checkout@v4
46+
with:
47+
persist-credentials: false
48+
fetch-depth: 0
49+
50+
- name: Extract context key from issue
51+
id: extract-context
52+
env:
53+
ISSUE_URL: ${{ inputs.issue_url }}
54+
run: |
55+
issue_number="$(gh issue view "${ISSUE_URL}" --json number --jq '.number')"
56+
context_key="gh-${issue_number}"
57+
echo "context_key=${context_key}" >> "${GITHUB_OUTPUT}"
58+
echo "CONTEXT_KEY=${context_key}" >> "${GITHUB_ENV}"
59+
60+
- name: Download and install Coder binary
61+
shell: bash
62+
env:
63+
CODER_URL: ${{ secrets.TRAIAGE_CODER_URL }}
64+
run: |
65+
if [ "${{ runner.arch }}" == "ARM64" ]; then
66+
ARCH="arm64"
67+
else
68+
ARCH="amd64"
69+
fi
70+
mkdir -p "${HOME}/.local/bin"
71+
curl -fsSL --compressed "$CODER_URL/bin/coder-linux-${ARCH}" -o "${HOME}/.local/bin/coder"
72+
chmod +x "${HOME}/.local/bin/coder"
73+
export PATH="$HOME/.local/bin:$PATH"
74+
coder version
75+
coder whoami
76+
echo "$HOME/.local/bin" >> "${GITHUB_PATH}"
77+
78+
- name: Create Coder workspace
79+
id: create-workspace
80+
env:
81+
PREFIX: ${{ inputs.prefix }}
82+
CONTEXT_KEY: ${{ steps.extract-context.outputs.context_key }}
83+
RUN_ID: ${{ github.run_id }}
84+
TEMPLATE_PARAMETERS: ${{ secrets.TRAIAGE_TEMPLATE_PARAMETERS }}
85+
run: |
86+
export WORKSPACE_NAME="${PREFIX}-${CONTEXT_KEY}-${RUN_ID}"
87+
echo "Creating workspace: $WORKSPACE_NAME"
88+
./scripts/traiage.sh create
89+
echo "workspace_name=$WORKSPACE_NAME" >> "${GITHUB_OUTPUT}"
90+
echo "WORKSPACE_NAME=${WORKSPACE_NAME}" >> "${GITHUB_ENV}"
91+
92+
- name: Send prompt to AI agent inside workspace
93+
id: prepare-prompt
94+
env:
95+
WORKSPACE_NAME: ${{ steps.create-workspace.outputs.workspace_name }}
96+
ISSUE_URL: ${{ inputs.issue_url }}
97+
run: |
98+
PROMPT_FILE=/tmp/prompt.txt
99+
trap 'rm -f "${PROMPT_FILE}"' EXIT
100+
101+
# Fetch issue description using `gh` CLI
102+
issue_description=$(gh issue view "${ISSUE_URL}")
103+
104+
# Write a prompt to PROMPT_FILE
105+
cat > "${PROMPT_FILE}" <<EOF
106+
Analyze the below GitHub issue description, understand the root cause, and make appropriate changes to resolve the issue.
107+
108+
ISSUE URL: ${ISSUE_URL}
109+
ISSUE DESCRIPTION BELOW:
110+
111+
${issue_description}
112+
EOF
113+
114+
echo "WORKSPACE_NAME: ${WORKSPACE_NAME}"
115+
# This command will run the prompt inside the workspace
116+
# and exit once the agent has completed the task.
117+
PROMPT=$(cat $PROMPT_FILE) ./scripts/traiage.sh prompt
118+
119+
- name: Commit and push changes
120+
id: commit-push
121+
if: ${{ inputs.persistence_mode == 'push' }}
122+
run: |
123+
echo "Committing and pushing changes in workspace: $WORKSPACE_NAME"
124+
./scripts/traiage.sh commit-push
125+
126+
- name: Create and upload archive
127+
id: create-archive
128+
if: ${{ inputs.persistence_mode == 'archive' }}
129+
env:
130+
DESTINATION_PREFIX: ${{ secrets.TRAIAGE_DESTINATION_PREFIX }}
131+
run: |
132+
echo "Creating archive for workspace: $WORKSPACE_NAME"
133+
./scripts/traiage.sh archive
134+
echo "archive_url=${DESTINATION_PREFIX%%/}/$WORKSPACE_NAME.tar.gz" >> "${GITHUB_OUTPUT}"
135+
136+
- name: Report results
137+
env:
138+
ISSUE_URL: ${{ inputs.issue_url }}
139+
CONTEXT_KEY: ${{ steps.extract-context.outputs.context_key }}
140+
WORKSPACE_NAME: ${{ steps.create-workspace.outputs.workspace_name }}
141+
ARCHIVE_URL: ${{ steps.create-archive.outputs.archive_url }}
142+
run: |
143+
{
144+
echo "## TrAIage Results";
145+
echo "- **Issue URL:** ${ISSUE_URL}";
146+
echo "- **Context Key:** ${CONTEXT_KEY}";
147+
echo "- **Workspace:** ${WORKSPACE_NAME}";
148+
echo "- **Archive URL:** ${ARCHIVE_URL}"
149+
} >> "${GITHUB_STEP_SUMMARY}"
150+
151+
- name: Cleanup workspace
152+
if: steps.create-workspace.outputs.workspace_name != '' && (inputs.persistence_mode == 'archive' && steps.create-archive.outputs.archive_url != '')
153+
run: |
154+
echo "Cleaning up workspace: $WORKSPACE_NAME"
155+
./scripts/traiage.sh delete || true

0 commit comments

Comments
 (0)