|
| 1 | +# Changelog fragments |
| 2 | + |
| 3 | +Each pull request adds one file here, `<PR#>-<slug>.md`, with its changelog entries. Pull requests no longer edit `CHANGELOG.md`, so they do not conflict with each other. |
| 4 | + |
| 5 | +On every push to `main`, a workflow recreates the `changelog-unreleased` branch from `main`, plus one commit that merges all fragments into the `[Unreleased]` section of [`CHANGELOG.md`](https://github.com/microsoft/BotFramework-WebChat/blob/changelog-unreleased/CHANGELOG.md#unreleased) and deletes them. When there are no fragments, the branch is the same as `main`, and its "Built from" line, if any, is left as it was. The workflow always pushes, so it also recreates the branch after it was deleted. |
| 6 | + |
| 7 | +## Merging back |
| 8 | + |
| 9 | +From time to time, a maintainer moves the entries into `CHANGELOG.md` on `main` by merging back a copy of the branch: |
| 10 | + |
| 11 | +```sh |
| 12 | +git fetch origin |
| 13 | +git push origin origin/changelog-unreleased:refs/heads/<user>/changelog-merge-back |
| 14 | +``` |
| 15 | + |
| 16 | +Then open a pull request from `<user>/changelog-merge-back` and squash-merge it. Do not open it from `changelog-unreleased` itself: the workflow pushes it with `GITHUB_TOKEN`, which does not run the required checks, and rebuilds it on every push to `main`, which resets approvals. If a pull request from `changelog-unreleased` is merged anyway, GitHub deletes the branch, and the resulting push to `main` recreates it right away, so the "Show most recent changelog" link keeps working. |
| 17 | + |
| 18 | +The copy may fall behind `main`: the check still passes, and fragments merged since then stay for the next merge-back. |
| 19 | + |
| 20 | +## Adding an entry |
| 21 | + |
| 22 | +After `gh pr create`, run: |
| 23 | + |
| 24 | +```sh |
| 25 | +node ./scripts/changelog/new.mjs --issue 5734 "animation cards showing an empty video player for GIF URLs with a query" |
| 26 | +``` |
| 27 | + |
| 28 | +It writes `.changelog/5930-fix-animated-image-formats.md`, using the number and the author of the pull request, and the branch name: |
| 29 | + |
| 30 | +```md |
| 31 | +### Fixed |
| 32 | + |
| 33 | +- Fixed [#5734](https://github.com/microsoft/BotFramework-WebChat/issues/5734), animation cards showing an empty video player for GIF URLs with a query, in PR [#5930](https://github.com/microsoft/BotFramework-WebChat/pull/5930), by [@OEvgeny](https://github.com/OEvgeny) |
| 34 | +``` |
| 35 | + |
| 36 | +| Option | Default | |
| 37 | +| ----------------------------------------------------------- | ----------------------------- | |
| 38 | +| `--section added\|changed\|removed\|fixed` | `fixed` | |
| 39 | +| `--issue <issue#>`, repeatable | none | |
| 40 | +| `--marker breaking\|known-issue\|experimental\|sample\|dev` | none | |
| 41 | +| `--pr <PR#>` | `gh pr view` | |
| 42 | +| `--author <login>` | `gh pr view` | |
| 43 | +| `--slug <slug>` | branch name without `<user>/` | |
| 44 | + |
| 45 | +## Format |
| 46 | + |
| 47 | +A fragment is a small changelog: `### Added`, `### Changed`, `### Removed`, or `### Fixed`, each with one or more entries. Nested bullets are indented by 3 spaces per level, the check fails on other indentation. Entries are published as written, so edit the file to add entries or sections. |
| 48 | + |
| 49 | +- Fixed, with issues: `- Fixed [#1](…) and [#2](…), <what was wrong>, in PR [#3](…), by [@user](…)` |
| 50 | +- Fixed, without issue: `- Fixed <what was wrong>, in PR [#3](…), by [@user](…)` |
| 51 | +- Added, changed, or removed, with issues: `- Added [#1](…), <what>, in PR [#3](…), by [@user](…)` |
| 52 | +- Added, changed, or removed, without issue: `- <Scope>: added <what>, in PR [#3](…), by [@user](…)` |
| 53 | +- Markers go first: 💥 breaking changes, 🐛 known issues, 🧪 experimental changes, 🏫 samples, 👷🏻 development environment changes |
| 54 | + |
| 55 | +Pull requests that only change the development environment can add a 👷🏻 entry, or be labeled `no-changelog` instead. |
| 56 | + |
| 57 | +## Checks |
| 58 | + |
| 59 | +The "Changelog" check of a pull request passes for: |
| 60 | + |
| 61 | +- A change: it adds `.changelog/<PR#>-<slug>.md` with its own number, or is labeled `no-changelog`. It must not edit the `[Unreleased]` section of `CHANGELOG.md` or delete fragments. |
| 62 | +- A merge-back of `changelog-unreleased`: it deletes fragments, adds none, changes no other files, and its `CHANGELOG.md` is exactly the one of `main` with the deleted fragments merged in, except for the "Built from" line. |
| 63 | +- A hand edit by a maintainer, labeled `changelog-edit`: it may edit `CHANGELOG.md` and delete fragments, for example a release or a typo fix in merged-back entries. Fragments are still validated. |
| 64 | + |
| 65 | +A pull request may also edit the fragment of another pull request, for example to fix a typo before it is merged back. |
| 66 | + |
| 67 | +## Scripts |
| 68 | + |
| 69 | +| Command | What it does | |
| 70 | +| ------------------------------------------------------- | --------------------------------------------------------------------------------------------- | |
| 71 | +| `node ./scripts/changelog/new.mjs` | Writes the fragment of a pull request | |
| 72 | +| `node ./scripts/changelog/consume.mjs` | Merges the fragments into `CHANGELOG.md` in the order they were merged, deletes them | |
| 73 | +| `node ./scripts/changelog/check.mjs --pr <PR#>` | Checks a pull request against `origin/main`, prints its entries | |
| 74 | +| `node ./scripts/changelog/publish.mjs` | Recreates and force-pushes `changelog-unreleased`, used by the workflow | |
| 75 | +| `node ./scripts/changelog/release.mjs <version> <date>` | Merges the fragments, then moves `[Unreleased]` into a new release, label it `changelog-edit` | |
| 76 | +| `node --test 'scripts/changelog/*.spec.mjs'` | Runs the tests | |
| 77 | + |
| 78 | +Except for `new.mjs`, the scripts read fragments from Git commits, not from the working tree. They need Node.js 22.18, 24.2, or later. |
| 79 | + |
| 80 | +Only the "Publish changelog-unreleased" workflow writes the `changelog-unreleased` branch, and it always force-pushes: do not protect the branch against force pushes. |
0 commit comments