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.
Status
Section titled “Status”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.
| Repository | State |
|---|---|
operations | live — merge queue enabled |
common-module, infrastructure | planned |
The one thing that is different
Section titled “The one thing that is different”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.
- Branch, change, run the pre-push gate.
- Write one changelog entry — in the pull-request body or in a
.changelog/file, never both. - Open the pull request, get a review, enable auto-merge.
- The queue batches, builds and merges it.
- Assembly writes the release block; the build then publishes and deploys.
Writing the entry
Section titled “Writing the entry”Two routes. Exactly one, and the pipeline refuses both or neither.
Route A — the pull-request body
Section titled “Route A — the pull-request body”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.
Route B — a file under .changelog/
Section titled “Route B — a file under .changelog/”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.
Categories decide the version
Section titled “Categories decide the version”The categories you use determine the bump. Pick the highest that applies.
| Category | Bump | Use for |
|---|---|---|
Changed, Removed | major | API-breaking changes only |
Added, Deprecated | minor | new capability |
Fixed, Security | patch | everything 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.
Amending
Section titled “Amending”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.
Feature builds
Section titled “Feature builds”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.
The merge queue
Section titled “The merge queue”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.
After the merge
Section titled “After the merge”Two pushes to main, in order:
- 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. - 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
devtakes roughly as long as a full build, because a complete publish build runs between them.
When something fails
Section titled “When something fails”The pipeline states its reasons. Match the message.
| Message | What it means | Fix |
|---|---|---|
no changelog entry: add a ## CHANGELOG section… | Neither route carries an entry | Add one |
both a .changelog/ file and a ## CHANGELOG section are present | Both routes used | Remove one |
a pull request carries at most one .changelog/ file, found N | Two entry files on one branch | Merge them into one |
this pull request edits CHANGELOG.md | You edited the assembled file | Revert 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 category | Use the table above |
#N is a draft; it must not merge | Draft, and drafting does not eject a queued entry | Mark it ready |
#N is marked as a feature build (M) | The marker is still present | Remove it |
"X" is not a usable feature-build marker | Marker is not <user>-<ticket> | Fix the shape |
<manifest> carries N feature-build lines | Two markers in one manifest | Keep one |
branch B has N open pull requests | Two pull requests share a head branch | Close one |
build derived X but assembly wrote Y | The build ran on the wrong commit | Report it — this is a pipeline defect, not yours |
Queue ejections
Section titled “Queue ejections”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.
Escape hatches
Section titled “Escape hatches”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.
Appendix — agent companions
Section titled “Appendix — agent companions”pr-steward— monitors checks, triages review comments, resolves threads.changelogrule — the entry conventions in machine-readable form.
Copyright: © Arda Systems 2025-2026, All rights reserved