Skip to content
platacardPublic

About

Finally, Swift deploy automation for Apple platforms.

Resources

Stars

61 stars

Watchers

2 watching

Forks

Repository files navigation

blimp_icon_dark Blimp

All Contributors

Finally, Swift deployment automation for Apple platforms.

Heavily inspired by fastlane.

Blimp refers to a non-rigid flying ship (like a zeppelin). Rarely used nowadays, it might be slow and clumsy, but still beautiful and gets the job done.

Disclaimer

This project is still a work in progress but aims to be a native Swift fastlane replacement in the future. However, the implementation is already stable enough for Plata to ship our apps with it. If you have questions or issues, just open an issue/discussion and we'll try to help. If you want to contribute, feel free to open a pull request.


Installation

As package dependency:

dependencies: [
    .package(url: "https://github.com/platacard/blimp.git", from: "0.9.0")
]

Features overview

What's working

  • Archiving and exporting the iOS app
  • Authenticating with the App Store Connect API
  • Uploading iOS apps to App Store Connect via the modern build upload API and waiting for processing
  • Assigning beta groups and sending builds for review
  • Inviting developers and beta testers to TestFlight

What's yet to be implemented

  • Testing support for watchOS, macOS, and other less-used platforms

Getting started

Blimp is meant to be a building block in your pipeline, not a final, opinionated solution. It is best used in combination with other packages:

  • cronista — A simple logger
  • corredor — A shell wrapper
  • gito — A git wrapper
  • slackito — A Slack API client using result builders
  • dotcontext — An environment variables manager that extends .env file functionality

These packages provide a modular way to build your deploy pipeline. But the best part is that they are not required to use blimp. Tweak everything to your liking.

You can try things out by calling the blimp CLI via swift run blimp {command}, or you can compile the project and use the binary artifact directly.

❗️ Moreover, blimp CLI provides an example of how you can use BlimpKit in your CLI. We recommend trying out the swift-argument-parser package, it works great for us.

Authenticating

Environment expects 3 variables:

  • APPSTORE_CONNECT_API_ISSUER_ID
  • APPSTORE_CONNECT_API_KEY_ID
  • APPSTORE_CONNECT_API_PRIVATE_KEY

To get the private key, go to https://appstoreconnect.apple.com/access/integrations/api and create your own key. This is also the page to find your private key ID and the issuer ID.

After downloading your private key, you can open the .p8 file containing the private key in any text editor:

-----BEGIN PRIVATE KEY-----
FDFDGgEAMBMGByqGSM49AgEGCCqGSM49AwEHBHkwdw...
49AgEGCCqG\...
...
-----END PRIVATE KEY-----

Copy the contents and remove all the whitespacesa and newlines, -----BEGIN PRIVATE KEY----- and -----END PRIVATE KEY-----.

Use export APPSTORE_CONNECT_API_PRIVATE_KEY={bare_key_without_newlines} && ... locally or create environment variables for your CI provider. JWT token for API client will be created (and recreated on expiration) authomatically if needed variables are in place.

Running

Using binary artifact:

swift build -c release

Then, you can use the binary artifact directly:

./build/release/blimp {command}

Available commands

Use -h with each command to see all available parameters and their default values.

  1. blimp takeoff {params} - Archive the project
  2. blimp approach {params} - Upload the archive to App Store Connect
  3. blimp land {params} - Assign the build's beta groups and send it to external review
  4. blimp hangar {subcommand} {params} - Additional checks and operations with App Store Connect API
  5. blimp maintenance {subcommand} {params} — Manage provisioning profiles, certificates, and devices

App Store Connect processing

By default, blimp approach blocks and polls the App Store Connect API every 30 seconds until the build finishes processing — zero setup, but the CI runner stays busy for the whole processing window.

Once the build is processed, blimp approach prints BuildId: <id> and hands the id to blimp land, which takes it from --build-id or, when the option is omitted, from the BUILD_ID environment variable.

How the id travels between steps depends on the CI provider, detected from the environment:

Provider Detected by Outputs go to
dotenv file (any CI or shell) BLIMP_OUTPUT name=value lines at that path
GitLab CI GITLAB_CI $CI_PROJECT_DIR/blimp.env, a dotenv artifact
GitHub Actions GITHUB_OUTPUT $GITHUB_OUTPUT, plus a note in the step summary

An explicit BLIMP_OUTPUT wins, so outputs can always be redirected. With neither set, nothing is written and the logged BuildId: line is the handoff.

GitHub Actions

blimp approach appends BUILD_ID=<id> to $GITHUB_OUTPUT. Give the step an id and pass the output to blimp land:

- name: Upload to App Store Connect
  id: approach
  run: blimp approach --bundle-id com.app --ipa-path build/App.ipa --app-version 1.0 --build-number ${{ github.run_number }}

- name: Assign beta groups and submit for review
  env:
    BUILD_ID: ${{ steps.approach.outputs.BUILD_ID }}
  run: blimp land --bundle-id com.app --beta-groups "Beta Testers"

Step outputs stay inside the job. To land in a separate job, expose the output at the job level and read it through needs:

jobs:
  upload:
    runs-on: macos-latest
    outputs:
      build-id: ${{ steps.approach.outputs.BUILD_ID }}
    steps:
      - id: approach
        run: blimp approach …

  land:
    needs: upload
    runs-on: macos-latest
    steps:
      - run: blimp land --bundle-id com.app --build-id "${{ needs.upload.outputs.build-id }}" --beta-groups "Beta Testers"

GitLab CI

blimp approach writes blimp.env in the project directory. Publish it as a dotenv artifact and GitLab injects BUILD_ID into every job that depends on the upload job:

upload:
  stage: deploy
  script:
    - blimp approach --bundle-id com.app --ipa-path build/App.ipa --app-version 1.0 --build-number $CI_PIPELINE_IID
  artifacts:
    reports:
      dotenv: blimp.env

land:
  stage: deploy
  needs: [upload]
  script:
    - blimp land --bundle-id com.app --beta-groups "Beta Testers"

Other CI and shells

The same dotenv file works anywhere: BLIMP_OUTPUT=build.env blimp approach … then source build.env (or set -a; . build.env) before blimp land. Without BLIMP_OUTPUT, capture the id from the log: blimp approach … | tee approach.log then BUILD_ID=$(grep -oE 'BuildId: [0-9A-Za-z-]+' approach.log | head -1 | awk '{print $2}').

blimp-relay is the webhook alternative: a small, separately deployable HTTP server that receives App Store Connect webhooks, verifies their signatures, and relays them to configurable sinks (log, HTTP forward, GitLab pipeline trigger) — so the upload job can exit right after the upload and a webhook resumes your pipeline.

See Sources/Relay/README.md for setup, configuration, and deployment.

Architecture overview

blimp aims to keep its dependencies to a minimum. It uses Apple's OpenAPI generator to create App Store Connect API clients. Swift Crypto is used for JWT signing. Swift Argument Parser is used for the command line interface implementation. Finally, our own cronista and corredor are used for logging and calling CLI tools.

  • Archiving and exporting are done via xcodebuild.
  • Uploading is done via the App Store Connect build upload API (with an optional legacy altool fallback).
  • Processing is done via the App Store Connect API.

Attributions

JWT signing was borrowed from AvdLee under MIT License.

Contributors ✨

Thanks goes to these wonderful people (emoji key):

Konstantin Iurichev
Konstantin Iurichev

💻
Ilya Kharabet
Ilya Kharabet

💻
tigati
tigati

💻
Claude
Claude

💻

This project follows the all-contributors specification. Contributions of any kind welcome!

About

Finally, Swift deploy automation for Apple platforms.

Resources

Stars

61 stars

Watchers

2 watching

Forks

Releases

Packages

Used by

Contributors

Languages