Skip to content

Release Process ​

@franksauvag/rpg-commons uses semantic-release to automate versioning, tagging, changelog generation, and publishing to GitHub Packages.


How it works ​

Every push to main triggers the Release workflow. If the CI gate passes (lint, typecheck, test, build), semantic-release analyzes commits since the last release and decides whether a new version is warranted.

push to main
     │
     ▼
┌─────────────────────────────────┐
│ CI gate                         │
│  lint → typecheck → test → build│
└────────────────┬────────────────┘
                 │ passes
                 ▼
┌─────────────────────────────────┐
│ semantic-release                │
│  analyze commits                │
│  → bump version (X.Y.Z)         │
│  → update CHANGELOG.md          │
│  → commit + tag vX.Y.Z          │
│  → GitHub Release               │
│  → pnpm publish → npm.pkg.github│
└─────────────────────────────────┘

If no commit since the last release is "releasable" (e.g. only chore: or docs:), semantic-release does nothing — no new version is published.


Conventional Commits ​

All commits must follow the Conventional Commits specification. This is what drives automatic versioning.

Format ​

<type>(<scope>): <description>

[optional body]

[optional footer(s)]

Version bump rules ​

Commit typeExampleVersion bump
fix:fix(media): handle null apiBaseUrlPatch 0.0.X
perf:perf(srd): cache bundle responsesPatch 0.0.X
feat:feat(srd): add buildSpellsBundleMinor 0.X.0
feat!: or BREAKING CHANGE:feat!: rename SrdClient.fetchMajor X.0.0
chore:, docs:, refactor:, style:, test:, build:, ci:—No release

Breaking change syntax ​

feat: rename createSrdClient config key

BREAKING CHANGE: `baseUrl` is now `apiBaseUrl` — update all call sites.

Or using the shorthand !:

feat!: rename createSrdClient config key

Examples ​

# Patch release (0.0.X)
fix(srd): prevent infinite retry on 401 responses
perf(components): memoize SelectionCard render

# Minor release (0.X.0)
feat(ui): add TooltipButton component
feat(srd): expose fetchDataset in SrdClient public API

# Major release (X.0.0)
feat!: drop support for React 18 — require React 19+

feat(srd): remove resolveEntryMediaSrc

BREAKING CHANGE: resolveEntryMediaSrc has been removed.
Use resolveSrdMediaUrl directly.

# No release (chore/docs/refactor)
chore: update pnpm to 10.12.1
docs(srd): add fetchDataset example to srd-data-api.md
refactor(normalizers): extract costToGp helper
test(srd): add missing edge cases for toSpellsBundle

Two publication channels ​

ChannelTrigger (on main)ArtifactAudience
npm packagerelease job after ci@franksauvag/rpg-commons@X.Y.Z on GitHub PackagesConsumer apps
Documentation sitedeploy-docs after ci + docsHTML at libs.heritiersdudonjon.comHumans + agents (browser)

A docs: commit can update the site without a new npm version. A feat: triggers a minor npm release when merged to main; the doc site redeploys on every green main build regardless.


CI jobs ​

JobRuns onRole
ciPR + mainlint, typecheck, test, pnpm build (library)
releasemain onlysemantic-release → npm, tag, CHANGELOG
docsPR + mainpnpm docs:build (VitePress + TypeDoc + Storybook)
deploy-docsmain onlyFTP deploy to OVH /www-libs/
push to main
     ├─► ci ──┬─► release ──► npm publish
     │        └─► docs ──► deploy-docs ──► libs.heritiersdudonjon.com

pull request
     ├─► ci
     └─► docs (no deploy)

Two-phase rule (library → consumers) ​

  1. Merge to rpg-commons main and wait for npm publish + git tag.
  2. Only then open/update consumer PRs with the new semver.

Do not merge consumer changes that depend on unpublished exports. Avoid long-lived file:../, pnpm link, or npm pack for shared CI.


Pipeline files ​

FileRole
.github/workflows/ci.ymlCI, release, docs, deploy-docs
.releaserc.jsonsemantic-release plugins
CHANGELOG.mdAuto-generated — do not edit manually
typedoc.jsonAPI reference generation
scripts/build-docs.mjsFull doc site build

Release bot commits use chore(release): X.Y.Z [skip ci] — the next normal push re-runs all jobs.

See also Documentation pipeline.


First release — bootstrapping ​

The current package.json version (0.0.1) is the starting point. semantic-release will set the initial published version based on commits. To ensure it publishes v0.1.0 on the first run, push at least one feat: commit.

If the repo has no previous tags, semantic-release treats all commits as new and will publish v1.0.0 for a feat: or v0.1.0 if configured with "firstRelease". The default behavior uses v1.0.0 as the first release for feat:. To start at v0.1.0, add a lightweight tag v0.0.0 before the first pipeline run:

bash
git tag v0.0.0
git push origin v0.0.0

This anchors semantic-release's history so the next feat: commit produces v0.1.0.


Consuming the package ​

Local development ​

Prefer a user-level ~/.npmrc with your PAT (do not commit tokens to the consumer repo):

ini
@franksauvag:registry=https://npm.pkg.github.com
//npm.pkg.github.com/:_authToken=YOUR_GITHUB_PAT

Then install as usual (pnpm add, npm install, etc.).

Optionally commit a project .npmrc that contains only the @franksauvag:registry=… line so the scope is explicit for everyone; tokens stay in ~/.npmrc or CI.

CI (GitHub Actions) ​

For a consumer repo's CI pipeline, add a PAT with read:packages scope as a repository secret (e.g. PACKAGES_READ_TOKEN), then configure setup-node and install:

yaml
- uses: actions/setup-node@v5
  with:
    node-version: 22
    registry-url: https://npm.pkg.github.com
    scope: "@franksauvag"
  env:
    NODE_AUTH_TOKEN: ${{ secrets.PACKAGES_READ_TOKEN }}

- name: Install
  run: pnpm install --frozen-lockfile

Note: The built-in GITHUB_TOKEN of a consumer repo can only access packages published by that same repo. A PAT is required to read packages from rpg-commons.


Emergency manual release ​

If semantic-release is blocked or you need to release from a local machine:

bash
# Ensure clean working tree on main
git checkout main && git pull

# Dry-run to preview what would be released
GITHUB_TOKEN=$(gh auth token) NODE_AUTH_TOKEN=$(gh auth token) pnpm exec semantic-release --dry-run

# Actual release
GITHUB_TOKEN=$(gh auth token) NODE_AUTH_TOKEN=$(gh auth token) pnpm exec semantic-release