- Notifications
You must be signed in to change notification settings - Fork1k
ci: allow dispatching workflow triage via label#20042
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
Changes fromall commits
5ed3bb0
565e945
7478df1
75c2d1b
edb4679
6920054
402f752
210ec2d
0f74b89
e6af33f
File filter
Filter by extension
Conversations
Uh oh!
There was an error while loading.Please reload this page.
Jump to
Uh oh!
There was an error while loading.Please reload this page.
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,9 @@ | ||
name: AI Triage Automation | ||
on: | ||
issues: | ||
types: | ||
- labeled | ||
johnstcn marked this conversation as resolved. Show resolvedHide resolvedUh oh!There was an error while loading.Please reload this page. | ||
workflow_dispatch: | ||
inputs: | ||
issue_url: | ||
@@ -32,6 +35,7 @@ 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 }} | ||
@@ -43,17 +47,58 @@ jobs: | ||
actions: write | ||
steps: | ||
- name: Get GitHub user ID | ||
id: github-user-id | ||
if: always() | ||
env: | ||
GITHUB_ACTOR: ${{ github.actor }} | ||
GITHUB_EVENT_NAME: ${{ github.event_name }} | ||
GITHUB_EVENT_USER_ID: ${{ github.event.sender.id }} | ||
GITHUB_EVENT_USER_LOGIN: ${{ github.event.sender.login }} | ||
GH_TOKEN: ${{ github.token }} | ||
run: | | ||
# 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}" | ||
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}" | ||
exit 0 | ||
else | ||
echo "::error::Unsupported event type: ${GITHUB_EVENT_NAME}" | ||
exit 1 | ||
fi | ||
- name: Verify organization membership | ||
env: | ||
GITHUB_ORG: ${{ github.repository_owner }} | ||
GH_TOKEN: ${{ github.token }} | ||
GITHUB_USERNAME: ${{ steps.github-user-id.outputs.github_username }} | ||
GITHUB_USER_ID: ${{ steps.github-user-id.outputs.github_user_id }} | ||
run: | | ||
# Check if the actor is a member of the organization | ||
if ! gh api "orgs/${GITHUB_ORG}/members/${GITHUB_USERNAME}" --silent 2>/dev/null; then | ||
echo "::error title=Access Denied::User ${GITHUB_USERNAME} is not a member of the ${GITHUB_ORG} organization" | ||
echo "::error::You must be a member of the ${GITHUB_ORG} GitHub organization to run this workflow." | ||
exit 1 | ||
fi | ||
echo "::notice::User ${GITHUB_USERNAME} verified as member of ${GITHUB_ORG} organization" | ||
- name: Extract context key from issue | ||
id: extract-context | ||
env: | ||
ISSUE_URL: ${{ inputs.issue_url }} | ||
GH_TOKEN: ${{ github.token }} | ||
run: | | ||
issue_number="$(gh issue view "${ISSUE_URL}" --json number --jq '.number')" | ||
context_key="gh-${issue_number}" | ||
@@ -82,25 +127,30 @@ jobs: | ||
id: get-coder-username | ||
env: | ||
CODER_SESSION_TOKEN: ${{ secrets.TRAIAGE_CODER_SESSION_TOKEN }} | ||
GH_TOKEN: ${{ github.token }} | ||
GITHUB_USER_ID: ${{ steps.github-user-id.outputs.github_user_id }} | ||
run: | | ||
user_json=$( | ||
coder users list --github-user-id="${GITHUB_USER_ID}" --output=json | ||
) | ||
coder_username=$(jq -r 'first | .username' <<< "$user_json") | ||
[[ -z "${coder_username}" || "${coder_username}" == "null" ]] && echo "No Coder user with GitHub user ID ${GITHUB_USER_ID} found" && exit 1 | ||
echo "coder_username=${coder_username}" >> "${GITHUB_OUTPUT}" | ||
- name: Checkout repository | ||
uses: actions/checkout@v4 | ||
with: | ||
persist-credentials: false | ||
fetch-depth: 0 | ||
# TODO(Cian): this is a good use-case for 'recipes' | ||
- name: Create Coder task | ||
id: create-task | ||
env: | ||
CODER_USERNAME: ${{ steps.get-coder-username.outputs.coder_username }} | ||
CONTEXT_KEY: ${{ steps.extract-context.outputs.context_key }} | ||
GH_TOKEN: ${{ github.token }} | ||
GITHUB_REPOSITORY: ${{ github.repository }} | ||
ISSUE_URL: ${{ inputs.issue_url }} | ||
PREFIX: ${{ inputs.prefix }} | ||
RUN_ID: ${{ github.run_id }} | ||
@@ -125,7 +175,11 @@ jobs: | ||
export TASK_NAME="${PREFIX}-${CONTEXT_KEY}-${RUN_ID}" | ||
echo "Creating task: $TASK_NAME" | ||
./scripts/traiage.sh create | ||
if [[ "${ISSUE_URL}" == "https://github.com/${GITHUB_REPOSITORY}"* ]]; then | ||
gh issue comment "${ISSUE_URL}" --body "Task created: ${TASK_NAME}" --create-if-none --edit-last | ||
else | ||
echo "Skipping comment on other repo." | ||
fi | ||
echo "TASK_NAME=${CODER_USERNAME}/${TASK_NAME}" >> "${GITHUB_OUTPUT}" | ||
echo "TASK_NAME=${CODER_USERNAME}/${TASK_NAME}" >> "${GITHUB_ENV}" | ||
@@ -134,7 +188,11 @@ jobs: | ||
if: inputs.cleanup | ||
env: | ||
BUCKET_PREFIX: "gs://coder-traiage-outputs/traiage" | ||
CODER_USERNAME: ${{ steps.get-coder-username.outputs.coder_username }} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others.Learn more. Thoughts about echoing into the env file rather than pulling from output? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others.Learn more. I'm mostly indifferent, but I think explicitly pulling from output makes it easier to see the dependency chain between the steps. If you just dump everything into | ||
TASK_NAME: ${{ steps.create-task.outputs.TASK_NAME }} | ||
run: | | ||
echo "Waiting for task to complete..." | ||
coder exp task status "${CODER_USERNAME}/$TASK_NAME" --watch | ||
echo "Creating archive for workspace: $TASK_NAME" | ||
./scripts/traiage.sh archive | ||
echo "archive_url=${BUCKET_PREFIX%%/}/$TASK_NAME.tar.gz" >> "${GITHUB_OUTPUT}" | ||
@@ -145,8 +203,9 @@ jobs: | ||
env: | ||
ARCHIVE_URL: ${{ steps.create-archive.outputs.archive_url }} | ||
BUCKET_PREFIX: "gs://coder-traiage-outputs/traiage" | ||
CODER_USERNAME: ${{ steps.get-coder-username.outputs.coder_username }} | ||
CONTEXT_KEY: ${{ steps.extract-context.outputs.context_key }} | ||
GH_TOKEN: ${{ github.token }} | ||
GITHUB_REPOSITORY: ${{ github.repository }} | ||
ISSUE_URL: ${{ inputs.issue_url }} | ||
TASK_NAME: ${{ steps.create-task.outputs.TASK_NAME }} | ||
Uh oh!
There was an error while loading.Please reload this page.