> ## Documentation Index
> Fetch the complete documentation index at: https://sponson.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Bitbucket Pipelines

> Pull request pipelines, a custom destroy pipeline, and production as a manual deployment step.

[bitbucket-pipelines.yml](https://github.com/MishaBear94/Sponson/blob/main/integrations/bitbucket/bitbucket-pipelines.yml) runs Sponson in pull request pipelines, finishes the lines that
wait on the deploy, and applies production in a manual step on `main`. Bitbucket Pipelines has no "pull request
merged or declined" trigger, so destroying a preview is a custom pipeline you run (below).

| Moment | Pipeline, step | What runs |
| - | - | - |
| PR created or updated | `pull-requests`: `sponson plan`, `sponson apply`, `sponson finish` | plan; apply (stops with status `partial` at the deploy barrier); `apply --wait` (finishes the lines that needed the preview URL) |
| PR merged or declined | `custom: sponson-destroy` | `sponson apply --destroy` for the PR id you enter |
| Push to `main` | `branches: main`: `production waits for approval`, then `sponson production` | `sponson apply --env production`, a manual step on the `production` deployment environment |

## Prerequisites

* Bitbucket Cloud with Pipelines enabled (**Repository settings → Pipelines → Settings**).
* A `release.plan.yaml` at the repository root (`sponson init` writes one).
* The image `node:22`.

## Setup

1. Copy [bitbucket-pipelines.yml](https://github.com/MishaBear94/Sponson/blob/main/integrations/bitbucket/bitbucket-pipelines.yml) to the repository root, or merge its pipelines into yours.
   If Pipelines deploys the app, put your deploy steps between `sponson apply` and `sponson finish`.
2. Replace `0.5.0` with the Sponson version you have reviewed.
3. Create the receipts token and the variables below.
4. In **Repository settings → Deployments**, keep the production tokens in the `Production` environment's variables
   and, on plans that offer it, restrict who may deploy to it.

## Variables

| Where | Variable | Value |
| - | - | - |
| Repository variables (secured) | `SPONSON_GIT_TOKEN` | repository access token with write access (below) |
| Repository variables (secured) | `VERCEL_TOKEN`, `NEON_API_KEY`, `CLERK_SECRET_KEY` | the preview tokens; one per adapter your plan uses |
| `Production` deployment variables (secured) | the same names | the production tokens; deployment variables override repository variables of the same name |
| either | every `env://NAME` a line references | the secret values |

Every adapter's variable is listed under [built-in ops](/reference/plan-format#built-in-ops).

## Receipts: push credentials

Sponson writes its receipts to orphan branches of the repository, `sponson-receipts/<env>/<scope>`, from a clone of
its own. The pipeline's clone credentials are configured for the build's checkout only, so the template points
Sponson's clone at a token that can push:

1. **Repository settings → Security → Access tokens → Create access token**: name `sponson-receipts`, scope
   **Repositories: Write**.
2. Save it as the secured repository variable `SPONSON_GIT_TOKEN`.
3. Each step exports
   `SPONSON_RECEIPTS_REMOTE=https://x-token-auth:${SPONSON_GIT_TOKEN}@bitbucket.org/${BITBUCKET_REPO_FULL_NAME}.git`
   (the `&receipts-remote` anchor). Sponson strips credentials from every git error it prints.

If a branch restriction matches `sponson-receipts/*`, let the access token push to it. The receipts branches carry no
`bitbucket-pipelines.yml`, so pushing them starts no pipeline.

## Destroying a closed pull request's preview

**Pipelines → Run pipeline**, branch `main`, pipeline `custom: sponson-destroy`, then enter `SPONSON_PR_ID` (the PR's
number) and `SPONSON_PR_BRANCH` (its source branch). The scope is `pr-<id>` whatever branch the pipeline runs on, so
this works after the PR's branch is deleted. The same pipeline can be started through the Bitbucket API with the two
variables.

## How the flags are filled

| Flag | Variable |
| - | - |
| `--pr` | `BITBUCKET_PR_ID` (pull request pipelines only) |
| `--branch` | `BITBUCKET_BRANCH` |
| `--sha` | `BITBUCKET_COMMIT` |
| `--approved-by` | `BITBUCKET_STEP_TRIGGERER_UUID`, the account that started the manual production step |

Sponson 0.5.0 and later read `BITBUCKET_PR_ID`, `BITBUCKET_BRANCH` and `BITBUCKET_COMMIT` themselves when
`BITBUCKET_BUILD_NUMBER` is set, so those flags may then be dropped. `--approved-by` always stays explicit.

## Notes

* The approver is recorded as an account UUID, the only identity of the person who started the step that Pipelines
  exposes. Look it up in the workspace's members if you need the name.
* `clone: depth: full` fetches the whole history; Sponson uses it to recognise a late build of an older commit.
* Pipelines rejects a pipeline whose first step is manual, so `branches: main` starts with a step that only says
  what to run next; put your own build or deploy steps there instead if you have them.
* What has been run (`scripts/try-ci-templates.sh bitbucket`): every step's script verbatim in `node:22`, in pipeline
  order, against the fake cloud: the pull request pipeline (apply stopping at the deploy barrier, finish waiting for
  it), both steps of `branches: main` with the triggerer recorded as the approver, and `custom: sponson-destroy` on
  `main` with the PR's id and branch. The clone and the predefined, custom and deployment variables are emulated; not
  run on Bitbucket itself. See [how the templates are checked](/integrations/overview#how-the-templates-are-checked).

## The template: bitbucket-pipelines.yml

```yaml bitbucket-pipelines.yml theme={null}
# Sponson on Bitbucket Pipelines. Copy into bitbucket-pipelines.yml (or merge the pipelines into yours).
# integrations/bitbucket/README.md lists the repository variables to set and how receipts are pushed.
#
#   pull request created or updated   sponson plan, sponson apply, sponson finish (waits for the deploy)
#   pull request merged or declined   Bitbucket has no such trigger: run the custom pipeline sponson-destroy
#                                     (Run pipeline in the UI, or the API) with the PR's id and branch
#   push to main                      sponson production: a manual step on the Production deployment environment
#                                     (after an automatic first step: a pipeline cannot start with a manual step)
#
# Replace 0.5.0 everywhere with the Sponson version you have reviewed. The flags are explicit so the template works
# with any version; Sponson 0.5.0 and later also read the same variables by themselves.

image: node:22

clone:
  # Full history: lets Sponson recognise a late build of an older commit.
  depth: full

pipelines:
  pull-requests:
    "**":
      - step:
          name: sponson plan
          script:
            # Receipts are pushed to orphan branches sponson-receipts/<env>/<scope>. SPONSON_GIT_TOKEN is a repository
            # access token with write access (README.md): the pipeline's own clone credentials do not reach the
            # separate clone Sponson pushes from. The anchor is reused by every step below.
            - &receipts-remote export SPONSON_RECEIPTS_REMOTE="https://x-token-auth:${SPONSON_GIT_TOKEN}@bitbucket.org/${BITBUCKET_REPO_FULL_NAME}.git"
            - npx -y sponson@0.5.0 plan --env preview --pr "$BITBUCKET_PR_ID" --branch "$BITBUCKET_BRANCH" --sha "$BITBUCKET_COMMIT"
      - step:
          name: sponson apply
          script:
            - *receipts-remote
            - npx -y sponson@0.5.0 apply --env preview --pr "$BITBUCKET_PR_ID" --branch "$BITBUCKET_BRANCH" --sha "$BITBUCKET_COMMIT"
      # Your own deploy steps go here, if Bitbucket Pipelines deploys the app.
      - step:
          name: sponson finish
          max-time: 20
          script:
            - *receipts-remote
            # Waits for the preview deployment of this commit, then applies the lines that needed its URL.
            - npx -y sponson@0.5.0 apply --wait --wait-timeout 900 --env preview --pr "$BITBUCKET_PR_ID" --branch "$BITBUCKET_BRANCH" --sha "$BITBUCKET_COMMIT"

  branches:
    main:
      # Pipelines refuses a pipeline whose first step is manual, so the manual production step comes second.
      - step:
          name: production waits for approval
          script:
            - echo "Run the manual step 'sponson production' to apply production; whoever runs it is the approver."
      - step:
          name: sponson production
          # Whoever starts this manual step is the approver. Restrict who may deploy to Production in the
          # deployment environment's settings, and keep the production tokens in its variables (README.md).
          deployment: production
          trigger: manual
          script:
            - *receipts-remote
            - npx -y sponson@0.5.0 apply --env production --pr "" --branch "$BITBUCKET_BRANCH" --sha "$BITBUCKET_COMMIT" --approved-by "$BITBUCKET_STEP_TRIGGERER_UUID"

  custom:
    sponson-destroy:
      - variables:
          - name: SPONSON_PR_ID
          - name: SPONSON_PR_BRANCH
      - step:
          name: sponson destroy
          script:
            - *receipts-remote
            - npx -y sponson@0.5.0 apply --destroy --env preview --pr "$SPONSON_PR_ID" --branch "$SPONSON_PR_BRANCH" --sha "$BITBUCKET_COMMIT"
```


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.