feat: add DigitalOcean integration with droplet trigger and action#2983
feat: add DigitalOcean integration with droplet trigger and action#2983aldoabellto235 wants to merge 10 commits intosuperplanehq:mainfrom
Conversation
|
Thanks @aldoabellto235 for the submission. Please review these instructions: https://github.com/superplanehq/superplane/blob/main/docs/contributing/integration-prs.md Can you attach the video of the working integration and components? |
web_src/src/pages/workflowv2/mappers/digitalocean/create_droplet.ts
Outdated
Show resolved
Hide resolved
i have attached link to google drive vedeo |
web_src/src/pages/workflowv2/mappers/digitalocean/on_droplet_event.ts
Outdated
Show resolved
Hide resolved
e960565 to
1789d18
Compare
0d0bc1c to
5d1cd59
Compare
|
@aldoabellto235 amazing work! Tested it and it runs good with no issues.
|
Done can you check again |
d89aa9b to
db1be15
Compare
|
@aldoabellto235 works well, thanks for prompt update! I will move it on to code review. Not sure about using 60s In the meantime - I see that there is a conflict - please resolve that one while code review is in progress. |
|
Hey @aldoabellto235. Congrats on your first PR. I see that you have quite a lot of unrelated changes, e.g. changes to GitLab, PagerDuty, etc. Please rebase with main if you haven't already, and remove changes from the Core system and from non-Digital Ocean components. Returning to |
c51b964 to
a72339f
Compare
56debde to
47ef679
Compare
Done updated |
|
Hey @aldoabellto235. The code looks great! I'm doing the final round of tests and trying to set up this flow: 1/ Create a dropplet
It seems that the IP address is not returned in the payload. Can we get it from DO's API? |
Okey let me add that |
7cdea17 to
43e2e11
Compare
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 2 potential issues.
Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.
0cea1d6 to
c10218b
Compare
Add DigitalOcean integration with: - Create Droplet component (with SSH keys, tags, user data support) - On Droplet Event trigger (polls for lifecycle events) - Client with account, regions, sizes, images, actions, and droplet APIs - Frontend mappers with execution details and event rendering - Icon registration in sidebar and component header Signed-off-by: Aldo <aldo.abellto14@gmail.com>
The validateList function accessed field.TypeOptions.List without first checking if TypeOptions was nil, unlike every other validator (validateNumber, validateString, validateText, validateSelect, etc). This could cause a nil pointer dereference when validating a FieldTypeList field that has no TypeOptions configured. Signed-off-by: Aldo <aldo.abellto14@gmail.com>
Avoid N+1 API calls when multiple actions reference the same droplet by caching GetDroplet results per ResourceID during each poll cycle. Signed-off-by: Aldo <aldo.abellto14@gmail.com>
Closes superplanehq#2618 This PR introduces the **Cursor** integration to SuperPlane, allowing users to build workflows utilizing Cursor's AI-powered capabilities. It includes the base integration setup and two starter components: 1. **Launch Cloud Agent (Action):** Triggers a Cursor Cloud Agent on a specific repository/branch and tracks the execution state to completion. It links to the Cloud Agent and PR in the output. This agent has no limits(except credit limit). 2. **Get Daily Usage Data (Action):** Fetches daily team usage metrics from the Cursor Admin API for reporting and cost tracking. - **Authentication:** Connects via Cursor BasicAuth (Admin API and Cloud Agents API). - **Code Logic:** The `Launch Cloud Agent` implementation handles significant logic to track the agent's lifecycle (polling status, handling completion, etc.). The code is structured to robustly handle this weight to ensure reliable execution tracking. [Watch the Loom Video](https://www.loom.com/share/2f6f3f98ab6b47ce88444a15f93afe45) - [x] My code follows the style guidelines of this project - [x] I have performed a self-review of my own code - [x] I have commented my code, particularly in hard-to-understand areas - [x] I have made corresponding changes to the documentation (`make gen.components.docs`) - [x] I have added tests that prove my fix is effective or that my feature works - [x] New and existing unit tests pass locally with my changes - [x] I have signed off my commits (`git commit -s`) --------- Signed-off-by: Harsh <harxhist@gmail.com> Signed-off-by: Igor Šarčević <igor@operately.com> Co-authored-by: Igor Šarčević <igisar@gmail.com> Co-authored-by: Igor Šarčević <igor@operately.com> Signed-off-by: Aldo <aldo.abellto14@gmail.com>
Add networks/v4 data to the droplet enrichment payload so the trigger detail tab can display the droplet's public IP address. Signed-off-by: Aldo <aldo.abellto14@gmail.com>
Signed-off-by: Aldo <aldo.abellto14@gmail.com>
Add DigitalOcean integration with: - Create Droplet component (with SSH keys, tags, user data support) - On Droplet Event trigger (polls for lifecycle events) - Client with account, regions, sizes, images, actions, and droplet APIs - Frontend mappers with execution details and event rendering - Icon registration in sidebar and component header Signed-off-by: Aldo <aldo.abellto14@gmail.com>
The rebase conflict resolution accidentally kept older versions of Cursor integration files, missing ConversationMessage and GetAgentConversation that get_last_message.go depends on. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: Aldo <aldo.abellto14@gmail.com>
Instead of emitting immediately after creation (when droplet status is "new" and has no IP), store the droplet ID in metadata and schedule a poll action every 10s. Once the droplet reaches "active" status with an assigned IP address, emit the full droplet data. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: Aldo <aldo.abellto14@gmail.com>
- createDroplet: handle terminal droplet states (off, archive) instead of polling indefinitely. Only continue polling for "new" status. - onDropletEvent: log emit failures instead of returning error, so the trigger keeps polling and doesn't stop permanently. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: Aldo <aldo.abellto14@gmail.com>
e8ed841 to
831df54
Compare
|
@shiroyasha i add ip address, you can try it |
|
Thanks @aldoabellto235! @shiroyasha I've tested this, it waits for droplet to spin up (Running state), and provides IP at the end. If code looks good I would like to merge this. |



Summary
Adds a new DigitalOcean integration to SuperPlane, connecting to the
DigitalOcean API via Personal Access Token authentication.
60s for droplet lifecycle events (create, destroy, power_on, power_off,
shutdown, reboot, snapshot, rebuild, resize, rename)
region, size, and image from the user's account; returns droplet ID, IP
address, and status
characters before hitting the API
display name registration
Changes
Backend (
pkg/integrations/digitalocean/)digitalocean.goGET /v2/account,client.goon_droplet_event.goScheduleActionCall—create_droplet.goPOST /v2/dropletswith hostnameexample.go+ JSON files*_test.goFrontend
mappers/digitalocean/integrationIcons.tsxintegrationDisplayName.tsmappers/index.tsModified
pkg/server/server.go— import for init() registrationTest plan
hostname, valid config)
set up)
emitted, no events re-schedules)
account
Closes #2398
Video:
https://drive.google.com/file/d/1frbOy9LM_DvesaIi_c0Zo4shlk2ebPhA/view?usp=sharing