Workflows

Workflows trigger builds automatically from a variety of events. Instead of starting every build by hand, you describe when a build should happen and Bifrost runs it for you.

Workflows are available from the main menu under each project. Each workflow belongs to a single project and starts one or more builds when its trigger fires — put an iOS build and an Android build in the same workflow and one event builds both, each with the signing credential and build configuration you choose.

When an event triggers a workflow, the workflow's configuration is copied onto the build at that moment. Editing or deleting a workflow never affects builds it has already started — although deleting a workflow does unlink its existing builds, so they'll show as manually triggered.

Requirements

  • Your project must be connected to a GitHub repository via the Bifrost GitHub App.
  • The platform you're building needs a signing credential set up under the project's Credentials tab — a workflow builds a native app, so it can't be saved without one.
  • Your team needs an active subscription with builds remaining — workflow builds count towards your plan's build usage exactly like manual builds. When you're out of builds, workflow triggers are skipped quietly.
  • Archived projects never trigger workflow builds.

How many workflows you get

Apprentice and Loki include one workflow per app. Because a single workflow can build both platforms and run follow-up steps, one is enough to automate your primary build end to end.

Hela and Thor include unlimited workflows per app, so you can run different automation for different events — build every pull request, build again on pushes to whichever branches you pick, and cut a release build from a tag, each with its own steps and notifications.

Triggers

Pull request opened

Builds when a pull request is opened or reopened, and again for every new commit pushed to it. The pull request gets a status check and a comment linking to the build, updated as the build progresses.

Only pull requests from branches in the same repository are built. Pull requests from forks are ignored — fork branches aren't reachable with your repository's installation token, and building unreviewed third-party code automatically isn't something you want.

The branch filter matches against the pull request's head branch (the branch being merged).

Push to branch

Builds when commits land on a branch, including when a pull request is merged into it. Tag pushes and branch deletions are ignored.

Branch created

Builds when a new branch is created in the repository.

Heads up: pushing a brand-new branch makes GitHub send both a branch created event and a push event. If the same branch matches both a "Push to branch" workflow and a "Branch created" workflow, each one starts its own build. Use your branch filters to keep them apart — or pick one trigger and stick with it.

Tag created

Builds when a new tag is created. The build checks out the tag, and — like releases — the tag becomes the build's version number (a leading v is stripped). For this trigger the filter matches against tag names, so v* builds every version-prefixed tag.

Heads up: publishing a GitHub release creates its tag if it doesn't exist yet, so a "Tag created" workflow and a "Release published" workflow matching the same tag will each start a build.

Release published

Builds when a GitHub release is published. The build checks out the release tag, and the tag becomes the build's version number (a leading v is stripped, so v2.3.0 builds version 2.3.0).

Release triggers target a tag rather than a branch, so the branch filter doesn't apply to them.

Run by an AI agent

A workflow with this trigger never fires from GitHub. It only runs when an AI agent connected to your team's Bifrost MCP server asks for it, and it is the only kind of workflow an agent can see. There is nothing to configure about what it builds: the agent says so every time it runs the workflow, passing exactly one of

  • branch: the latest commit on that branch is built.
  • tag: that tag is built, and it becomes the build's version (a leading v is stripped).

The agent uses list-workflows to see what it may run, run-workflow to start one, and get-workflow-run to follow it. The run records the branch or tag and who asked.

Called from Webhook

A workflow with this trigger runs when something POSTs to its webhook URL, shown on the workflow's page: a CI/CD pipeline, a deploy script, anything that can make an HTTP request. The URL contains a secret, so treat it like a password; regenerate it from the same place if it leaks, and the old one stops working immediately.

Nothing about what gets built is configured on the workflow. Every call says so in its JSON body, with exactly one of:

  • branch: the latest commit on that branch is built.
  • tag: that tag is built, and it becomes the build's version (a leading v is stripped).

Optionally add source to name what started the run in the run history; it shows as "Webhook" otherwise.

curl -X POST "https://bifrost.nativephp.com/triggers/…" \
  -H "Content-Type: application/json" \
  -d '{"branch": "main", "source": "GitHub Actions"}'
curl -X POST "https://bifrost.nativephp.com/triggers/…" \
  -H "Content-Type: application/json" \
  -d '{"tag": "v1.4.0", "source": "Release pipeline"}'

A 202 response carries the run_id, the run's status, the ref and version being built, and a link to the run. A body with neither or both of branch and tag is a 422; a paused workflow or an archived project is a 409; an unknown key is a 404.

Branch and tag filters

Every GitHub trigger except Release published accepts an optional filter. It matches branch names — or tag names for the Tag created trigger. Agent and webhook workflows take no filter; the caller names what to build:

  • Leave it blank to run for any branch (or tag).
  • Enter a name for an exact match — main runs only for main.
  • Use * as a wildcardrelease/* matches release/1.0, feature-* matches feature-login, and v* matches v2.3.0.

Matching is case-sensitive, and a filter without a wildcard never matches partially: feature- matches only a branch literally named feature-, not feature-login.

Duplicate protection

GitHub occasionally redelivers webhooks. A workflow won't build the same commit twice within a ten-minute window, so redeliveries don't eat your build credits. Distinct commits always build — every new commit pushed to an open pull request gets its own build.

Pipelines

A workflow is a trigger followed by two stages. Open a workflow from the Workflows screen to see it laid out left to right.

  • When triggered holds the builds, which start the moment the trigger fires. Put an iOS build and an Android build here to build both at the same time. At most one build per platform, because a project only runs one store build per platform at a time. An Android build that distributes to the store also picks its Play Store track: internal testing (the default), closed testing, open testing, or production.
  • Then waits for every build to finish and runs all of its steps, whatever the outcome. What each step sends says whether the builds passed or failed: the email subject reads "passed" or "failed", the webhook payload carries run.outcome, and both list each build with its own status. If Android passes and iOS fails, the workflow counts as failed.

Besides builds, a stage can hold:

  • Send to a URL — a JSON POST describing the run and every build it has started so far, including each build's status, version and page link. Set a signing secret and every request carries an X-Bifrost-Signature header holding sha256= followed by the HMAC-SHA256 of the request body, so your endpoint can verify it came from Bifrost. A URL that cannot be reached, or that answers with an error status, fails the step.
  • Send to Slack — a message in a Slack channel through an incoming webhook, saying whether the workflow started, passed or failed and linking to each build. Mattermost and Rocket.Chat webhooks accept the same message.
  • Send to Discord — the same message posted to a Discord channel through a channel webhook.
  • Email — the same summary, sent to the addresses you list. The subject says the workflow started, passed or failed, depending on where the step sits.

The Runs tab on a workflow shows each run with its steps grouped by stage, why a step was refused, and a link to every build.

Tracing builds back to workflows

Builds started by a workflow show the workflow's name in the Triggered by column of your project's builds list and on the build's detail page. Builds you start by hand show as Manual. The Workflows settings screen also shows how many builds each workflow has triggered.

Need to pause a workflow without deleting it? Flip its Active switch off — it keeps its configuration and history, and stops responding to events until you switch it back on.