Skip to content

feat!: migrate to Biome + Lefthook + Vitest + esbuild + Node 24#8

Merged
hershmire merged 4 commits into
mainfrom
eddie/strange-darwin-577c5e
May 21, 2026
Merged

feat!: migrate to Biome + Lefthook + Vitest + esbuild + Node 24#8
hershmire merged 4 commits into
mainfrom
eddie/strange-darwin-577c5e

Conversation

@hershmire

Copy link
Copy Markdown

Summary

Brings replace-comment-html-action in line with the org's modern toolchain template, mirroring reside-eng/npm-dependency-stats-action#1655 (the closest analog — also a GitHub Action). Also adopts the Claude Code scaffolding patterns from reside-eng/test-service-ci#692 and reside-eng/payment-statement-components#1797.

What changed

Toolchain swap

  • Biome 2.4.15 replaces ESLint 8 + Prettier 3 + their plugins + @side/eslint-config-* + @side/prettier-config
  • Lefthook 2.1.8 replaces Husky + lint-staged + @side/lint-staged-config
  • Vitest 4.1.7 + @vitest/coverage-v8 replaces the echo 'No tests yet' placeholder — adds smoke tests for action.ts and github.ts (11 tests, 80% line coverage, threshold gated at 75%)
  • esbuild 0.28.0 replaces @vercel/ncc — bundle output is now dist/index.mjs (ESM) with a createRequire banner so CommonJS deps like @actions/github still resolve
  • TypeScript ^6.0.3 (bumped from ^5.3.3 — required by @tsconfig/node24's lib values)

Runtime bump (Node 20 → Node 24)

  • engines.node: ^24.0.0
  • .node-version: 24.15.0
  • @tsconfig/node24 + @types/node@^24
  • action.yml: runs.using: node20node24, main: dist/index.jsdist/index.mjs
  • CI NODE_VERSION: 24.x

Release workflow

  • cycjimmy/semantic-release-action v2.7.0 → v6.0.0 (SHA pin updated)
  • semantic_version: ^18^25 (current semantic-release major)
  • dist/ is now gitignored on main; the existing "Push updates to branch for major version" step continues to git add --force dist and force-push the rebuilt dist/index.mjs to the v<major> branch (same pattern as the reference repo's v3 branch)

Claude Code scaffolding (all options enabled)

  • AGENTS.md + one-line CLAUDE.md stub pointing at it
  • .claude/{agents,commands}/.gitkeep placeholder dirs
  • .claude/settings.json with fine-grained allow/deny/ask permissions
  • .vscode/extensions.json recommending Biome + EditorConfig
  • .github/workflows/claude-code.yml calling reside-eng/workflow-templates/.github/workflows/claude-code.yml@v12
  • .gitignore shifts: .vscode/* deny + !.vscode/extensions.json; plus .claude/worktrees/, .claude/memory, .claude/projects, .claude/settings.local.json, coverage, dist

Source changes (mechanical)

Three Biome autofixes applied to src/action.ts:

  • useOptionalChain × 2 (id && id.startsWith(...)id?.startsWith(...), Map.get(k)!.push(x)Map.get(k)?.push(x))
  • useAwait (removed redundant async from a pass-through function)

src/github.ts had its imports re-sorted by organizeImports. No behavioural changes.

Breaking change

action.yml now uses the node24 runtime and dist/index.mjs entrypoint. Consumers must pin to @v2 (the new major branch produced by semantic-release on merge). Existing @v1 consumers are unaffected — that branch keeps its old dist/index.js and Node 20 runtime.

The feat!: commit prefix triggers the major version bump via semantic-release.

Test plan

  • yarn check — clean (no Biome warnings or errors)
  • yarn types:check — passes
  • yarn test:cov — 11/11 tests pass, 80% line coverage (above 75% threshold)
  • yarn build — produces dist/index.mjs (1.5 MB) with the createRequire banner verified
  • action.yml entrypoint resolves: node24 + dist/index.mjs
  • Lefthook installed: commit-msg (commitlint) + pre-commit (check:fix:staged + types:check) hooks present in .git/hooks/
  • Reference pattern verified: npm-dependency-stats-action@v3 branch contains exactly dist/index.mjs + action.yml with node24 + dist/index.mjs — same shape this PR's release will produce on the v2 branch
  • After merge: confirm the release workflow runs, semantic-release publishes v2.0.0, and the v2 branch contains the rebuilt dist/index.mjs
  • After merge: spot-check a consumer repo that uses @v1 to confirm it's unaffected

🤖 Generated with Claude Code

hershmire and others added 2 commits May 21, 2026 09:34
Brings the action in line with the org's modern toolchain template
(mirroring reside-eng/npm-dependency-stats-action#1655):

- Replace ESLint 8 + Prettier 3 + Husky + lint-staged + @side/eslint-config-*
  + @side/prettier-config with @biomejs/biome 2.4.15 + lefthook 2.1.8.
- Replace @vercel/ncc with esbuild 0.28.0 — bundle output is now
  dist/index.mjs (ESM) with a createRequire banner for CommonJS deps.
- Add Vitest 4.1.7 + @vitest/coverage-v8 plus smoke tests for action.ts
  and github.ts (80% line coverage, gate set at 75%).
- Bump Node engine ^24.0.0, @tsconfig/node24, @types/node@^24,
  TypeScript ^6.0.3 (required by @tsconfig/node24's lib values).
- action.yml: runs.using node20 -> node24, main dist/index.js -> dist/index.mjs.
- Bump cycjimmy/semantic-release-action v2.7.0 -> v6.0.0 and
  semantic_version ^18 -> ^25 in the release workflow.
- gitignore dist/ on main (release workflow continues to force-commit the
  rebuilt bundle to the v<major> branch, matching the reference template).
- Add Claude Code scaffolding: AGENTS.md, CLAUDE.md stub,
  .claude/{agents,commands}/.gitkeep, .claude/settings.json permissions,
  .vscode/extensions.json, .github/workflows/claude-code.yml.

BREAKING CHANGE: action.yml now uses node24 runtime and dist/index.mjs
entrypoint. Consumers must pin to @v2 (the new major branch produced by
semantic-release). Existing @v1 consumers are unaffected.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Drops three sections that don't change agent behaviour at execution time:

- Release: version pins and trigger branches aren't load-bearing for dev
  work; the dist/ ownership rule (the one piece that mattered) is now
  folded into Conventions.
- Atlassian: already declared in ~/.claude/CLAUDE.md and the parent
  Side/CLAUDE.md; no Atlassian touchpoints in this repo anyway.
- Side org context: already declared in the parent Side/CLAUDE.md.

Adds the non-obvious things an agent would otherwise rediscover:

- The two action modes (upsert vs create-only) and the parent-selector
  behaviour.
- A pointer to the reorderTableRows quirk in src/action.ts.
- The module-load side effect in src/github.ts (why tests mock
  @actions/core before importing it).
- The feat!: / BREAKING CHANGE: rule for triggering major bumps.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Comment thread dist/index.js
The pre-migration verify.yml and release.yml had a commented-out
Coveralls upload step waiting for tests to exist. Now that we have 11
tests at 80% line coverage, wire it up:

- vitest.config.ts: add 'lcov' to coverage.reporter so coverage/lcov.info
  is produced (Coveralls default input path). Keeps 'text' for local CLI
  output.
- verify.yml + release.yml: add Coveralls upload step
  (coverallsapp/github-action@v2.3.6, SHA-pinned) immediately after the
  test step.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@hershmire hershmire marked this pull request as ready for review May 21, 2026 15:55
@hershmire hershmire requested a review from mathieudi May 21, 2026 15:56
@hershmire hershmire merged commit a4e477c into main May 21, 2026
2 checks passed
@hershmire hershmire deleted the eddie/strange-darwin-577c5e branch May 21, 2026 16:06
@github-actions

Copy link
Copy Markdown

🎉 This PR is included in version 2.0.0 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants