Skip to content

Backend PR Process

How to compose a pull request against operations, common-module or infrastructure, what the pipeline does with it, and how to read it when something fails. The frontend counterpart is Frontend PR Process.

For the model itself — its structure, objectives and rationale — see Queued CI/CD. Every example here links to cicd-testbed, which runs the same machinery and can be read freely.

Cut over per repository. Check for a .changelog/ directory: if it is there, this guide applies; if not, Release Lifecycle still describes what to do.

RepositoryState
operationslive — merge queue enabled
common-module, infrastructureplanned

In these repositories CHANGELOG.md is the version. gradle.properties carries version=0.0.0; the git tag, image tag, chart version, Maven coordinates and Release body all come from the top release heading at build time.

Which is why you never edit CHANGELOG.md. You write an entry somewhere else, and the pipeline composes the file after your change merges.

  1. Branch, change, run the pre-push gate.
  2. Write one changelog entry — in the pull-request body or in a .changelog/ file, never both.
  3. Open the pull request, get a review, enable auto-merge.
  4. The queue batches, builds and merges it.
  5. Assembly writes the release block; the build then publishes and deploys.

Two routes. Exactly one, and the pipeline refuses both or neither.

A ## CHANGELOG section in the description. The pull-request template pre-fills it.

## CHANGELOG
### Fixed
- Scanning an item with a damaged barcode no longer aborts the session.

Use this by default. Nothing to rebase, nothing to collide with.

A single Markdown file, named with a prefix of your own — jmpicnic-scan-fix.md. Author-chosen names are not decoration: a merge batch stages several branches’ files side by side, and a fixed name would guarantee a collision. See .changelog/README.md.

Use this when you want the entry to evolve with the branch in review, or when the branch publishes feature builds without an open pull request — there is no body to read in that case.

Assembly consumes the file, so nothing stale survives onto main.

The categories you use determine the bump. Pick the highest that applies.

CategoryBumpUse for
Changed, RemovedmajorAPI-breaking changes only
Added, Deprecatedminornew capability
Fixed, Securitypatcheverything else, including internal work

Order sections by impact, largest first. Write what the change enables or prevents, not what you edited — the entry is read by people who did not see the diff.

Body route: edit the description, or post a comment containing a replacement ## CHANGELOG section. The most recent wins, and only the author or an assignee counts — anyone may comment, but only those accountable may rewrite a release note. Re-run the check after amending without pushing.

File route: edit the file and push.

To publish prereleases from a branch, mark it. Every push then publishes <next-version>-<marker>-<run> and deploys it to dev and nowhere else — the other environments are absent from that build’s deploy matrix, not merely gated.

The marker lives in whichever manifest the branch already carries. In a file, as frontmatter:

---
feature-build: jmpicnic-1408
---
### Added
- Item scanning by GTIN.

In the body, as a line inside the ## CHANGELOG section:

## CHANGELOG
feature-build: jmpicnic-1408
### Added
- Item scanning by GTIN.

Rules worth knowing before you rely on it:

  • The shape is <user>-<ticket> — two alphanumeric segments, one hyphen. Anything else is rejected with a reason rather than quietly producing an ordinary build.
  • A marked pull request cannot merge. Remove the marker first; the gate names it when it blocks you.
  • No open pull request means no body to read. Use the file route.
  • Closing the pull request takes a body marker with it. The next push builds ordinarily, and the environment keeps whatever it was last given. A branch whose marker must outlive its pull request should use the file.

Enable auto-merge once approved. The queue takes entries, groups passing ones into an ALLGREEN batch, builds the batch — not your branch — and merges the group together.

This is why nothing rebases: your pull request never touched CHANGELOG.md, so it cannot conflict with anyone else’s entry.

What runs on a queued entry: the merge-eligibility gate re-evaluates, and the build runs against the batch head and publishes nothing.

Two pushes to main, in order:

  1. Your merge commit triggers assembly. It collects every pending merge since the last assembly, composes one release block, computes the version from the categories, and commits chore: assemble CHANGELOG x.y.z. No tag.
  2. The assembly commit triggers the build, which reads the version back out of the file, publishes, tags, creates the Release and deploys.

Two consequences to expect:

  • A batch produces one release, not one per pull request. Your entry appears under a version that also covers whatever merged alongside it.
  • Merge to dev takes roughly as long as a full build, because a complete publish build runs between them.

The pipeline states its reasons. Match the message.

MessageWhat it meansFix
no changelog entry: add a ## CHANGELOG section…Neither route carries an entryAdd one
both a .changelog/ file and a ## CHANGELOG section are presentBoth routes usedRemove one
a pull request carries at most one .changelog/ file, found NTwo entry files on one branchMerge them into one
this pull request edits CHANGELOG.mdYou edited the assembled fileRevert that edit; put the entry in a route
the changelog entry is not valid; it must use the categories in …A heading is not a known categoryUse the table above
#N is a draft; it must not mergeDraft, and drafting does not eject a queued entryMark it ready
#N is marked as a feature build (M)The marker is still presentRemove it
"X" is not a usable feature-build markerMarker is not <user>-<ticket>Fix the shape
<manifest> carries N feature-build linesTwo markers in one manifestKeep one
branch B has N open pull requestsTwo pull requests share a head branchClose one
build derived X but assembly wrote YThe build ran on the wrong commitReport it — this is a pipeline defect, not yours

An entry leaves the queue when a required check fails. Two things make this confusing, and both are worth recognising.

A check that never started looks exactly like a check that failed. The queue ejects on its response timeout either way. The tell is the run itself: an abandoned run reports failure with no steps and no log. If you see that, nothing is wrong with your change — re-queue it.

Ejection clears auto-merge. The pull request goes back to open with auto-merge off, so re-arm it when you re-queue.

A batch failure ejects the entry that caused it, not the whole group.

manual-changelog label — permits an edit to CHANGELOG.md. For correcting history, not for routine use: it reintroduces the exact conflict the model removes, and a rising usage rate is a signal that the assembler has a gap worth fixing instead.

Emergency fixes still go through a pull request. The gates apply; the only acceleration is a fast review.

  • pr-steward — monitors checks, triages review comments, resolves threads.
  • changelog rule — the entry conventions in machine-readable form.