From d07dd3e97c96cde215aab7687dc5aa0cfdf6e5a3 Mon Sep 17 00:00:00 2001 From: Mattia Panzeri <1754457+panz3r@users.noreply.github.com> Date: Tue, 29 Sep 2026 19:43:00 +0200 Subject: [PATCH 1/5] ci: release weekly from git history with git-cliff instead of release-please --- .github/workflows/release.yml | 139 ++++++++++++++++------------------ .release-please-manifest.json | 1 - CHANGELOG.md | 2 + README.md | 4 + cliff.toml | 36 +++++++++ release-please-config.json | 10 --- 6 files changed, 106 insertions(+), 86 deletions(-) delete mode 100644 .release-please-manifest.json create mode 100644 cliff.toml delete mode 100644 release-please-config.json diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 6079e9e..d0ae1df 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,114 +1,103 @@ name: Release on: - push: - branches: - - main schedule: - cron: "0 17 * * 2" # Weekly on Tuesday evenings workflow_dispatch: + inputs: + dry-run: + description: Compute the next version and release notes without publishing + type: boolean + default: false -jobs: - release-please: - name: Run Release Please - - runs-on: ubuntu-latest - - permissions: - contents: write - pull-requests: write +permissions: + contents: read - outputs: - releases_created: ${{ steps.release.outputs.releases_created }} +concurrency: + group: release - steps: - - name: Run release-please command - id: release - uses: googleapis/release-please-action@45996ed1f6d02564a971a2fa1b5860e934307cf7 # v5.0.0 - - merge-release-pr: - name: Merge Release PR +jobs: + release: + name: Release runs-on: ubuntu-latest - needs: [release-please] - - if: github.event_name == 'schedule' && needs.release-please.outputs.releases_created != 'true' - permissions: - actions: write - contents: write - pull-requests: write + contents: write # create the tag and GitHub release + id-token: write # npm trusted publishing env: - GH_TOKEN: ${{ github.token }} - GH_REPO: ${{ github.repository }} + NOTES: ${{ runner.temp }}/RELEASE_NOTES.md steps: - - name: Find pending release PR - id: pr - run: | - gh pr list --state open --label "autorelease: pending" --json number,headRefName,headRefOid \ - --jq '.[0] // empty | "number=\(.number)\nbranch=\(.headRefName)\nsha=\(.headRefOid)"' >> "$GITHUB_OUTPUT" + - name: Checkout repository + uses: actions/checkout@v7 + with: + fetch-depth: 0 - # Pushes made with GITHUB_TOKEN don't trigger CI, so dispatch it to get the required checks - - name: Run Build & Test on release PR - if: steps.pr.outputs.number - env: - PR_NUMBER: ${{ steps.pr.outputs.number }} - PR_BRANCH: ${{ steps.pr.outputs.branch }} - run: | - gh workflow run build-test.yml --ref "$PR_BRANCH" - sleep 30 - gh pr checks "$PR_NUMBER" --required --watch --fail-fast --interval 30 + - name: Generate release notes + id: notes + uses: orhun/git-cliff-action@a9a95522b26fe6403f7bb24031f21fb573d0f5ff # v4.9.1 + with: + args: --unreleased --bump --strip all --output ${{ runner.temp }}/RELEASE_NOTES.md - - name: Merge release PR - if: steps.pr.outputs.number + # git-cliff reports the latest tag as the next version when nothing is releasable + - name: Check for releasable changes + id: check env: - PR_NUMBER: ${{ steps.pr.outputs.number }} - PR_SHA: ${{ steps.pr.outputs.sha }} - run: gh pr merge "$PR_NUMBER" --squash --match-head-commit "$PR_SHA" - - # The merge push is made with GITHUB_TOKEN and won't start this workflow on its own - - name: Trigger release - if: steps.pr.outputs.number - run: gh workflow run release.yml --ref main - - build-and-publish: - name: Build & Publish - - runs-on: ubuntu-latest - - needs: [release-please] - - if: needs.release-please.outputs.releases_created != 'false' - - concurrency: publish-group # optional: ensure only one action runs at a time - - permissions: - contents: read - id-token: write - - steps: - - name: Checkout repository - uses: actions/checkout@v7 + VERSION: ${{ steps.notes.outputs.version }} + run: | + if ! grep -q '[^[:space:]]' "$NOTES" || git rev-parse -q --verify "refs/tags/$VERSION" >/dev/null; then + echo "No releasable changes since the last release" + echo "release=false" >> "$GITHUB_OUTPUT" + else + { echo "## $VERSION"; echo; cat "$NOTES"; } >> "$GITHUB_STEP_SUMMARY" + echo "release=true" >> "$GITHUB_OUTPUT" + fi - name: Setup pnpm + if: steps.check.outputs.release == 'true' uses: pnpm/setup@fbda4c85fc2e1e08721cd8763afea8f48d60f024 # v3.0.0 with: install: false - name: Setup NodeJS + if: steps.check.outputs.release == 'true' uses: actions/setup-node@v7 with: node-version: latest registry-url: "https://registry.npmjs.org" - name: Install dependencies + if: steps.check.outputs.release == 'true' run: pnpm i --frozen-lockfile - name: Build package + if: steps.check.outputs.release == 'true' run: pnpm build + - name: Set package version + if: steps.check.outputs.release == 'true' + env: + VERSION: ${{ steps.notes.outputs.version }} + run: npm version "${VERSION#v}" --no-git-tag-version --allow-same-version + + # Skipping an already published version lets a failed run be retried safely - name: Publish package - run: npm publish + if: steps.check.outputs.release == 'true' && !inputs.dry-run + env: + VERSION: ${{ steps.notes.outputs.version }} + run: | + name="$(jq -r .name package.json)" + if [[ -n "$(npm view "$name@${VERSION#v}" version 2>/dev/null)" ]]; then + echo "$name@${VERSION#v} is already published" + else + npm publish + fi + + - name: Create GitHub release + if: steps.check.outputs.release == 'true' && !inputs.dry-run + env: + GH_TOKEN: ${{ github.token }} + VERSION: ${{ steps.notes.outputs.version }} + run: gh release create "$VERSION" --target "$GITHUB_SHA" --title "$VERSION" --notes-file "$NOTES" diff --git a/.release-please-manifest.json b/.release-please-manifest.json deleted file mode 100644 index 0878d45..0000000 --- a/.release-please-manifest.json +++ /dev/null @@ -1 +0,0 @@ -{".":"1.0.0"} \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 4933c22..01739eb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,7 @@ # Changelog +> This file is no longer updated. Release notes for newer versions are published on the [GitHub Releases](https://github.com/forwardsoftware/qrcodets/releases) page. + ## 1.0.0 (2025-04-01) diff --git a/README.md b/README.md index 545b60a..8de9add 100644 --- a/README.md +++ b/README.md @@ -133,6 +133,10 @@ The QRCode class takes an object with the following properties as initialization - mode (optional): "svg" | "dom" - The rendering mode. Either 'svg' for SVG rendering or 'dom' for HTML DOM rendering. +## Changelog + +Release notes for every version are published on the [GitHub Releases](https://github.com/forwardsoftware/qrcodets/releases) page. + ## License MIT License diff --git a/cliff.toml b/cliff.toml new file mode 100644 index 0000000..94d9fb8 --- /dev/null +++ b/cliff.toml @@ -0,0 +1,36 @@ +# git-cliff configuration, see https://git-cliff.org/docs/configuration + +[changelog] +body = """ +{% for group, commits in commits | group_by(attribute="group") %} +### {{ group | striptags | trim }} +{% for commit in commits %} +- {% if commit.scope %}**{{ commit.scope }}:** {% endif %}{% if commit.breaking %}[**breaking**] {% endif %}{{ commit.message | upper_first }} ({{ commit.id | truncate(length=7, end="") }})\ +{% endfor %} +{% endfor %} +""" +trim = true + +[git] +conventional_commits = true +filter_unconventional = true +filter_commits = true +protect_breaking_commits = true +tag_pattern = "^v[0-9]+\\.[0-9]+\\.[0-9]+$" +sort_commits = "newest" +# Only changes to shipped files count towards a release +exclude_paths = [".github/**", ".devcontainer/**", "website/**", "cliff.toml"] +# Group names are prefixed with an HTML comment to control their order +commit_parsers = [ + { message = "^feat", group = "Features" }, + { message = "^fix", group = "Bug Fixes" }, + { message = "^perf", group = "Performance" }, + { message = "^refactor", group = "Refactoring" }, + { message = "^docs", group = "Documentation" }, + { message = "^chore", group = "Miscellaneous" }, + { message = "^(ci|build|test|style)", skip = true }, +] + +[bump] +features_always_bump_minor = true +breaking_always_bump_major = true diff --git a/release-please-config.json b/release-please-config.json deleted file mode 100644 index 4538c6c..0000000 --- a/release-please-config.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "$schema": "https://raw.githubusercontent.com/googleapis/release-please/main/schemas/config.json", - "release-type": "node", - "always-update": true, - "packages": { - ".": { - "include-component-in-tag": false - } - } -} \ No newline at end of file From f5962a2b6c05c2b64707dbbcf40503d7f8393e9b Mon Sep 17 00:00:00 2001 From: Mattia Panzeri <1754457+panz3r@users.noreply.github.com> Date: Tue, 29 Sep 2026 19:43:17 +0200 Subject: [PATCH 2/5] ci: set release notes path at step level --- .github/workflows/release.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index d0ae1df..2c15818 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -26,9 +26,6 @@ jobs: contents: write # create the tag and GitHub release id-token: write # npm trusted publishing - env: - NOTES: ${{ runner.temp }}/RELEASE_NOTES.md - steps: - name: Checkout repository uses: actions/checkout@v7 @@ -45,6 +42,7 @@ jobs: - name: Check for releasable changes id: check env: + NOTES: ${{ runner.temp }}/RELEASE_NOTES.md VERSION: ${{ steps.notes.outputs.version }} run: | if ! grep -q '[^[:space:]]' "$NOTES" || git rev-parse -q --verify "refs/tags/$VERSION" >/dev/null; then @@ -99,5 +97,6 @@ jobs: if: steps.check.outputs.release == 'true' && !inputs.dry-run env: GH_TOKEN: ${{ github.token }} + NOTES: ${{ runner.temp }}/RELEASE_NOTES.md VERSION: ${{ steps.notes.outputs.version }} run: gh release create "$VERSION" --target "$GITHUB_SHA" --title "$VERSION" --notes-file "$NOTES" From 2eaee06d9fd61dc0fb995c9ae7c9c5c20bf1130b Mon Sep 17 00:00:00 2001 From: Mattia Panzeri <1754457+panz3r@users.noreply.github.com> Date: Tue, 29 Sep 2026 23:05:55 +0200 Subject: [PATCH 3/5] ci: set up pnpm and Node.js in a single step --- .github/workflows/release.yml | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 2c15818..d7d436c 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -53,19 +53,13 @@ jobs: echo "release=true" >> "$GITHUB_OUTPUT" fi - - name: Setup pnpm + - name: Setup pnpm & Node.js if: steps.check.outputs.release == 'true' uses: pnpm/setup@fbda4c85fc2e1e08721cd8763afea8f48d60f024 # v3.0.0 with: + runtime: node@latest install: false - - name: Setup NodeJS - if: steps.check.outputs.release == 'true' - uses: actions/setup-node@v7 - with: - node-version: latest - registry-url: "https://registry.npmjs.org" - - name: Install dependencies if: steps.check.outputs.release == 'true' run: pnpm i --frozen-lockfile From 481e7e4cedeb0aa4eb863cadcaaca37ffee5a72b Mon Sep 17 00:00:00 2001 From: Mattia Panzeri <1754457+panz3r@users.noreply.github.com> Date: Tue, 29 Sep 2026 23:06:58 +0200 Subject: [PATCH 4/5] ci: temporary npm diagnostics --- .github/workflows/release.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index d7d436c..5d82680 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -72,7 +72,9 @@ jobs: if: steps.check.outputs.release == 'true' env: VERSION: ${{ steps.notes.outputs.version }} - run: npm version "${VERSION#v}" --no-git-tag-version --allow-same-version + run: | + which -a node npm; node --version; npm --version + npm version "${VERSION#v}" --no-git-tag-version --allow-same-version # Skipping an already published version lets a failed run be retried safely - name: Publish package From 23732c3096d09833a7464bcf77b8ead40b5bb004 Mon Sep 17 00:00:00 2001 From: Mattia Panzeri <1754457+panz3r@users.noreply.github.com> Date: Tue, 29 Sep 2026 23:09:40 +0200 Subject: [PATCH 5/5] ci: publish with pnpm, which supports trusted publishing natively --- .github/workflows/release.yml | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 5d82680..4449a5b 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -72,21 +72,23 @@ jobs: if: steps.check.outputs.release == 'true' env: VERSION: ${{ steps.notes.outputs.version }} - run: | - which -a node npm; node --version; npm --version - npm version "${VERSION#v}" --no-git-tag-version --allow-same-version + run: pnpm version "${VERSION#v}" --no-git-tag-version --allow-same-version + # pnpm publishes via npm trusted publishing (OIDC) itself; the runner's npm is too old for it # Skipping an already published version lets a failed run be retried safely - name: Publish package - if: steps.check.outputs.release == 'true' && !inputs.dry-run + if: steps.check.outputs.release == 'true' env: + DRY_RUN: ${{ inputs.dry-run }} VERSION: ${{ steps.notes.outputs.version }} run: | name="$(jq -r .name package.json)" - if [[ -n "$(npm view "$name@${VERSION#v}" version 2>/dev/null)" ]]; then + if [[ "$DRY_RUN" == "true" ]]; then + pnpm publish --no-git-checks --dry-run + elif [[ -n "$(pnpm view "$name@${VERSION#v}" version 2>/dev/null)" ]]; then echo "$name@${VERSION#v} is already published" else - npm publish + pnpm publish --no-git-checks fi - name: Create GitHub release