Sextant – Understand your Release Branches

Sextant is a tool for generating a report (in various formats) that describes the state of GitHub
repositories and their branches. It is meant as a helper for release teams to quickly get an
overview over unreleased changes, merge queues etc., in order to plan the upcoming releases.
You run Sextant locally, provide your GitHub API token and a configuration file with the repositories
in it. Sextant will then scan the repositories and spit out an HTML file that you can view in your
browser of choice.
Example
Using Sextant, a report like this can be generated:

For each repository, the most recent release branches are shown, and for each of those
- the latest tag in that branch
- the number of changes since the most recent tag (the unreleased changes)
- a graphical overview over the open pull requests (approved, in-review, work-in-progress and blocked,
in that order)
- any number of arbitrary custom fields that extract data right from a file in the repository
Limitations
- Sextant should deal fine with
squash+rebase and merge merge strategies, but rebase alone
is untested.
- All release branches must branch off from the default branch and may never be merged back into it.
- All version tags must be set on first parents (i.e. if you use
merge strategy, no version tag
must be set on a merged-in commit, only on the merge commit itself).
- Release branches must be naturally sortable, as must version tags.
Install
Download one of the precompiled releases, use the
ready-made container image codeberg.org/xrstf/sextant or install from source:
$ go install go.xrstf.de/sextant@latest
Usage
- Create a
sextant.yaml (see examples below)
- Create a GitHub access token.
- Export the token as
GITHUB_TOKEN.
- Run
sextant
Usage of sextant:
--cache-directory string optional directory to use for caching data
-c, --config string path to the Sextant YAML config file (default "sextant.yaml")
-f, --format string how to format the resulting report (one of [html json markdown]) (default "markdown")
--load-state-from string instead of querying live data, use this previous state dump for the report
-p, --parallel int how many repositories to scan at the same time (default 3)
-v, --verbose enable more verbose logging
-V, --version show version info and exit immediately
--write-state-to string store entire result machine-readable to allow quick re-runs (for development purposes mainly, you probably want to use --cache-directory instead)
Configuration
By default Sextant uses the sextant.yaml config file, but you can override that using the
--config/-c flag.
Basics
The config file uses YAML and contains all repositories that shall be scanned. For each repository
some basic necessary configuration needs to be made.
repositories:
- owner: me
name: my-repo
releaseBranches:
# Go regexp to match release branches
pattern: release/v.+
# How many release branches to process (branches will be naturally sorted in reverse)
max: 3
Now you're already ready to go:
$ export GITHUB_TOKEN=ghp_....
$ sextant --format html > index.html
Sextant can extract additional information from each found branch and display it along the basic
information it always shows (like the number of unrelased commits, or the latest tag). Extraction
happens by reading files from the repository and potentially processing them with external
scripts/programs.
Each "field" has a unique ID, a display name and a location, specifying where in the report the
field is meant to be shown. Location can be one of
column – The field will be an additional column, right next to the latest tag.
label – There will be an additional row below each branch in the release report, and all label
fields will be placed there.
tooltip – The field will be placed in the tooltip that shows when hovering over a branch name.
Each field is backed by exactly one source. There are currently 2 sources:
goDependency – configure a Go module name and the field will contain this module's dependency
in each of the release branches and the default branch
file – read an arbitrary file from the repository, optionally processing it through an external
program
Go Dependencies
If you want to display your controller-runtime version, your config would look like this:
repositories:
- owner: me
name: my-repo
releaseBranches:
pattern: release/v.+
max: 3
fields:
- id: controllerruntime
label: controller-runtime
location: tooltip
goDependency:
dependency: sigs.k8s.io/controller-runtime
File-based Fields
To read the contents of a file, your configuration could look like this:
repositories:
- owner: me
name: my-repo
releaseBranches:
pattern: release/v.+
max: 3
fields:
- id: depversion
label: An important dependency
location: tooltip
file:
paths:
- config/scripts/app-version.txt
Since files can be renamed, you can specify multiple paths for each file field,
and Sextant will try them in order to find the first one that exists in a release
branch.
Files often don't just contain the important bit, but also other stuf, so it's
possible to process (filter) the file contents with an external program.
repositories:
- owner: me
name: my-repo
releaseBranches:
pattern: release/v.+
max: 3
fields:
- id: depversion
label: An important dependency
location: tooltip
file:
paths:
- config/scripts/app-version.txt
filterCommand:
- ./my-script.sh
- --option
allowedEnv:
- PATH
- HOME
extraEnv:
APP_SPECIFIC_THING: "example.txt"
The given filter command will receive the file contents on stdin and is expected
to produce the desired final field value on stdout. The script receives the
following environment variables:
SEXTANT_FILE_PATH – the actual path that the file was read from
SEXTANT_BRANCH – the branch the file was read from
SEXTANT_REPO_OWNER – self explanatory
SEXTANT_REPO_NAME – self explanatory
Additionally you can configure allowedEnv, which is a list of environment
variables that will be passed-through to the script, useful for things like
PATH. And finally you can give explicit environment variables using extraEnv.
Pull Requests
Especially when additional column fields are configured, it can become necessary
to limit the number of PRs that are shown for each branch. This can be achieved
using the pullRequests configuration section:
repositories:
- owner: me
name: my-repo
releaseBranches:
pattern: release/v.+
max: 3
pullRequests:
maxDisplay: 5
License
MIT