-
Notifications
You must be signed in to change notification settings - Fork 1
134 lines (124 loc) · 4.98 KB
/
Copy pathagent-devops.yml
File metadata and controls
134 lines (124 loc) · 4.98 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
name: DevOps Agent
# Triggers Cursor's DevOps Cloud Agent via API after a qa-passed PR merges
# into staging. The workflow waits for the agent and posts its report as
# a comment on the merged PR (Cursor's sandbox token can't comment).
on:
pull_request:
types: [closed]
jobs:
# Gate the agent on CURSOR_API_KEY being present. Secrets can't be used in
# job-level `if:`, so we surface presence as an output here and skip cleanly
# (neutral, not failed) on repos that haven't set the key.
guard:
name: Check Cursor API key
runs-on: ubuntu-latest
outputs:
has_key: ${{ steps.check.outputs.has_key }}
steps:
- id: check
env:
CURSOR_API_KEY: ${{ secrets.CURSOR_API_KEY }}
run: |
if [ -n "$CURSOR_API_KEY" ]; then
echo "has_key=true" >> "$GITHUB_OUTPUT"
else
echo "has_key=false" >> "$GITHUB_OUTPUT"
echo "::notice title=Cursor agent skipped::CURSOR_API_KEY is not set on this repo — skipping. Set it with: gh secret set CURSOR_API_KEY --repo <owner>/<repo>"
fi
trigger:
name: Run DevOps Agent
needs: guard
if: >
needs.guard.outputs.has_key == 'true' &&
github.event.pull_request.merged == true &&
github.event.pull_request.base.ref == 'staging' &&
contains(github.event.pull_request.labels.*.name, 'qa-passed')
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write
issues: write
timeout-minutes: 20
steps:
- uses: actions/checkout@v7
with:
ref: ${{ github.event.repository.default_branch }}
- name: Trigger Cursor agent
id: trigger
env:
CURSOR_API_KEY: ${{ secrets.CURSOR_API_KEY }}
REPO: ${{ github.repository }}
DEFAULT_BRANCH: ${{ github.event.repository.default_branch }}
PR_TITLE: ${{ github.event.pull_request.title }}
PR_URL: ${{ github.event.pull_request.html_url }}
PR_BASE: ${{ github.event.pull_request.base.ref }}
run: |
set -euo pipefail
PROMPT=$(jq -Rs \
--arg repo "$REPO" \
--arg t "$PR_TITLE" \
--arg u "$PR_URL" \
--arg base "$PR_BASE" \
'
gsub("\\{\\{repo\\}\\}"; $repo)
| gsub("\\{\\{pr.title\\}\\}"; $t)
| gsub("\\{\\{pr.url\\}\\}"; $u)
| gsub("\\{\\{pr.base_ref\\}\\}"; $base)
' .cursor/agent-prompts/devops.md)
PAYLOAD=$(jq -n \
--arg prompt "$PROMPT" \
--arg repo "$REPO" \
--arg ref "$DEFAULT_BRANCH" \
'{
prompt: { text: $prompt },
source: { repository: ("github.com/" + $repo), ref: $ref },
target: { autoCreatePr: false, openAsCursorGithubApp: true },
model: "composer-2.5"
}')
response=$(curl -sS -X POST "https://api.cursor.com/v0/agents" \
-H "Authorization: Bearer $CURSOR_API_KEY" \
-H "Content-Type: application/json" \
-d "$PAYLOAD")
echo "$response" | jq .
AGENT_ID=$(echo "$response" | jq -er '.id')
echo "agent_id=$AGENT_ID" >> "$GITHUB_OUTPUT"
- name: Wait for agent to finish
id: wait
env:
CURSOR_API_KEY: ${{ secrets.CURSOR_API_KEY }}
AGENT_ID: ${{ steps.trigger.outputs.agent_id }}
run: |
set -euo pipefail
for i in $(seq 1 30); do
agent_status=$(curl -sS "https://api.cursor.com/v0/agents/$AGENT_ID" \
-H "Authorization: Bearer $CURSOR_API_KEY" | jq -r '.status')
echo "[$i/30] status: $agent_status"
if [[ "$agent_status" != "RUNNING" && "$agent_status" != "CREATING" ]]; then
echo "final_status=$agent_status" >> "$GITHUB_OUTPUT"
exit 0
fi
sleep 30
done
echo "final_status=TIMEOUT" >> "$GITHUB_OUTPUT"
- name: Post agent report as PR comment
env:
CURSOR_API_KEY: ${{ secrets.CURSOR_API_KEY }}
AGENT_ID: ${{ steps.trigger.outputs.agent_id }}
AGENT_STATUS: ${{ steps.wait.outputs.final_status }}
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PR: ${{ github.event.pull_request.number }}
REPO: ${{ github.repository }}
run: |
set -euo pipefail
REPORT=$(curl -sS "https://api.cursor.com/v0/agents/$AGENT_ID/conversation" \
-H "Authorization: Bearer $CURSOR_API_KEY" \
| jq -r '[.messages[] | select(.type == "assistant_message") | .text] | last')
{
echo "## DevOps verification (Cursor DevOps agent — IaC)"
echo ""
echo "**Agent run:** [\`$AGENT_ID\`](https://cursor.com/agents/$AGENT_ID)"
echo "**Status:** \`$AGENT_STATUS\`"
echo ""
echo "$REPORT"
} > /tmp/devops-comment.md
gh pr comment "$PR" --repo "$REPO" --body-file /tmp/devops-comment.md