Skip to content

Components

How the code is arranged, and why it is arranged that way. Go API details are on pkg.go.dev; this page is the map.

The shape

The design turns on one decision: the version decision is a pure function, and everything that touches the world sits below it.

  policy      decides the next version — pure, no I/O at all
     ▲
  history     reads git and produces exactly what the decision needs
     ▲
  propose / publish   the two verbs, and the forge calls they make

That is what makes the consequential part exhaustively testable as a table and reviewable without running anything.

The packages

Package Responsibility
policy Decides the next version. Pure: no clock, no network, no filesystem, no git. Same inputs, same decision, every time.
history Reads a repository and produces what a version decision needs: where the project is now, and what has landed since. The seam where I/O enters.
manifest Reads .colophon.yaml, the file a maintainer commits to hold a release back.
trailer Reads git trailers from a commit message.
notes Collects the prose a commit contributes to its release's notes.
proposal Builds the release proposal: the release commit's subject, and the merge request body. The body is regenerated wholesale on every run, so identical inputs must produce an identical body.
propose The propose verb: re-cut the branch, write the changelog, open or update the merge request.
publish The publish verb: resolve what landed, tag it, create the release.
remote Turns a git remote URL into the pieces a forge call needs.
render Renders the changelog: entries, categories, links, and inserting a new top section into an existing file. Breaking changes are ordered first.
tree Git operations the verbs need: creating a tag, and reading a file at a specific commit rather than at the branch head.
cmd Cobra wiring, one subdirectory per command.

Two extractions worth knowing about

trailer came out of policy when a second consumer appeared: the version decision reads Release-As:, and release notes read Release-Note:. Two copies of a parser this fiddly would have drifted, and the fiddliness is the point, because "a trailer" means something specific and narrow in git.

manifest holds far less than it once did. An earlier design carried version overrides in it: an exact version, a bump floor, a prerelease marker. They moved to a Release-As: commit trailer, because the mechanism should match the lifetime of the thing it controls. A hold is a state a project is in until somebody lifts it, which suits a committed file. A version override applies to one release and should expire with it.

Built on gtb

colophon is generated from and built on go-tool-base, which supplies the command scaffolding, configuration loading, logging, self-update, signing and the forge integrations. The manifest at .gtb/manifest.yaml records which features are enabled and which gtb version generated the tree.

That is where the commands colophon does not implement itself come from: config, doctor, init, docs, mcp, update, version, changelog and completion.

See also