From 8c155c2114d65c837f82397424d17e600c52725c Mon Sep 17 00:00:00 2001 From: Dawson Toth Date: Tue, 21 Jul 2026 17:15:01 -0400 Subject: [PATCH 1/3] ci: add semantic-release workflow ported from @harperfast/vite MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bring the release automation from the sibling `@harperfast/vite` plugin so merges to `main` cut versioned releases and publish to npm automatically. - `.github/workflows/release.yaml` — semantic-release on push to `main` (and via merge queue / manual dispatch), publishing to npm with provenance (`id-token: write` + `NPM_CONFIG_PROVENANCE`). Runs under a `Release` environment. Gated on `npm run build` (`dist/` is gitignored and rebuilt on publish via `prepublishOnly`, so this fails a broken build before it ships). - `.github/workflows/verify-commits.yaml` + `commitlint.config.cjs` — enforce the conventional commits that semantic-release parses for version bumps. - `.releaserc.json` — semantic-release config (commit-analyzer, release notes, npm, git, github), matching vite. - `package.json` — add `prepublishOnly: "npm run build"` so `npm publish` (invoked by @semantic-release/npm) compiles `dist/` in CI. Adapted from vite: the `github.repository` guard targets `HarperFast/nextjs`, and the pre-release gate is `npm run build` (vite's `format:check` / `test:coverage` scripts don't exist here yet). Action SHAs are pinned as in vite. Co-Authored-By: Claude Opus 4.8 --- .github/workflows/release.yaml | 59 +++++++++++++++++++++++++++ .github/workflows/verify-commits.yaml | 20 +++++++++ .releaserc.json | 34 +++++++++++++++ commitlint.config.cjs | 8 ++++ package.json | 3 +- 5 files changed, 123 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/release.yaml create mode 100644 .github/workflows/verify-commits.yaml create mode 100644 .releaserc.json create mode 100644 commitlint.config.cjs diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml new file mode 100644 index 0000000..40bfd38 --- /dev/null +++ b/.github/workflows/release.yaml @@ -0,0 +1,59 @@ +name: Release + +on: + merge_group: + branches: + - main + push: + branches: + - main + workflow_dispatch: + +# Needed for semantic-release to create GitHub releases and publish to npm via OIDC +permissions: + contents: write + issues: write + pull-requests: write + id-token: write + +concurrency: + group: Release + cancel-in-progress: false + +jobs: + release: + name: Release + environment: Release + # Ensure releases run only when code reaches main via GitHub Merge Queue, or when manually dispatched + runs-on: ubuntu-latest + if: github.repository == 'HarperFast/nextjs' || github.repository == 'harperfast/nextjs' + steps: + - name: Checkout + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + fetch-depth: 0 + - name: Setup Node.js + uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6.5.0 + with: + node-version-file: '.nvmrc' + cache: npm + registry-url: 'https://registry.npmjs.org' + - name: Install dependencies + run: npm ci + # Compile the plugin so a broken build fails the release before it publishes. `dist/` is gitignored + # and rebuilt on publish via the `prepublishOnly` script, so this also surfaces build errors early. + - name: Build + run: npm run build + - name: Semantic Release + if: ${{ github.event_name == 'push' || github.event_name == 'workflow_dispatch' || (github.event_name == 'merge_group' && github.event.merge_group.base_ref == 'refs/heads/main') }} + uses: cycjimmy/semantic-release-action@b12c8f6015dc215fe37bc154d4ad456dd3833c90 # v6.0.0 + with: + extra_plugins: | + @semantic-release/commit-analyzer + @semantic-release/release-notes-generator + @semantic-release/npm + @semantic-release/git + @semantic-release/github + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + NPM_CONFIG_PROVENANCE: true diff --git a/.github/workflows/verify-commits.yaml b/.github/workflows/verify-commits.yaml new file mode 100644 index 0000000..eff4609 --- /dev/null +++ b/.github/workflows/verify-commits.yaml @@ -0,0 +1,20 @@ +name: Verify Commits + +on: + pull_request: + types: [opened, synchronize, edited, reopened, ready_for_review] + push: + branches: [main] + +jobs: + commitlint: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + fetch-depth: 0 + - name: Commitlint + uses: wagoid/commitlint-github-action@b948419dd99f3fd78a6548d48f94e3df7f6bf3ed # v6.2.1 + with: + configFile: commitlint.config.cjs diff --git a/.releaserc.json b/.releaserc.json new file mode 100644 index 0000000..61e5326 --- /dev/null +++ b/.releaserc.json @@ -0,0 +1,34 @@ +{ + "branches": ["main"], + "plugins": [ + "@semantic-release/commit-analyzer", + [ + "@semantic-release/release-notes-generator", + { + "preset": "conventionalcommits", + "presetConfig": { + "types": [ + { "type": "feat", "section": "Features" }, + { "type": "feature", "section": "Features" }, + { "type": "docs", "section": "Documentation" }, + { "type": "fix", "section": "Bug Fixes" }, + { "type": "perf", "section": "Performance Improvements" }, + { "type": "refactor", "section": "Code Improvements" }, + { "type": "revert", "section": "Reverts" }, + { "type": "test", "section": "Test Improvements" }, + { "type": "chore", "scope": "deps", "section": "Dependency Updates" } + ] + } + } + ], + "@semantic-release/npm", + [ + "@semantic-release/git", + { + "assets": ["package.json", "package-lock.json"], + "message": "chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}" + } + ], + "@semantic-release/github" + ] +} diff --git a/commitlint.config.cjs b/commitlint.config.cjs new file mode 100644 index 0000000..0327923 --- /dev/null +++ b/commitlint.config.cjs @@ -0,0 +1,8 @@ +module.exports = { + extends: ['@commitlint/config-conventional'], + rules: { + 'subject-case': [0, 'never'], + 'body-max-line-length': [0, 'never'], + 'footer-max-line-length': [0, 'never'], + }, +}; diff --git a/package.json b/package.json index f199c0e..c8496e8 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,8 @@ "build": "tsc -p tsconfig.build.json", "install:fixtures": "node scripts/install-fixtures.js", "test": "npm run build && node --test \"dist/**/*.test.js\"", - "test:integration": "playwright test --config integrationTests/playwright.config.ts" + "test:integration": "playwright test --config integrationTests/playwright.config.ts", + "prepublishOnly": "npm run build" }, "engines": { "node": ">=20" From f46441139bad7d60921cd5dda77b3d4115540c62 Mon Sep 17 00:00:00 2001 From: Dawson Toth Date: Tue, 21 Jul 2026 17:25:42 -0400 Subject: [PATCH 2/3] ci: publish the scoped package with public access MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `@harperfast/nextjs` is a scoped package, which npm publishes with restricted access by default — the automated release would fail with 402 Payment Required on a fresh publish. Add `publishConfig.access = "public"`, matching `@harperfast/vite` (this was missing from the initial port). Co-Authored-By: Claude Opus 4.8 --- package.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/package.json b/package.json index c8496e8..2f5d3c7 100644 --- a/package.json +++ b/package.json @@ -23,6 +23,9 @@ "url": "git+https://github.com/HarperFast/nextjs.git" }, "license": "Apache-2.0", + "publishConfig": { + "access": "public" + }, "files": [ "dist/**", "!dist/**/*.test.*", From 504f31053c03dc4f7230cf4eb6427eb8ca314f67 Mon Sep 17 00:00:00 2001 From: Dawson Toth Date: Thu, 23 Jul 2026 10:27:06 -0400 Subject: [PATCH 3/3] chore: drop the unused "feature" changelog type from release config MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `feature` is not a valid @commitlint/config-conventional type, so a `feature:` commit can never pass the Verify Commits workflow — the release-notes-generator mapping for it is dead config that contradicts our commitlint rules. Drop it and rely on the standard `feat` type. Mirrors the same cleanup in @harperfast/vite. Co-Authored-By: Claude Opus 4.8 --- .releaserc.json | 1 - 1 file changed, 1 deletion(-) diff --git a/.releaserc.json b/.releaserc.json index 61e5326..43ff8b4 100644 --- a/.releaserc.json +++ b/.releaserc.json @@ -9,7 +9,6 @@ "presetConfig": { "types": [ { "type": "feat", "section": "Features" }, - { "type": "feature", "section": "Features" }, { "type": "docs", "section": "Documentation" }, { "type": "fix", "section": "Bug Fixes" }, { "type": "perf", "section": "Performance Improvements" },