Skip to content

Commit d202682

Browse files
dhairyashiilanikdhabaldevin-ai-integration[bot]keithwillcodeAnshumancanrock
authored
feat(companion): new event type detail page (#26678)
* fix: skip stale run-ci label check on workflow re-runs (#26590) * fix: trust community PRs when maintainer pushes to the branch When a maintainer merges main into a community PR branch, the new SHA invalidates the run-ci label timing check because the label was added before the new push. This fix adds a check to trust the PR if the person who pushed the latest commit has write access. This handles the case where a maintainer: - Merges main into a community PR to resolve conflicts - Pushes any changes to help the contributor The security model is maintained because: - Only users with write access can trigger this trust - The maintainer has reviewed the code by pushing to it Co-Authored-By: anik@cal.com <adhabal2002@gmail.com> * fix: skip stale label check on workflow re-runs Instead of implicitly trusting maintainer pushes (which could be just a sync action without code review), use github.run_attempt to detect re-runs. If run_attempt > 1, it means the workflow was explicitly re-triggered (via run-ci.yml or manual re-run), so we skip the stale label check. This avoids the need to remove and re-add the 'run-ci' label after syncing a community PR with main, while keeping the explicit approval flow intact. Co-Authored-By: anik@cal.com <adhabal2002@gmail.com> * Simplify comment about re-runs in PR workflow --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: Keith Williams <keithwillcode@gmail.com> * fix: Text cursor barely visible in calendar event name field (#26563) * fix: cursor visibility in input fields * fix: cursor visibility in input fields with suffix addons * fix: text cursor visibility in input fields --------- Co-authored-by: Keith Williams <keithwillcode@gmail.com> * fix: PayPal setup page inconsistent spacing and button styling (#26612) * chore: api v2 generate swagger only in dev (#26617) * feat: add BUILD_FROM_BRANCH option to release-docker workflow (#26615) * feat: add BUILD_FROM_BRANCH option to release-docker workflow Co-Authored-By: keith@cal.com <keithwillcode@gmail.com> * fix: sanitize branch names with slashes for valid Docker tags Co-Authored-By: keith@cal.com <keithwillcode@gmail.com> * refactor: extract common logic into prepare job to avoid duplication Co-Authored-By: keith@cal.com <keithwillcode@gmail.com> --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * feat: add Cubic AI to Devin review integration workflow (#26618) * feat: add Cubic AI to Devin review integration workflow Co-Authored-By: keith@cal.com <keithwillcode@gmail.com> * fix: update permissions to allow posting PR comments Co-Authored-By: keith@cal.com <keithwillcode@gmail.com> * fix: remove sensitive API response logging from CI workflow Address Cubic AI review feedback: Remove the debug log that outputs the full Devin API response, which could expose sensitive session tokens or authentication data in CI logs. The session URL is still logged when successfully extracted. Co-Authored-By: unknown <> --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * chore: enable/disable slots workers via env (#26621) * chore: enable/disable slots workers via env * fix: address Cubic AI review feedback - Fix incorrect JSDoc comment for getSerializableContext method - Remove debug console.log statement from slots controller - Fix port suffix condition to preserve original behavior Co-Authored-By: unknown <> --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * chore: USE_POOL env var for api v2 prisma pooling * fix list numbering in Manual setup section of README (#26620) * Revert "chore: USE_POOL env var for api v2 prisma pooling" This reverts commit a970926. * feat: limit badges to 2 with hover/click popover in UserListTable (#26556) * feat: limit badges to 2 with hover tooltip in UserListTable Co-Authored-By: eunjae@cal.com <hey@eunjae.dev> * refactor: reuse LimitedBadges component with clickable popover for mobile Co-Authored-By: eunjae@cal.com <hey@eunjae.dev> * refactor: move LimitedBadges to components/ui with hover+click support Co-Authored-By: eunjae@cal.com <hey@eunjae.dev> * refactor: fix Biome lint issues in LimitedBadges and UserListTable - Refactor LimitedBadges to concrete component with BadgeItem type - Move exports to end of files to comply with useExportsLast rule - Add explicit types to callback parameters for useExplicitType rule - Convert nested ternary to if-else for filterType calculation - Remove unused imports (Row, Table types) - Update ResponseValueCell and UserListTable to use new LimitedBadges API Co-Authored-By: eunjae@cal.com <hey@eunjae.dev> * fix: add proper types for filterType and getFacetedUniqueValues - Add FilterType import from @calcom/types/data-table - Add FacetedValue import from @calcom/features/data-table - Type filterType as FilterType to allow reassignment to different ColumnFilterType values - Type getFacetedUniqueValues return as Map<FacetedValue, number> Co-Authored-By: eunjae@cal.com <hey@eunjae.dev> * add vertical gap * fix: address code review feedback for LimitedBadges - Add index to id for unique keys in ResponseValueCell.tsx - Restore orange variant for group options in UserListTable.tsx - Fix useMemo dependency array (add t, remove dispatch) - Fix import ordering with biome - Convert ternary operators to if-else statements for biome compliance Co-Authored-By: eunjae@cal.com <hey@eunjae.dev> * refactor: remove id from BadgeItem type, use label as key - Remove id field from BadgeItem type in LimitedBadges - Use label as React key instead of id - Remove unused rowId parameter from ResponseValueCell - Update all consumers to not pass id field Co-Authored-By: eunjae@cal.com <hey@eunjae.dev> * refactor: use index for key instead of label in LimitedBadges Co-Authored-By: eunjae@cal.com <hey@eunjae.dev> * Revert "refactor: use index for key instead of label in LimitedBadges" This reverts commit 1daaac4. --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * chore: add database-backed feature flag for sidebar tips section (#26516) * chore: remove tips section from sidebar Co-Authored-By: amit@cal.com <samit91848@gmail.com> * chore: add feature flag for sidebar tips section Co-Authored-By: amit@cal.com <samit91848@gmail.com> * chore: use database-backed feature flag for sidebar tips section Co-Authored-By: amit@cal.com <samit91848@gmail.com> --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * feat: add automated stale PR completion workflow with Devin API (#26627) * feat: add stale PR completion workflow with Devin API Co-Authored-By: anik@cal.com <adhabal2002@gmail.com> * feat: only trigger for community PRs (non-calcom org members) Co-Authored-By: anik@cal.com <adhabal2002@gmail.com> * refactor: use author_association pattern from pr.yml for community check Co-Authored-By: anik@cal.com <adhabal2002@gmail.com> * refactor: simplify workflow - use community label check and let Devin gather PR details Co-Authored-By: anik@cal.com <adhabal2002@gmail.com> --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * feat: add Devin PR conflict resolver workflow (#26624) * feat: add Devin PR conflict resolver workflow Adds a GitHub Actions workflow that automatically detects PRs with merge conflicts and spins up Devin sessions to resolve them. How it works: 1. Triggers on push to main branch (when main updates could cause conflicts) 2. Also supports manual trigger via workflow_dispatch 3. Lists all open PRs and checks their mergeable status 4. For PRs with conflicts (mergeable=false, mergeable_state=dirty): - Checks if a Devin session was already created (avoids duplicates) - Creates a new Devin session with instructions to resolve conflicts - Posts a comment on the PR with the Devin session link The workflow follows the same pattern as cubic-devin-review.yml for consistency. Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * fix: skip draft PRs in conflict detection workflow Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * refactor: use GitHub Search API to filter draft PRs at API level Instead of filtering draft PRs in the loop, use the GitHub Search API with 'draft:false' filter which is more efficient as it filters at the API level rather than fetching all PRs and filtering locally. Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * style: remove explanatory comments from workflow Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * style: remove all unnecessary explanatory comments Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * refactor: use GraphQL for batched PR fetching and labels for tracking Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * feat: add support for resolving conflicts on fork PRs Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * fix: check response.ok before parsing Devin API response Address Cubic AI review feedback: Add response.ok check before parsing the response body to explicitly handle HTTP error status codes from the Devin API. This distinguishes API failures (authentication errors, server errors) from successful responses that might be missing expected fields. Co-Authored-By: unknown <> * fix: improve Devin API error logging with PR number Co-Authored-By: unknown <> * feat: add pr_number input for manual fork PR conflict resolution Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * feat: add maximum 15 PRs safety net limit Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * feat: make stale PR workflow fork-aware with workflow_dispatch support (#26633) * feat: make stale PR workflow fork-aware with workflow_dispatch support Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * fix: add null check for pr.head.repo in stale PR workflow When a fork is deleted after a PR is created, pr.head.repo can be null (documented GitHub API behavior). This would cause a TypeError when accessing properties like fork, full_name, or clone_url. Added a null check that fails gracefully with a clear error message when the source repository has been deleted. Co-Authored-By: unknown <> --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * 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> * chore: Remove stale label when work is completed (#26638) * chore: Remove stale label when work is completed * Mark as ready for review too * feat: add retry mechanism for UNKNOWN mergeable status PRs (#26635) * feat: add retry mechanism for UNKNOWN mergeable status PRs Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * fix: remove redundant filtering logic for unknown mergeable status PRs Address Cubic AI review feedback by: - Having processPR return isTargetPR in the unknown case (like the conflict case) - Simplifying the main loop to just push PRs to unknownPRs without re-checking draft status and devin label (already checked in processPR) Co-Authored-By: unknown <> --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * chore: Add sentry http integration (#26634) * chore: ignore fork PRs in devin-conflict-resolver workflow (#26640) Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * limits and advanced tabs * availability tab * basics tab * black toggles!! * new recurring, others tab and update basics * version 1 --------- Co-authored-by: Anik Dhabal Babu <81948346+anikdhabal@users.noreply.github.com> Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: Keith Williams <keithwillcode@gmail.com> Co-authored-by: Anshumancanrock <109489361+Anshumancanrock@users.noreply.github.com> Co-authored-by: Morgan <33722304+ThyMinimalDev@users.noreply.github.com> Co-authored-by: cal.com <morgan@cal.com> Co-authored-by: Anas Najam <129951478+anzz14@users.noreply.github.com> Co-authored-by: Eunjae Lee <hey@eunjae.dev> Co-authored-by: Amit Sharma <74371312+Amit91848@users.noreply.github.com> Co-authored-by: Volnei Munhoz <volnei@cal.com>
1 parent 1b4bad9 commit d202682

File tree

35 files changed

+3567
-1709
lines changed

35 files changed

+3567
-1709
lines changed
Lines changed: 200 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,200 @@
1+
name: Cubic AI to Devin Review
2+
3+
on:
4+
pull_request_review:
5+
types: [submitted]
6+
7+
permissions:
8+
contents: read
9+
pull-requests: write
10+
11+
jobs:
12+
trigger-devin:
13+
name: Trigger Devin to Address Cubic AI Review
14+
# Only run if the review is from cubic-dev-ai bot and contains the AI prompt
15+
if: github.event.review.user.login == 'cubic-dev-ai[bot]'
16+
runs-on: blacksmith-2vcpu-ubuntu-2404
17+
steps:
18+
- name: Extract AI prompt from Cubic review
19+
id: extract-prompt
20+
uses: actions/github-script@v7
21+
with:
22+
script: |
23+
const reviewBody = context.payload.review.body || '';
24+
25+
// Look for the AI prompt section in Cubic's review
26+
// Format: <details><summary>Prompt for AI agents (all issues)</summary>
27+
// ```text
28+
// ... prompt content ...
29+
// ```
30+
// </details>
31+
const promptMatch = reviewBody.match(/<details>\s*<summary>Prompt for AI agents[^<]*<\/summary>\s*```(?:text)?\s*([\s\S]*?)```\s*<\/details>/i);
32+
33+
if (!promptMatch || !promptMatch[1]) {
34+
console.log('No AI prompt found in review body');
35+
console.log('Review body:', reviewBody);
36+
core.setOutput('has-prompt', 'false');
37+
return;
38+
}
39+
40+
const prompt = promptMatch[1].trim();
41+
console.log('Extracted prompt:', prompt);
42+
43+
// Save prompt to file to avoid shell escaping issues
44+
const fs = require('fs');
45+
fs.writeFileSync('/tmp/cubic-prompt.txt', prompt);
46+
47+
core.setOutput('has-prompt', 'true');
48+
49+
- name: Check for existing Devin session from PR comments
50+
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'
138+
env:
139+
DEVIN_API_KEY: ${{ secrets.DEVIN_API_KEY }}
140+
run: |
141+
CUBIC_PROMPT=$(cat /tmp/cubic-prompt.txt)
142+
143+
FULL_PROMPT="You are addressing code review feedback from Cubic AI on PR #${{ github.event.pull_request.number }} in repository ${{ github.repository }}.
144+
145+
Your tasks:
146+
1. Clone the repository ${{ github.repository }} locally.
147+
2. Check out the PR branch and review the current code.
148+
3. Read and understand the Cubic AI review feedback below.
149+
4. Address each issue identified by Cubic AI by making the necessary code changes.
150+
5. Commit your changes with clear commit messages referencing the issues fixed.
151+
6. Push your changes to the PR branch.
152+
153+
Cubic AI Review Feedback:
154+
${CUBIC_PROMPT}
155+
156+
Rules and Guidelines:
157+
1. Make minimal, focused changes that directly address the feedback.
158+
2. Follow the existing code style and conventions in the repository.
159+
3. Test your changes if possible before pushing.
160+
4. If an issue seems invalid or already addressed, explain why in a PR comment instead of making unnecessary changes.
161+
5. Never ask for user confirmation. Never wait for user messages."
162+
163+
RESPONSE=$(curl -s -X POST "https://api.devin.ai/v1/sessions" \
164+
-H "Authorization: Bearer ${DEVIN_API_KEY}" \
165+
-H "Content-Type: application/json" \
166+
-d "$(jq -n \
167+
--arg prompt "$FULL_PROMPT" \
168+
--arg title "Cubic AI Review: PR #${{ github.event.pull_request.number }}" \
169+
'{
170+
prompt: $prompt,
171+
title: $title,
172+
tags: ["cubic-ai-review", "pr-${{ github.event.pull_request.number }}"]
173+
}')")
174+
175+
SESSION_URL=$(echo "$RESPONSE" | jq -r '.url // .session_url // empty')
176+
if [ -n "$SESSION_URL" ]; then
177+
echo "Devin session created: $SESSION_URL"
178+
echo "SESSION_URL=$SESSION_URL" >> $GITHUB_ENV
179+
echo "NEW_SESSION=true" >> $GITHUB_ENV
180+
fi
181+
182+
- name: Post comment with Devin session link
183+
if: steps.extract-prompt.outputs.has-prompt == 'true' && env.SESSION_URL != ''
184+
uses: actions/github-script@v7
185+
with:
186+
github-token: ${{ secrets.GITHUB_TOKEN }}
187+
script: |
188+
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+
195+
await github.rest.issues.createComment({
196+
owner: context.repo.owner,
197+
repo: context.repo.repo,
198+
issue_number: context.payload.pull_request.number,
199+
body: message
200+
});

0 commit comments

Comments
 (0)