Skip to content

feat: Fly.io base integration#2830

Open
aleksandar94ns wants to merge 4 commits intosuperplanehq:mainfrom
aleksandar94ns:integration/flyio
Open

feat: Fly.io base integration#2830
aleksandar94ns wants to merge 4 commits intosuperplanehq:mainfrom
aleksandar94ns:integration/flyio

Conversation

@aleksandar94ns
Copy link
Contributor

Fly.io Base Integration

Description

Adds the base integration scaffolding for Fly.io, an application platform that runs full VMs (Machines) and apps globally.

Relates to: #2785

What's Included

  • Integration registration (flyio)
  • Configuration fields:
    • API Token (required, sensitive): Bearer token for authentication
    • Organization Slug (optional): Default org slug (e.g., personal)
  • Setup instructions for obtaining API tokens
  • Sync() implementation to validate token and populate app metadata
  • ListResources() for apps and machines
  • HTTP client for https://api.machines.dev

Connection Method

API Token (Bearer) authentication:

Authorization: Bearer <token>
Content-Type: application/json

Tokens can be created via:

  • Dashboard: Organization → Access Tokens
  • CLI: fly tokens deploy or fly tokens create

Files Changed

File Description
pkg/integrations/flyio/flyio.go Main integration definition
pkg/integrations/flyio/flyio_test.go Integration tests
pkg/integrations/flyio/client.go HTTP client for Fly.io API

Checklist

  • Has proper tests
  • Has proper documentation
  • Passed code quality review
  • Passed functionality review
  • Passed UI/UX review

Reference

See Integration & component checklist

Signed-off-by: Aleksandar Radosevic <aradosevicarchon@gmail.com>
Signed-off-by: Aleksandar Radosevic <aradosevicarchon@gmail.com>
"github.com/superplanehq/superplane/pkg/core"
)

func Test__FlyIO__Name(t *testing.T) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Static methods do not require unit tests

@@ -0,0 +1,83 @@
package flyio
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tests for Sync() are required though

@lucaspin
Copy link
Contributor

lucaspin commented Feb 3, 2026

@aleksandar94ns code looks good, left just a few comments regarding unit tests. One issue though: base integrations require 1 component + 1 trigger to be added as part of it. Usually, the trickiest part about building the base integration is to figure out how the events from the integration will be received in SuperPlane, so it's good to do that as part of the base integration.

Signed-off-by: Aleksandar Radosevic <aradosevicarchon@gmail.com>
for _, app := range metadata.Apps {
machines, err := client.ListMachines(app.Name)
if err != nil {
continue
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Silently ignoring machine listing errors hides failures

Medium Severity

In ListResources for the machine resource type, errors from client.ListMachines(app.Name) are silently swallowed with continue. When an API call fails (due to network issues, rate limiting, permissions, or other errors), the user receives a partial result with no indication that some apps' machines couldn't be fetched. This could lead to users making decisions based on incomplete data, believing they have a complete inventory when machines are actually missing.

Fix in Cursor Fix in Web


// If already set up for this org, skip
if metadata.OrgSlug == orgSlug && metadata.AppStates != nil {
return nil
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Trigger setup skips scheduling poll on restart

High Severity

When Setup is called and metadata already exists for the same org (e.g., after a system restart), the function returns early at line 135 without scheduling the next poll action. The ScheduleActionCall at lines 170-174 is bypassed, causing the polling mechanism to never resume. This effectively breaks the trigger after any restart or re-setup scenario since no new poll will be scheduled.

Fix in Cursor Fix in Web

Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.


// ListApps retrieves all apps for an organization
func (c *Client) ListApps(orgSlug string) ([]App, error) {
url := fmt.Sprintf("%s/v1/apps?org_slug=%s", c.BaseURL, orgSlug)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

URL parameters not escaped in API client

Medium Severity

URL path segments and query parameters are constructed using fmt.Sprintf without URL encoding. Values like orgSlug, appName, machineID, and state are directly interpolated into URLs. If any of these contain special characters (spaces, /, ?, &, #, %), the resulting URL will be malformed or incorrectly parsed. Other integrations in this codebase (e.g., AWS Lambda) correctly use url.PathEscape() and url.Values for this purpose.

Additional Locations (2)

Fix in Cursor Fix in Web

"github.com/superplanehq/superplane/pkg/core"
)

type ListApps struct{}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have been discussing List operations in this thread. I'm not so sure I see a concrete real use case for this

@shiroyasha shiroyasha changed the title Finalize implementation of basic flyio feat: Fly.io base integration Feb 5, 2026
@lucaspin
Copy link
Contributor

lucaspin commented Feb 5, 2026

We should consider making SuperPlane a fly.io extension. Fly.io extensions can receive webhooks, so we could create a fly.io extension, which acts like an agent, receives the webhooks, and sends to SuperPlane.

cc @shiroyasha

@shiroyasha
Copy link
Collaborator

@aleksandar94ns go for it. Let us know what is the complexity of building such an extension.

@shiroyasha shiroyasha self-requested a review February 6, 2026 09:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants