Skip to content

Commit 20ba869

Browse files
fix: end-to-end agent testing on this PR
- Fix system prompt: concrete example, no angle brackets - Fix filepath parsing edge cases - Add 3-min wait for PR CI to complete before checking failures - Add aiohttp==3.9.0 to Dockerfile to trigger CVE scan failure - Remove workflow_dispatch (not needed) - Add docker/vllm/Dockerfile to PR trigger paths Flow: PR push → PR-vLLM-EC2 runs (fails on CVE) → agent waits 3min → finds failure → downloads logs → LLM fixes → applies TODO after validation: remove pull_request trigger, remove aiohttp, restore branch validation
1 parent 9d519f6 commit 20ba869

3 files changed

Lines changed: 54 additions & 17 deletions

File tree

.github/workflows/agent-currency-fix.yml

Lines changed: 41 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,13 @@ on:
88
workflow_run:
99
workflows: ["Merge Conditions"]
1010
types: [completed]
11+
# PR trigger for testing (remove after validation)
12+
pull_request:
13+
branches: [main]
14+
paths:
15+
- "scripts/autocurrency/agent-fix.py"
16+
- ".github/workflows/agent-currency-fix.yml"
17+
- "docker/vllm/Dockerfile"
1118

1219
permissions:
1320
contents: read
@@ -23,19 +30,27 @@ env:
2330
jobs:
2431
fix-agent:
2532
if: >-
26-
github.event.workflow_run.conclusion == 'failure' &&
27-
startsWith(github.event.workflow_run.head_branch, 'auto-update/')
33+
github.event_name == 'workflow_dispatch' ||
34+
github.event_name == 'pull_request' || (
35+
github.event.workflow_run.conclusion == 'failure' &&
36+
startsWith(github.event.workflow_run.head_branch, 'auto-update/')
37+
)
2838
runs-on:
2939
- codebuild-runner-${{ github.run_id }}-${{ github.run_attempt }}
3040
fleet:default-runner
3141
buildspec-override:true
3242
env:
33-
HEAD_BRANCH: ${{ github.event.workflow_run.head_branch }}
34-
RUN_ID: ${{ github.event.workflow_run.id }}
35-
RUN_URL: ${{ github.event.workflow_run.html_url }}
43+
HEAD_BRANCH: ${{ github.event.workflow_run.head_branch || github.head_ref }}
44+
RUN_ID: ${{ github.event.workflow_run.id || '' }}
45+
RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
3646
steps:
3747
- name: Validate branch name
3848
run: |
49+
# Skip validation for pull_request testing
50+
if [ "${{ github.event_name }}" = "pull_request" ]; then
51+
echo "Skipping branch validation for PR testing"
52+
exit 0
53+
fi
3954
if [[ ! "$HEAD_BRANCH" =~ ^auto-update/[a-z]+-[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
4055
echo "::error::Branch '${HEAD_BRANCH}' does not match expected pattern."
4156
exit 1
@@ -51,13 +66,27 @@ jobs:
5166
fi
5267
gh --version
5368
69+
# For pull_request testing: wait for PR CI to complete before checking
70+
- name: Wait for CI to complete
71+
if: github.event_name == 'pull_request'
72+
run: |
73+
echo "Waiting 3 minutes for PR CI workflows to complete..."
74+
sleep 180
75+
5476
- name: Find failed tracked workflows
5577
id: failures
5678
env:
5779
GH_TOKEN: ${{ github.token }}
5880
run: |
5981
TRACKED="PR - vLLM EC2|PR - vLLM SageMaker|PR - SGLang EC2|PR - SGLang SageMaker"
60-
SHA=$(gh api "/repos/${{ github.repository }}/actions/runs/${RUN_ID}" --jq '.head_sha')
82+
83+
# Get HEAD SHA depending on event type
84+
if [ -n "$RUN_ID" ]; then
85+
SHA=$(gh api "/repos/${{ github.repository }}/actions/runs/${RUN_ID}" --jq '.head_sha')
86+
else
87+
SHA="${{ github.event.pull_request.head.sha || github.sha }}"
88+
fi
89+
echo "SHA: $SHA"
6190
6291
FAILED_RUN_IDS=$(gh api "/repos/${{ github.repository }}/actions/runs?head_sha=${SHA}&status=completed&per_page=50" \
6392
--jq "[.workflow_runs[] | select(.conclusion == \"failure\" and (.name | test(\"${TRACKED}\")))] | .[].id" \
@@ -93,16 +122,19 @@ jobs:
93122
if: steps.failures.outputs.has_failures == 'true'
94123
uses: actions/checkout@v5
95124
with:
96-
ref: main
125+
ref: ${{ github.event_name == 'pull_request' && github.head_ref || 'main' }}
97126
fetch-depth: 0
98127
token: ${{ steps.app-token.outputs.token }}
99128

100129
- name: Prepare workspace
101130
if: steps.failures.outputs.has_failures == 'true'
102131
run: |
103132
cp scripts/autocurrency/agent-fix.py /tmp/agent-fix.py
104-
git fetch origin "$HEAD_BRANCH"
105-
git checkout "origin/$HEAD_BRANCH" -B pr-branch
133+
# For pull_request testing, we're already on the right branch
134+
if [ "${{ github.event_name }}" != "pull_request" ]; then
135+
git fetch origin "$HEAD_BRANCH"
136+
git checkout "origin/$HEAD_BRANCH" -B pr-branch
137+
fi
106138
107139
- name: Count previous attempts
108140
if: steps.failures.outputs.has_failures == 'true'

docker/vllm/Dockerfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ RUN uv pip install --system \
3838
"PyJWT>=2.12.0" \
3939
"model-hosting-container-standards>=0.1.15,<1.0.0" \
4040
"pyasn1>=0.6.3" \
41+
"aiohttp==3.9.0" \
4142
&& uv cache clean
4243

4344
COPY ./scripts/telemetry/deep_learning_container.py /usr/local/bin/deep_learning_container.py

scripts/autocurrency/agent-fix.py

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -43,19 +43,21 @@
4343
If the failure is TRANSIENT (capacity, timeout, runner crash), respond with exactly:
4444
TRANSIENT: <brief reason>
4545
46-
Otherwise, respond with search/replace blocks:
46+
Otherwise, respond with search/replace blocks. Use this EXACT format:
4747
48-
<filepath>
48+
path/to/file.ext
4949
<<<<<<< SEARCH
50-
<exact text to find in the file>
50+
exact text to find in the file
5151
=======
52-
<replacement text>
52+
replacement text
5353
>>>>>>> REPLACE
5454
55+
IMPORTANT: Write the file path as plain text (e.g., docker/vllm/Dockerfile). Do NOT wrap it in angle brackets, backticks, or any other formatting.
56+
5557
Include 1-2 surrounding lines in SEARCH for unique anchoring.
5658
For JSON arrays (allowlists), SEARCH the last few lines and REPLACE with those lines plus the new entry.
5759
58-
End with: DESCRIPTION: <one-line commit message>"""
60+
End with: DESCRIPTION: one-line commit message"""
5961

6062

6163
def parse_args():
@@ -193,8 +195,9 @@ def parse_blocks(response: str) -> list:
193195
blocks = []
194196
for m in SEARCH_REPLACE_PATTERN.finditer(response):
195197
filepath = m.group(1).strip().strip("`").strip()
196-
# Strip common LLM artifacts: <filepath>, **filepath**, `filepath`
197-
filepath = re.sub(r"^<\w+>|<\/\w+>$", "", filepath).strip()
198+
# Strip all common LLM artifacts: <filepath>path, <path>, **path**, `path`
199+
filepath = re.sub(r"^<[^>]*>", "", filepath).strip() # strips <filepath>, <file>, etc.
200+
filepath = re.sub(r"^<|>$", "", filepath).strip() # strips bare < >
198201
filepath = filepath.strip("*").strip("`").strip()
199202
blocks.append({"path": filepath, "search": m.group(2), "replace": m.group(3)})
200203
return blocks
@@ -336,7 +339,8 @@ def main():
336339

337340
blocks = parse_blocks(response)
338341
if blocks:
339-
print(f"Parsed {len(blocks)} block(s): {[b["path"] for b in blocks]}")
342+
paths = [b["path"] for b in blocks]
343+
print(f"Parsed {len(blocks)} block(s): {paths}")
340344
if not blocks:
341345
retry_context = (
342346
f"Could not parse search/replace blocks from response.\n"

0 commit comments

Comments
 (0)