How it works

One pull request, all the way to a tester

Five stages. The interesting part is not any one of them — it is that the whole path holds together without somebody watching it.

  1. 01

    Somebody opens a pull request

    Conductor reads release.yaml from the repository at that commit and validates it before scheduling anything. A malformed pipeline fails in half a second with a line number, not twenty minutes into a build.

    A pull request from a fork runs on the untrusted pool: zero credentials, no distribution, and an unsigned build. That is not a setting — it follows from the steps the workflow names, and there is no flag anybody can set wrongly.

  2. 02

    A machine that can actually run it picks it up

    Jobs are matched to runners by capability, not by name. A job needing Xcode 16.4 goes to a machine that has Xcode 16.4, because Xcode is far too large to install on demand and pretending otherwise is how a queue silently stops moving.

    Everything else the build needs — Node, Flutter, Ruby, the JDK — is installed and cached on demand from your own pins: .nvmrc, .fvmrc, .ruby-version, the Gradle wrapper.

  3. 03

    It builds, signs, and keeps what matters

    Credentials are fetched per job, scoped to exactly the purposes the steps in that job declare, and never written where the next job can read them. Logs are scrubbed before they leave the machine.

    dSYMs, mapping files, Hermes sourcemaps — collected per build and kept, so the crash report you get in three weeks resolves to a line of your code.

  4. 04

    You decide what ships

    A release is a version, a build number and a set of artifacts. Where it goes is a decision — and where approval is required, the approval is checked before any bytes move.

    That ordering is the whole point. An uploaded TestFlight build is already visible to internal testers, so a system that uploads and then waits is guarding a door that is already open.

  5. 05

    And you can move it later

    No Apple Team ID and no Play developer id appears in your repository. The validator refuses one outright. Targets resolve by name at run time, so moving a project to a different store account is a configuration change rather than a rewrite.

    This is the feature nobody asks for at evaluation and everybody needs eventually — an acquisition, a rebrand, a developer account somebody set up in a hurry four years ago.

What Conductor will not do

Refusals are a design, not a gap. Each of these could be built and each would make the product worse.

Supply the Macs
You run your own fleet, on Cloud as well as self-hosted. That is why the price here is not per build minute — and why nothing we do gets more profitable when your builds get slower.
Regenerate an upload keystore
Under Play App Signing that requires Google’s upload-key reset process. A tool that “helpfully” makes a new one has locked you out of your own listing.
Auto-issue an Apple distribution certificate
The per-team cap means issuing one when the team is full requires revoking another — which breaks signing for every app on that team, including apps Conductor does not manage.
Show you a credential again
Material is encrypted at rest and no API returns it, to anybody, including you. A minted secret is shown exactly once, and the console says so rather than implying otherwise.
Tick a provisioning box for you
A manual item is done when a probe confirms it against the provider, never when somebody says it is. That check is what catches an app record created under the wrong team.

The honest version of “it just works”

Apple and Google expose no API for several things a release needs — creating an App Store Connect app record, accepting a developer agreement. Those gaps are permanent. A tool that hides them fails opaquely at exactly the gap, which is the worst possible place to fail.

So Conductor names them. The provisioning plan lists each one with a deep link to the right console page and the exact thing to do — and then verifies it against the provider afterwards, rather than trusting a checkbox.