Skip to content

Commit 013f33f

Browse files
Gkrumbach07Ambient Code Botclaude
authored
feat: amber GHA — stop-on-run-finished, prompt split, security fixes (#1193)
## Summary GHA workflow updates. Depends on ambient-action v0.0.5 (ambient-code/ambient-action#4). ### Changes - Use `stop-on-run-finished: 'true'` with `timeout: '0'` — sessions stop when done, no inactivity timer - `@amber` alone → fix prompt (PR: resolve CI/conflicts/reviews, issue: investigate and fix) - `@amber <text>` → custom prompt (just context + user's words) - Shell injection fix: comment body passed via env var - Session summary uses `||` fallback - Bump ambient-action to v0.0.5 ## Test plan - [ ] `@amber` on PR → fix prompt triggers - [ ] `@amber do something` on issue → custom prompt triggers - [ ] `amber:auto-fix` label → fresh prompt triggers - [ ] Batch cron runs and processes amber:managed PRs 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Chores** * Renamed comment command and workflow labels from "@amber"/"amber:*" to "@ambient-code"/"ambient-code:*". * Improved comment parsing to detect and handle "@ambient-code" comments and added explicit PR-vs-issue branching via an IS_PR flag. * Disabled automatic timeouts for several workflow steps to avoid premature termination. * Consolidated session-summary selection to choose the first available summary. * Removed a fixed inactivity timeout and cleaned up session initialization logic. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Ambient Code Bot <bot@ambient-code.local> Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 440f5b9 commit 013f33f

1 file changed

Lines changed: 41 additions & 39 deletions

File tree

.github/workflows/amber-issue-handler.yml

Lines changed: 41 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@
33
# Single workflow for all Amber AI automation.
44
#
55
# TRIGGERS:
6-
# - Issue labeled with: amber:auto-fix → fresh session prompt
7-
# - Comment "@amber" alone on issue/PR → follow-up/fix prompt
8-
# - Comment "@amber <instruction>" on issue/PR → custom prompt
9-
# - Cron every 30 min → shell-driven batch for all amber:managed PRs
6+
# - Issue labeled with: ambient-code:auto-fix → fresh session prompt
7+
# - Comment "@ambient-code" alone on issue/PR → follow-up/fix prompt
8+
# - Comment "@ambient-code <instruction>" on issue/PR → custom prompt
9+
# - Cron every 30 min → shell-driven batch for all ambient-code:managed PRs
1010
# - Manual dispatch → same as cron
1111
#
1212
# SESSION REUSE:
@@ -30,11 +30,11 @@ permissions:
3030
pull-requests: write
3131

3232
jobs:
33-
# -- Issue: labeled amber:auto-fix → fresh session prompt --
33+
# -- Issue: labeled ambient-code:auto-fix → fresh session prompt --
3434
handle-issue-label:
3535
if: >-
3636
github.event_name == 'issues'
37-
&& github.event.label.name == 'amber:auto-fix'
37+
&& github.event.label.name == 'ambient-code:auto-fix'
3838
concurrency:
3939
group: amber-${{ github.event.issue.number }}
4040
cancel-in-progress: false
@@ -57,9 +57,9 @@ jobs:
5757
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
5858
run: |
5959
NUMBER="${{ steps.issue.outputs.number }}"
60-
EXISTING=$(gh pr list --repo "${{ github.repository }}" --state open --label "amber:managed" --limit 200 --json number,body --jq ".[] | select((.body // \"\") | test(\"source=#${NUMBER}(\\\\s|$)\")) | .number" | head -1 || echo "")
60+
EXISTING=$(gh pr list --repo "${{ github.repository }}" --state open --label "ambient-code:managed" --limit 200 --json number,body --jq ".[] | select((.body // \"\") | test(\"source=#${NUMBER}(\\\\s|$)\")) | .number" | head -1 || echo "")
6161
if [ -n "$EXISTING" ]; then
62-
echo "Found existing amber:managed PR #$EXISTING for issue #$NUMBER — skipping"
62+
echo "Found existing ambient-code:managed PR #$EXISTING for issue #$NUMBER — skipping"
6363
echo "skip=true" >> $GITHUB_OUTPUT
6464
else
6565
echo "skip=false" >> $GITHUB_OUTPUT
@@ -88,14 +88,14 @@ jobs:
8888
first line of the PR body (read your session ID from the
8989
AGENTIC_SESSION_NAME environment variable):
9090
<!-- acp:session_id=$AGENTIC_SESSION_NAME source=#${{ steps.issue.outputs.number }} last_action=<ISO8601_NOW> retry_count=0 -->
91-
5. Add the `amber:managed` label to the PR.
91+
5. Add the `ambient-code:managed` label to the PR.
9292
6. Ensure CI passes. If it fails, investigate and fix.
9393
7. Do not merge. Leave the PR open for human review.
9494
repos: >-
9595
[{"url": "https://github.com/${{ github.repository }}", "branch": "main"}]
9696
model: claude-opus-4-6
9797
wait: 'true'
98-
timeout: '60'
98+
timeout: '0'
9999

100100
- name: Post-session labels and comment
101101
if: steps.existing.outputs.skip != 'true'
@@ -105,8 +105,8 @@ jobs:
105105
SESSION_PHASE: ${{ steps.session.outputs.session-phase }}
106106
run: |
107107
if [ -n "$SESSION_NAME" ]; then
108-
gh issue edit ${{ steps.issue.outputs.number }} --repo "${{ github.repository }}" --add-label "amber:triaged" || true
109-
gh issue comment ${{ steps.issue.outputs.number }} --repo "${{ github.repository }}" --body "Session \`$SESSION_NAME\` created (phase: $SESSION_PHASE). PR will have the \`amber:managed\` label."
108+
gh issue edit ${{ steps.issue.outputs.number }} --repo "${{ github.repository }}" --add-label "ambient-code:triaged" || true
109+
gh issue comment ${{ steps.issue.outputs.number }} --repo "${{ github.repository }}" --body "Session \`$SESSION_NAME\` created (phase: $SESSION_PHASE). PR will have the \`ambient-code:managed\` label."
110110
fi
111111
112112
- name: Session summary
@@ -124,11 +124,11 @@ jobs:
124124
echo "- **Status**: Failed to create session" >> $GITHUB_STEP_SUMMARY
125125
fi
126126
127-
# -- @amber comment on an issue or PR --
127+
# -- @ambient-code comment on an issue or PR --
128128
handle-comment:
129129
if: >-
130130
github.event_name == 'issue_comment'
131-
&& contains(github.event.comment.body, '@amber')
131+
&& contains(github.event.comment.body, '@ambient-code')
132132
&& (github.event.comment.author_association == 'MEMBER'
133133
|| github.event.comment.author_association == 'OWNER'
134134
|| github.event.comment.author_association == 'COLLABORATOR')
@@ -143,19 +143,20 @@ jobs:
143143
env:
144144
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
145145
COMMENT_BODY: ${{ github.event.comment.body }}
146+
IS_PR: ${{ github.event.issue.pull_request && 'true' || 'false' }}
146147
run: |
147148
NUMBER="${{ github.event.issue.number }}"
148149
echo "number=$NUMBER" >> $GITHUB_OUTPUT
149150
150-
# Determine if @amber is alone (fix prompt) or has instruction text (custom prompt)
151-
STRIPPED=$(echo "$COMMENT_BODY" | sed 's/@amber//g' | tr -d '[:space:]')
151+
# Determine if @ambient-code is alone (fix prompt) or has instruction text (custom prompt)
152+
STRIPPED=$(echo "$COMMENT_BODY" | sed 's/@ambient-code//g' | tr -d '[:space:]')
152153
if [ -z "$STRIPPED" ]; then
153154
echo "prompt_type=fix" >> $GITHUB_OUTPUT
154155
else
155156
echo "prompt_type=custom" >> $GITHUB_OUTPUT
156157
fi
157158
158-
if [ -n "${{ github.event.issue.pull_request }}" ]; then
159+
if [ "$IS_PR" = "true" ]; then
159160
echo "type=pr" >> $GITHUB_OUTPUT
160161
echo "url=https://github.com/${{ github.repository }}/pull/$NUMBER" >> $GITHUB_OUTPUT
161162
@@ -171,8 +172,8 @@ jobs:
171172
echo "url=https://github.com/${{ github.repository }}/issues/$NUMBER" >> $GITHUB_OUTPUT
172173
echo "is_fork=false" >> $GITHUB_OUTPUT
173174
174-
# Check for existing amber:managed PR for this issue and get its session ID
175-
EXISTING_PR=$(gh pr list --repo "${{ github.repository }}" --state open --label "amber:managed" --limit 200 --json number,body --jq ".[] | select((.body // \"\") | test(\"source=#${NUMBER}(\\\\s|$)\"))" | head -1 || echo "")
175+
# Check for existing ambient-code:managed PR for this issue and get its session ID
176+
EXISTING_PR=$(gh pr list --repo "${{ github.repository }}" --state open --label "ambient-code:managed" --limit 200 --json number,body --jq ".[] | select((.body // \"\") | test(\"source=#${NUMBER}(\\\\s|$)\"))" | head -1 || echo "")
176177
if [ -n "$EXISTING_PR" ]; then
177178
SESSION_ID=$(echo "$EXISTING_PR" | jq -r '.body' | grep -oP 'acp:session_id=\K[^ ]+' | head -1 || echo "")
178179
echo "session_id=$SESSION_ID" >> $GITHUB_OUTPUT
@@ -181,7 +182,7 @@ jobs:
181182
fi
182183
fi
183184
184-
# Fix prompt on a PR: @amber alone — assess and fix CI/conflicts/reviews
185+
# Fix prompt on a PR: @ambient-code alone — assess and fix CI/conflicts/reviews
185186
- name: Run fix prompt (PR)
186187
if: >-
187188
steps.context.outputs.is_fork != 'true'
@@ -209,11 +210,11 @@ jobs:
209210
3. Ensure the PR body contains this frontmatter as the first line
210211
(read your session ID from the AGENTIC_SESSION_NAME environment variable):
211212
<!-- acp:session_id=$AGENTIC_SESSION_NAME source=#${{ steps.context.outputs.number }} last_action=<ISO8601_NOW> retry_count=0 -->
212-
4. Add the `amber:managed` label.
213+
4. Add the `ambient-code:managed` label.
213214
5. Do not merge. Do not close. Do not force-push.
214215
6. If fundamentally broken beyond repair, add a comment explaining and stop.
215216
216-
# Fix prompt on an issue: @amber alone — investigate and create PR (same as fresh prompt)
217+
# Fix prompt on an issue: @ambient-code alone — investigate and create PR (same as fresh prompt)
217218
- name: Run fix prompt (issue)
218219
if: >-
219220
steps.context.outputs.is_fork != 'true'
@@ -241,16 +242,16 @@ jobs:
241242
first line of the PR body (read your session ID from the
242243
AGENTIC_SESSION_NAME environment variable):
243244
<!-- acp:session_id=$AGENTIC_SESSION_NAME source=#${{ steps.context.outputs.number }} last_action=<ISO8601_NOW> retry_count=0 -->
244-
5. Add the `amber:managed` label to the PR.
245+
5. Add the `ambient-code:managed` label to the PR.
245246
6. Ensure CI passes. If it fails, investigate and fix.
246247
7. Do not merge. Leave the PR open for human review.
247248
repos: >-
248249
[{"url": "https://github.com/${{ github.repository }}", "branch": "main"}]
249250
model: claude-opus-4-6
250251
wait: 'true'
251-
timeout: '60'
252+
timeout: '0'
252253

253-
# Custom prompt: @amber <instruction> — pass user's text
254+
# Custom prompt: @ambient-code <instruction> — pass user's text
254255
- name: Run custom prompt
255256
if: >-
256257
steps.context.outputs.is_fork != 'true'
@@ -271,14 +272,14 @@ jobs:
271272
[{"url": "https://github.com/${{ github.repository }}", "branch": "main"}]
272273
model: claude-opus-4-6
273274
wait: 'true'
274-
timeout: '60'
275+
timeout: '0'
275276

276277
- name: Session summary
277278
if: always() && steps.context.outputs.is_fork != 'true'
278279
run: |
279-
# Get session name from whichever step ran
280-
SESSION_NAME="${{ steps.fix-session.outputs.session-name }}${{ steps.fix-issue-session.outputs.session-name }}${{ steps.custom-session.outputs.session-name }}"
281-
SESSION_PHASE="${{ steps.fix-session.outputs.session-phase }}${{ steps.fix-issue-session.outputs.session-phase }}${{ steps.custom-session.outputs.session-phase }}"
280+
# Get session name from whichever step ran (only one will have output)
281+
SESSION_NAME="${{ steps.fix-session.outputs.session-name || steps.fix-issue-session.outputs.session-name || steps.custom-session.outputs.session-name }}"
282+
SESSION_PHASE="${{ steps.fix-session.outputs.session-phase || steps.fix-issue-session.outputs.session-phase || steps.custom-session.outputs.session-phase }}"
282283
283284
echo "### Amber — ${{ steps.context.outputs.type }} #${{ steps.context.outputs.number }}" >> $GITHUB_STEP_SUMMARY
284285
echo "" >> $GITHUB_STEP_SUMMARY
@@ -290,7 +291,7 @@ jobs:
290291
echo "- **Status**: Failed to create session" >> $GITHUB_STEP_SUMMARY
291292
fi
292293
293-
# -- Batch: manage all amber:managed PRs (shell-driven) --
294+
# -- Batch: manage all ambient-code:managed PRs (shell-driven) --
294295
batch-pr-fixer:
295296
if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch'
296297
concurrency:
@@ -299,7 +300,7 @@ jobs:
299300
runs-on: ubuntu-latest
300301
timeout-minutes: 45
301302
steps:
302-
- name: Find and process amber:managed PRs
303+
- name: Find and process ambient-code:managed PRs
303304
env:
304305
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
305306
AMBIENT_API_URL: ${{ secrets.AMBIENT_API_URL }}
@@ -313,6 +314,8 @@ jobs:
313314
import os
314315
import re
315316
import subprocess
317+
import time
318+
import uuid
316319
import requests
317320
from datetime import datetime, timezone
318321
@@ -368,7 +371,6 @@ jobs:
368371
369372
def create_session_api(prompt, session_name="", model="claude-opus-4-6"):
370373
"""Create a new session or send message to existing one."""
371-
import time, uuid
372374
373375
if session_name:
374376
# Ensure session is running
@@ -401,7 +403,7 @@ jobs:
401403
402404
# Create new session
403405
url = f"{API_URL.rstrip('/')}/projects/{PROJECT}/agentic-sessions"
404-
body = {"initialPrompt": prompt, "inactivityTimeout": 60,
406+
body = {"initialPrompt": prompt,
405407
"llmSettings": {"model": model},
406408
"repos": [{"url": f"https://github.com/{REPO}", "branch": "main"}]}
407409
try:
@@ -415,12 +417,12 @@ jobs:
415417
print(f" Failed to create session: {e}")
416418
return None
417419
418-
# Get all open amber:managed PRs (include updatedAt to avoid per-PR API calls)
420+
# Get all open ambient-code:managed PRs (include updatedAt to avoid per-PR API calls)
419421
prs_json = gh("pr", "list", "--repo", REPO, "--state", "open",
420-
"--label", "amber:managed", "--limit", "200",
422+
"--label", "ambient-code:managed", "--limit", "200",
421423
"--json", "number,body,title,updatedAt")
422424
prs = json.loads(prs_json) if prs_json else []
423-
print(f"Found {len(prs)} amber:managed PRs")
425+
print(f"Found {len(prs)} ambient-code:managed PRs")
424426
425427
processed = 0
426428
skipped = 0
@@ -441,8 +443,8 @@ jobs:
441443
442444
# Circuit breaker
443445
if fm["retry_count"] >= 3:
444-
print(f"PR #{number}: circuit breaker (retry_count={fm['retry_count']}), adding amber:needs-human")
445-
gh("pr", "edit", str(number), "--repo", REPO, "--add-label", "amber:needs-human", "--remove-label", "amber:managed")
446+
print(f"PR #{number}: circuit breaker (retry_count={fm['retry_count']}), adding ambient-code:needs-human")
447+
gh("pr", "edit", str(number), "--repo", REPO, "--add-label", "ambient-code:needs-human", "--remove-label", "ambient-code:managed")
446448
gh("pr", "comment", str(number), "--repo", REPO, "--body", "AI was unable to resolve issues after 3 attempts. Needs human attention.")
447449
continue
448450
@@ -470,7 +472,7 @@ jobs:
470472
3. Ensure the PR body contains this frontmatter as the first line
471473
(read your session ID from the AGENTIC_SESSION_NAME environment variable):
472474
<!-- acp:session_id=$AGENTIC_SESSION_NAME source={source} last_action=<ISO8601_NOW> retry_count=0 -->
473-
4. Add the `amber:managed` label.
475+
4. Add the `ambient-code:managed` label.
474476
5. Do not merge. Do not close. Do not force-push.
475477
6. If fundamentally broken beyond repair, add a comment explaining and stop."""
476478

0 commit comments

Comments
 (0)