From ed13980a41c4a9413db6f6c827960de29e3f8cda Mon Sep 17 00:00:00 2001 From: Roz Date: Wed, 19 Aug 2026 23:56:11 +0200 Subject: [PATCH] fix(ci): generate release notes for the tagged range The v0.4.0 release came out with an empty version header and no commits. `conventional-changelog -r 1` on its own emits the unreleased section, which is empty when HEAD is the tag being released, and the header it does emit carries no version because the root package.json has none, so the `sed` that was meant to strip it never matched and the fallback to GitHub's generated notes never ran. Pass the range explicitly (previous tag .. this tag) and add `--stdout`, which v8 needs to print instead of writing CHANGELOG.md. Presets are no longer bundled with the CLI, so `conventional-changelog` and `conventional-changelog-conventionalcommits` move into devDependencies and the job installs them. That also lets the changelog read its config from .github/changelog.config.mjs, which unhides docs, chore, refactor, test, build, style and ci so the notes list every commit. --- .github/changelog.config.mjs | 12 +++++++++++ .github/workflows/create-release.yml | 29 +++++++++++++++++++------ bun.lock | 32 ++++++++++++++++++++++++++++ package.json | 2 ++ 4 files changed, 69 insertions(+), 6 deletions(-) create mode 100644 .github/changelog.config.mjs diff --git a/.github/changelog.config.mjs b/.github/changelog.config.mjs new file mode 100644 index 0000000..c7be752 --- /dev/null +++ b/.github/changelog.config.mjs @@ -0,0 +1,12 @@ +import createPreset, { DEFAULT_COMMIT_TYPES } from 'conventional-changelog-conventionalcommits' + +// The conventionalcommits preset hides docs, style, chore, refactor, test, +// build and ci from the changelog. Release notes here list every commit, so +// clear the `hidden` effect and let each type render under its own section. +export default createPreset({ + types: DEFAULT_COMMIT_TYPES.map(type => + type.effect === 'hidden' + ? { type: type.type, section: type.section } + : type, + ), +}) diff --git a/.github/workflows/create-release.yml b/.github/workflows/create-release.yml index d42958b..2d3c80f 100644 --- a/.github/workflows/create-release.yml +++ b/.github/workflows/create-release.yml @@ -25,6 +25,11 @@ jobs: with: bun-version: 1.3.14 + # conventional-changelog v8 ships without presets, so both it and the + # preset used by .github/changelog.config.mjs come from devDependencies. + - name: Install dependencies + run: bun install --frozen-lockfile --ignore-scripts + - name: Create the GitHub release env: TAG: ${{ github.ref_name }} @@ -32,12 +37,24 @@ jobs: run: | set -euo pipefail - # Build the changelog for just this release (latest tag .. previous tag), - # grouped into Features / Bug Fixes by conventional-commit type. Strip - # the auto-generated version header — the release title already shows the - # version. Fall back to GitHub's generated notes if it comes back empty. - NOTES="$(bunx conventional-changelog-cli -p conventionalcommits -r 1 \ - | sed -E '/^#+ \[?v?[0-9]+\.[0-9]+\.[0-9]+/d')" + PREV_TAG="$(git describe --tags --abbrev=0 "$TAG^" 2>/dev/null || true)" + + # Build the changelog for just this release (previous tag .. this tag), + # grouped into sections by conventional-commit type. The range has to + # be explicit: on its own, -r 1 emits the unreleased section, which is + # empty when HEAD is the tag being released. --stdout is required as + # well, since the CLI writes to CHANGELOG.md by default. + ARGS=(-n .github/changelog.config.mjs --stdout -r 1 --to "$TAG") + if [ -n "$PREV_TAG" ]; then + ARGS+=(--from "$PREV_TAG") + fi + + # Strip the `## ` headings — the release title already shows + # the version — and the blank lines they leave at the top. Fall back to + # GitHub's generated notes if the result comes back empty. + NOTES="$(bunx conventional-changelog "${ARGS[@]}" \ + | sed -E '/^## /d' \ + | awk 'NF { p = 1 } p')" if [ -n "$(printf '%s' "$NOTES" | tr -d '[:space:]')" ]; then printf '%s\n' "$NOTES" > "$RUNNER_TEMP/notes.md" diff --git a/bun.lock b/bun.lock index 99b8681..00a234f 100644 --- a/bun.lock +++ b/bun.lock @@ -8,6 +8,8 @@ "@antfu/eslint-config": "^7.7.3", "@types/bencode": "^2.0.4", "@types/bun": "latest", + "conventional-changelog": "^8.1.3", + "conventional-changelog-conventionalcommits": "^10.4.0", "eslint": "10.6.0", "eslint-plugin-markdown-links": "0.9.1", }, @@ -151,6 +153,10 @@ "@colordx/core": ["@colordx/core@5.5.0", "", {}, "sha512-3PxTH8itZzltK0U9jTwVVnjLXvnDYuq3m+QXsHkENxWiPRh4WaoLcs1SQjqgZ55kS+QyirpH5BVwzP2gMVG6EQ=="], + "@conventional-changelog/git-client": ["@conventional-changelog/git-client@3.1.2", "", { "dependencies": { "@simple-libs/child-process-utils": "^2.0.0", "@simple-libs/stream-utils": "^2.0.0", "semver": "^7.5.2" }, "peerDependencies": { "conventional-commits-filter": "^6.0.1", "conventional-commits-parser": "^7.1.2" }, "optionalPeers": ["conventional-commits-filter", "conventional-commits-parser"] }, "sha512-jZqwnJwf7nboIlAcw/mkOjVa6DexCcUOgT2oOQgkoi3z9vR8tGFkcMy2BFcYwjhL9sYcDDXkRQDayiDieCoW7A=="], + + "@conventional-changelog/template": ["@conventional-changelog/template@1.4.0", "", {}, "sha512-aalGyl7dbB5PArRebDIX43ZvBlXrYm9uWzGJ26t+4SzJVPsOuvfILGGbw5X4yX7i50YEmJ8zvbiWnqH/AAnZqg=="], + "@drizzle-team/brocli": ["@drizzle-team/brocli@0.10.2", "", {}, "sha512-z33Il7l5dKjUgGULTqBsQBQwckHh5AbIuxhdsIxDDiZAzBOrZO6q9ogcWC65kU382AfynTfgNumVcNIjuIua6w=="], "@dxup/nuxt": ["@dxup/nuxt@0.4.1", "", { "dependencies": { "@dxup/unimport": "^0.1.2", "@nuxt/kit": "^4.4.2", "chokidar": "^5.0.0", "pathe": "^2.0.3", "tinyglobby": "^0.2.16" }, "peerDependencies": { "typescript": "*" }, "optionalPeers": ["typescript"] }, "sha512-gtYffW6OfWNvoLW+XD3Mx/K8uUq08PMGLYJoDxc92EzZAWqR0FhcR5iaLm5r/OxyGTKz+P5f5Y7Aoir9+SjYaw=="], @@ -715,6 +721,14 @@ "@simple-git/argv-parser": ["@simple-git/argv-parser@1.1.1", "", { "dependencies": { "@simple-git/args-pathspec": "^1.0.3" } }, "sha512-Q9lBcfQ+VQCpQqGJFHe5yooOS5hGdLFFbJ5R+R5aDsnkPCahtn1hSkMcORX65J2Z5lxSkD0lQorMsncuBQxYUw=="], + "@simple-libs/child-process-utils": ["@simple-libs/child-process-utils@2.0.0", "", { "dependencies": { "@simple-libs/stream-utils": "^2.0.0" } }, "sha512-dvNoRKLijXnD0XoJAz94pbNuB5GQgDr55UhpSPhffDkTT0Cmcqh9jSCOtwfT2d4H6MI9E7c4SgtMuJXZ6F3c6A=="], + + "@simple-libs/hosted-git-info": ["@simple-libs/hosted-git-info@2.0.0", "", {}, "sha512-55XwK/GYgV58PuN8lZFhI1qRxdKoMLJocXl/yM1EPqazFDmM4QWY7q6BxPCPDNKTNunj794DSD4h0H7SrqUdMg=="], + + "@simple-libs/normalize-package-data": ["@simple-libs/normalize-package-data@1.0.0", "", { "dependencies": { "@simple-libs/hosted-git-info": "^2.0.0", "semver": "^7.8.5" } }, "sha512-/EOmFBekV9tGee8gac/k+5Ox3twkypNqh5TfxA9vTkmcJkjm6f1xqrlstDNOrEhTvnYyVtU6Du2ZhY/IV1+9GA=="], + + "@simple-libs/stream-utils": ["@simple-libs/stream-utils@2.0.0", "", {}, "sha512-fCTuZK4QBa+39Oz9l4OGfJfz+GpwCp3AqO7Zch3to99xHPgstVsRFpeQ8LNd2o1Gv8raL2mCFwiaHh7bFSp5DQ=="], + "@sindresorhus/base62": ["@sindresorhus/base62@1.0.0", "", {}, "sha512-TeheYy0ILzBEI/CO55CP6zJCSdSWeRtGnHy8U8dWSUH4I68iqTsy7HkMktR4xakThc9jotkPQUXT4ITdbV7cHA=="], "@sindresorhus/is": ["@sindresorhus/is@7.2.0", "", {}, "sha512-P1Cz1dWaFfR4IR+U13mqqiGsLFf1KbayybWwdd2vfctdV6hDpUkgCY0nKOLLTMSoRd/jJNjtbqzf13K8DCCXQw=="], @@ -1005,6 +1019,8 @@ "argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="], + "argue-cli": ["argue-cli@3.1.0", "", {}, "sha512-DhBpBfXL4SS2uC0N922MMajKR3CdrTG0u2or1PNYgXMsrSzViJrbtvT0nCLlLGUI0plam/ZZCs7aAauHtW9thw=="], + "aria-hidden": ["aria-hidden@1.2.6", "", { "dependencies": { "tslib": "^2.0.0" } }, "sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA=="], "ast-kit": ["ast-kit@2.2.0", "", { "dependencies": { "@babel/parser": "^7.28.5", "pathe": "^2.0.3" } }, "sha512-m1Q/RaVOnTp9JxPX+F+Zn7IcLYMzM8kZofDImfsKZd8MbR+ikdOzTeztStWqfrqIxZnYWryyI9ePm3NGjnZgGw=="], @@ -1123,6 +1139,18 @@ "consola": ["consola@3.4.2", "", {}, "sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA=="], + "conventional-changelog": ["conventional-changelog@8.1.3", "", { "dependencies": { "@conventional-changelog/git-client": "^3.1.2", "@simple-libs/hosted-git-info": "^2.0.0", "@simple-libs/normalize-package-data": "^1.0.0", "argue-cli": "^3.1.0", "conventional-changelog-preset-loader": "^6.0.1", "conventional-changelog-writer": "^9.2.1", "conventional-commits-filter": "^6.0.1", "conventional-commits-parser": "^7.1.2", "fd-package-json": "^2.0.0" }, "bin": { "conventional-changelog": "./dist/cli/index.js" } }, "sha512-fOMwLCxm46znJKPB08jLxl1FD8SOZOQHktlzCVhvhhVUfq0KgQSryoYXsRRHs1aRlZPR1/QK5wztnY8sBNC2AA=="], + + "conventional-changelog-conventionalcommits": ["conventional-changelog-conventionalcommits@10.4.0", "", { "dependencies": { "@conventional-changelog/template": "^1.4.0" } }, "sha512-Rriac6ZrAlVm6cy9Bz4NSp+WMHpwNXoPIYex+HjCgduAVUSbnew29DQjQw0C4g9u3HtSYzGiGY+pdBXAZo+4aA=="], + + "conventional-changelog-preset-loader": ["conventional-changelog-preset-loader@6.0.1", "", {}, "sha512-GZ8E3RQzXQb3JFy0pKl8oeSf7ENIhvAMvJr+PlWkavZOesLHHdhkfNJ4SvW35eo1Fu2+EyVxWQ1tVvtzAG2iWg=="], + + "conventional-changelog-writer": ["conventional-changelog-writer@9.2.1", "", { "dependencies": { "@conventional-changelog/template": "^1.3.0", "@simple-libs/stream-utils": "^2.0.0", "argue-cli": "^3.1.0", "conventional-commits-filter": "^6.0.1", "semver": "^7.5.2" }, "bin": { "conventional-changelog-writer": "./dist/cli/index.js" } }, "sha512-StlYSmW3wLedRaqohJMpP3YuWiAqtgD0/cpsai9frdDkXv7rxj0hRbpJrubPYvJxJsjplONsOobEQnPuS9UgCg=="], + + "conventional-commits-filter": ["conventional-commits-filter@6.0.1", "", {}, "sha512-cs+LadpH7Kpw0M3k8wurk+sOVVDAENA0iK4OBOrkL94j5lEVYRJ4j3zd2bhY9qgzyrPqthdcYT3axzRN7AliMg=="], + + "conventional-commits-parser": ["conventional-commits-parser@7.1.2", "", { "dependencies": { "@simple-libs/stream-utils": "^2.0.0", "argue-cli": "^3.1.0" }, "bin": { "conventional-commits-parser": "./dist/cli/index.js" } }, "sha512-O+x4N2yH+ijvqWlIyTHsXTAP+algNWgGbjY2duCe8w2vUMvUB95cLRslCPfTMQyLAKlet3bhZTdu6ozn4M+QJQ=="], + "convert-source-map": ["convert-source-map@2.0.0", "", {}, "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg=="], "cookie": ["cookie@1.1.1", "", {}, "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ=="], @@ -1377,6 +1405,8 @@ "fault": ["fault@2.0.1", "", { "dependencies": { "format": "^0.2.0" } }, "sha512-WtySTkS4OKev5JtpHXnib4Gxiurzh5NCGvWrFaZ34m6JehfTUhKZvn9njTfw48t6JumVQOmrKqpmGcdwxnhqBQ=="], + "fd-package-json": ["fd-package-json@2.0.0", "", { "dependencies": { "walk-up-path": "^4.0.0" } }, "sha512-jKmm9YtsNXN789RS/0mSzOC1NUq9mkVd65vbSSVsKdjGvYXBuE4oWe2QOEoFeRmJg+lPuZxpmrfFclNhoRMneQ=="], + "fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="], "file-entry-cache": ["file-entry-cache@8.0.0", "", { "dependencies": { "flat-cache": "^4.0.0" } }, "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ=="], @@ -2351,6 +2381,8 @@ "w3c-keyname": ["w3c-keyname@2.2.8", "", {}, "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ=="], + "walk-up-path": ["walk-up-path@4.0.0", "", {}, "sha512-3hu+tD8YzSLGuFYtPRb48vdhKMi0KQV5sn+uWr8+7dMEq/2G/dtLrdDinkLjqq5TIbIBjYJ4Ax/n3YiaW7QM8A=="], + "webidl-conversions": ["webidl-conversions@3.0.1", "", {}, "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="], "webpack-virtual-modules": ["webpack-virtual-modules@0.6.2", "", {}, "sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ=="], diff --git a/package.json b/package.json index 9c88cfa..c048865 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,8 @@ "@antfu/eslint-config": "^7.7.3", "@types/bencode": "^2.0.4", "@types/bun": "latest", + "conventional-changelog": "^8.1.3", + "conventional-changelog-conventionalcommits": "^10.4.0", "eslint": "10.6.0", "eslint-plugin-markdown-links": "0.9.1" }