Assemble-changelog
Release-time changelog assembly for the Rerun repo.
Always work in the root of a standalone rerun-io/rerun checkout — normally the prepare-release-0.x.y branch, where the result is committed.
This is step 4 of RELEASES.md; read it for the surrounding context.
Before doing any release work, verify that the current directory is the repository root and that its origin is rerun-io/rerun:
test "$(git rev-parse --show-toplevel)" = "$PWD"
git remote get-url origin
Do not run the workflow in the reality monorepo, including from its rerun/ directory.
The release scripts need the standalone repository's 0.x.y tags and resolve (#N) commit references against rerun-io/rerun.
Running them against reality can silently resolve reality PR numbers to unrelated Rerun PRs.
If either precondition is not met, stop before running any release command.
Tell the user that the skill requires the root of a standalone rerun-io/rerun checkout, and ask them to restart it there.
Do not clone a repository, fetch tags, or switch branches for the user.
Resolve the target version from $ARGUMENTS (e.g. 0.34.0). If absent, read it
from Cargo.toml (version = "0.x.y-…") and confirm with the user.
Workflow
1. Assemble upcoming/ → the release changeset
The curated entries live one-file-per-PR in docs/content/changelog/upcoming/*.md
(skip _template.md). Each declares type: highlight|breaking|feature in its
frontmatter. Merge them into docs/content/changelog/changeset-0-XX.md, creating that file from
docs/content/changelog/_template.md if it does not exist yet (set title to the version — keep it
quoted, e.g. title: "0.36", so YAML keeps it a string — and order one lower than the previous release):
highlight→ one###subsection each under## Highlights.feature→ one###subsection each under## New features.breaking→ one###subsection each under## Breaking changes. If none, writeNone..
Keep the sections in that order and omit Highlights if there are no highlight entries.
The changelog is user-facing (it's part of the website), so it leads with what's new;
the verbose, developer-only breaking-change migration guides go last so most readers
don't have to scroll past them.
Tailor the output to the release type:
- Patch release (
0.x.Y, Y > 0) → typically only bug fixes. SkipHighlightsandNew features(there usually won't beupcoming/entries anyway); keepBreaking changesonly if there are any. - Minor release (
0.X.0) → the full template: highlights, new features, breaking changes.
Preserve each entry's prose and structure (migration guides, tables, snippet: directives,
screenshots, links).
De-duplicate overlapping entries and order breaking changes most-impactful first.
Drop the per-entry frontmatter.
Relative doc links in entries were written as if from changelog/ (e.g.
../reference/migration/...), which is correct once merged — keep them as-is.
Finally, point the redirect: frontmatter in docs/content/changelog.md at
changelog/changeset-0-XX: CI's scripts/ci/check_changelog_redirect.py requires the
newest changeset to be the redirect target, so the repoint must land together with the
new changeset.
2. Resolve release blockers
Ensure that every non-template file from upcoming/ was merged into the changeset, then search the assembled changeset for unresolved placeholders:
rg -n 'TODO\([^)]+\)' docs/content/changelog/changeset-0-XX.md # NOLINT
Resolve every match before continuing.
An unresolved TODO(name) blocks the release.
3. Generate the summary and detail sections into CHANGELOG.md
pixi run uvpy scripts/generate_changelog.py --version 0.x.y
Edit PR titles/labels to improve the output, then copy the result into CHANGELOG.md
(drop the trailing "Chronological changes" section; replace the placeholder video/blogpost
lines as previous releases did). Spot-check a few entries against the actual PRs:
polluted titles (old, unrelated PRs; thanks @… for core team members) mean a PR-number
lookup misfired — see the warning at the top.
Do this after step 1: the script reads the assembled changeset and emits a summary of it
(section headings + links to the changeset on the website), rather than inlining its prose.
CHANGELOG.md therefore never duplicates the changeset — if the changeset is missing, the
script emits an unresolved placeholder instead.
4. Empty the inbox
Delete the merged upcoming/*.md entries, keeping _template.md:
find docs/content/changelog/upcoming -maxdepth 1 -type f -name '*.md' ! -name '_template.md' -exec git rm -- {} +
Every entry was a published docs page, so each deletion needs a redirect in
docs/content/_redirects.yaml pointing at the section it was merged into, otherwise
scripts/ci/check_doc_redirects.py fails:
# Changelog - 0.XX upcoming entries merged into the release changeset
changelog/upcoming/<slug>: changelog/changeset-0-XX#<heading-anchor>
The anchor is the ### heading lowercased with punctuation dropped and spaces turned into
dashes, so the heading ### `ParquetReader` loading options moved to `stream()` becomes
parquetreader-loading-options-moved-to-stream.
Checklist before declaring done
- Every non-template
upcoming/entry is represented in the changeset. - No
TODO(name)remains in the changeset. - No summaries or other prose were synthesized for existing entries.
-
upcoming/contains only_template.md. -
python scripts/ci/check_changelog_redirect.pypasses (redirect points at this changeset). -
python scripts/ci/check_doc_redirects.py --base origin/mainpasses (every deletedupcoming/entry has a redirect).
Notes
- This skill lives in
skills/assemble-changelogin the standalone Rerun repository. - Synced commits in
rerun-io/reruncarry aSource-Reftrailer (the reality merge commit);generate_changelog.pyresolves it back to the originating reality PR for correct titles, labels, and contributors. - The next release's changeset is not pre-created: an empty changeset for an
unreleased version would make
check_changelog_redirect.pyfail, since it requires the newestchangeset-0-xx.mdto be the redirect target. During a cycle,upcoming/is the only in-flight artifact.