stableFor developers

Bitbucket

This guide connects a pixmoat project to a Bitbucket Cloud or Bitbucket Data Center repository. When you’re done:

  • pixmoat posts a build status named pixmoat/visual/<project-slug> on each commit it builds, linking to the review page;
  • a merge check can block pull requests until that status passes;
  • merging a pull request promotes its approved baselines to the target branch.

pixmoat doesn’t comment on pull requests and doesn’t rerun pipelines. The support matrix lists what’s supported on each Git host.

Upload screenshots from Bitbucket Pipelines

Fragment. This bitbucket-pipelines.yml runs your Playwright tests with the pixmoat fixture on pull requests and on the default branch. It needs playwright.config.ts, global-setup.ts and global-teardown.ts from Connect Playwright, and your project’s slug in PIXMOAT_PROJECT:

image: mcr.microsoft.com/playwright:v1.52.0-noble

definitions:
  steps:
    - step: &visual
        name: Visual regression
        script:
          - export PIXMOAT_PROJECT="my-project"
          - export PIXMOAT_BRANCH="$BITBUCKET_BRANCH"
          - export PIXMOAT_COMMIT="$BITBUCKET_COMMIT"
          - export PIXMOAT_PR="${BITBUCKET_PR_ID:-}"
          - npm ci
          - npx playwright test

pipelines:
  pull-requests:
    '**':
      - step: *visual
  branches:
    main:
      - step: *visual

Store the project access token from pixmoat (Settings, then the Tokens tab) as a secured repository variable named PIXMOAT_TOKEN (Repository settings > Repository variables, with Secured selected). Repository variables can’t refer to other variables, so the branch and commit are exported in the script instead.

The default branch needs its own builds, because pull request builds compare with its baselines. Replace main if your default branch has another name. See Baselines and branches.

The step doesn’t fail on visual changes: finishBuild() never fails the test run. The build status in the next sections carries the review result instead.

Create an access token in Bitbucket

pixmoat sends the token as a bearer token, so it has to be an access token. Bitbucket Cloud app passwords and API tokens use a different sign-in method and don’t work, even though the Access Token field’s hint mentions app passwords.

Bitbucket Cloud: open the repository’s Repository settings > Security > Access tokens and select Create Repository Access Token. Give it the Repositories: Write permission, create it, and copy the token. It isn’t shown again.

Bitbucket Data Center: open your profile’s Manage account > HTTP access tokens and select Create token. Give it Project read and Repository write permissions, create it, and copy the token.

Connect the repository in pixmoat

  1. In pixmoat, open the project’s Settings and the Git Provider tab.

  2. Set Provider to Bitbucket Cloud or Bitbucket Server. Use Bitbucket Server for Data Center. Select Enable integration.

  3. Fill in the fields:

    FieldBitbucket CloudBitbucket Data Center
    Base URLLeave empty. pixmoat uses https://api.bitbucket.org/2.0.Your Bitbucket address, for example https://bitbucket.example.com
    Workspace / Project keyThe workspace slug, for example acmeThe project key, for example PROJ
    Repository slugThe repository slug, for example storefrontThe repository slug
    Access TokenThe access token from the previous sectionThe HTTP access token
  4. Select Save changes. You’ll see “Git provider settings saved.”

The Test connection check isn’t available for Bitbucket yet: it reports that the check isn’t implemented for this provider. Verify the connection with a build instead, as described in the next section.

pixmoat sends statuses only to public addresses. A Bitbucket Data Center server that isn’t reachable from the internet can’t receive them.

Check the build status

Push a commit that runs your pipeline. In Bitbucket, open the commit or its pull request. You’ll see a build named pixmoat/visual/<project-slug>, linking to the build in pixmoat:

WhenBitbucket status
The build startsIn progress
The build finishes with nothing to reviewSuccessful
The build finishes with changes to reviewFailed (Successful if the project is in report-only mode)
The review is finished and approvedSuccessful
The review is finished and something was rejectedFailed

In blocking mode, if the project has an approval policy, the status stays failed until the review is finished with the policy met.

If no status appears after the build finishes, check the token’s permission and that Workspace / Project key and Repository slug match the repository’s URL exactly. Then push another commit. pixmoat doesn’t resend statuses for earlier builds.

Block merges on the build status

Because pixmoat updates the status itself when a review is finished, you don’t need a gate step or a pipeline rerun: the status turns green as soon as the review is approved.

Bitbucket Cloud: open Repository settings > Branch restrictions, edit or add the restriction for your default branch, and turn on the merge check that requires successful builds with no failed or in-progress builds. Bitbucket Cloud enforces merge checks only on the Premium plan. On other plans they show a warning but don’t block the merge.

Bitbucket Data Center: open Repository settings > Required builds, add a required build for your default branch, and enter pixmoat/visual/<project-slug> as the build key.

Promote baselines on merge

When a pull request is merged, pixmoat can copy its approved baselines to the target branch. This is merge promotion. It needs a webhook from Bitbucket. Without it, the next default-branch build shows the changes you already approved as Changed again.

  1. In pixmoat, on the Git Provider tab, enter a random string as the Webhook Secret (for example the output of openssl rand -hex 32) and select Save changes.
  2. Copy the Webhook URL shown on the same tab. It looks like https://app.pixmoat.com/api/projects/<project-slug>/webhooks/bitbucket.
  3. Add the webhook in Bitbucket:
    • Cloud: Repository settings > Webhooks > Add webhook. Paste the URL, enter the same string as the Secret, and under Triggers select only Pull Request: Merged.
    • Data Center: Repository settings > Webhooks > Create webhook. Paste the URL, enter the same string as the Secret, and under Events select only Pull request: Merged.
  4. Save the webhook.

To check it, merge a pull request whose build is Approved. The build shows a Merged badge in pixmoat, and the target branch’s baselines are updated. The Recent deliveries list at the bottom of the Git Provider tab shows each webhook pixmoat received, with its status.

pixmoat promotes a screenshot only if the target branch’s baseline is still the one the reviewer compared against. If another pull request changed the same snapshot and merged first, that snapshot is skipped, and the next target-branch build shows it as Changed for a fresh review.

If a webhook was lost, a project admin can promote the approved build by hand. See Manual promotion.

CODEOWNERS

The Playwright client uploads your code owners file with each build. It looks for .bitbucket/CODEOWNERS as well as CODEOWNERS, .github/CODEOWNERS, .gitlab/CODEOWNERS and docs/CODEOWNERS. See Approval policy for how code owners affect a review.

Troubleshooting

SymptomCause and fix
No build status appears on commitsThe token is an app password or API token, lacks write permission, or the workspace, project key or repository slug doesn’t match. See Create an access token in Bitbucket.
The status stays failed after approvalThe review isn’t finished. Select Finish review and Confirm in pixmoat. If the project has an approval policy, check that it’s met.
Webhook returns 401The secret in Bitbucket doesn’t match the Webhook Secret in pixmoat, or no Webhook Secret is saved in pixmoat.
Webhook returns 403The pull request’s repository doesn’t match Workspace / Project key and Repository slug.
Webhook returns 404The project slug in the URL is wrong, or the project’s provider isn’t Bitbucket. Copy the Webhook URL from pixmoat again.
Baselines weren’t promoted after a mergeThe build wasn’t Approved before the merge, or the webhook isn’t set up. Promote it by hand: see Manual promotion.