-
Notifications
You must be signed in to change notification settings - Fork 97
feat: Add Bitbucket integration #3039
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
8efd8e0
feat: add Bitbucket backend integration
ishaksebsib 67847a7
feat: add Bitbucket trigger example data
ishaksebsib 6359f5e
feat: add Bitbucket UI mappers and icons
ishaksebsib ead5769
Merge branch 'main' into feat/bitbucket
ishaksebsib fb0b4f9
fix: implement Merge for Bitbucket webhook handler
ishaksebsib dfd27ab
support for workspace access token + unit tests
lucaspin f75e64e
Merge branch 'main' into feat/bitbucket
lucaspin 67bc315
docs(bitbucket): add setup instructions for API and workspace access …
ishaksebsib f91b72f
use []string for event types + docs
lucaspin befe880
Merge branch 'main' into feat/bitbucket
lucaspin File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,151 @@ | ||
| --- | ||
| title: "Bitbucket" | ||
| --- | ||
|
|
||
| React to events in your Bitbucket repositories | ||
|
|
||
| ## Triggers | ||
|
|
||
| <CardGrid> | ||
| <LinkCard title="On Push" href="#on-push" description="Listen to Bitbucket push events" /> | ||
| </CardGrid> | ||
|
|
||
| ## Instructions | ||
|
|
||
| To configure Bitbucket with SuperPlane: | ||
|
|
||
| - **API Token mode**: | ||
| - Go to **Atlassian Settings → Security → Create API token**. | ||
| - Select **Bitbucket** App. | ||
| - Create a token with admin:workspace:bitbucket scope. | ||
|
|
||
| - **Workspace Access Token mode**: | ||
| - Go to **Bitbucket Workspace Settings → Security → Access tokens**. | ||
| - Create a workspace access token. | ||
|
|
||
| - **Copy the token** and your workspace slug (for example: `my-workspace`) below. | ||
|
|
||
| <a id="on-push"></a> | ||
|
|
||
| ## On Push | ||
|
|
||
| The On Push trigger starts a workflow execution when code is pushed to a Bitbucket repository. | ||
|
|
||
| ### Use Cases | ||
|
|
||
| - **CI/CD automation**: Trigger builds and deployments on code pushes | ||
| - **Code quality checks**: Run linting and tests on every push | ||
| - **Notification workflows**: Send notifications when code is pushed | ||
|
|
||
| ### Configuration | ||
|
|
||
| - **Repository**: Select the Bitbucket repository to monitor | ||
| - **Refs**: Configure which branches to monitor (e.g., `refs/heads/main`) | ||
|
|
||
| ### Event Data | ||
|
|
||
| Each push event includes: | ||
| - **repository**: Repository information | ||
| - **push.changes**: Array of reference changes with new/old commit details | ||
| - **actor**: Information about who pushed | ||
|
|
||
| ### Webhook Setup | ||
|
|
||
| This trigger automatically sets up a Bitbucket webhook when configured. The webhook is managed by SuperPlane and will be cleaned up when the trigger is removed. | ||
|
|
||
| ### Example Data | ||
|
|
||
| ```json | ||
| { | ||
| "actor": { | ||
| "display_name": "John Doe", | ||
| "links": { | ||
| "avatar": { | ||
| "href": "https://bitbucket.org/account/johndoe/avatar/" | ||
| }, | ||
| "html": { | ||
| "href": "https://bitbucket.org/johndoe/" | ||
| } | ||
| }, | ||
| "nickname": "johndoe", | ||
| "type": "user", | ||
| "uuid": "{d301aafa-d676-4ee0-a3f1-8b94c681feaa}" | ||
| }, | ||
| "push": { | ||
| "changes": [ | ||
| { | ||
| "closed": false, | ||
| "commits": [ | ||
| { | ||
| "author": { | ||
| "raw": "John Doe \u003cjohn@example.com\u003e", | ||
| "type": "author" | ||
| }, | ||
| "hash": "709d658dc5b6d6afcd46049c2f332ee3f515a67d", | ||
| "links": { | ||
| "html": { | ||
| "href": "https://bitbucket.org/my-workspace/my-repo/commits/709d658dc5b6d6afcd46049c2f332ee3f515a67d" | ||
| } | ||
| }, | ||
| "message": "Add new feature\n", | ||
| "type": "commit" | ||
| } | ||
| ], | ||
| "created": false, | ||
| "forced": false, | ||
| "new": { | ||
| "name": "main", | ||
| "target": { | ||
| "author": { | ||
| "raw": "John Doe \u003cjohn@example.com\u003e", | ||
| "type": "author", | ||
| "user": { | ||
| "display_name": "John Doe", | ||
| "type": "user", | ||
| "uuid": "{d301aafa-d676-4ee0-a3f1-8b94c681feaa}" | ||
| } | ||
| }, | ||
| "date": "2024-01-15T10:30:00+00:00", | ||
| "hash": "709d658dc5b6d6afcd46049c2f332ee3f515a67d", | ||
| "links": { | ||
| "html": { | ||
| "href": "https://bitbucket.org/my-workspace/my-repo/commits/709d658dc5b6d6afcd46049c2f332ee3f515a67d" | ||
| } | ||
| }, | ||
| "message": "Add new feature\n", | ||
| "type": "commit" | ||
| }, | ||
| "type": "branch" | ||
| }, | ||
| "old": { | ||
| "name": "main", | ||
| "target": { | ||
| "author": { | ||
| "raw": "John Doe \u003cjohn@example.com\u003e", | ||
| "type": "author" | ||
| }, | ||
| "date": "2024-01-14T15:00:00+00:00", | ||
| "hash": "1e65c05c1d5171631d92438a13901ca7dae9618c", | ||
| "message": "Previous commit\n", | ||
| "type": "commit" | ||
| }, | ||
| "type": "branch" | ||
| }, | ||
| "truncated": false | ||
| } | ||
| ] | ||
| }, | ||
| "repository": { | ||
| "full_name": "my-workspace/my-repo", | ||
| "links": { | ||
| "html": { | ||
| "href": "https://bitbucket.org/my-workspace/my-repo" | ||
| } | ||
| }, | ||
| "name": "my-repo", | ||
| "type": "repository", | ||
| "uuid": "{b7f10c3a-2a1e-4c36-af54-7e818f3b6e1d}" | ||
| } | ||
| } | ||
| ``` | ||
|
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,188 @@ | ||
| package bitbucket | ||
|
|
||
| import ( | ||
| "fmt" | ||
|
|
||
| "github.com/mitchellh/mapstructure" | ||
| "github.com/superplanehq/superplane/pkg/configuration" | ||
| "github.com/superplanehq/superplane/pkg/core" | ||
| "github.com/superplanehq/superplane/pkg/registry" | ||
| ) | ||
|
|
||
| const ( | ||
| AuthTypeAPIToken = "apiToken" | ||
| AuthTypeWorkspaceAccessToken = "workspaceAccessToken" | ||
|
|
||
| installationInstructions = ` | ||
| To configure Bitbucket with SuperPlane: | ||
|
|
||
| - **API Token mode**: | ||
| - Go to **Atlassian Settings → Security → Create API token**. | ||
| - Select **Bitbucket** App. | ||
| - Create a token with admin:workspace:bitbucket scope. | ||
|
|
||
| - **Workspace Access Token mode**: | ||
| - Go to **Bitbucket Workspace Settings → Security → Access tokens**. | ||
| - Create a workspace access token. | ||
|
|
||
| - **Copy the token** and your workspace slug (for example: ` + "`my-workspace`" + `) below. | ||
| ` | ||
| ) | ||
|
|
||
| func init() { | ||
| registry.RegisterIntegrationWithWebhookHandler("bitbucket", &Bitbucket{}, &BitbucketWebhookHandler{}) | ||
| } | ||
|
|
||
| type Bitbucket struct{} | ||
|
|
||
| type Configuration struct { | ||
| Workspace string `json:"workspace"` | ||
| AuthType string `json:"authType"` | ||
| Token *string `json:"token"` | ||
| Email *string `json:"email"` | ||
| } | ||
|
|
||
| type Metadata struct { | ||
| AuthType string `json:"authType" mapstructure:"authType"` | ||
| Workspace *WorkspaceMetadata `json:"workspace,omitempty" mapstructure:"workspace,omitempty"` | ||
| } | ||
|
|
||
| type WorkspaceMetadata struct { | ||
| UUID string `json:"uuid" mapstructure:"uuid"` | ||
| Name string `json:"name" mapstructure:"name"` | ||
| Slug string `json:"slug" mapstructure:"slug"` | ||
| } | ||
|
|
||
| func (b *Bitbucket) Name() string { | ||
| return "bitbucket" | ||
| } | ||
|
|
||
| func (b *Bitbucket) Label() string { | ||
| return "Bitbucket" | ||
| } | ||
|
|
||
| func (b *Bitbucket) Icon() string { | ||
| return "bitbucket" | ||
| } | ||
|
|
||
| func (b *Bitbucket) Description() string { | ||
| return "React to events in your Bitbucket repositories" | ||
| } | ||
|
|
||
| func (b *Bitbucket) Instructions() string { | ||
| return installationInstructions | ||
| } | ||
|
|
||
| func (b *Bitbucket) Configuration() []configuration.Field { | ||
| return []configuration.Field{ | ||
| { | ||
| Name: "workspace", | ||
| Label: "Workspace", | ||
| Type: configuration.FieldTypeString, | ||
| Description: "Bitbucket workspace slug", | ||
| Placeholder: "e.g. my-workspace", | ||
| Required: true, | ||
| }, | ||
| { | ||
| Name: "authType", | ||
| Label: "Authentication Type", | ||
| Type: configuration.FieldTypeSelect, | ||
| Required: true, | ||
| Description: "Bitbucket authentication type", | ||
| TypeOptions: &configuration.TypeOptions{ | ||
| Select: &configuration.SelectTypeOptions{ | ||
| Options: []configuration.FieldOption{ | ||
| {Label: "API Token", Value: AuthTypeAPIToken}, | ||
| {Label: "Workspace Access Token", Value: AuthTypeWorkspaceAccessToken}, | ||
| }, | ||
| }, | ||
| }, | ||
| }, | ||
| { | ||
| Name: "token", | ||
| Label: "Token", | ||
| Type: configuration.FieldTypeString, | ||
| Sensitive: true, | ||
| Description: "The API token or workspace access token to use for authentication", | ||
| Required: true, | ||
| }, | ||
| { | ||
| Name: "email", | ||
| Label: "Email", | ||
| Type: configuration.FieldTypeString, | ||
| Description: "Atlassian account email", | ||
| Required: true, | ||
| VisibilityConditions: []configuration.VisibilityCondition{ | ||
| {Field: "authType", Values: []string{AuthTypeAPIToken}}, | ||
| }, | ||
| }, | ||
| } | ||
| } | ||
|
|
||
| func (b *Bitbucket) Components() []core.Component { | ||
| return []core.Component{} | ||
| } | ||
|
|
||
| func (b *Bitbucket) Triggers() []core.Trigger { | ||
| return []core.Trigger{ | ||
| &OnPush{}, | ||
| } | ||
| } | ||
|
|
||
| func (b *Bitbucket) Cleanup(ctx core.IntegrationCleanupContext) error { | ||
| return nil | ||
| } | ||
|
|
||
| func (b *Bitbucket) Sync(ctx core.SyncContext) error { | ||
| config := Configuration{} | ||
| if err := mapstructure.Decode(ctx.Configuration, &config); err != nil { | ||
| return fmt.Errorf("failed to decode configuration: %w", err) | ||
| } | ||
|
|
||
| if config.Workspace == "" { | ||
| return fmt.Errorf("workspace is required") | ||
| } | ||
|
|
||
| if config.AuthType == "" { | ||
| return fmt.Errorf("authType is required") | ||
| } | ||
|
|
||
| if config.AuthType != AuthTypeAPIToken && config.AuthType != AuthTypeWorkspaceAccessToken { | ||
| return fmt.Errorf("authType %s is not supported", config.AuthType) | ||
| } | ||
|
|
||
| client, err := NewClient(config.AuthType, ctx.HTTP, ctx.Integration) | ||
| if err != nil { | ||
| return fmt.Errorf("error creating client: %w", err) | ||
| } | ||
|
|
||
| workspace, err := client.GetWorkspace(config.Workspace) | ||
| if err != nil { | ||
| return fmt.Errorf("error getting workspace: %w", err) | ||
| } | ||
|
|
||
| ctx.Integration.SetMetadata(Metadata{ | ||
| AuthType: config.AuthType, | ||
| Workspace: &WorkspaceMetadata{ | ||
| UUID: workspace.UUID, | ||
| Name: workspace.Name, | ||
| Slug: workspace.Slug, | ||
| }, | ||
| }) | ||
|
|
||
| ctx.Integration.Ready() | ||
|
|
||
| return nil | ||
| } | ||
|
|
||
| func (b *Bitbucket) HandleRequest(ctx core.HTTPRequestContext) { | ||
| // no-op | ||
| } | ||
|
|
||
| func (b *Bitbucket) Actions() []core.Action { | ||
| return []core.Action{} | ||
| } | ||
|
|
||
| func (b *Bitbucket) HandleAction(ctx core.IntegrationActionContext) error { | ||
| return nil | ||
| } | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.