Skip to content

colophon apply

Description

Carry what a commit asserted to the forge object it names

Read the commits a push added, take the Updates: trailers they carry, and apply each to the issue, merge request or wiki page it names. This is the one verb that runs when a merge lands rather than when a release is cut, so a record outside the repository can be told what became of the work.

Nothing is inferred. A commit says what happened to a record or the record is left alone, for the reason a Release-As: trailer exists: a tool cannot know which merge finished a piece of work, and a record it marks done too early is worse than one left stale, because a wrong record is trusted.

Usage

colophon apply --from <commit> --to <commit> [flags]

Run colophon apply --help for the authoritative, always-current flag set.

Flags

Flag Description Default
--from Commit the push started from. Empty, or the all-zero SHA a forge sends for a branch's first push, means the tip alone. empty
--to Commit the push ended at HEAD
--remote Git remote to read origin
--forge Forge the remote is on when its host does not say: gitlab, github or gitea. Same as forge in .colophon.yaml; both must agree when given. empty
-C, --repo Path to the git repository .

The span

--from and --to are the commits a push added, which the CI environment knows: on GitLab they are CI_COMMIT_BEFORE_SHA and CI_COMMIT_SHA.

This is deliberately not the span the release verbs use. plan and propose ask what has landed since the last release; a run that acts on what a person wrote must see exactly what this push carried, or a repository releasing weekly would act on the whole week again on every merge.

What it writes

Target What happens
issue a comment
merge request a comment
wiki page one frontmatter field is set; nothing else on the page is touched

The syntax of the trailer, its targets and its keywords are in Commit trailers and annotations.

A wiki page whose frontmatter does not carry the field a keyword names is refused rather than grown one, and a page already carrying the value is reported as unchanged and not rewritten.

Running it twice

Safe. Each comment is posted under an idempotency key naming the commit that asserted it and the object it was about, and the forge provider returns the existing comment rather than posting a second. A later commit saying the same thing about the same object is a second comment, because it is a second assertion.

The key defends against a retry, not against two runs racing: it is not atomic, and two concurrent pushes asserting the same thing can both post.

What each forge can do

Every capability is optional and separately absent. An instruction the forge cannot carry is reported and skipped; the rest still apply.

Forge Issue comment Merge request comment Wiki
GitLab yes yes yes
GitHub yes yes yes
Gitea no no yes
Bitbucket no yes no

Checked at go/forge v0.25.0 and its adapters. Bitbucket Cloud has no issue tracker; Gitea's comment capability is not implemented in its adapter yet.

Output

One line per instruction, then a summary when anything wants attention:

  applied   #13
  applied   cicd/wikis/specs/0079-pipeline-churn — status set to IMPLEMENTED
  unchanged cicd/wikis/specs/0080-other — status is already IMPLEMENTED
  skipped   !45 — this forge has no comment capability for merge request
  failed    phpboyscout/go/forge#23 — 403 forbidden

2 of 5 needed attention. The merge stands; nothing here failed the pipeline.

Exit code

Zero, even when a target failed. By the time this runs the merge has happened, and a red pipeline because an annotation did not post is worse signal than a yellow one. A non-zero exit means the run could not start at all: an unreadable manifest, an unrecognised forge, or a span the repository does not carry.