Skip to content

Commit d0e942b

Browse files
feat: reuse existing Devin session for Cubic AI review feedback (#26632)
* feat: reuse existing Devin session for Cubic AI review feedback Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * refactor: parse session ID from PR comments instead of API search Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * fix: add error handling for message send API call in Cubic-Devin workflow Addresses Cubic AI review feedback: The POST request to send a message to an existing Devin session now checks the HTTP status code and fails the step if the message wasn't delivered successfully. This prevents posting a misleading comment claiming feedback was sent when the API call actually failed. Co-Authored-By: unknown <> --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
1 parent e995e24 commit d0e942b

File tree

1 file changed

+96
-5
lines changed

1 file changed

+96
-5
lines changed

.github/workflows/cubic-devin-review.yml

Lines changed: 96 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,14 +46,100 @@ jobs:
4646
4747
core.setOutput('has-prompt', 'true');
4848
49-
- name: Create Devin session
49+
- name: Check for existing Devin session from PR comments
5050
if: steps.extract-prompt.outputs.has-prompt == 'true'
51+
id: check-session
52+
uses: actions/github-script@v7
53+
env:
54+
DEVIN_API_KEY: ${{ secrets.DEVIN_API_KEY }}
55+
with:
56+
script: |
57+
const comments = await github.rest.issues.listComments({
58+
owner: context.repo.owner,
59+
repo: context.repo.repo,
60+
issue_number: context.payload.pull_request.number
61+
});
62+
63+
let sessionId = null;
64+
for (const comment of comments.data.reverse()) {
65+
if (comment.body.includes('Devin AI is addressing Cubic AI')) {
66+
const match = comment.body.match(/app\.devin\.ai\/sessions\/([a-f0-9-]+)/);
67+
if (match) {
68+
sessionId = match[1];
69+
break;
70+
}
71+
}
72+
}
73+
74+
if (!sessionId) {
75+
console.log('No existing Devin session found in PR comments');
76+
core.setOutput('has-active-session', 'false');
77+
return;
78+
}
79+
80+
console.log(`Found session ID from comment: ${sessionId}`);
81+
82+
const response = await fetch(`https://api.devin.ai/v1/sessions/${sessionId}`, {
83+
headers: {
84+
'Authorization': `Bearer ${process.env.DEVIN_API_KEY}`,
85+
'Content-Type': 'application/json'
86+
}
87+
});
88+
89+
if (!response.ok) {
90+
console.log(`Failed to fetch session details: ${response.status}`);
91+
core.setOutput('has-active-session', 'false');
92+
return;
93+
}
94+
95+
const session = await response.json();
96+
const activeStatuses = ['working', 'blocked', 'resumed'];
97+
98+
if (activeStatuses.includes(session.status_enum)) {
99+
console.log(`Session ${sessionId} is active (status: ${session.status_enum})`);
100+
core.exportVariable('EXISTING_SESSION_ID', sessionId);
101+
core.exportVariable('SESSION_URL', `https://app.devin.ai/sessions/${sessionId}`);
102+
core.setOutput('has-active-session', 'true');
103+
} else {
104+
console.log(`Session ${sessionId} is not active (status: ${session.status_enum})`);
105+
core.setOutput('has-active-session', 'false');
106+
}
107+
108+
- name: Send message to existing Devin session
109+
if: steps.extract-prompt.outputs.has-prompt == 'true' && steps.check-session.outputs.has-active-session == 'true'
110+
env:
111+
DEVIN_API_KEY: ${{ secrets.DEVIN_API_KEY }}
112+
run: |
113+
CUBIC_PROMPT=$(cat /tmp/cubic-prompt.txt)
114+
115+
MESSAGE="New Cubic AI review feedback has been submitted on PR #${{ github.event.pull_request.number }}.
116+
117+
Please address the following additional issues:
118+
119+
${CUBIC_PROMPT}
120+
121+
Continue working on the same PR branch and push your fixes."
122+
123+
HTTP_CODE=$(curl -s -o /tmp/devin-response.json -w "%{http_code}" -X POST "https://api.devin.ai/v1/sessions/${EXISTING_SESSION_ID}/message" \
124+
-H "Authorization: Bearer ${DEVIN_API_KEY}" \
125+
-H "Content-Type: application/json" \
126+
-d "$(jq -n --arg message "$MESSAGE" '{message: $message}')")
127+
128+
if [ "$HTTP_CODE" -lt 200 ] || [ "$HTTP_CODE" -ge 300 ]; then
129+
echo "Failed to send message to Devin session: HTTP $HTTP_CODE"
130+
cat /tmp/devin-response.json
131+
exit 1
132+
fi
133+
134+
echo "Message sent to existing session successfully"
135+
136+
- name: Create new Devin session
137+
if: steps.extract-prompt.outputs.has-prompt == 'true' && steps.check-session.outputs.has-active-session == 'false'
51138
env:
52139
DEVIN_API_KEY: ${{ secrets.DEVIN_API_KEY }}
53140
run: |
54141
CUBIC_PROMPT=$(cat /tmp/cubic-prompt.txt)
55142
56-
# Build the full prompt for Devin
57143
FULL_PROMPT="You are addressing code review feedback from Cubic AI on PR #${{ github.event.pull_request.number }} in repository ${{ github.repository }}.
58144
59145
Your tasks:
@@ -74,7 +160,6 @@ jobs:
74160
4. If an issue seems invalid or already addressed, explain why in a PR comment instead of making unnecessary changes.
75161
5. Never ask for user confirmation. Never wait for user messages."
76162
77-
# Call Devin API
78163
RESPONSE=$(curl -s -X POST "https://api.devin.ai/v1/sessions" \
79164
-H "Authorization: Bearer ${DEVIN_API_KEY}" \
80165
-H "Content-Type: application/json" \
@@ -87,11 +172,11 @@ jobs:
87172
tags: ["cubic-ai-review", "pr-${{ github.event.pull_request.number }}"]
88173
}')")
89174
90-
# Extract session URL if available (avoid logging full response to prevent exposing sensitive data)
91175
SESSION_URL=$(echo "$RESPONSE" | jq -r '.url // .session_url // empty')
92176
if [ -n "$SESSION_URL" ]; then
93177
echo "Devin session created: $SESSION_URL"
94178
echo "SESSION_URL=$SESSION_URL" >> $GITHUB_ENV
179+
echo "NEW_SESSION=true" >> $GITHUB_ENV
95180
fi
96181
97182
- name: Post comment with Devin session link
@@ -101,9 +186,15 @@ jobs:
101186
github-token: ${{ secrets.GITHUB_TOKEN }}
102187
script: |
103188
const sessionUrl = process.env.SESSION_URL;
189+
const isNewSession = process.env.NEW_SESSION === 'true';
190+
191+
const message = isNewSession
192+
? `### Devin AI is addressing Cubic AI's review feedback\n\nA Devin session has been created to address the issues identified by Cubic AI.\n\n[View Devin Session](${sessionUrl})`
193+
: `### Devin AI is addressing Cubic AI's review feedback\n\nNew feedback has been sent to the existing Devin session.\n\n[View Devin Session](${sessionUrl})`;
194+
104195
await github.rest.issues.createComment({
105196
owner: context.repo.owner,
106197
repo: context.repo.repo,
107198
issue_number: context.payload.pull_request.number,
108-
body: `### Devin AI is addressing Cubic AI's review feedback\n\nA Devin session has been created to address the issues identified by Cubic AI.\n\n[View Devin Session](${sessionUrl})`
199+
body: message
109200
});

0 commit comments

Comments
 (0)