Run it in Bitbucket Pipelines¶
Goal: every push to your default branch keeps a release pull request up to date, and merging it tags the commit that landed.
Bitbucket Cloud has no release object, so on Bitbucket the tag is the release.
publish pushes it and says so, and there is no tag pipeline to write, because
there is nothing for release to create and nothing for announce to read.
Forge support says what else Bitbucket can and
cannot do.
The pipeline below is the one TestReleasingInBitbucketPipelines in
test/integration committed and ran on mattcockayne/colophon-e2e on
2026-11-02, installing colophon v0.19.2 in the golang:1.27 image. The test
switched Pipelines on, let the pipeline propose and then tag, and only merged
the pull request itself, as a person would. It ran the pipeline on a test
branch rather than main; nothing else differs.
1. Switch Pipelines on¶
In the repository, open Repository settings, then Pipelines, then Settings, and enable Pipelines.
2. Provide a token¶
colophon signs in to Bitbucket with an Atlassian API token and the account's email address. Make the token with Create API token with scopes, choose the Bitbucket app, and give it:
read:repositoryandwrite:repository, to push the release branch and the tag;read:pullrequestandwrite:pullrequest, to open, update and comment on the release pull request.
A token made with the plain Create API token signs in and is then refused on every call, which reads as a bad token.
Those are the scopes colophon's calls use. The run above gave the pipeline the
integration suite's own token, which carries more, so this is not a measured
minimum the way the Gitea and Forgejo scopes are. The suite's token also
carried write:pipeline and admin:pipeline to switch Pipelines on and set the
variables through the API; doing that by hand in the settings needs neither.
Add two repository variables under Repository settings, then Pipelines, then Repository variables, both marked Secured:
COLOPHON_TOKEN, the API token;COLOPHON_USER, the email address of the account that made it.
colophon reads BITBUCKET_USERNAME, BITBUCKET_TOKEN and
BITBUCKET_APP_PASSWORD, but Bitbucket reserves the BITBUCKET_ prefix for its
own variables, so the pipeline sets them from yours.
3. Add the pipeline¶
# bitbucket-pipelines.yml
image: golang:1.27
clone:
depth: full
pipelines:
branches:
main:
- step:
name: publish
script:
- export BITBUCKET_USERNAME="$COLOPHON_USER" BITBUCKET_TOKEN="$COLOPHON_TOKEN" BITBUCKET_APP_PASSWORD="$COLOPHON_TOKEN"
- go install gitlab.com/phpboyscout/colophon/cmd/[email protected]
- colophon --ci publish --target "$BITBUCKET_BRANCH" --author-name colophon --author-email [email protected]
- step:
name: propose
script:
- export BITBUCKET_USERNAME="$COLOPHON_USER" BITBUCKET_TOKEN="$COLOPHON_TOKEN" BITBUCKET_APP_PASSWORD="$COLOPHON_TOKEN"
- go install gitlab.com/phpboyscout/colophon/cmd/[email protected]
- colophon --ci propose --target "$BITBUCKET_BRANCH" --author-name colophon --author-email [email protected]
Why each part is there:
clone: depth: full. Pipelines clones 50 commits deep by default, and colophon refuses a shallow checkout, because the version decision needs the history the clone left out.- Two steps,
proposeafterpublish. When a release pull request has just merged,publishtags it.proposemust then see that tag, or it tries to propose the version that has just shipped and stops. Each step clones afresh, so the second carries the tag the first pushed. In one step, in one checkout, it does not. - A pinned colophon version. colophon decides what ships, so
@latestwould let that decision change without a commit saying so. --ci. Marks the run as unattended. Bitbucket has no labels, so there is no label prompt to suppress here anyway.
4. Merge the release pull request¶
Merge it however the repository merges. colophon resolves the commit that landed against the target branch, rather than trusting the pull request's head.
If it fails¶
| symptom | cause |
|---|---|
this checkout is shallow (depth-limited clone) |
clone: depth: full is missing |
that version has already been released … propose must run AFTER publish |
publish and propose run in the same step; give propose a step of its own |
bitbucket API returned HTTP 401: the credential is not valid |
COLOPHON_USER is not the account's email address, or the token has no Bitbucket scopes |
Your credentials lack one or more required privilege scopes on the push |
the token lacks write:repository |