Split release into per-track packages

Each shippable artifact (prb, probod server group, probod-bootstrap,
@probo/n8n-nodes-probo, @probo/cookie-banner) now has its own version
file, its own CHANGELOG.md, its own annotated-tag scheme of the form
<track>/v<version>, and its own GitHub Actions release workflow. The
unified release.yaml is removed; the unified CHANGELOG.md becomes a
short index pointing at each per-track file, with the prior history
preserved in CHANGELOG.archive.md.

Probod's CHANGELOG carries the post-split monorepo releases (0.174.0
through 0.181.0) so the server-group history stays continuous and the
probod docker image keeps its existing version line.

contrib/claude/release.md is split into contrib/claude/release/ with
one entrypoint per track plus a README that drives the agent: detect
which tracks have user-facing commits since their last tag and skip
tracks with no relevant changes, so a release request never tags an
unchanged track. The cookie-banner and n8n-node entrypoints add an
explicit npm run build step after the version bump (build.mjs bakes
package.json's version into __SDK_VERSION__) so compile errors and
package-lock.json updates are caught before tagging.

Signed-off-by: Bryan Frimin <bryan@getprobo.com>
This commit is contained in:
Bryan Frimin
2026-05-05 16:03:46 +02:00
parent 5e55c888c4
commit ac526fb54d
25 changed files with 4599 additions and 3957 deletions

View File

@@ -1,149 +0,0 @@
# Release
This guide describes how to cut a new release. The outcome is a single
commit on `main` plus a Git tag; CI handles everything else (binaries,
Docker images, npm packages, signatures).
## Steps
### 1. Pull the latest main
Ensure you are on `main` and have the latest changes before starting:
```shell
git checkout main && git pull origin main
```
### 2. List changes since the last release
Find the latest tag and review every commit since then:
```shell
git log $(git describe --tags --abbrev=0)..HEAD --oneline
```
### 3. Write the changelog entry
Create a new version section in `CHANGELOG.md` from those commits.
Keep the empty `## Unreleased` heading above it.
**Categorize** entries under Keep-a-Changelog sections:
| Section | Use for |
|---------------|------------------------------------------------|
| `### Added` | New features, new commands, new endpoints |
| `### Changed` | Behavioral changes, refactors visible to users |
| `### Fixed` | Bug fixes |
| `### Removed` | Removed features or deprecated code |
**Skip** commits that are not user-facing:
- Style / formatting (`Style`, `Run go fmt/fix`)
- CI-only changes (`Add reviewdog`, `Cache Go modules`)
- Internal refactors (`Move X to contrib/claude`, `Remove deadcode`)
- Documentation-only changes
- Release commits (`Release v…`)
**Only list fixes for pre-existing bugs.** If a "fix" commit repairs something
introduced by another commit in the same release cycle, do NOT list it as a
separate fix. To verify, check whether the affected file or feature existed
at the previous tag:
```shell
git ls-tree <previous-tag> -- path/to/file
```
If the file did not exist at the previous tag, the fix is part of the new
feature and should not appear in `### Fixed`.
**Escape underscores** — wrap identifiers containing underscores in
backticks (e.g., `` `probo_consent` ``) so they are not rendered as
italic in Markdown.
**Summarize** related commits into a single line when appropriate.
For example a series of `Add proboctl X commands` commits becomes
`Add CLI`.
Format: `## [X.Y.Z] - YYYY-MM-DD` (today's date).
Example result:
```markdown
## Unreleased
## [0.144.0] - 2026-03-17
### Added
- Add document viewer with 404 handling for trust center
## [0.143.0] - 2026-03-16
```
### 4. Decide the version bump
The project is in the **0.x** series. Never bump MAJOR.
- Bug fixes only → bump **PATCH**
- New features or non-breaking changes → bump **MINOR**
### 5. Bump version in `GNUmakefile`
Update the `VERSION` variable at the top of `GNUmakefile`:
```makefile
VERSION= 0.144.0
```
### 6. Review with the user
Before committing, show the user the full `CHANGELOG.md` entry and
the new `VERSION` value. Ask them to confirm everything looks good.
Only proceed once they approve.
### 7. Create the release commit
Stage only `CHANGELOG.md` and `GNUmakefile`. The commit message
**must** follow this exact format:
```
Release v<VERSION>
```
No body is needed.
### 8. Create the tag
Tag the release commit with an **annotated** tag. The tag **must**
match `v<VERSION>`:
```shell
git tag -a v<VERSION> -m "v<VERSION>"
```
### 9. Push
Push both the commit and the tag:
```shell
git push origin main --follow-tags
```
CI (`.github/workflows/release.yaml`) triggers on `v*` tags and takes
care of:
- Building binaries via GoReleaser (probod, probod-bootstrap, prb)
- Publishing multi-arch Docker images to `ghcr.io/getprobo/probo`
- Publishing the npm package `@probo/n8n-nodes-probo`
- Generating SBOMs, attestations, and Cosign signatures
## Checklist
1. [ ] Pulled latest `main`
2. [ ] Reviewed commits since last tag
3. [ ] `CHANGELOG.md` — new version section with categorized entries
4. [ ] `GNUmakefile` — `VERSION` bumped
5. [ ] User confirmed changelog and version look good
6. [ ] Commit message is `Release v<VERSION>`
7. [ ] Annotated tag `v<VERSION>` on the release commit
8. [ ] Push commit and tag

View File

@@ -0,0 +1,127 @@
# Release
The repository ships five independently-versioned tracks. Each has its own
version source, its own `CHANGELOG.md`, its own tag pattern, and its own
release workflow. Cutting a release means: bump the version, write a
changelog entry, commit, tag, push.
| Track | Tag pattern | Entrypoint |
| ----------------------- | ------------------------------ | -------------------------------- |
| CLI (`prb`) | `prb/v*` | [prb.md](./prb.md) |
| Server (`probod` group) | `probod/v*` | [probod.md](./probod.md) |
| `probod-bootstrap` | `probod-bootstrap/v*` | [probod-bootstrap.md](./probod-bootstrap.md) |
| `@probo/n8n-nodes-probo` | `@probo/n8n-nodes-probo/v*` | [n8n-nodes-probo.md](./n8n-nodes-probo.md) |
| `@probo/cookie-banner` | `@probo/cookie-banner/v*` | [cookie-banner.md](./cookie-banner.md) |
When the user asks for a release **without specifying a track**, follow
[Step 1](#1-decide-which-tracks-to-release) below to detect which tracks
have user-facing changes since their last tag, then ask the user which of
those tracks to release. **Only release tracks that actually have
user-facing changes.** Never release a track that has no commits since its
last tag.
When the user asks for a release **for a specific track** (e.g. "release
the CLI", "release probod"), open the corresponding entrypoint above and
follow it.
Versions are SemVer in the **0.x** series. Never bump MAJOR.
Bug fixes only -> bump PATCH; new features or non-breaking changes -> bump
MINOR.
## 1. Decide which tracks to release
Before any release, identify which tracks have user-facing commits since
their last tag. A track with zero commits, or only non-user-facing
commits (style, CI, internal refactors, doc-only, release commits) must
**not** be released.
Run this from a clean `main`:
```shell
git checkout main && git pull origin main
```
Then for each track, list commits since its last tag, scoped to that
track's paths:
```shell
# prb
git log $(git describe --tags --abbrev=0 --match='prb/v*')..HEAD --oneline \
-- cmd/prb pkg/cli pkg/cmd
# probod (server group: probod + console + trust + ui)
git log $(git describe --tags --abbrev=0 --match='probod/v*')..HEAD --oneline \
-- cmd/probod apps/console apps/trust packages/ui pkg
# probod-bootstrap
git log $(git describe --tags --abbrev=0 --match='probod-bootstrap/v*')..HEAD --oneline \
-- cmd/probod-bootstrap
# @probo/n8n-nodes-probo
git log $(git describe --tags --abbrev=0 --match='@probo/n8n-nodes-probo/v*')..HEAD --oneline \
-- packages/n8n-node
# @probo/cookie-banner
git log $(git describe --tags --abbrev=0 --match='@probo/cookie-banner/v*')..HEAD --oneline \
-- packages/cookie-banner
```
If a track returns no commits, skip it. If all commits for a track are
non-user-facing, skip it (and tell the user). For each remaining track,
proceed with its entrypoint.
## 2. Writing a changelog entry
Categorize entries under Keep-a-Changelog sections in the relevant track's
`CHANGELOG.md`:
| Section | Use for |
| ------------- | ---------------------------------------------- |
| `### Added` | New features, new commands, new endpoints |
| `### Changed` | Behavioral changes, refactors visible to users |
| `### Fixed` | Bug fixes |
| `### Removed` | Removed features or deprecated code |
**Skip** non-user-facing commits (style/formatting, CI-only, internal
refactors, doc-only, release commits).
**Only list fixes for pre-existing bugs.** If a "fix" commit repairs
something introduced earlier in the same release cycle, do NOT list it as
a separate fix.
**Summarize** related commits into a single line when appropriate.
Format: `## [X.Y.Z] - YYYY-MM-DD` (today's date). Always keep an
`## Unreleased` heading above the latest version.
## 3. Common steps (every track)
After choosing the track and reviewing its commits:
1. Bump the version in the track's source of truth (see the per-track
entrypoint).
2. Write the changelog entry in the track's `CHANGELOG.md`.
3. For npm tracks, run the workspace `build` script after the version
bump (see the per-track entrypoint for why).
4. Show the user the proposed `CHANGELOG.md` diff and the new version.
Wait for confirmation.
5. Commit only the files modified by the version bump and changelog
edit. Subject: `Release <pkg>/v<version>`. No body.
6. Annotated tag: `git tag -a <pkg>/v<version> -m "<pkg>/v<version>"`.
7. Push: `git push origin main --follow-tags`.
CI handles the rest: binary builds, npm publish, Docker image, Homebrew
formula, SBOMs, attestations, GitHub Release.
## Checklist (every track)
1. [ ] Pulled latest `main`
2. [ ] Confirmed the track has user-facing commits since its last tag
3. [ ] Reviewed track-specific commits
4. [ ] Track CHANGELOG entry written, categorized, summarized
5. [ ] Version bumped in the track's source of truth
6. [ ] (npm tracks) Workspace `build` script run successfully after bump
7. [ ] User confirmed changelog and version
8. [ ] Commit message is `Release <pkg>/v<version>`
9. [ ] Annotated tag `<pkg>/v<version>` on the release commit
10. [ ] Pushed commit and tag

View File

@@ -0,0 +1,73 @@
# Release `@probo/cookie-banner`
Entrypoint for releasing the cookie banner SDK. Read
[README.md](./README.md) first for overall flow, changelog rules, and the
non-empty-track guarantee.
## Track facts
- **Tag pattern**: `@probo/cookie-banner/v*`
- **Version source**: `packages/cookie-banner/package.json`
- **Changelog**: `packages/cookie-banner/CHANGELOG.md`
- **Workflow**: `.github/workflows/release-npm-cookie-banner.yaml`
- **Path filter** (for log/scoping): `packages/cookie-banner`
## Important: build script bakes the version
`packages/cookie-banner/build.mjs` reads `version` from `package.json`
and exposes it to the bundle as the `__SDK_VERSION__` define. The SDK
uses this value at runtime (e.g. when calling the Probo REST API), so
the build **must** run after the version bump to make sure the new
version is what gets published. The release CI workflow does run the
build, but we still run it locally as part of the release commit so:
- compile errors are caught before tagging,
- any tracked side-effects (`package-lock.json`, etc.) are part of the
same `Release @probo/cookie-banner/v<version>` commit.
## Steps
1. From a clean `main`, list commits since the last
`@probo/cookie-banner` tag:
```shell
git log $(git describe --tags --abbrev=0 --match='@probo/cookie-banner/v*')..HEAD --oneline \
-- packages/cookie-banner
```
If the list is empty (or contains only non-user-facing commits), do
not release this track.
2. Decide the version bump (PATCH for fixes, MINOR for features).
3. Bump the version using npm so `package.json` and `package-lock.json`
stay consistent:
```shell
npm --workspace @probo/cookie-banner version <X.Y.Z> --no-git-tag-version
```
4. Run the workspace build so `__SDK_VERSION__` is rebuilt from the new
`package.json` and any compile error surfaces before we tag:
```shell
npm --workspace @probo/cookie-banner run build
```
`dist/` is gitignored, so this step does not produce checked-in build
artifacts — but it must succeed for the release to be valid.
5. Write the new entry in `packages/cookie-banner/CHANGELOG.md` following
the rules in [README.md](./README.md#2-writing-a-changelog-entry).
6. Show the user the changelog diff and the new version. Wait for
confirmation.
7. Stage the files modified by the version bump and changelog edit
(typically `packages/cookie-banner/package.json`,
`packages/cookie-banner/CHANGELOG.md`, and `package-lock.json`).
Commit subject: `Release @probo/cookie-banner/v<version>`. No body.
8. Annotated tag:
`git tag -a @probo/cookie-banner/v<version> -m "@probo/cookie-banner/v<version>"`.
9. Push: `git push origin main --follow-tags`.
CI workflow `release-npm-cookie-banner.yaml` verifies the tag matches
`package.json`, runs the build again, publishes to npm with provenance +
SBOM, and creates a GitHub Release.

View File

@@ -0,0 +1,58 @@
# Release `@probo/n8n-nodes-probo`
Entrypoint for releasing the n8n nodes package. Read
[README.md](./README.md) first for overall flow, changelog rules, and the
non-empty-track guarantee.
## Track facts
- **Tag pattern**: `@probo/n8n-nodes-probo/v*` (the `@` and `/` are valid
in Git tag refs)
- **Version source**: `packages/n8n-node/package.json`
- **Changelog**: `packages/n8n-node/CHANGELOG.md`
- **Workflow**: `.github/workflows/release-npm-n8n-node.yaml`
- **Path filter** (for log/scoping): `packages/n8n-node`
## Steps
1. From a clean `main`, list commits since the last
`@probo/n8n-nodes-probo` tag:
```shell
git log $(git describe --tags --abbrev=0 --match='@probo/n8n-nodes-probo/v*')..HEAD --oneline \
-- packages/n8n-node
```
If the list is empty (or contains only non-user-facing commits), do
not release this track.
2. Decide the version bump (PATCH for fixes, MINOR for features).
3. Bump the version using npm so `package.json` and `package-lock.json`
stay consistent:
```shell
npm --workspace @probo/n8n-nodes-probo version <X.Y.Z> --no-git-tag-version
```
4. Run the workspace build to confirm it succeeds with the new version
(and to surface any compile errors before we tag):
```shell
npm --workspace @probo/n8n-nodes-probo run build
```
5. Write the new entry in `packages/n8n-node/CHANGELOG.md` following the
rules in [README.md](./README.md#2-writing-a-changelog-entry).
6. Show the user the changelog diff and the new version. Wait for
confirmation.
7. Stage the files modified by the version bump and changelog edit
(typically `packages/n8n-node/package.json`,
`packages/n8n-node/CHANGELOG.md`, and `package-lock.json`). Commit
subject: `Release @probo/n8n-nodes-probo/v<version>`. No body.
8. Annotated tag:
`git tag -a @probo/n8n-nodes-probo/v<version> -m "@probo/n8n-nodes-probo/v<version>"`.
9. Push: `git push origin main --follow-tags`.
CI workflow `release-npm-n8n-node.yaml` verifies the tag matches
`package.json`, publishes to npm with provenance + SBOM, and creates a
GitHub Release.

View File

@@ -0,0 +1,42 @@
# Release `prb` (CLI)
Entrypoint for releasing the `prb` CLI. Read [README.md](./README.md)
first for overall flow, changelog rules, and the
non-empty-track guarantee.
## Track facts
- **Tag pattern**: `prb/v*`
- **Version source**: `cmd/prb/VERSION` (contains only `X.Y.Z`)
- **Changelog**: `cmd/prb/CHANGELOG.md`
- **Workflow**: `.github/workflows/release-prb.yaml`
- **Path filter** (for log/scoping): `cmd/prb pkg/cli pkg/cmd`
## Steps
1. From a clean `main`, list commits since the last `prb` tag:
```shell
git log $(git describe --tags --abbrev=0 --match='prb/v*')..HEAD --oneline \
-- cmd/prb pkg/cli pkg/cmd
```
If the list is empty (or contains only non-user-facing commits), do
not release this track.
2. Decide the version bump (PATCH for fixes, MINOR for features).
3. Bump the version in `cmd/prb/VERSION` (the file contains a single
`X.Y.Z` line — no trailing newline conventions beyond what is already
there).
4. Write the new entry in `cmd/prb/CHANGELOG.md` following the rules in
[README.md](./README.md#2-writing-a-changelog-entry).
5. Show the user the changelog diff and the new version. Wait for
confirmation.
6. Stage only `cmd/prb/VERSION` and `cmd/prb/CHANGELOG.md`. Commit
subject: `Release prb/v<version>`. No body.
7. Annotated tag: `git tag -a prb/v<version> -m "prb/v<version>"`.
8. Push: `git push origin main --follow-tags`.
CI workflow `release-prb.yaml` builds binaries for 9 OS/arch targets,
publishes a GitHub Release, and updates the Homebrew formula at
`getprobo/homebrew-tap`.

View File

@@ -0,0 +1,44 @@
# Release `probod-bootstrap`
Entrypoint for releasing `probod-bootstrap`. Read [README.md](./README.md)
first for overall flow, changelog rules, and the non-empty-track
guarantee.
## Track facts
- **Tag pattern**: `probod-bootstrap/v*`
- **Version source**: `cmd/probod-bootstrap/VERSION` (contains only `X.Y.Z`)
- **Changelog**: `cmd/probod-bootstrap/CHANGELOG.md`
- **Workflow**: `.github/workflows/release-probod-bootstrap.yaml`
- **Path filter** (for log/scoping): `cmd/probod-bootstrap`
## Steps
1. From a clean `main`, list commits since the last `probod-bootstrap`
tag:
```shell
git log $(git describe --tags --abbrev=0 --match='probod-bootstrap/v*')..HEAD --oneline \
-- cmd/probod-bootstrap
```
If the list is empty (or contains only non-user-facing commits), do
not release this track.
2. Decide the version bump (PATCH for fixes, MINOR for features).
3. Bump the version in `cmd/probod-bootstrap/VERSION`.
4. Write the new entry in `cmd/probod-bootstrap/CHANGELOG.md` following
the rules in [README.md](./README.md#2-writing-a-changelog-entry).
5. Show the user the changelog diff and the new version. Wait for
confirmation.
6. Stage only `cmd/probod-bootstrap/VERSION` and
`cmd/probod-bootstrap/CHANGELOG.md`. Commit subject:
`Release probod-bootstrap/v<version>`. No body.
7. Annotated tag:
`git tag -a probod-bootstrap/v<version> -m "probod-bootstrap/v<version>"`.
8. Push: `git push origin main --follow-tags`.
CI workflow `release-probod-bootstrap.yaml` builds binaries for 9 OS/arch
targets and publishes a GitHub Release. Note: the same binary, built
from the tagged ref, is also bundled into the probod Docker image when
`probod/v*` runs.

View File

@@ -0,0 +1,48 @@
# Release `probod` (server group)
Entrypoint for releasing the `probod` server group. Read
[README.md](./README.md) first for overall flow, changelog rules, and the
non-empty-track guarantee.
This track ships `probod`, `@probo/console`, `@probo/trust`, and
`@probo/ui` together as the Docker image and accompanying binary archive.
They share the same version.
## Track facts
- **Tag pattern**: `probod/v*`
- **Version source**: `cmd/probod/VERSION` (contains only `X.Y.Z`)
- **Changelog**: `cmd/probod/CHANGELOG.md` (covers all four components)
- **Workflow**: `.github/workflows/release-probod.yaml`
- **Path filter** (for log/scoping):
`cmd/probod apps/console apps/trust packages/ui pkg`
## Steps
1. From a clean `main`, list commits since the last `probod` tag:
```shell
git log $(git describe --tags --abbrev=0 --match='probod/v*')..HEAD --oneline \
-- cmd/probod apps/console apps/trust packages/ui pkg
```
If the list is empty (or contains only non-user-facing commits), do
not release this track.
2. Decide the version bump (PATCH for fixes, MINOR for features).
3. Bump the version in `cmd/probod/VERSION`.
4. Write the new entry in `cmd/probod/CHANGELOG.md` covering changes
across `probod`, `@probo/console`, `@probo/trust`, and `@probo/ui`.
Follow the rules in
[README.md](./README.md#2-writing-a-changelog-entry).
5. Show the user the changelog diff and the new version. Wait for
confirmation.
6. Stage only `cmd/probod/VERSION` and `cmd/probod/CHANGELOG.md`.
Commit subject: `Release probod/v<version>`. No body.
7. Annotated tag: `git tag -a probod/v<version> -m "probod/v<version>"`.
8. Push: `git push origin main --follow-tags`.
CI workflow `release-probod.yaml` builds the frontends, builds the Go
binaries, builds and pushes the multi-arch image to
`ghcr.io/getprobo/probo:probod-v<version>` (and `:latest`), runs Trivy +
cosign + attestations, and publishes the GitHub Release.