Browse Source

Create a single GitHub release with the changes of all packages

The release notes combine the changelogs of every package for the version,
list an entry shared by several packages once and leave out "Updated
dependencies" entries. The release pull request shows a preview of that
release instead of the per-package sections from Changesets.
pull/1647/head
codecalm 6 days ago
parent
commit
9790d591a4
  1. 78
      .build/release-notes.mjs
  2. 20
      .github/workflows/release.yml

78
.build/release-notes.mjs

@ -1,12 +1,19 @@
// Prints the notes of the current release: the preview image of the new icons
// followed by the section of the @tabler/icons changelog for this version.
// Prints the notes of the current release, published as a single GitHub
// release for all packages: the preview image of the new icons followed by the
// changes from the changelogs of every package for this version. An entry
// shared by several packages is listed once, "Updated dependencies" entries are
// left out.
//
// --ref <git ref> ref the image is loaded from (default: the `v<version>` tag)
// --image-only print just the image
import { existsSync, readFileSync } from 'fs';
import { resolve } from 'path';
import { globSync } from 'glob';
import { dirname, resolve } from 'path';
import { GITHUB_DIR, PACKAGES_DIR, getArgvs } from './helpers.mjs';
const MAIN_PACKAGE = '@tabler/icons';
const CHANGE_TYPES = ['Major', 'Minor', 'Patch'];
const { version } = JSON.parse(readFileSync(resolve(PACKAGES_DIR, 'icons/package.json'), 'utf-8'));
const argvs = getArgvs();
const repo = process.env.GITHUB_REPOSITORY || 'tabler/tabler-icons';
@ -21,12 +28,61 @@ if (existsSync(resolve(GITHUB_DIR, image))) {
}
if (!argvs['image-only']) {
const changelogPath = resolve(PACKAGES_DIR, 'icons/CHANGELOG.md');
const changelog = existsSync(changelogPath) ? readFileSync(changelogPath, 'utf-8') : '';
const [, section = ''] =
changelog.match(
new RegExp(`^## ${version.replace(/\./g, '\\.')}\\n([\\s\\S]*?)(?=^## |(?![\\s\\S]))`, 'm'),
) || [];
console.log(section.trim());
const escapedVersion = version.replace(/\./g, '\\.');
// { [type]: Map<entry, packages[]> } in the order the entries first appear,
// starting with the main package
const changes = Object.fromEntries(CHANGE_TYPES.map((type) => [type, new Map()]));
const packages = globSync(resolve(PACKAGES_DIR, '*/CHANGELOG.md'))
.map((changelogPath) => ({
name: JSON.parse(readFileSync(resolve(dirname(changelogPath), 'package.json'), 'utf-8')).name,
changelog: readFileSync(changelogPath, 'utf-8'),
}))
.sort((a, b) => (a.name === MAIN_PACKAGE ? -1 : b.name === MAIN_PACKAGE ? 1 : 0));
packages.forEach(({ name, changelog }) => {
const [, section = ''] =
changelog.match(
new RegExp(`^## ${escapedVersion}\\n([\\s\\S]*?)(?=^## |(?![\\s\\S]))`, 'm'),
) || [];
CHANGE_TYPES.forEach((type) => {
const [, list = ''] =
section.match(
new RegExp(`^### ${type} Changes\\n([\\s\\S]*?)(?=^### |(?![\\s\\S]))`, 'm'),
) || [];
// Top-level list items, together with their indented continuation lines
list
.split(/^(?=- )/m)
.map((entry) => entry.trim())
.filter((entry) => entry.startsWith('- ') && !entry.startsWith('- Updated dependencies'))
.forEach((entry) => {
changes[type].set(entry, [...(changes[type].get(entry) || []), name]);
});
});
});
CHANGE_TYPES.forEach((type) => {
if (changes[type].size === 0) {
return;
}
console.log(`### ${type} Changes\n`);
changes[type].forEach((names, entry) => {
// Entries of the main package (icons) need no label
const label = names.includes(MAIN_PACKAGE)
? ''
: `${[...names]
.sort()
.map((name) => `\`${name}\``)
.join(', ')}: `;
console.log(entry.replace(/^- /, `- ${label}`));
});
console.log('');
});
}

20
.github/workflows/release.yml

@ -74,10 +74,12 @@ jobs:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
# Changesets builds the description from the changelogs only, so the
# preview of the new icons is put on top of it. The image is loaded from
# the commit on the release branch, the `v<version>` tag does not exist yet.
- name: Add new icons preview to the release pull request
# Changesets describes every package separately, while GitHub gets a single
# release for all of them. The description is replaced with a preview of
# that release, with the image of the new icons on top. The image is loaded
# from the commit on the release branch, the `v<version>` tag does not
# exist yet.
- name: Show the GitHub release in the release pull request
if: steps.changesets.outputs.pullRequestNumber != ''
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@ -86,8 +88,14 @@ jobs:
SHA=$(gh api "repos/${GITHUB_REPOSITORY}/commits/changeset-release/main" --jq .sha)
git fetch origin changeset-release/main
git checkout --detach "$SHA"
node ./.build/release-notes.mjs --image-only --ref "$SHA" > body.md
gh pr view "$PR_NUMBER" --json body --jq .body >> body.md
VERSION=$(node -p "require('./packages/icons/package.json').version")
{
echo "Merging this pull request publishes all \`@tabler/icons*\` packages in version **${VERSION}** to npm and creates the following GitHub release."
echo
echo "---"
echo
node ./.build/release-notes.mjs --ref "$SHA"
} > body.md
gh pr edit "$PR_NUMBER" --body-file body.md
- name: Create GitHub release

Loading…
Cancel
Save