Skip to content
GhostbranchdocsGitHub

Configuration

Every key in .ghostbranch.yml, with its type, its default and what it changes.

.ghostbranch.yml holds a repo pair’s settings. It lives on the ghostbranch branch of the shadow repo, the overlay branch, and is never published. Every command that needs the settings reads them from there, never from a feature branch.

  1. Check out the ghostbranch branch from the shadow repo, and edit .ghostbranch.yml.
  2. Commit, and push the branch to the shadow repo. The next command reads the new settings.
  3. If you changed sync.schedule, run ghostbranch upgrade --plan, then ghostbranch upgrade, to add or remove the sync workflow.

ghostbranch init writes this file, with your repos’ names:

.ghostbranch.yml
# Ghostbranch configuration. It lives only on this shadow repo's
# "ghostbranch" branch and is never promoted.
version: 1
public: you/project
shadow: you/project-shadow
promote:
target: pr
# preserve publishes each feature commit; squash publishes one commit;
# curated regroups, reorders and rewords commits from a --curate file.
default_mode: preserve
# noreply publishes every commit as your GitHub noreply identity; keep
# publishes the original authors; map uses author_map.
author_email: noreply
leak_scan:
strip: [".ghostbranch/**"]
markers:
begin: BEGIN-INTERNAL
end: END-INTERNAL
block_patterns: []
large_file: 5MB
secrets: true
sync:
# Scheduled sync is off: run ghostbranch sync yourself (commands warn when
# shadow main falls behind public). To opt in, set a cron such as
# "23 */6 * * *" (about 120 Actions minutes a month), then run
# ghostbranch upgrade.
schedule: "off"
branches: [main]
ci:
rewrite_repo_guards: rewrite
gate:
ci_appear_timeout: 10m
ci_timeout: 60m

A key you leave out takes its default, shown in the tables below. Leave out a whole section rather than leaving it empty: an empty promote:, leak_scan: or gate:, or one with only comments under it, is read as a key Ghostbranch doesn’t know (see below). Only sync: and ci: may be empty.

Key Type Default What it does
version integer 1 The file’s format. It must be 1.
public owner/name none, required The public repo. It must name this pair’s public repo.
shadow owner/name none, required The shadow repo. It must name this pair’s shadow repo.

The keys under promote: decide how promote publishes. See History modes.

Key Type Default What it does
target string pr What a publish makes. Only pr, a pull request, is supported.
default_mode squash, preserve or curated preserve The history mode when promote has no --mode.
author_email noreply, keep or map noreply Whose name each public commit carries: the publishing account’s GitHub noreply identity, each commit’s own author, or the identity author_map names.
author_map map of email to "Name <email>" empty The identity to publish for each author email, under author_email: map. Emails match ignoring case. With map, it must list at least one email.
.ghostbranch.yml
promote:
author_email: map
author_map:
"you@laptop.local": "Your Name <you@example.com>"

The keys under leak_scan: decide what the leak scan looks for, and what is never published.

Key Type Default What it does
strip list of path patterns .ghostbranch/** More overlay paths: they may live on the overlay branch, and they are removed from everything published.
secrets boolean true Secret scanning. It must be true: it can’t be turned off.
markers.begin string BEGIN-INTERNAL The line that opens an internal section.
markers.end string END-INTERNAL The line that closes one.
block_patterns list of regular expressions [] Extra patterns the scan blocks, in Go’s regular expression syntax.
large_file size 5MB New or changed files larger than this give a LARGE_FILE warning.

The details:

  • Overlay paths: .ghostbranch.yml, .ghostbranch/** and .github/workflows/ghostbranch-* always are, whatever strip says.
  • Path patterns: * and ? never match a /; ** matches across folders. A leading **/ also matches no folder at all, so **/NOTES.md matches NOTES.md, and a trailing /** matches everything under a folder.
  • Markers are matched ignoring case. Each must be one word (no spaces), not made only of comment characters such as #, - or *, and the two must differ. A letter or a digit in each keeps them clear.
  • Sizes are a number of bytes, such as 1048576, or a whole number with KB, MB or GB (powers of 1024), such as 512KB.

The keys under sync: decide how the shadow repo keeps up with public. See Sync.

Key Type Default What it does
schedule "off" or a cron schedule "off" Scheduled sync: five cron fields, such as "23 */6 * * *", on one line. GitHub runs schedules at most every 5 minutes, so a minute field of * or */1 to */4 is refused. Run ghostbranch upgrade after changing it.
branches list of branch names [main] The branches sync fast-forwards from public. It must include main, and list each branch once.

sync must be a section. To turn scheduled sync off, set schedule: "off"; sync: off is an error.

The key under ci: decides how the gate treats your workflows. See Repo guards.

Key Type Default What it does
rewrite_repo_guards rewrite, warn or off rewrite What the gate does with jobs guarded to the public repo, such as if: github.repository == 'you/project'. rewrite rewrites the guard in the gate’s CI candidate only, so the job runs in the shadow repo. warn leaves it, so the job skips, and warns REPO_GUARD. off leaves it and doesn’t warn.

If any guarded job deploys or publishes, use warn: a rewritten guard would run that job in the shadow repo, on unreleased code.

The keys under gate: decide how long the gate waits for CI. See Long CI.

Key Type Default What it does
ci_appear_timeout duration 10m How long to wait for the first check to appear. Past it, the gate fails with NO_CI.
ci_timeout duration 60m How long CI may run, counted from the start of the gate. Past it, the gate fails with CI_TIMEOUT.

A duration is a number with a unit, such as 90s, 10m or 1h30m, and must be more than zero.

A key Ghostbranch doesn’t know is an error, at any level, sync: and ci: included, so a typo is never silently ignored. Commands stop with UPGRADE_NEEDED and name the key in error.details.unknown_key: the file may have been written by a newer Ghostbranch, so upgrade, or fix the typo.

Two kinds of key only warn, with CONFIG_KEY_IGNORED:

A bad value, or a file that names another pair, stops commands with CONFIG_INVALID. So does a file on the overlay branch that isn’t an overlay path.

CONFIG_INVALIDexit 1.ghostbranch.yml on the overlay branch is missing or invalid, or the overlay branch holds non-overlay paths.
What to do

A person fixes .ghostbranch.yml on the shadow repo's ghostbranch branch.

This needs a person.

UPGRADE_NEEDEDexit 1Something this pair uses was written by a newer Ghostbranch: a record (error.details.record: feature, plan, grants or waivers) or the overlay config (error.details.unknown_key, a key this binary doesn't know).
What to do

Upgrade ghostbranch on this machine to the version that wrote it, or newer (the other machine is probably newer). Don't edit the record or the overlay config to make an older binary accept it. If the key in error.details.unknown_key is a typo, a person fixes it in .ghostbranch.yml on the overlay branch.

CONFIG_KEY_IGNOREDwarning.ghostbranch.yml has a key this version does not use.
What to do

Nothing is required; remove the key to silence the warning.

OVERLAY_OUTDATEDwarningA Ghostbranch-managed file on the overlay branch is missing, out of date, or edited by hand.
What to do

Run ghostbranch upgrade --plan to see the change, then ghostbranch upgrade.