skills/assemble-changelog/SKILL.md
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.
upcoming/ → the release changesetThe 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 ## New features, listed before the
feature ones.feature → one ### subsection each under ## New features.breaking → one ### subsection each under ## Breaking changes. If none, write None..Keep the sections in that order. 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.
The changeset opens with a table of contents, not prose, and it carries no heading of its own.
Write one bullet per ### heading in the changeset, in the order the headings appear,
linking to the heading's anchor, grouped under a bold label per ## section:
**New features**
- [Assets](#assets)
- [Improved selection panel navigation](#improved-selection-panel-navigation)
**Breaking changes**
- [`datatypes` renamed to `encodings`](#datatypes-renamed-to-encodings)
The labels are bold text, not headings, so the ToC does not list itself and the page's
first ## heading is still New features.
Skip a group whose section has no ### headings.
The anchor is derived the same way as in step 4.
Stripping the punctuation can leave a word that pixi run lint-rerun rejects, such as
sdkdataplatform from rerun-sdk[dataplatform], so append <!-- NOLINT --> to a bullet
whose anchor trips the linter.
Do not write a summary paragraph above or below the list, and do not describe an entry
beyond its heading text — a reader who wants the detail clicks through.
Tailor the output to the release type:
0.x.Y, Y > 0) → typically only bug fixes. Skip the table of contents and
New features (there usually won't be upcoming/ entries anyway); keep Breaking changes only if there are any.0.X.0) → the full template: table of contents, 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.
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.
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.
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.
upcoming/ entry is represented in the changeset.TODO(name) remains in the changeset.### heading of the changeset, and every link resolves.upcoming/ contains only _template.md.python scripts/ci/check_changelog_redirect.py passes (redirect points at this changeset).python scripts/ci/check_doc_redirects.py --base origin/main passes (every deleted upcoming/ entry has a redirect).skills/assemble-changelog in the standalone Rerun repository.rerun-io/rerun carry a Source-Ref trailer (the reality merge
commit); generate_changelog.py resolves it back to the originating reality PR for
correct titles, labels, and contributors.check_changelog_redirect.py fail, since it requires the newest
changeset-0-xx.md to be the redirect target. During a cycle, upcoming/ is the only in-flight
artifact.