RFD 122: Release Pipeline
Summary
This RFD adds the release pipeline to the jp release plugin of RFD 121. jp release cut branches release/0.3 from main to hold the code 0.3.x ships, and opens a pull request that moves every unreleased fragment into the release's directory on main. Release notes are written and corrected on main alone; release branches carry code and no notes, and jp release pick adds code to them by cherry-picking from main. jp release finalize tags a release. Each release gets release notes and, when it breaks something, an upgrade guide, rendered from its directory whenever they are needed. Every step is a command a person runs, and every change to main is a pull request like any other; a project without a forge merges those branches however it merges. JP's CI adds a reminder, checks, and distribution, and writes to no branch. It retires jilu; building, signing, and distributing binaries are separate RFDs.
Motivation
A release has to be automated and smooth enough that cutting one does not feel like an event. JP releases every two weeks at first: development moves fast, and the releases serve the people building JP more than users who would have to keep up with them. The cadence is a setting, so it can slow down once JP has such users.
RFD 121 gives the raw material, per-change fragments and per-feature highlights recorded in each pull request; this RFD turns that material into published releases. Each release has two documents, as Bevy's do: release notes to read, and an upgrade guide to work through when something breaks. Keeping upgrade steps out of the notes lets them take the room they need without burying the story.
Preparing a release's notes can take days, and nobody else should wait for it. So a release is cut onto its own branch: what it ships is fixed when it is cut, main keeps moving, and anything that should still ship is picked over deliberately.
The workflow has one path. Every artifact has one home and every step one command: release notes live on main alone, so correcting any release's notes has one answer; release branches have no notes, so there is nothing on them to correct; and changes reach main the way every change does, so main needs no exception for releases. The design gets there by construction rather than by checks that catch the other paths.
The plugin serves other JP workspaces alongside RFD 116's, and not every contributor uses a forge's web interface. So every step is a command, a forge is only where changes are reviewed, and a project without one runs every step with git alone. JP's CI is a convenience around the commands, not a requirement.
Design
Where things live
| Where | Holds |
|---|---|
main | Development, and every release's notes: unreleased fragments at the top level of changelog.d/, each release's in its version's directory |
release/0.3 | The code 0.3.x releases ship: main at the cut, without changelog.d/, plus the commits picked onto it |
v0.3.0, v0.3.1 | Tags on release/0.3: the releases |
Nothing else records state:
- A release ships a change when its branch contains the commit that made it, from
main's history at the cut or through a pick. - A fragment in a version's directory belongs to that release. One at the top level is unreleased until a release ships its change; the change request that
cutorpickopens then moves it, and until that merges it still shows as unreleased. - A release is in preparation from the commit that starts it on its branch until its tag, and a tag is a finalized release.
Commands
RFD 121 creates the plugin with init, add, and check. This RFD adds:
| Command | Does |
|---|---|
jp release cut [--version VERSION] | Starts the next minor or major release from main |
jp release pick VERSION COMMIT... | Adds commits from main to a release in preparation, or starts the next patch release with them |
jp release finalize VERSION | Tags a release |
jp release render [VERSION] | Prints a release's notes or upgrade guide, or the unreleased fragments |
jp release due | Succeeds when the next release should be cut |
jp release review [VERSION] | Asks the assistant to review a release's notes and upgrade guide |
cut, pick, and finalize work in a temporary worktree based on origin's branches, so the checkout they run from is left alone. They push as the person running them: release branches and tags directly, and changes to main on a branch of their own, through a change request (Changes to main). None is served as a tool: under RFD 116's rule, commands that reach the network or decide something for the project are the user's to run.
Configuration
[plugins.command.release.options]
cadence = "2w"
forge = "github"
bump = "cargo set-version --package jp_cli {version}"
change_request_labels = ["no-changelog"]
[plugins.command.release.options.headings]
added = "New features"
fixed = "Bug fixes"These are JP's values, and every option is optional:
cadencedefaults to two weeks, and takes a duration asjp query --tmpdoes.forgeisgithub,gitlab, ornone, and decides how releases credit and link change requests (Credits and links) and howcutandpickopen theirs (Changes tomain). Unset, it follows git'soriginremote:githubfor github.com,gitlabfor gitlab.com, andnonefor any other host. A self-hosted GitHub or GitLab sets it, and links use the remote's host.bumphas no default. Without it, a version lives only in its tag.change_request_labelslists the forge labelscutandpickgive the change requests they open, and defaults to none. JP's listsno-changelog, which passes RFD 121's gate: those change requests move fragments rather than add them.headingsrenames a type's section in the release notes. A type it does not name keeps its default heading, its id capitalized (Added,Performance), and layeredheadingsmerge key by key.
fragments_dir belongs to RFD 121.
Versions
Git tags are the record of what was released: the current version is the highest v-prefixed semantic-version tag, and with none, the first release is 0.1.0. Tags are annotated, and a release's date is its tag's date.
A cut from main is a minor release, or from 1.0 on a major one when an unreleased fragment has an upgrade section; --version overrides. Its version follows the highest of the tags and the releases in preparation, so a cut while another release is in preparation cuts the one after it. A patch release comes only from a release branch, through pick (Patch releases).
JP tagged v0.1.0 before this pipeline existed and published no release for it, so its first release is v0.2.0, covering what merged after RFD 121's gate landed. A release meant to introduce JP to new readers says so in its overview and highlights; the pipeline treats every release alike.
bump runs with {version} replaced by the new version in the commit that starts a release on its branch, and for a cut also in its change request, so main carries the version it was last cut at. So a project writes its version wherever it keeps one, with a tool it already has. JP's command, cargo set-version from cargo-edit, sets [workspace.package] version and every crate that inherits it, leaves the crates under crates/contrib/ with their own versions alone, and updates Cargo.lock, which JP's CI checks with --locked. It names jp_cli, one of the crates that inherit the workspace version, because --workspace would also overwrite the crates that keep their own.
Cutting a release
jp release cut:
- Refuses a shallow clone, which lacks the history credits come from, and a
mainwith no unreleased fragments, which has nothing to release. - Computes the version, at the tip of
origin'smain: the commit the release is cut at. - Starts the release branch: creates
release/<major>.<minor>at that commit, adds one commit that deleteschangelog.d/and runsbump, and pushes it. - Files the cut on
main: on a branchrelease-cut/v<version>from the same commit, moves (git mv) every unreleased fragment and highlight intochangelog.d/<version>/, runsbump, commits, pushes the branch, and opens its change request.
changelog.d/
README.md
enable-explicit.md # merged after the cut: unreleased
0.3.0/
retry-idle-turns.md
highlights/plugin-tools.mdBoth branches start at the same commit, so the code the release ships and the fragments it lists are chosen together, however long the change request takes to merge. A fragment merged meanwhile stays at the top level, since the change request moves only the ones it found, and its code is not on the release branch: it belongs to the next release on both counts. A correction merged meanwhile to a fragment the cut moves is carried into the release's directory when the change request merges, since git follows the rename; under RFD 121's rule that every change adds its own fragment, an edit to an existing fragment is a correction, and it belongs on the released copy.
"Unreleased" is decided by what release branches ship, not by where a fragment sits: a fragment still at the top level because another cut's or pick's change request has not merged yet is already shipped, and cut leaves it for that change request. Cuts and picks never wait for each other's change requests.
The release branch has no changelog.d/, so notes cannot be written there: there is nowhere to write them. The commits that start releases on it, which bump the version, are the only commits on it that do not come from main.
Changes to main
cut and pick push the release branch directly and change main through a branch of their own and a change request, the way any change reaches main:
githubopens a pull request through thejp_githubclient crate, extended with pull-request create and label calls, and authenticates the way JP's other GitHub features do. It never runsgh.gitlabopens a merge request with git push options (merge_request.create,merge_request.target,merge_request.title, andmerge_request.label), so it needs nothing beyondgitand the credentials that push.nonestops after pushing the branch, for the project to merge however it merges.
Each change request carries change_request_labels. The person running the command opens it, so its checks run as on any change request they open, and it is reviewed and merged like one.
Preparing a release
A release in preparation takes as long as its notes need, and nobody waits for it:
- Notes are changes on
main, made the way any change is made: the wording of fragments and highlights in the release's directory, and its overview. Two entries for one change, such as a change and its follow-up, become one by editing one, deleting the other, and listing both change requests in the kept fragment'schange_requests. - The overview opens the release notes. Without an
overview.mdin the release's directory, it is a summary generated at render: the version, how many entries of each type the release has, and its highlights' titles. Writingoverview.mdreplaces it, andjp release render <version>prints the summary to start from. - More code comes from
jp release pick 0.3.0 <commit>.... It cherry-picks the commits ontorelease/0.3(git cherry-pick -x), leaving out what they change underchangelog.d/, and pushes it. On a branchrelease-pick/v0.3.0-<short-sha>frommain, it puts each fragment and highlight the commits added intochangelog.d/0.3.0/, and opens its change request. A fragment no other release ships moves, so the next release does not list the change a second time. One that a later release already ships, because that release was cut after the commit merged, is copied, with its credits written into the copy'schange_requests(RFD 121): both releases ship the change, and both list it. A conflict stopspickin its worktree, which it names; resolve the conflict there and runjp release pick --continue.
Code reaches a release branch only through pick, so every change lands on main first.
Finalizing a release
jp release finalize 0.3.0 tags the tip of origin's release/0.3 with an annotated v0.3.0 and pushes the tag. That is the release. The person running it decides when: on GitHub, CI runs on every push to a release branch and shows on its tip; elsewhere, just ci runs the same checks locally.
The tag push is a person's, so it starts JP's distribution workflow, which the RFD that distributes the jp binary defines. The release's notes stay on main: correcting them, at any time, is a change to its directory there, and every place the notes appear renders them again. A cut's or pick's change request that merges after the tag is one such change.
Patch releases
A patch release is cut from its line's branch, not from main. After v0.3.0, jp release pick 0.3.1 <commit>... starts 0.3.1 with a commit on release/0.3 that runs bump, then picks the commits as above, moving or copying their fragments into changelog.d/0.3.1/. A patch release refuses a fragment with an upgrade section. jp release finalize 0.3.1 tags it. pick accepts a release in preparation, or the next patch release of a line whose last release is tagged, which is the version any other number would collide with.
Releases in parallel
Each release branch holds one release in preparation at a time: a patch release starts after the previous release on its line is tagged. Releases on different branches do not touch each other. release/0.3 can prepare 0.3.1 while main cuts 0.4.0, since each writes its own branch and its own version's directory on main.
Release notes and the upgrade guide
Each release has two documents:
- Release notes: the overview, the highlights, and every fragment grouped by type under its heading. A breaking entry is marked and links to its section of the upgrade guide.
- The upgrade guide: one section per fragment with an upgrade section (RFD 121), headed by its title and followed by the entry's credits and the section's body. A release without upgrade sections has no upgrade guide.
Release notes, as jp release render 0.3.0 prints them. The entries are paraphrased from recent pull requests; the breaking change and the last entry are invented:
JP 0.3.0 lets the assistant call one tool on many inputs at once, and lets the
plugins you install give it new tools. It also changes how JP finds plugins, so
read the upgrade guide before you upgrade.
## Tool calls fan out
When the assistant needs the same tool on several inputs, such as reading ten
files, it asks once and JP runs the calls side by side. Each result still shows
up under its own call, and one failing call does not stop the others.
By @JeanMertz in [#1182](https://github.com/dcdpr/jp/pull/1182) and
[#1183](https://github.com/dcdpr/jp/pull/1183).
## Changelog
### New features
- The assistant can call one tool on many inputs in a single request.
([#1182](https://github.com/dcdpr/jp/pull/1182))
- `jp conversation show` shows the conversation's model.
([#1243](https://github.com/dcdpr/jp/pull/1243))
### Changed
- JP finds a command plugin by the manifest its binary embeds, not by its file
name. **Breaking**: see
[the upgrade guide](upgrade#command-plugins-are-found-by-their-manifest).
([#1216](https://github.com/dcdpr/jp/pull/1216))
### Bug fixes
- A turn that stalls while idle is retried instead of failing.
([#1207](https://github.com/dcdpr/jp/pull/1207))
- The help for `jp query --tmp` names the right default.
([`4e1f0a2`](https://github.com/dcdpr/jp/commit/4e1f0a2))The same release's upgrade guide, as jp release render 0.3.0 --page upgrade prints it:
## Command plugins are found by their manifest
[#1216](https://github.com/dcdpr/jp/pull/1216)
Before 0.3.0, `jp <name>` ran a binary called `jp-<name>` from your `PATH`.
JP now reads the manifest each plugin binary embeds, which names the commands
it serves, and a plugin built before 0.3.0 has none, so JP no longer finds it.
Rebuild the plugin against 0.3.0, or reinstall it:
```sh
jp plugin install <name>
```Neither document has a title or a date; whoever places them adds both.
The release model
The changelog crate builds a release model from a release's directory, or from the unreleased top level, and serializes it. Markdown is one view of that model; a consumer that renders its own way reads the JSON:
{
"format": 1,
"version": "0.3.0",
"date": "2026-10-28",
"overview": "JP 0.3.0 lets the assistant call one tool on many inputs ...",
"highlights": [
{
"slug": "fan-out",
"title": "Tool calls fan out",
"authors": ["@JeanMertz"],
"body": "When the assistant needs the same tool on several inputs ...",
"credits": [
{ "kind": "change_request", "label": "#1182", "url": "https://github.com/dcdpr/jp/pull/1182" }
]
}
],
"entries": [
{
"slug": "plugin-manifest-routing",
"type": "changed",
"body": "JP finds a command plugin by the manifest its binary embeds, ...",
"credits": [
{ "kind": "change_request", "label": "#1216", "url": "https://github.com/dcdpr/jp/pull/1216" }
],
"upgrade": {
"title": "Command plugins are found by their manifest",
"body": "Before 0.3.0, `jp <name>` ran a binary called ..."
}
}
]
}- Bodies, titles, and the overview are Markdown strings; the overview is the generated summary when the release has no
overview.md. typeis RFD 121's id, never a heading: a consumer maps ids to the headings it shows.- A credit's
kindischange_requestorcommit, and itslabelis how the forge writes it (#1182on GitHub,!1182on GitLab, a short hash for a commit), so a consumer shows the label linked to the URL without knowing which forge it came from. Underforge = "none", credits are commits with no URL. - A release in preparation has a
nulldate, and the unreleased model anullversion too. - Within a type, entries are ordered by their first credit and then by slug, so the same files always give the same output.
formatis the model's version, so a consumer can refuse output it does not understand.
changelog render (the crate's binary) and jp release render take --format json or --format markdown, and for Markdown --page notes or --page upgrade. The binary reads no configuration: the fragments directory, the forge, and the headings arrive as arguments, which jp release render fills in from the plugin's options. In Markdown, a breaking entry links to its upgrade section at a location the consumer passes.
Every consumer renders from main, where the notes live, and places the documents itself:
jp release renderprints them, to read while a release is prepared or to hand to another tool.jp viteturns them into pages on the site (On the site).- The RFD that distributes the
jpbinary puts the release notes in the GitHub Release, linking to the upgrade guide on the site, and renders them again when the release's directory changes onmain.
Credits and links
Credits come from main's history. For each fragment and highlight, the crate reads the commits that wrote or changed it while it sat at the top level of changelog.d/, following renames, up to the commit that moved it into a release's directory. Corrections after that credit nobody. A commit's change request is read from its message or, when the commit reached main through a merge, from the merge commit's message. A fragment whose change_requests list is set takes that list instead, which is how a copy made for a patch release keeps the original's credits.
forge | Change request read from | Label | Links to |
|---|---|---|---|
github | (#123) ending a squash commit's subject, or Merge pull request #123 | #123 | https://<host>/<owner>/<repo>/pull/123 |
gitlab | See merge request <project>!123, as GitLab's default merge commit message ends | !123 | https://<host>/<project>/-/merge_requests/123 |
none | nothing |
A commit with no change request is credited as itself, linked to its page on the forge: /commit/<sha> on GitHub, /-/commit/<sha> on GitLab. JP squash-merges with GitHub's default subject, so its entries credit their pull requests. GitLab's default squash commit message is the merge request's title alone, so a GitLab project that squashes gets commit credits unless it adds %{reference} to its squash template.
Crediting reads history, so rendering refuses a shallow clone rather than produce documents without their credits.
The train
due succeeds when cadence has passed since the newest minor or major release was cut, and that release has been finalized.
- Cut. A maintainer runs
jp release cut, whenduesays so or on any other day. - Prepare. They and others edit the release's notes on
mainand pick later work onto its branch, for as long as it takes. - Finalize. They run
jp release finalizeonce the release branch's checks pass.
A patch release is a pick into the next patch version, then finalize.
JP's CI
Every workflow runs a just recipe, so each step also runs on a machine without GitHub, and no workflow writes to a branch:
| When | Runs | Writes |
|---|---|---|
| A pull request | The changelog gate and format validation (RFD 121) | Nothing |
A push to main or release/* | The checks; on main, just changelog-ci among them, since release branches have no fragments | Nothing |
| Daily | just release-due | An issue labelled release when a release is due and none is open |
A push to main | The site build (On the site) | The site |
A push of a v* tag | Distribution of the jp binary | The jp binaries, the GitHub Release; closes the reminder issue |
Every push and every tag comes from a person running a command, so every workflow starts on its own. A push made with a workflow's own token starts no other workflow, and a pull request it opens waits for a maintainer to approve its checks (Triggering a workflow from a workflow); the pipeline never does either, so it needs no approval and no bot identity.
On the site
Releases are a third workflow for jp vite (RFD 116), next to tickets and RFDs, and the site builds without jp. jp vite sync writes fragments_dir, forge, and headings into its settings snapshot with the other plugins' settings. The releases loader runs changelog render --format json for each version's directory and for the unreleased top level, with arguments from the snapshot, and builds the pages from the model: release notes and an upgrade guide for each release, and an "Unreleased" page. A release in preparation has its pages from the moment its cut's change request merges, marked as such, so they double as the preview while its notes are prepared. The pages are never committed. Where they go is jp vite's choice: JP serves them under /releases/, with an index of releases and their dates, and replaces the navigation's "Change Log" entry with "Releases".
The docs build installs the changelog binary in place of jilu, compiled from the checkout; it builds the changelog crate alone. Its checkout already fetches full history, which crediting needs.
Release pages are rendered from main, where the notes live. A release tag's tree has no changelog.d/, and jp vite enables a workflow only when its directory exists (RFD 116), so a site built from a tag has no release pages, and must not replace main's. JP's docs workflow deploys on tag pushes today, and that stops. A future site with documentation per release stays open: it builds each tag's tree into a path of its own and links to the release pages main's site serves.
review
review asks the host for a structured query (protocol 11) about a release's notes and upgrade guide, as jp rfd track does in RFD 116: entries that read like commit messages, entries that do not say what changed for the user, upgrade sections that do not say what to do, and typos. It prints what it finds and edits nothing. It is an opinion, not a gate.
Other artifacts
Command plugins ship continuously through the rolling plugins release, so a plugin change reaches users before its fragment reaches a release's notes. Plugin crates inherit the workspace version, but plugins.yml does not rebuild them on a version bump, so the rolling binaries report the previous version until their next build. A later RFD on distributing plugins decides whether a release also publishes versioned plugin binaries.
The macOS app (RFD 099) is not distributed and keeps its own version, so it is outside the release.
Retiring jilu
Release pages replace the git-history-generated docs/change-log.md. The build-changelog recipe, the jilu dependency, and the docs-build step that generates the change log are removed.
Drawbacks
- The project owns the assembly logic.
jiluis replaced by code JP maintains. The logic is small (parse, credit, model, render), but it is now ours to test and fix. - A cut or pick lands in two steps. The release branch moves at once;
mainfollows when the change request merges, and until then the release's new fragments still show as unreleased. pickwrites two branches. A conflict stops it between them, and--continuefinishes the job.- Branches and directories accumulate: a release branch per minor release and a directory per release, 26 of each a year at JP's cadence.
- Tags off
main. Every release is tagged on its branch, past the commit that deleteschangelog.d/, sogit describeonmainfinds no release. A release's starting point onmainis the parent of its branch's first commit. - Workflows that run
jp releasecompilejpandjp-releaseuntil releases publish both; the dailydueis the main one. - Credits depend on merge messages. A forge or project that writes no change request into its merge or squash commits gets commit credits instead.
Alternatives
- A
just-invoked binary instead of a command plugin. Free of the plugin system, but it cannot ask the host for the queryreviewneeds, and it splits release tooling from the plugin family other workspaces install. - Release pull requests into the release branch, with the notes synced back to
mainafterwards. The notes would live on both branches, and correcting an old release would have two possible places, one of them wrong. - Committing the cut to
maindirectly. One step instead of two, but on GitHub it needs a bypass ofmain's pull-request rule for whoever cuts releases, which lets them push anything else too, and it puts unreviewed commits onmain. Starting the release branch and the change request from the same commit makes the cut just as atomic. - Orphan release branches, with no history shared with
main, so a release branch could not be merged back. Nothing would come back anyway: every commit on a release branch comes frommainexcept the ones that start releases, and a merge would delete every release note, which nobody merges unnoticed. The cost would land on everyday debugging: nogit bisectbetween two release tags, nogit log v0.3.0..v0.4.0of what changed between releases, and no link in git from a tag to the commit ofmainit was cut from. - No release branches: tagging
mainwhere a release is cut. One branch fewer, but no picks, and no patch release without everything else merged since. - Preparing on a short-lived branch merged into
main. Whatever merges tomainmeanwhile ships unless someone holds it back. - Freezing
mainduring a release, as Vector's release checklist does. Everyone else waits while the notes are prepared. - Workflows that prepare releases or open pull requests. A workflow's pushes and pull requests wait for approval unless it holds a GitHub App token, and either way the flow needs GitHub.
- A check on
mainthat fails when a release is overdue. Every pull request would show it red, and no change in it can fix it, which teaches people to ignore red. - An overview written at the cut. Picks change what it summarizes, and regenerating it until someone edits it is state nobody can see.
- Committing rendered pages. The site would need no
changelogbinary, but each page would be frozen at release time: a typo fix or a format change would mean editing generated Markdown. - Deleting fragments once released. A smaller tree, with the same frozen pages.
- Version handling built in for Rust workspaces. It would tie
cutto one kind of project, where a command reaches the same result with tools projects already have. - Reading the version from a manifest. Tags record what was released, and a file that is only written cannot drift from them.
Non-Goals
- Building, signing, and distributing binaries. Separate RFDs, started by the tag push: one for the
jpbinary alone, then one for the command plugins ready to ship,jp-releaseamong them. Until releases publishjpandjp-release, JP's release workflows compile them from the checkout. - Pre-releases. A release candidate must not consume the fragments its final release needs, which needs its own design.
- Independent package versions. One release, one version.
- CI for other workspaces. JP's workflows are JP's, and
jp releaseneeds none. - Publishing to crates.io. JP ships as binaries.
Risks and Open Questions
- Configuration without
jp. JP's release workflows runjpbecause onlyjpresolves configuration; the site does not. A follow-up RFD can give plugins a standalone mode that resolves configuration with the same codejpuses; thechangelogcrate reads none, so only the plugins would change. Release binaries makejpa download rather than a compile in the meantime. - A breaking change that has to ship in a release that cannot break.
pickrefuses a fragment with an upgrade section into a patch release, and from1.0on into a minor one. Shipping it means abandoning the release in preparation and cutting a major one. - Abandoning a release in preparation has no command: move its fragments back to the top level on
mainand delete its branch. It has never been needed; a command can follow if it is. - Lockfile conflicts. A cut's change request changes
Cargo.lock, so a pull request that changes it too may conflict with it, and runningbumpagain on the rebased branch resolves it. - Highlights extended across a cut. Highlights are edited by every pull request that builds their feature (RFD 121), so a pull request merged after the cut that extends a highlight the cut moves has its extension carried into the released copy, describing work the release does not ship. Fragments avoid this by being added rather than extended; highlights cannot, since a highlight is one story per feature. The release's highlights are read while its notes are prepared, and a correction is an edit to the released copy on
main.
Implementation Plan
Phase 1: Model, credits, and rendering
Add the release model, crediting for all three forges, and the Markdown views to crates/internal/changelog, with changelog render, and add jp release render with the forge and headings options. Depends on RFD 121 Phases 2 and 3.
Phase 2: cut, pick, and finalize
Versions from tags and from the commits that start releases, bump, release branches, the change requests on main under all three forges, through jp_github (extended with pull-request create and label calls) and GitLab's push options, picks with their moves and copies, patch releases, and tagging. Configure JP's bump and change_request_labels, and run JP's checks on pushes to release/*. Depends on Phase 1.
Phase 3: due and the reminder
Add due and just release-due, and JP's daily workflow with its reminder issue, which the tag push closes. Depends on Phase 2.
Repository settings
Nothing here blocks Phase 2: main's rules already accept the change requests cut and pick open, and no rules apply to release/* today, so jp release can push release branches. These settings keep the record of releases from being rewritten; someone with admin access to the repository applies them once Phase 2 has merged:
- On
release/*, block force pushes and deletion. - On
v*tags, block updates and deletion.
Phase 4: Site and jilu
Add releases to jp vite as a workflow: the snapshot entries, the loader, the release notes and upgrade guide pages, the index, and the "Unreleased" page. Install the changelog binary in the docs build, stop deploying the site on tag pushes, switch the navigation to "Releases", and retire jilu. Depends on Phase 1 and on RFD 116's site phase.
Phase 5: review
Depends on Phase 1.
References
- RFD 116: Shareable RFD, Ticket, and Site Tooling, the plugin family and the
jp viteworkflows this RFD adds to. - RFD 121: Changelog Fragments and Validation, the inputs this pipeline consumes and the plugin it extends.
- RFD 001: The JP RFD Process, the lifecycle this RFD follows.
- Bevy release news example and Bevy migration guide example, the split between release notes and upgrade guide, and bevy-website
generate-release, prior art for assembling them from fragments. - Vector releases index, prior art for the per-release page and index, and Vector's release checklist, the freeze this RFD avoids.
- Triggering a workflow from a workflow, GitHub's rules for what the workflow token can and cannot start.
- GitLab commit message templates and GitLab push options, what GitLab writes into merge and squash commits and how a push opens a merge request.
- cargo-edit, whose
cargo set-versionis JP'sbump.