From 7ad8e4bbdec74a5b82e5915f6fb1aef9942dfd53 Mon Sep 17 00:00:00 2001 From: jamesbeedy Date: Sun, 6 Sep 2026 21:49:00 +0000 Subject: [PATCH] fix: unbreak the npm publish, and track the theme by range in the docs Two unrelated fixes that both came out of the v0.1.8 release attempt. ## The publish job died before it published `registry-url` makes setup-node write an .npmrc containing the literal `${NODE_AUTH_TOKEN}`, and `cache: yarn` then shells out to yarn to locate the cache directory. Yarn 1 expands env vars in .npmrc eagerly and dies on an unset one, so with the token scoped to the publish step alone, setup-node itself failed: error Failed to replace env in config: ${NODE_AUTH_TOKEN} Reproduced outside CI: an .npmrc with that line makes even `yarn cache dir` fail when the variable is unset, and succeed when it is set. So the variable has to be in the environment from the moment the .npmrc exists, which means the whole job rather than one step. This did not bite before because the previous workflow was on actions/setup-node@v4, which restored the cache before writing the .npmrc. ## The docs site now follows 0.4.x rather than one exact version The site declared an exact 0.4.7, which meant a patch release reached readers only when someone remembered to bump it. It now declares `^0.4.7`: below 1.0.0 npm reads a caret as "this minor only", so patch releases arrive on their own and a 0.5.0 still needs a deliberate bump. A range in package.json is not enough on its own. `npm ci` is lockfile-exact by design, so the site would have sat on whatever version the lockfile was last regenerated against however wide the range was. Both workflows therefore run npm update --no-save @vantagecompute/docusaurus-theme after installing, which takes the newest release in range while leaving the lockfile and package.json untouched, so every other dependency stays reproducible and CI produces no diff. Verified: a clean `npm ci` followed by that update leaves `git status` clean. `just docs-pin` now writes a caret range and is only needed to cross a minor. The consumer-facing guidance in the installation page changes with it: it used to argue for an exact pin, which would have contradicted what this repository now does. Co-Authored-By: Claude Opus 5 (1M context) --- .github/workflows/ci.yml | 10 ++++++++++ .github/workflows/deploy-docs.yml | 10 ++++++++++ .github/workflows/publish.yml | 16 ++++++++++++++-- README.md | 11 ++++++----- docusaurus/docs/contributing.md | 23 ++++++++++++++--------- docusaurus/docs/index.md | 16 +++++++--------- docusaurus/docs/installation.md | 31 +++++++++++++++++++++++-------- docusaurus/docusaurus.config.ts | 10 ++++++---- docusaurus/package-lock.json | 2 +- docusaurus/package.json | 2 +- justfile | 24 ++++++++++++++---------- 11 files changed, 106 insertions(+), 49 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3767026..b8c579f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -92,6 +92,16 @@ jobs: working-directory: docusaurus run: npm ci + # `npm ci` is lockfile-exact by design, so the caret range in package.json + # alone would never pick up a newer 0.4.x: the site would sit on whatever + # version the lockfile was last regenerated against. This pulls the newest + # release matching the declared range, and `--no-save` leaves both the + # lockfile and package.json untouched, so every other dependency stays + # reproducible and CI never produces a diff. + - name: Take the newest theme release in range + working-directory: docusaurus + run: npm update --no-save @vantagecompute/docusaurus-theme + - name: Typecheck working-directory: docusaurus run: npm run typecheck diff --git a/.github/workflows/deploy-docs.yml b/.github/workflows/deploy-docs.yml index 5a9d81c..545174a 100644 --- a/.github/workflows/deploy-docs.yml +++ b/.github/workflows/deploy-docs.yml @@ -69,6 +69,16 @@ jobs: working-directory: docusaurus run: npm ci + # `npm ci` is lockfile-exact by design, so the caret range in package.json + # alone would never pick up a newer 0.4.x: the site would sit on whatever + # version the lockfile was last regenerated against. This pulls the newest + # release matching the declared range, and `--no-save` leaves both the + # lockfile and package.json untouched, so every other dependency stays + # reproducible and CI never produces a diff. + - name: Take the newest theme release in range + working-directory: docusaurus + run: npm update --no-save @vantagecompute/docusaurus-theme + - name: Typecheck working-directory: docusaurus run: npm run typecheck diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index b1c3076..d1bf83f 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -11,6 +11,20 @@ permissions: jobs: publish: runs-on: ubuntu-latest + + # Job level, not step level. `registry-url` makes setup-node write an .npmrc + # containing the literal `${NODE_AUTH_TOKEN}`, and `cache: yarn` then shells + # out to yarn to locate the cache directory. Yarn 1 expands env vars in + # .npmrc eagerly and dies on an unset one, so with the token scoped to the + # publish step alone, setup-node itself failed: + # + # error Failed to replace env in config: ${NODE_AUTH_TOKEN} + # + # The variable has to be in the environment from the moment the .npmrc + # exists, which means the whole job. + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 @@ -30,5 +44,3 @@ jobs: # Publish stays on the npm CLI: yarn 1 cannot emit provenance attestations. - run: npm publish --provenance --access public - env: - NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} diff --git a/README.md b/README.md index 8aeb991..d510834 100644 --- a/README.md +++ b/README.md @@ -160,14 +160,15 @@ Full documentation is published as a spoke site on the Vantage docs hub: **https://docs.vantagecompute.ai/developer/docusaurus-theme/** -It lives in `docusaurus/` in this repository and installs the theme from npm at -a pinned version, so it renders what consumers actually get rather than the -working tree. +It lives in `docusaurus/` in this repository and installs the theme from npm, so +it renders what consumers actually get rather than the working tree. The +declared range is `^0.4.7`, so patch releases reach the site on the next deploy +with no commit. ```bash just docs-serve # local preview at /developer/docusaurus-theme/ just docs-build # build and link-check -just docs-pin 0.4.8 # point the site at a newly published version +just docs-pin 0.5.0 # move the range across a minor ``` ## Development @@ -187,7 +188,7 @@ The package uses TypeScript for the plugin entry point (`src/index.cts` -> `lib/ just release 0.4.8 ``` -Bumps `package.json`, commits, tags, pushes, and creates the GitHub release. The npm publish runs in CI on `release: published`, with provenance attestation. Afterwards, bump the docs site's pin with `just docs-pin`. +Bumps `package.json`, commits, tags, pushes, and creates the GitHub release. The npm publish runs in CI on `release: published`, with provenance attestation. A patch release needs nothing else; a new minor needs `just docs-pin` for the docs site. ## License diff --git a/docusaurus/docs/contributing.md b/docusaurus/docs/contributing.md index 86f81e9..8ec20d4 100644 --- a/docusaurus/docs/contributing.md +++ b/docusaurus/docs/contributing.md @@ -51,16 +51,20 @@ just docs-serve # http://localhost:3000/developer/docusaurus-theme/ just docs-build ``` -It installs the theme from npm at a pinned version rather than through a -`file:` link to the repository around it. That is what makes the site an honest -preview: it renders what consumers actually get, and it fails if a release ever -ships a tarball missing something the build needs. +It installs the theme from npm rather than through a `file:` link to the +repository around it. That is what makes the site an honest preview: it renders +what consumers actually get, and it fails if a release ever ships a tarball +missing something the build needs. -The pin therefore trails the package by up to one release, and moving it is a -separate deliberate commit after the version is on npm: +The declared range is `^0.4.7`, so a new 0.4.x patch reaches the site on the +next deploy with no commit here. Both workflows run +`npm update --no-save @vantagecompute/docusaurus-theme` after `npm ci`, because +`npm ci` is lockfile-exact and the range on its own would never move. + +Moving to a new minor is deliberate: ```bash -just docs-pin 0.4.8 +just docs-pin 0.5.0 ``` ## Releasing @@ -81,8 +85,9 @@ Two details worth knowing: - The working tree must be clean; the recipe refuses to run otherwise, so a release can never contain something that was never committed. -After the release lands on npm, bump this site's pin and, when the change -matters to them, the pins in the consuming sites. +A patch release needs nothing here: the site's range already covers it. A new +minor needs `just docs-pin`, and the same bump in the consuming sites when the +change matters to them. ## What belongs in the theme diff --git a/docusaurus/docs/index.md b/docusaurus/docs/index.md index d0cc3da..59d46e1 100644 --- a/docusaurus/docs/index.md +++ b/docusaurus/docs/index.md @@ -56,13 +56,11 @@ styles and nothing else. ## This site dogfoods the theme -The site you are reading installs `@vantagecompute/docusaurus-theme` from npm -at a pinned version, exactly as any other consumer does, not through a -`file:` link to the repository it lives in. So it renders the design that is -actually published, and a packaging mistake (a file the build needs that -`files` in `package.json` does not ship) fails this build before it reaches -anybody else. +The site you are reading installs `@vantagecompute/docusaurus-theme` from npm, +exactly as any other consumer does, not through a `file:` link to the +repository it lives in. So it renders the design that is actually published, +and a packaging mistake (a file the build needs that `files` in `package.json` +does not ship) fails this build before it reaches anybody else. -The trade-off is that this site trails the package by up to one release. -Bumping the pin is a deliberate step after a version is on npm, not something -a release does on its own. +It follows the `^0.4.7` range, so each deploy picks up the newest 0.4.x +release. A new minor is a deliberate bump. diff --git a/docusaurus/docs/installation.md b/docusaurus/docs/installation.md index 107612a..b1a2288 100644 --- a/docusaurus/docs/installation.md +++ b/docusaurus/docs/installation.md @@ -30,23 +30,38 @@ site already installed rather than pulling in a second one. `@docusaurus/core`, The package itself depends only on `clsx` and `unist-util-visit`. -## Pin the version +## Declare the range -Pin an exact version rather than a range: +A caret range on the current minor: ```json { "dependencies": { - "@vantagecompute/docusaurus-theme": "0.4.7" + "@vantagecompute/docusaurus-theme": "^0.4.7" } } ``` -The theme changes how every page on the site looks. A caret range means a -design change can land in a build nobody intended to change the design in, -which is a bad way to find out about it. An exact pin makes the adoption a -commit you can point at, and makes "which sites have this fix" a question -`grep` answers. +Below 1.0.0 npm reads a caret as "this minor only", so `^0.4.7` means +`>=0.4.7 <0.5.0`. Patch releases within 0.4.x, which is where fixes land, +arrive on their own. A 0.5.0 does not, so a release that changes the design +deliberately stays a deliberate adoption in each site. + +:::caution `npm ci` will not move this on its own +`npm ci` installs exactly what the lockfile says, by design, so a site whose CI +uses it stays on whatever version the lockfile was last regenerated against +however wide the range is. Either regenerate the lockfile when you want the +newer theme, or refresh just this package after installing: + +```bash +npm ci +npm update --no-save @vantagecompute/docusaurus-theme +``` + +`--no-save` leaves the lockfile and `package.json` alone, so every other +dependency stays reproducible and the build produces no diff. That is what this +package's own documentation site does. +::: ## What lands in `node_modules` diff --git a/docusaurus/docusaurus.config.ts b/docusaurus/docusaurus.config.ts index 25864c1..cb23034 100644 --- a/docusaurus/docusaurus.config.ts +++ b/docusaurus/docusaurus.config.ts @@ -8,16 +8,18 @@ import { } from '@vantagecompute/docusaurus-theme'; // This site is the theme's own documentation, and it dogfoods the theme: the -// dependency in package.json is the PUBLISHED version from npm, not a file: +// dependency in package.json is the PUBLISHED package from npm, not a file: // link to the repository root. That is deliberate. A file: link would render // the working tree, so the site would show a design nobody can install yet and // would never catch a packaging mistake -- a file the build needs that // `files` in package.json does not ship. Building against the tarball readers // actually get is the only way this site stays honest. // -// The consequence to keep in mind: the site trails the theme by up to one -// release. Bumping the pin is a deliberate step after a version is on npm -- -// `just docs-pin ` -- not something a release does on its own. +// The range is `^0.4.7`, so the site follows the newest 0.4.x automatically and +// a 0.5.0 needs a deliberate bump. Note that `npm ci` is lockfile-exact, so the +// range on its own would not move: both workflows run +// `npm update --no-save @vantagecompute/docusaurus-theme` after installing to +// take the newest release in range without writing a lockfile diff. // // From the theme rather than hand-rolled here, so every Vantage site advertises // its version the same way. It returns `git describe --tags --always`, so the diff --git a/docusaurus/package-lock.json b/docusaurus/package-lock.json index 8cea106..5df4119 100644 --- a/docusaurus/package-lock.json +++ b/docusaurus/package-lock.json @@ -12,7 +12,7 @@ "@docusaurus/preset-classic": "^3.10.2", "@docusaurus/theme-mermaid": "^3.10.2", "@mdx-js/react": "^3.1.1", - "@vantagecompute/docusaurus-theme": "0.4.7", + "@vantagecompute/docusaurus-theme": "^0.4.7", "clsx": "^2.1.1", "prism-react-renderer": "^2.4.1", "react": "^19.2.8", diff --git a/docusaurus/package.json b/docusaurus/package.json index eee7071..596bfa8 100644 --- a/docusaurus/package.json +++ b/docusaurus/package.json @@ -18,7 +18,7 @@ "@docusaurus/preset-classic": "^3.10.2", "@docusaurus/theme-mermaid": "^3.10.2", "@mdx-js/react": "^3.1.1", - "@vantagecompute/docusaurus-theme": "0.4.7", + "@vantagecompute/docusaurus-theme": "^0.4.7", "clsx": "^2.1.1", "prism-react-renderer": "^2.4.1", "react": "^19.2.8", diff --git a/justfile b/justfile index 8e82e8e..e2a80e6 100644 --- a/justfile +++ b/justfile @@ -30,12 +30,15 @@ clean: # Documentation site (docusaurus/) # # Published as a spoke under docs.vantagecompute.ai/developer/docusaurus-theme/. -# It installs @vantagecompute/docusaurus-theme from npm at a PINNED version -# rather than through a file: link to this working tree. That is deliberate: the -# site then renders what consumers actually get, and a release that ships a -# tarball missing something the build needs fails here first. The cost is that -# the pin trails the package by up to one release -- move it with `docs-pin` -# once the version is on npm. +# It installs @vantagecompute/docusaurus-theme from npm rather than through a +# file: link to this working tree. That is deliberate: the site then renders +# what consumers actually get, and a release that ships a tarball missing +# something the build needs fails here first. +# +# The declared range is ^0.4.7, so patch releases arrive on the next deploy with +# no commit. `docs-pin` is for crossing a minor, which stays deliberate. Note +# that `npm ci` is lockfile-exact, so both workflows run +# `npm update --no-save @vantagecompute/docusaurus-theme` after installing. # --------------------------------------------------------------------------- # Install the docs site's dependencies @@ -60,7 +63,8 @@ docs-build: docs-install docs-clean: rm -rf docusaurus/build docusaurus/.docusaurus -# Point the docs site at a published theme version, and refresh its lockfile +# Move the docs site's theme range to ^, and refresh its lockfile. +# Only needed to cross a minor: patch releases are already inside the range. [group("docs")] docs-pin version: #!/usr/bin/env bash @@ -71,9 +75,9 @@ docs-pin version: exit 1 fi cd docusaurus - npm pkg set 'dependencies.@vantagecompute/docusaurus-theme={{version}}' + npm pkg set 'dependencies.@vantagecompute/docusaurus-theme=^{{version}}' npm install - echo "✅ Docs site pinned to {{version}}. Commit docusaurus/package.json and package-lock.json." + echo "✅ Docs site now tracks ^{{version}}. Commit docusaurus/package.json and package-lock.json." # Bump version, commit, tag, push, and create GitHub release to trigger npm publish [group("release")] @@ -104,5 +108,5 @@ help: @echo " docs-serve - Serve the docs site locally" @echo " docs-build - Build (and link-check) the docs site" @echo " docs-clean - Clean the docs site build output" - @echo " docs-pin x.x.x - Point the docs site at a published theme version" + @echo " docs-pin x.x.x - Move the docs site's theme range to ^x.x.x" @echo " release x.x.x - Bump, tag, push, and publish to npm"