Skip to content

MichaelProjects/blazelane

Repository files navigation

blazelane

A self-hosted alternative to Fastlane for signing and distributing iOS apps via the App Store Connect API. Designed for modern cloud infrastructure — no Ruby, no fragile toolchain, no per-machine setup headaches.

Table of contents

Getting started

1. Clone the repo and build

git clone https://github.com/MichaelProjects/blazelane
cd blazelane

2. Create your project config

Copy the template and fill it in:

cp create-template.yaml myapp.yaml
# App Store Connect API credentials
# Create an API key at: App Store Connect > Users and Access > Integrations > API Keys
system:
  issuer_id: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"  # Issuer ID from the API Keys page
  key_id: "XXXXXXXXXX"                                # 10-character key ID
  key:
    path: "/path/to/AuthKey_XXXXXXXXXX.p8"            # Path to the downloaded .p8 file

# GitLab project where CI/CD variables will be stored
gitlab:
  url: "gitlab.com"
  project_id: 12345678
  auth_key: "glpat-xxxxxxxxxxxxxxxxxxxx"              # GitLab personal access token

# Your app and its bundle IDs
# Add one entry per signing target (main app + each extension)
app:
  name: "My App"
  app_id: "1234567890"      # Numeric App ID from App Store Connect
  team_id: "XXXXXXXXXX"     # Apple Developer Team ID
  bundles:
    - bundle: "com.example.app"
      name: APP_PROVISIONING              # Used as the GitLab variable prefix
    - bundle: "com.example.app.share"
      name: SHARE_EXTENSION_PROVISIONING

3. Run prepare

blazelane prepare setup --project-cfg myapp.yaml

4. Investigate the logs

blazelane logs each step as it runs.

⚠️ Warning: The distribution certificate must be created in the same run as the provisioning profiles; a future release will allow re-use of an existing certificate. blazelane currently cannot fetch or import a pre-existing distribution certificate.

If no valid distribution certificate exists, blazelane generates a new RSA 2048 CSR, creates the certificate via the API, and writes a csr_info.json to the working directory containing the private key. Store this file securely — it cannot be recovered if lost.

Once prepare completes, the following variables will be set in your GitLab project:

Variable Contents
DISTRIBUTION_CERT_P12 Base64-encoded PKCS#12 archive (cert + private key)
DISTRIBUTION_CERT_PASSWORD Password to import the .p12
<PREFIX>_ID Profile id for each bundle
<PREFIX>_PROFILE Base64-encoded .mobileprovision for each bundle

Why

Fastlane works, but it's painful to set up and maintain, especially in CI environments. blazelane takes a different approach:

  • Talks directly to the App Store Connect API
  • Stores certificates and secrets in your existing secret manager
  • Access to secrets is controlled by your IAM provider — no shared passwords or .env files
  • Single binary, no runtime dependencies

How it works

blazelane is split into two distinct phases that map naturally to your workflow.

Part 1 — Prepare (run locally by a developer)

The prepare phase is a one-time (or infrequent) setup step run from a developer machine. It handles everything that requires human interaction or elevated App Store Connect permissions:

  • Generating an RSA 2048 distribution certificate via the App Store Connect API
  • Generating provisioning profiles for each bundle ID (main app + extensions)
  • Uploading certificates and profiles to your secret manager

After running prepare, all secrets needed for CI are stored securely and centrally. No developer machine state is required to reproduce the build environment.

blazelane prepare setup --project-cfg ./myapp.yaml

NOT YET IMPLEMENTED | Part 2 — CI (runs in your pipeline)

The CI phase is designed to run headlessly in any standard CI environment (GitHub Actions, GitLab CI, Cloud Build, etc.). It pulls the certificates and profiles stored by the prepare phase from your secret manager and uses them to sign and distribute your .ipa.

blazelane sign --project-cfg ./myapp.yaml --ipa ./MyApp.ipa
blazelane distribute --project-cfg ./myapp.yaml --ipa ./MyApp.ipa test-flight
blazelane distribute --project-cfg ./myapp.yaml --ipa ./MyApp.ipa app-store

CI runners authenticate to the secret manager via their attached IAM role or service account — no credentials need to be injected manually.

Feature availability

blazelane prepare setup

Step Status Notes
Generate RSA 2048 CSR ✅ Implemented
Create distribution certificate ✅ Implemented
Fetch registered bundle IDs ✅ Implemented
Generate provisioning profiles ✅ Implemented One profile per bundle ID
Store secrets in GitLab CI/CD variables ✅ Implemented
Validate before creation (skip if valid cert/profile exists) ⚠️ Partial Duplicate creation not yet guarded
Detect and regenerate expired profiles ⚠️ Partial is_valid() exists, auto-regeneration not wired up
Atomic / resumable setup (fail-safe) ❌ Not yet If a step fails the process must be restarted from scratch

Signing

Feature Status Notes
Code signing (re-sign .ipa) 🔜 Planned Will fully replace fastlane's signing step

Distribution

Feature Status Notes
Upload to TestFlight 🔜 Planned
Submit to App Store 🔜 Planned

Secret backends

Backend Status
GitLab CI/CD variables ✅ Implemented
Google Secret Manager 🔜 Planned
Other backends (Vault, etc.) 🔜 Optional / community

Known limitations

  • Not fail-safe: the prepare setup flow is not atomic. If any step fails mid-way (e.g. profile creation succeeds but secret upload fails), the process must be run again from the beginning. Idempotency and partial-state recovery are planned.
  • No duplicate detection: running prepare setup twice may create duplicate certificates or profiles in App Store Connect. Validation to check for existing valid resources before creation is planned.
  • GitLab only: secret storage is currently limited to GitLab CI/CD variables. Google Secret Manager and AWS Secrets Manager support is on the roadmap.

Project structure

blazelane/
  cli/              # CLI entry point and commands (prepare, sign, distribute)
  client/           # Generated App Store Connect API client (via progenitor)
  openapi.oas.json  # App Store Connect OpenAPI spec (filtered to relevant tags)

About

Self-hosted iOS code signing and App Store distribution — no Ruby, no Fastlane, no per-machine setup. Talks directly to the App Store Connect API and stores secrets in your CI/CD secret manager.

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages