---
title: "Other CI providers"
description: "Release and patch with Shorebird from Azure Pipelines, Jenkins, Bitrise, CircleCI and Bitbucket Pipelines"
---

Shorebird has no plugin for these CI systems, and doesn’t need one. Each recipe on this page is the [generic CI setup](/code-push/ci/generic/) in that provider’s syntax:

1. Install Shorebird with its install script and add `~/.shorebird/bin` to the `PATH`. When the machine sets `XDG_CONFIG_HOME`, as Microsoft’s hosted Ubuntu images do, Shorebird installs to `$XDG_CONFIG_HOME/shorebird` instead, so use that path.
2. Store a Shorebird key as a secret named `SHOREBIRD_TOKEN` and pass it to the job as an environment variable. Use a [service account](/account/service-accounts/) key; see [Authentication](/code-push/ci/generic/#getting-shorebird-credentials-onto-the-builder).
3. Run `shorebird release` or `shorebird patch` where you ran `flutter build`.

Each recipe shows an Android release job and an iOS release job. For a patch, run `shorebird patch` in the same job instead, with the release’s version:

```
shorebird patch android --release-version=1.0.0+1 --track=stable
```

The Android jobs need a JDK and the Android SDK, and the iOS jobs a macOS machine with Xcode and CocoaPods; Shorebird installs its own Flutter. Sign the app on the builder as you would for `flutter build`: Android reads your Gradle signing config (see [Android code signing](/code-push/ci/github/#android-code-signing)), and iOS needs your distribution certificate and profile (see [iOS code signing](/code-push/ci/github/#ios-code-signing)). A patch built with a different Xcode or CocoaPods than its release can stop in CI, so the recipes for hosted machines (Azure, Bitrise, CircleCI) pin the macOS image and Xcode. On a Mac you run yourself (Jenkins, Bitbucket), keep its Xcode and CocoaPods the same while you patch a release. Hosted images can still update CocoaPods, so check it too; see [Build patches with the same toolchain as the release](/code-push/ci/generic/#build-patches-with-the-same-toolchain-as-the-release).

## Azure

Add `SHOREBIRD_TOKEN` as a secret variable: edit the pipeline, open **Variables**, add the variable and select **Keep this value secret**. Azure Pipelines doesn’t pass secret variables to scripts on its own, so each step that runs `shorebird` maps it with `env:` ([Set secret variables](https://learn.microsoft.com/en-us/azure/devops/pipelines/process/set-secret-variables)). The `task.prependpath` [logging command](https://learn.microsoft.com/en-us/azure/devops/pipelines/scripts/logging-commands#prependpath-prepend-a-path-to-the--path-environment-variable) adds Shorebird to the `PATH` of the steps after it.

azure-pipelines.yml

```
trigger: none

variables:
  FLUTTER_VERSION: '3.47.9'

jobs:
  - job: release_android
    pool:
      vmImage: ubuntu-24.04
    steps:
      - bash: |
          curl -fsSL https://shorebird.dev/install.sh | bash
          # Shorebird installs under XDG_CONFIG_HOME when it is set, as on Ubuntu.
          SHOREBIRD_DIR="${XDG_CONFIG_HOME:+$XDG_CONFIG_HOME/shorebird}"
          echo "##vso[task.prependpath]${SHOREBIRD_DIR:-$HOME/.shorebird}/bin"
        displayName: Install Shorebird
      - bash: shorebird release android --flutter-version="$FLUTTER_VERSION"
        displayName: Shorebird release
        env:
          SHOREBIRD_TOKEN: $(SHOREBIRD_TOKEN)

  - job: release_ios
    pool:
      vmImage: macOS-26
    steps:
      - bash:
          sudo xcode-select -s /Applications/Xcode_26.6.app/Contents/Developer
        displayName: Select Xcode
      - bash: |
          curl -fsSL https://shorebird.dev/install.sh | bash
          # Shorebird installs under XDG_CONFIG_HOME when it is set, as on Ubuntu.
          SHOREBIRD_DIR="${XDG_CONFIG_HOME:+$XDG_CONFIG_HOME/shorebird}"
          echo "##vso[task.prependpath]${SHOREBIRD_DIR:-$HOME/.shorebird}/bin"
        displayName: Install Shorebird
      - bash: shorebird release ios --flutter-version="$FLUTTER_VERSION"
        displayName: Shorebird release
        env:
          SHOREBIRD_TOKEN: $(SHOREBIRD_TOKEN)
```

The Ubuntu image includes Java 17 and the Android SDK. `macOS-latest` moves to a new image when Microsoft updates it, so the iOS job names `macOS-26` and selects an Xcode from [the image’s software list](https://github.com/actions/runner-images/blob/main/images/macos/macos-26-Readme.md). For iOS signing, Azure Pipelines has [Install Apple certificate and provisioning profile tasks](https://learn.microsoft.com/en-us/azure/devops/pipelines/apps/mobile/app-signing).

## Jenkins

Add the key as a **Secret text** credential, here with the ID `shorebird-token`, and bind it with `credentials()` in the `environment` directive ([Using a Jenkinsfile](https://www.jenkins.io/doc/book/pipeline/jenkinsfile/#secret-text)). Jenkins agents usually keep their home directory between builds, and the install script stops with `Error: Shorebird is already installed` when `~/.shorebird` exists, so the stage installs Shorebird only when it’s missing.

Jenkinsfile

```
pipeline {
  agent none
  environment {
    SHOREBIRD_TOKEN = credentials('shorebird-token')
    FLUTTER_VERSION = '3.47.9'
  }
  stages {
    stage('Release Android') {
      agent { label 'android' }
      steps {
        sh '''
          [ -d "$HOME/.shorebird" ] || curl -fsSL https://shorebird.dev/install.sh | bash
          export PATH="$HOME/.shorebird/bin:$PATH"
          shorebird release android --flutter-version="$FLUTTER_VERSION"
        '''
      }
    }
    stage('Release iOS') {
      agent { label 'macos' }
      steps {
        sh '''
          [ -d "$HOME/.shorebird" ] || curl -fsSL https://shorebird.dev/install.sh | bash
          export PATH="$HOME/.shorebird/bin:$PATH"
          shorebird release ios --flutter-version="$FLUTTER_VERSION"
        '''
      }
    }
  }
}
```

Replace `android` and `macos` with the labels of your agents. An agent keeps the Shorebird version it installed, so run `shorebird upgrade` on it from time to time; Shorebird’s servers stop accepting old CLI versions over time. On a Mac agent, the Xcode that `xcode-select -p` prints is the one that builds, and the agent’s user needs your signing certificate in a keychain it can unlock. Keep both the same while you patch a release.

## Bitrise

Add `SHOREBIRD_TOKEN` under **Secrets** in the Workflow Editor. Bitrise passes secrets to steps as environment variables. Each workflow picks its stack, which sets the machine image and the Xcode version.

bitrise.yml

```
format_version: '25'
default_step_lib_source: https://github.com/bitrise-io/bitrise-steplib.git
project_type: flutter

workflows:
  release-android:
    meta:
      bitrise.io:
        stack: ubuntu-noble-24.04-bitrise-2025-android
    steps:
      - git-clone@8: {}
      - script@1:
          title: Shorebird release
          inputs:
            - content: |-
                set -ex
                curl -fsSL https://shorebird.dev/install.sh | bash
                export PATH="$HOME/.shorebird/bin:$PATH"
                shorebird release android --flutter-version=3.47.9

  release-ios:
    meta:
      bitrise.io:
        stack: osx-xcode-26.6.x
    steps:
      - git-clone@8: {}
      - certificate-and-profile-installer@1: {}
      - script@1:
          title: Shorebird release
          inputs:
            - content: |-
                set -ex
                curl -fsSL https://shorebird.dev/install.sh | bash
                export PATH="$HOME/.shorebird/bin:$PATH"
                shorebird release ios --flutter-version=3.47.9
```

Each script step installs Shorebird and runs it, so `PATH` doesn’t need to carry over to later steps. The stack ID names an Xcode version; keep the same stack while you patch a release. [Bitrise’s stack list](https://github.com/bitrise-io/stacks/tree/main/data) has the current IDs. The `certificate-and-profile-installer` step installs the `.p12` certificates and provisioning profiles you’ve uploaded to the app’s **Code Signing** tab in Bitrise; see [iOS code signing](https://docs.bitrise.io/en/bitrise-ci/code-signing/ios-code-signing.html).

## CircleCI

Add `SHOREBIRD_TOKEN` as an environment variable in your project’s settings, or in a [context](https://circleci.com/docs/guides/security/contexts/) shared by several projects. A job gets a context’s variables only when the workflow names it, so with a context add `context: <name>` to each job under `workflows:`. A `run` step that appends to `$BASH_ENV` sets the `PATH` for the steps after it ([Environment variables](https://circleci.com/docs/guides/security/env-vars/)).

.circleci/config.yml

```
version: 2.1

commands:
  install_shorebird:
    steps:
      - run:
          name: Install Shorebird
          command: |
            curl -fsSL https://shorebird.dev/install.sh | bash
            echo 'export PATH="$HOME/.shorebird/bin:$PATH"' >> "$BASH_ENV"

jobs:
  release-android:
    docker:
      - image: cimg/android:2026.10
    # 8 GB of memory; a Flutter release build can run out of the default 4 GB.
    resource_class: large
    steps:
      - checkout
      - install_shorebird
      - run: shorebird release android --flutter-version=3.47.9

  release-ios:
    macos:
      xcode: '26.6'
    resource_class: m4pro.medium
    steps:
      - checkout
      - install_shorebird
      - run: shorebird release ios --flutter-version=3.47.9

workflows:
  release:
    jobs:
      - release-android
      - release-ios
```

The `cimg/android` image includes a JDK and the Android SDK. On macOS, the `xcode` key picks the machine image and its Xcode; [Using macOS](https://circleci.com/docs/guides/execute/using-macos/) lists the versions and when CircleCI retires each one. Keep the same value while you patch a release, and move to a new Xcode with a new release.

## Bitbucket

Add `SHOREBIRD_TOKEN` under **Repository settings → Pipelines → Repository variables** and check **Secured**. Bitbucket passes repository variables to every step as environment variables ([Variables and secrets](https://support.atlassian.com/bitbucket-cloud/docs/variables-and-secrets/)).

Bitbucket’s own steps run Linux containers. For iOS, a step runs on a [macOS runner](https://support.atlassian.com/bitbucket-cloud/docs/set-up-runners-for-macos/) that you host on your own Mac, selected with `runs-on`.

bitbucket-pipelines.yml

```
pipelines:
  custom:
    release:
      - step:
          name: Release Android
          # Any image with Git, a JDK and the Android SDK works.
          image: ghcr.io/cirruslabs/flutter:stable
          # 8 GB of memory, billed at twice the rate; a Flutter release build
          # can run out of the default 4 GB.
          size: 2x
          script:
            - curl -fsSL https://shorebird.dev/install.sh | bash
            - export PATH="$HOME/.shorebird/bin:$PATH"
            - shorebird release android --flutter-version=3.47.9
      - step:
          name: Release iOS
          runs-on:
            - self.hosted
            - macos
          script:
            - '[ -d "$HOME/.shorebird" ] || curl -fsSL
              https://shorebird.dev/install.sh | bash'
            - export PATH="$HOME/.shorebird/bin:$PATH"
            - shorebird release ios --flutter-version=3.47.9
```

Run it from the pipeline’s **Run pipeline** dialog, which lists `custom` pipelines. A macOS runner isn’t a container, so `~/.shorebird` stays between builds; the iOS step installs Shorebird only when it’s missing. The runner’s Xcode and signing certificate are whatever that Mac has, so keep them the same while you patch a release.
