From c9bb0a1439ec4d401a1ede7266a432a4af703a37 Mon Sep 17 00:00:00 2001 From: Kevin Boshold Date: Fri, 31 Jul 2026 08:48:16 +0200 Subject: [PATCH 1/2] docs(release): unpark the release workflow and record the backfilled tag The workflow was still named "draft, parked, not enabled" and its header said it cannot publish until someone wires the secrets. Both are false now: 0.1.0 is on the registry and the provenance flow is wired. A maintainer reading either would conclude releasing is not possible. Also records two things the next releaser would otherwise hit. The generated release notes diff against the previous tag, and 0.1.0 was published outside this workflow so no tag existed; v0.1.0 has been backfilled onto 265809b. And the version is a workflow input, so bumping package.json by hand before dispatching produces a release commit with no version change in it. The one-time setup section is kept rather than deleted, marked as done, since it is the checklist to re-run if the org, token or environment is rebuilt. --- .github/workflows/release.yml | 11 +++++------ docs/release.md | 13 +++++++++++++ 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 06bd132..289c556 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,11 +1,10 @@ -name: Release (draft, parked, not enabled) +name: Release -# PARKED. This is a design draft for the @sidebase/streamctl publish path. It -# is workflow_dispatch only and gated behind the protected `release` -# environment, so it cannot publish until someone wires the secrets and -# dispatches it by hand. docs/release.md has the ship-time checklist. +# Live. Publishes @sidebase/streamctl to the public npm registry under the +# @sidebase scope. workflow_dispatch only and gated behind the protected +# `release` environment, so every publish is a deliberate manual dispatch that +# pauses for approval. docs/release.md has the ship-time checklist. # -# Single-package publish to the public npm registry under the @sidebase scope. # The two packages version independently, no lockstep. Publish the CLI before # the config package on a first publish: the config repo's validate-presets # consumes the schema this package exports. See docs/release.md. diff --git a/docs/release.md b/docs/release.md index 16c35d3..bd2d77e 100644 --- a/docs/release.md +++ b/docs/release.md @@ -36,6 +36,9 @@ removed) so consumer CI that parses it survives CLI upgrades. ## One-time setup +Done as of `0.1.0`. Kept as a record of what the release path depends on, and as +the checklist to re-run if the org, token or environment is ever rebuilt. + 1. **npm org / scope.** Create/claim the `@sidebase` org on npmjs.com and add the release machine account. Confirm the package name `@sidebase/streamctl` is free (or owned). `publishConfig.access` is already `public` in `package.json`. @@ -66,6 +69,16 @@ approve the environment gate. The workflow: After the run, verify the published tarball on npm, the `vX.Y.Z` tag, and the generated GitHub Release notes. +Step 6 diffs against the previous tag, so every release needs its predecessor +tagged or the notes cover the whole history. **`0.1.0` was published outside this +workflow and left no tag.** `v0.1.0` has since been backfilled onto +`265809b` (`chore: bump deps (#6)`), the last commit carrying that version, so +the next release diffs against the right point. Nothing else needs backfilling. + +The version is an input, not something you edit first. Do not bump +`package.json` by hand before dispatching: step 2 sets it, and a pre-bumped +working tree just means the release commit contains no version change. + ## Notes for the next release Include these in the release notes; the rest is generated from commit subjects. From 433c3506be93c275245af8d34df4c20378cacaed Mon Sep 17 00:00:00 2001 From: Kevin Boshold Date: Fri, 31 Jul 2026 08:54:15 +0200 Subject: [PATCH 2/2] docs(release): correct the setup status, it is not confirmed done 0.1.0 reached npm by a manual publish that bypassed this workflow, so its presence is not evidence the workflow can publish. The previous wording read the artifact as proof of the setup the artifact had skipped. Measured: repos/sidebase/streamctl/environments returns zero environments and the repo has no secrets, so the `release` environment does not exist. GitHub creates a referenced-but-missing environment unprotected and secretless, so an unconfigured dispatch loses its approval gate and then fails at publish on auth, before the push, leaving origin untouched. NPM_TOKEN may still exist as an org secret, which is not readable without org admin, so this records the check to run rather than asserting the token is absent. --- .github/workflows/release.yml | 11 +++++++---- docs/release.md | 22 ++++++++++++++++------ 2 files changed, 23 insertions(+), 10 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 289c556..152c745 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,9 +1,12 @@ name: Release -# Live. Publishes @sidebase/streamctl to the public npm registry under the -# @sidebase scope. workflow_dispatch only and gated behind the protected -# `release` environment, so every publish is a deliberate manual dispatch that -# pauses for approval. docs/release.md has the ship-time checklist. +# Publishes @sidebase/streamctl to the public npm registry under the @sidebase +# scope. workflow_dispatch only, and scoped to the `release` environment. +# +# That environment is only a gate once it exists and carries reviewers plus +# NPM_TOKEN. GitHub auto-creates a missing environment unprotected and +# secretless, so an unconfigured dispatch skips the approval pause and dies at +# publish on auth. docs/release.md has the setup checklist and how to check it. # # The two packages version independently, no lockstep. Publish the CLI before # the config package on a first publish: the config repo's validate-presets diff --git a/docs/release.md b/docs/release.md index bd2d77e..35bff72 100644 --- a/docs/release.md +++ b/docs/release.md @@ -1,9 +1,10 @@ # Release runbook (`@sidebase/streamctl`) -> **Status: 0.1.0 is on the registry.** The `Release` workflow -> (`.github/workflows/release.yml`) stays `workflow_dispatch`-only and gated behind -> the protected `release` environment, so every publish is a deliberate manual -> dispatch by a maintainer who has completed the one-time setup below. +> **Status: `0.1.0` is on the registry, published by hand.** The `Release` +> workflow (`.github/workflows/release.yml`) has never published, and the +> one-time setup below is not confirmed done. It stays `workflow_dispatch`-only +> and scoped to the `release` environment, so every publish is a deliberate +> manual dispatch. `streamctl` publishes to the public npm registry under the `@sidebase` scope. It is an intentionally ESM-only package; the published tarball ships only `dist/`. @@ -36,8 +37,17 @@ removed) so consumer CI that parses it survives CLI upgrades. ## One-time setup -Done as of `0.1.0`. Kept as a record of what the release path depends on, and as -the checklist to re-run if the org, token or environment is ever rebuilt. +**Not verified as done.** `0.1.0` reached the registry by a manual publish that +bypassed this workflow, so its presence says nothing about whether the workflow +can publish. As of writing, `gh api repos/sidebase/streamctl/environments` +returns zero environments and `gh secret list` is empty, so at minimum step 3 is +outstanding. Step 2's token may exist as an **org** secret, which is not readable +without org admin. Confirm before the first dispatch. + +A missing environment does not fail loudly: GitHub creates one on demand with no +protection rules and no secrets, so the run loses its approval gate and reaches +the publish step with an empty `NODE_AUTH_TOKEN`. It then fails on auth, before +the push, leaving origin untouched. 1. **npm org / scope.** Create/claim the `@sidebase` org on npmjs.com and add the release machine account. Confirm the package name `@sidebase/streamctl` is free