diff --git a/.github/workflows/post-publish-lockfile.yml b/.github/workflows/post-publish-lockfile.yml new file mode 100644 index 0000000..6cdd416 --- /dev/null +++ b/.github/workflows/post-publish-lockfile.yml @@ -0,0 +1,42 @@ +name: post-publish / refresh lockfile + +# Runs after a release tag is pushed. Resolves "latest" in demo package.json +# files to the newly published version and commits the updated lock file, +# so npm ci never fails on the next CI run. + +permissions: + contents: write + +on: + push: + tags: + - 'v*' + +jobs: + refresh-lockfile: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + ref: main + token: ${{ secrets.GITHUB_TOKEN }} + + - uses: actions/setup-node@v4 + with: + node-version: 22 + cache: npm + + - name: Refresh lock file + run: npm install --package-lock-only + + - name: Commit if changed + run: | + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + git diff --quiet package-lock.json || ( + git add package-lock.json && + git commit -m "chore: refresh lock file after ${GITHUB_REF_NAME} publish" + ) + + - name: Push + run: git push origin main diff --git a/PUBLISHING.md b/PUBLISHING.md index 9a4ea3e..cf95e62 100644 --- a/PUBLISHING.md +++ b/PUBLISHING.md @@ -51,25 +51,36 @@ npm version patch - `package-lock.json` - `CHANGELOG.md` -Update these only when needed for compatibility or StackBlitz: - -- `demo/package.json` -- `demo-react/package.json` +Do **not** change `demo/package.json` or `demo-react/package.json` — both use `"latest"` which always resolves to the newest published version automatically. ## Demo / StackBlitz Rules -- minor or patch core release: no `demo/package.json` change is needed because `@passiveintent/core` is already `^1.0.0`, which accepts later `1.x` versions -- minor or patch React release: no `demo-react/package.json` change is needed because both package ranges are already `^1.0.0` -- major core release: update `demo/package.json` to `@passiveintent/core@^X.0.0` -- major React release: update `demo-react/package.json` to `@passiveintent/core@^X.0.0` and `@passiveintent/react@^X.0.0` -- if `@passiveintent/react` starts requiring a newer minimum core minor, update `demo-react/package.json` and `packages/react/package.json` to that minimum compatible range +Both demos pin their dependencies to `"latest"`: + +```json +"@passiveintent/core": "latest" +"@passiveintent/react": "latest" +``` + +This means: + +- No `demo/package.json` or `demo-react/package.json` changes are ever needed on release +- StackBlitz always installs the newest published version +- The only required post-publish step is refreshing `package-lock.json` (see below), so `npm ci` in CI resolves to the new version instead of the previously locked one -Practical rule: +**After every publish**, run: -- StackBlitz does not care about the demo app's own `version` -- StackBlitz only cares that the dependency ranges in `demo/package.json` and `demo-react/package.json` can resolve the published npm packages -- for normal `1.x` minor and patch releases, the existing `^1.0.0` ranges are enough -- only change the demo dependency ranges when the published package compatibility range changes +```bash +npm install --package-lock-only +git add package-lock.json +git commit -m "chore: refresh lock file after vX.Y.Z publish" +``` + +If you forget this step, CI will fail with: + +```text +npm error Missing: @passiveintent/core@X.Y.Z from lock file +``` ## Release Checks diff --git a/demo-react/package.json b/demo-react/package.json index ee89b2d..9226d67 100644 --- a/demo-react/package.json +++ b/demo-react/package.json @@ -10,8 +10,8 @@ "preview": "vite preview" }, "dependencies": { - "@passiveintent/core": "^1.0.0", - "@passiveintent/react": "^1.0.0", + "@passiveintent/core": "latest", + "@passiveintent/react": "latest", "react": "^19.2.4", "react-dom": "^19.2.4" }, diff --git a/demo/package.json b/demo/package.json index cc6706c..bd4846b 100644 --- a/demo/package.json +++ b/demo/package.json @@ -10,7 +10,7 @@ "preview": "vite preview" }, "dependencies": { - "@passiveintent/core": "^1.0.0" + "@passiveintent/core": "latest" }, "devDependencies": { "typescript": "^5.6.3", diff --git a/package-lock.json b/package-lock.json index b13a040..38ca242 100644 --- a/package-lock.json +++ b/package-lock.json @@ -28,7 +28,7 @@ "name": "passiveintent-demo", "version": "1.0.0", "dependencies": { - "@passiveintent/core": "^1.0.0" + "@passiveintent/core": "latest" }, "devDependencies": { "typescript": "^5.6.3", @@ -39,8 +39,8 @@ "name": "passiveintent-demo-react", "version": "1.0.0", "dependencies": { - "@passiveintent/core": "^1.0.0", - "@passiveintent/react": "^1.0.0", + "@passiveintent/core": "latest", + "@passiveintent/react": "latest", "react": "^19.2.4", "react-dom": "^19.2.4" }, @@ -52,6 +52,46 @@ "vite": "^7.3.1" } }, + "demo-react/node_modules/@passiveintent/core": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@passiveintent/core/-/core-1.3.0.tgz", + "integrity": "sha512-Bjz2XKFFfX20sH5c4kiWt/o38sxaq1GRKOsWEN1bURe2BC5zLYrIY+3WDox2Fd6ce7Z9rxTvz8Yi7qgbCcfz5Q==", + "license": "AGPL-3.0-only", + "engines": { + "node": ">=20" + } + }, + "demo-react/node_modules/@passiveintent/react": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@passiveintent/react/-/react-1.3.1.tgz", + "integrity": "sha512-qEmqbx8GBHPtH+K7v5/E3goUJon1PzetV988/Zj+wZ1SuFcBSCNifOtGuHW2zX+31igU2yMHBgJM/5ZobtFXGw==", + "license": "AGPL-3.0-only", + "dependencies": { + "use-sync-external-store": "^1.6.0" + }, + "engines": { + "node": ">=20" + }, + "peerDependencies": { + "@passiveintent/core": "^1.1.0", + "react": ">=18.0.0", + "react-dom": ">=18.0.0" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + } + } + }, + "demo/node_modules/@passiveintent/core": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@passiveintent/core/-/core-1.3.0.tgz", + "integrity": "sha512-Bjz2XKFFfX20sH5c4kiWt/o38sxaq1GRKOsWEN1bURe2BC5zLYrIY+3WDox2Fd6ce7Z9rxTvz8Yi7qgbCcfz5Q==", + "license": "AGPL-3.0-only", + "engines": { + "node": ">=20" + } + }, "node_modules/@acemir/cssom": { "version": "0.9.31", "resolved": "https://registry.npmjs.org/@acemir/cssom/-/cssom-0.9.31.tgz", @@ -688,6 +728,14 @@ "ms": "^2.1.1" } }, + "node_modules/@edgesignal/adaptive-ui": { + "resolved": "packages/adaptive-ui", + "link": true + }, + "node_modules/@edgesignal/security": { + "resolved": "packages/security", + "link": true + }, "node_modules/@esbuild/aix-ppc64": { "version": "0.27.3", "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.3.tgz", @@ -6403,8 +6451,7 @@ }, "packages/adaptive-ui": { "name": "@edgesignal/adaptive-ui", - "version": "0.0.0", - "extraneous": true + "version": "0.0.0" }, "packages/angular": { "name": "@passiveintent/angular", @@ -6765,8 +6812,7 @@ }, "packages/security": { "name": "@edgesignal/security", - "version": "0.0.0", - "extraneous": true + "version": "0.0.0" }, "packages/vanilla": { "name": "@passiveintent/vanilla",