Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 73 additions & 0 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
name: Publish package

# Publishes a workspace package to npm when a matching tag is pushed.
#
# Tag conventions (also documented in docs/releasing.md):
# - docs-invariants-v<X.Y.Z> → publishes @dash0hq/docs-invariants
#
# Prerequisites:
# - `DASH0_NPMJS_PUBLISH_TOKEN` repository secret, an npm automation token with publish access on
# the @dash0hq scope.
# - The corresponding package must have `"private": false` and a `publishConfig` block.

on:
push:
tags:
- "docs-invariants-v[0-9]+.[0-9]+.[0-9]+"
- "docs-invariants-v[0-9]+.[0-9]+.[0-9]+-*"

jobs:
publish-docs-invariants:
if: startsWith(github.ref_name, 'docs-invariants-v')
runs-on: ubuntu-latest
timeout-minutes: 10

# `id-token: write` is required for npm provenance attestations, which prove the package was
# built from this repository at this commit. `contents: read` is the default; explicit here so
# the whole permission set stays visible.
permissions:
contents: read
id-token: write

steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false

- name: Install Node.js
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version-file: .nvmrc
registry-url: https://registry.npmjs.org

- name: Install pnpm
uses: pnpm/action-setup@8912a9102ac27614460f54aedde9e1e7f9aec20d # v6.0.5

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

- name: Verify tag matches package version
env:
TAG: ${{ github.ref_name }}
run: |
# Strip the `docs-invariants-v` prefix from the tag to derive the expected version.
expected="${TAG#docs-invariants-v}"
actual=$(node -p "require('./packages/docs-invariants/package.json').version")
if [ "$expected" != "$actual" ]; then
echo "Tag version ($expected) does not match package.json version ($actual). Aborting." >&2
exit 1
fi
echo "Tag version matches package.json ($actual)."

- name: Typecheck all packages
run: pnpm run typecheck

- name: Test all packages
run: pnpm run test

- name: Publish @dash0hq/docs-invariants to npm
env:
NODE_AUTH_TOKEN: ${{ secrets.DASH0_NPMJS_PUBLISH_TOKEN }}
NPM_CONFIG_PROVENANCE: "true"
run: pnpm --filter @dash0hq/docs-invariants publish --access public --no-git-checks
31 changes: 22 additions & 9 deletions docs/releasing.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,21 +29,34 @@ Semver rules for `action.yml`:
### 2. `@dash0hq/docs-invariants`

**Consumed by** `dash0-website`'s own CI via npm.
Not published in the initial scaffold; the process below applies once the package is unmasked (`"private": false`).

**Versioning.** Semver on the `version` field in `packages/docs-invariants/package.json`.
Package tags are namespaced (`docs-invariants-v<X.Y.Z>`) so they don't collide with the composite action's tags on the same repo.

**When to publish.** Whenever the CLI or programmatic API surface stabilises to the point that downstream can rely on it, and whenever a bug fix or behaviour change wants to reach consumers.
**When to publish.** Whenever the API surface stabilises to the point that downstream can rely on it, and whenever a bug fix or behaviour change wants to reach consumers.

**How to publish** (once the workflow lands):
**How to publish** (once the tag lands):

1. Bump `version` in `packages/docs-invariants/package.json` on `main`.
2. Push a tag `docs-invariants-v<X.Y.Z>` (namespaced so it doesn't collide with the composite action's tags).
3. CI runs `pnpm publish --filter @dash0hq/docs-invariants` from the tagged commit, authenticated via the `DASH0_NPMJS_PUBLISH_TOKEN` repository secret.
4. Update `dash0-website`'s dependency to the new version (separate PR in that repo).
1. Bump `version` in `packages/docs-invariants/package.json` on `main` via a normal PR.
The publish workflow refuses to publish if the tag version does not match the package.json version.
2. After merge, tag from `main`:
```bash
git tag -a docs-invariants-v<X.Y.Z> -m "Release @dash0hq/docs-invariants v<X.Y.Z>"
git push origin docs-invariants-v<X.Y.Z>
```
3. `.github/workflows/publish.yml` fires on the tag push.
It reinstalls, verifies the version match, runs typecheck + tests, then `pnpm --filter @dash0hq/docs-invariants publish --access public --no-git-checks` with npm provenance enabled.
4. Update `dash0-website`'s dependency to the new version in a separate PR in that repo.

The `DASH0_NPMJS_PUBLISH_TOKEN` secret is an org-scoped npm automation token; it must be present on this repository before the first release workflow run.
Rotate it whenever a maintainer with access to the token leaves the org.
**Prerequisites** the publish workflow expects on this repository:

- **`DASH0_NPMJS_PUBLISH_TOKEN`** repository secret — an npm automation token with publish access on the `@dash0hq` scope.
Rotate it whenever a maintainer with access to the token leaves the org.
- The npm `@dash0hq` scope must exist and grant the token publish permission.
- The workflow uses `id-token: write` to attach provenance attestations, so npm can verify the tarball was built from this exact commit.

**Pre-release tags** (e.g. `docs-invariants-v0.1.0-alpha.1`) are supported: the workflow's tag pattern matches both plain semver and pre-release suffixes.
Use pre-release tags to iterate before cutting a stable release.

## CHANGELOG

Expand Down
1 change: 1 addition & 0 deletions packages/docs-invariants/LICENSE
26 changes: 24 additions & 2 deletions packages/docs-invariants/package.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,32 @@
{
"name": "@dash0hq/docs-invariants",
"version": "0.0.0",
"private": true,
"version": "0.0.1",
"type": "module",
"description": "Invariants library for dash0-website's docs tree: redirect uniqueness, dangling-URL detection, deletion-without-redirect check. Consumed by both dash0hq/sync-docs-action and dash0hq/dash0-website.",
"license": "Apache-2.0",
"repository": {
"type": "git",
"url": "https://github.com/dash0hq/sync-docs-action.git",
"directory": "packages/docs-invariants"
},
"homepage": "https://github.com/dash0hq/sync-docs-action/tree/main/packages/docs-invariants",
"bugs": {
"url": "https://github.com/dash0hq/sync-docs-action/issues"
},
"publishConfig": {
"access": "public",
"provenance": true
},
"files": [
"src/**/*.ts",
"!src/**/*.test.ts",
"README.md",
"LICENSE"
],
"main": "src/index.ts",
"exports": {
".": "./src/index.ts"
},
"engines": {
"node": ">=24.0.0"
},
Expand Down