Prerequisites
- An app already synced to Nuon, with at least one install.
- The Nuon CLI installed and authenticated (
nuon auth login). - For pull request previews, the Nuon GitHub App connected in your org for the repository’s owner. See connecting a repository.
Every branch of a given app must point at the same repository, and an install can belong to only one branch at a
time. See rules and limits before you plan more than one branch.
Write a branch config
Add abranch.toml file to the root of your app config directory, next to metadata.toml. It declares the branch
name, the repo and branch to track, and the deployment groups the rollout moves through.
branch.toml
- The repo block. Use
[connected_repo]for a repository connected through the Nuon GitHub App, or[public_repo]for a public one. Exactly one of the two, andrepo,directory, andbranchare all required.directoryis the path to your app config within the repo, or"."if it is at the root. nameis the branch’s name in Nuon, and it comes from this key, not from the filename. It is what you pass tonuon sync --branch.- Group order.
orderdecides which group deploys first, lowest first. List your groups in the order you want them to run.
Every branch needs one of
[connected_repo] or [public_repo]: the repo block is what the deployment groups sync
against.Selecting installs for a group
Each group picks its installs one of two ways: alabel_selector, or an explicit list (install_ids and
install_names, which may be combined; names resolve to IDs at sync time). A label selector cannot be combined with
an explicit list in the same group:
One branch or several
Two layouts are supported, and they are mutually exclusive:branch.toml: a single branch. This is what most apps want, and what the rest of this guide assumes.branches/*.toml: one file per branch, for tracking several branches of the same repo (astagingbranch and amainbranch, for example). Thenamekey inside each file sets the branch name; the filename does not.
Label your installs
A label selector only matches installs that actually carry the labels. Set them with the CLI:key=value arguments. To inspect or remove them:
--labels must match, so this is the same AND semantics a group’s label_selector uses. On a
fleet of more than 20 installs, pass --limit at least your install count to list every match.
Sync the branch config
Syncing your app config creates or updates the branch, along with its deployment groups:nuon apps branches delete for that.
Confirm what Nuon now has:
list prints each branch’s name and ID; get takes the branch ID and returns the full branch, deployment groups
included.
The
nuon apps branches subcommands take the app ID (app...), which nuon apps list prints. Or select the
app once with nuon apps select (no flags, pick from the list) and omit --app-id wherever it is optional.Trigger a run
Once the branch exists, a push to the tracked branch is all it takes:nuon apps branches runs.
You do not have to wait for a push, though. Two other ways to start a run, both using the app you selected with
nuon apps select:
--preview on a manual run suppresses the apply, not the workflow. The run still creates
plan install group: <name> and deploy install group: <name> for every group, but each approval gate
auto-approves (“Auto-approved in plan-only mode”) and nothing is applied — the run finishes on its own, and you read
the per-install diffs from the completed run. This differs from a pull request preview, which never creates the
group steps at all.nuon sync --branch runs against your local, uncommitted files, not the tracked branch’s commit — the right
tool for iterating on a change before pushing it. The --branch, --app-branch, and --preview flags live on
nuon sync (not nuon apps sync), and --preview takes effect alongside --branch or --app-branch.nuon sync --branch hands Nuon a config it already built locally, that run’s first two steps appear as
fetch commit (skipped) and fetch app config (skipped). A run started from a push or from
nuon apps branches trigger fetches from git and shows both steps running.
nuon apps branches trigger and nuon apps branches runs open the full-screen workflow TUI, so you can watch steps
and approve from the terminal. See the TUI reference.
Approve or skip a deployment group
A run pauses at each group’s plan step until someone acts on it. In the dashboard, open the app’s Branches view, then the run, and you will see the Deployment plan with each group’s steps. For each group:- Approve install group plan — read the per-install diff, then approve to let the group’s deploy step run.
- Skip install group — move the rollout past this group’s deploy without applying it.

A branch run holding at the stage gate: review the proposed changes, then approve to deploy to that group.
There is no setting that auto-approves a deployment group’s plan. Each one needs a human in the dashboard or an API
caller. If you want a machine to advance a rollout, subscribe to the webhook events for the run
and drive the approval through the API once your own checks pass.
Set up pull request previews
There is nothing to configure on the branch itself. Opening a pull request against a tracked branch, or pushing another commit to an open one, starts a plan-only run, and Nuon reports back on the pull request:- a comment headed
## Nuon Preview — <BranchName>(the branch’sname, so usuallymain) with a table of config changes by section, edited in place on each later push rather than added to. - a commit status with the context
nuon/preview, moving from pending to success or failure.
[public_repo] branch pointing at acmeco/my-app gets
previews just like a [connected_repo] one, provided your org has connected acmeco.
Previews start posting as soon as your org has the GitHub App connection for the repository’s owner. If they have
not appeared yet, that connection is the thing to check — not your
branch.toml.Roll back when a change goes badly
Every config change to an install is recorded as an app config version, and any earlier version can be applied again, to one install or to a whole deployment group, with a plan in front of it. The rollback guide walks through the exact calls.Command reference
Troubleshooting
The branch synced but has no deployment groups. The branch config is missing its[connected_repo] /
[public_repo] block. Add one and sync again.
A push did not start a run. Branch matching is on the exact repository and branch name. Check that the branch’s
branch value matches the ref you pushed and that the repo is the one Nuon has connected. There are no path filters,
so a push that matches always starts a run. If nothing happened, the match itself failed.
The pull request has no Nuon comment. Your org has no GitHub App connection for that repository’s owner. The
preview run itself succeeds and this is not reported as an error, so check the connection rather than the branch config.
Note this is about the owner, not the branch’s repo block. A [public_repo] branch is fine if the owner is connected.
A sync failed on an install name. install_names must resolve to installs that exist in the org you are syncing
into. Switch the group to a label_selector, or create the install first.
A group deployed to nothing. No install carried the selector’s labels. Check with
nuon installs list --labels ....
Next steps
How app branches work
Run types, plan and approval flow, and install version history.
Walkthrough
Roll a change through the
eks-simple example app end to end.Roll back an install
Re-apply a previous config version to an install or a whole group.
Branch config reference
Every field on
branch.toml.Webhooks
React to branch runs from your own systems.