Bitbucket repositories
Create a Bitbucket OAuth consumer once, connect workspaces to your organization, and see what a Bitbucket token can read.
Loomplane reads public Bitbucket Cloud repositories with no setup. A source is written bitbucket.org/<workspace>/<repo>, and you can paste the repository's URL wherever Loomplane asks for one. To read private repositories you create an OAuth consumer once for the whole instance, and your organization's owners and admins connect their workspaces to it. Bitbucket Data Center and Server aren't supported.
Create the OAuth consumer
In Bitbucket, open a workspace's Settings, choose OAuth consumers, then Add consumer. It can live under any workspace, including one your organization will never connect.
| Setting | Value |
|---|---|
| Name | Anything, such as Loomplane |
| Callback URL | <public_url>/integrations/bitbucket/callback |
| Permissions: Account | Read |
| Permissions: Repositories | Read |
| Permissions: Webhooks | Read and write |
| Everything else | No access |
Save it, then open the consumer to copy its Key and Secret.
Account Read is how Loomplane learns who signed in and checks they belong to the workspace. Repositories Read is the only access to code. Webhooks is for push events, which the Webhooks section covers. Loomplane never asks for write access to your code.
Configure Loomplane
Set both variables for loomplane and loomplane-worker, and keep the secret out of any file you commit:
LOOMPLANE_BITBUCKET_CLIENT_ID=<the consumer's key>
LOOMPLANE_BITBUCKET_CLIENT_SECRET=<the consumer's secret>Set both or neither. Loomplane refuses to start with only one. With neither, Bitbucket keeps working for public repositories, and connecting a workspace is refused with a message saying there's no consumer. Values Bitbucket turns down don't stop Loomplane starting. You still get public repositories, but not private ones until you fix them, as Revoking access explains. The configuration reference lists LOOMPLANE_BITBUCKET_API_URL and LOOMPLANE_BITBUCKET_WEB_URL too, which you'd change only to point at a test double.
Connect a workspace
An owner or admin opens Integrations, finds the Bitbucket card, types the workspace's slug (the acme in bitbucket.org/acme) and chooses Connect workspace. Bitbucket asks them to approve the consumer and sends them back to Loomplane. If they've approved it before, Bitbucket skips the question.
Each workspace is its own connection, so a second workspace means repeating the steps. Several organizations can connect the same workspace, and each gets a sign-in of its own. Once it's connected, any project in the organization whose repository sits in that workspace is analyzed with access to it.
What a Bitbucket token can read
This is the one place Bitbucket is looser than GitHub. A GitHub installation token reads one repository. A Bitbucket OAuth token reads every repository the connecting person can read, in every workspace they belong to, because the consumer's permissions say what kind of access the token has and not which repositories it covers.
We narrow it on our side:
- A token is only used for a repository in the workspace its connection names. A connection to
acmeis never used forother/repo, even if the person who connected it can read that too. - Only the organization's own connections are used, so one organization can't read code through another's.
- A connection that needs connecting again is never used. The repository is read anonymously instead, which works for a public one and fails for a private one.
- When someone connects, Loomplane checks that their Bitbucket account belongs to the workspace they typed. If it doesn't, the sign-in is dropped and nothing is kept.
- Tokens never appear in an API response, a log line, an audit record or an error message.
Access tokens live in memory only and expire within a couple of hours. The one long-lived secret is the refresh token, which is encrypted in Vault under a key derived from your secret_key, and disconnecting deletes it. If you want a tighter boundary, connect a workspace with a Bitbucket account that can read only the repositories you want Loomplane to see.
When a workspace needs connecting again
The card shows Reconnect needed, with the reason, when Bitbucket stops accepting the stored sign-in, when the member who connected the workspace has left your Loomplane organization, when the Bitbucket account that connected it is no longer in the workspace, or when Loomplane can't read the stored sign-in from Vault. Anyone who may connect workspaces fixes it by connecting the same workspace again. It keeps its place, and the new sign-in replaces the old one.
When the member who connected a workspace leaves your organization, Loomplane stops reading as them at the next token renewal, which is within about two hours.
Webhooks
When you attach a Bitbucket repository to a project, Loomplane adds a webhook to it, so a push to the default branch re-analyzes the project without anyone pressing Analyze. Your organization gets one webhook per repository. A second project on the same repository shares it, and it's removed when the organization's last source on that repository goes.
The webhook only goes in when three things are true:
- Your organization has connected the workspace the repository is in, and the connection is ready.
- The person who connected the workspace is an admin of the repository. Bitbucket only lets a repository admin add a webhook, which is also why the consumer asks for Webhooks Read and write.
- Your
public_urlis https. Loomplane only adds a webhook when it is, so a local instance onhttp://localhost:8780never gets one.
If any of them isn't, the source still attaches and Analyze works as it always has. The Sources list shows Push re-analysis is off beside the source, with the reason. Fix what the reason names (connect the workspace, have a repository admin connect it again, or move to an https address), then choose Turn on. Loomplane tries to add the webhook again and keeps it if Bitbucket agrees. You need the same role to turn it on as to connect a workspace.
Only pushes to the repository's default branch re-analyze, the same as with GitHub. A source with no branch set follows the default, and a source that names a branch is re-analyzed only while that branch is the default. A push to any other branch, a tag or a deleted branch starts nothing. Loomplane asks Bitbucket which branch is the default each time a push arrives, so if you rename it, the next push already uses the new name.
Each webhook has a secret of its own, derived from your secret_key and never stored, and Loomplane checks the signature on every delivery. A delivery only re-analyzes projects in the organization that owns the webhook, even when another organization has projects on the same repository.
Disconnecting a workspace removes every webhook it added, on Bitbucket and in Loomplane. If Bitbucket refuses to remove one (say the account lost admin on the repository), Loomplane stops listening to it anyway and its deliveries get a 404. You can delete it yourself on Bitbucket, under the repository's settings.
Revoking access
You revoke a workspace one of two ways. In Loomplane, disconnect it on the Integrations card: that removes it from the organization, deletes its refresh token and takes its webhooks off. On Bitbucket, the person who connected it opens their Personal settings, finds Loomplane among the apps they've authorized, and revokes it there. The next renewal then fails and the card shows Reconnect needed. Disconnecting doesn't un-approve the consumer on Bitbucket, so if you want it gone on both sides, do both.
Changing the consumer's secret doesn't revoke anyone, but until you give Loomplane the new one, Bitbucket turns down every renewal. A mistyped key or secret does the same. While that lasts, Loomplane can't read private repositories, and an analysis of one fails with "the repository or ref doesn't exist, or it's private and Loomplane can't read it". Public repositories are still read, including the ones in workspaces you've connected. Push re-analysis pauses too. Loomplane renews the workspace's sign-in before it asks Bitbucket for the default branch, so it answers each push with an error, and Bitbucket's retries fail the same way until the consumer is fixed.
Analyses run in loomplane-worker, so its log is usually where the warning to check bitbucket.client_id and bitbucket.client_secret shows up first. The Bitbucket card on Integrations comes from loomplane, which only finds out once it renews a sign-in itself: when you list a workspace's repositories, attach a source, try to connect a workspace, or a push arrives. From then on the card says the consumer was turned down. No workspace is marked Reconnect needed. Each keeps its sign-in and its status, so once LOOMPLANE_BITBUCKET_CLIENT_ID and LOOMPLANE_BITBUCKET_CLIENT_SECRET hold values Bitbucket accepts, the next renewal works and you can read private repositories again without connecting anything.