From 1f1090f25b949571a965fa01e49cb333dcb33e16 Mon Sep 17 00:00:00 2001 From: codingChewie Date: Fri, 17 Jul 2026 11:31:23 -0500 Subject: [PATCH 1/2] init --- .github/workflows/release-package.yml | 13 ++--- .npmrc | 1 - README.md | 70 ++++++--------------------- docs/importing.md | 9 ++-- package.json | 2 +- 5 files changed, 25 insertions(+), 70 deletions(-) delete mode 100644 .npmrc diff --git a/.github/workflows/release-package.yml b/.github/workflows/release-package.yml index 3e609df..ea5d388 100644 --- a/.github/workflows/release-package.yml +++ b/.github/workflows/release-package.yml @@ -1,4 +1,4 @@ -name: Publish @epubknowledge/common package to Github Packages Registry +name: Publish @epubknowledge/common package to npm on: push: branches: @@ -9,19 +9,16 @@ jobs: runs-on: ubuntu-latest permissions: contents: read - packages: write env: - NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true steps: - uses: actions/checkout@v4 - # Setup .npmrc file to publish to GitHub Packages + # Setup .npmrc file to publish to the public npm registry - uses: actions/setup-node@v4 with: node-version: '22.x' - registry-url: 'https://npm.pkg.github.com' - always-auth: true - # Defaults to the user or organization that owns the workflow file + registry-url: 'https://registry.npmjs.org' scope: '@epubknowledge' - run: yarn install --frozen-lockfile - name: Run Vitest and capture results @@ -29,4 +26,4 @@ jobs: run: yarn test --reporter=json --outputFile=.test-results.json - name: Require 85% test pass rate run: node .github/scripts/verify-test-pass-rate.mjs .test-results.json 85 - - run: yarn publish + - run: npm publish --access public diff --git a/.npmrc b/.npmrc deleted file mode 100644 index a193f9b..0000000 --- a/.npmrc +++ /dev/null @@ -1 +0,0 @@ -@epubknowledge:registry=https://npm.pkg.github.com diff --git a/README.md b/README.md index 8f8cdde..bac8bc8 100644 --- a/README.md +++ b/README.md @@ -2,9 +2,9 @@ Shared runtime helpers for the Epub Knowledge package ecosystem. -## Install From NPM +## Install -After public testing is complete and this package is published to the public NPM registry, install it directly from NPM with no extra registry configuration or auth token: +This package is intended to be published to the public npm registry, so consuming repos can install it with no extra registry configuration or GitHub token: pnpm: @@ -26,71 +26,29 @@ npm install @epubknowledge/common Requires Node.js `>= 22.0.0`. -## Install From GitHub Packages +## Publishing -This package is published to the GitHub Package Registry, so consuming repos must be configured to read the `@epubknowledge` scope from `https://npm.pkg.github.com`. +Maintainers publish this package to npm, not GitHub Packages. -### 1. Configure the registry +### Publish prerequisites -Add this to the consuming repo's `.npmrc`: +- The `@epubknowledge` scope must exist on npm and the publisher must have permission to publish under it. +- Local publishing uses `npm login`. +- GitHub Actions publishing uses an `NPM_TOKEN` repository secret with permission to publish the package. -```ini -@epubknowledge:registry=https://npm.pkg.github.com -//npm.pkg.github.com/:_authToken=${GITHUB_TOKEN} -``` - -Commit the file, but never commit the token itself. - -If the consuming repo uses Yarn Berry (`v2+`), add the equivalent to `.yarnrc.yml`: - -```yaml -npmScopes: - epubknowledge: - npmRegistryServer: 'https://npm.pkg.github.com' - npmAuthToken: '${GITHUB_TOKEN}' -``` - -### 2. Provide a token +### Publish from CI -The token needs `read:packages`. If the org uses SSO, the token must also be authorized for `epubknowledge`. - -Local development: - -```sh -export GITHUB_TOKEN=ghp_your_token_here -``` - -GitHub Actions: +The release workflow publishes to `https://registry.npmjs.org` with: ```yaml -permissions: - contents: read - packages: read - -steps: - - run: npm install - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} +env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} ``` -### 3. Install the package - -pnpm: +### Publish locally ```sh -pnpm add @epubknowledge/common -``` - -yarn: - -```sh -yarn add @epubknowledge/common -``` - -npm: - -```sh -npm install @epubknowledge/common +npm publish --access public ``` ## Importing diff --git a/docs/importing.md b/docs/importing.md index 5cf05a8..7376934 100644 --- a/docs/importing.md +++ b/docs/importing.md @@ -1,20 +1,20 @@ # Import Readiness Plan -This package is intended to be consumed from other repositories through GitHub Packages. +This package is intended to be consumed from other repositories through the public npm registry. ## Completed In This Repo - The build now emits `dist/` output instead of type-checking only. - The package export map matches the documented subpath modules. -- The README now documents private-registry setup, supported import paths, and TypeScript usage. +- The README documents public npm install usage, npm publish prerequisites, supported import paths, and TypeScript usage. ## Remaining Checklist 1. Add a publish verification step in CI that runs `npm run build` and fails if `dist/` is missing. 2. Add a packaging smoke test that runs `npm pack` and verifies the tarball contains `dist/*.js` and `dist/*.d.ts`. 3. Add a consumer smoke test that installs the packed tarball into a temporary project and imports at least one runtime module plus one type-only module. -4. Publish a new package version to GitHub Packages after the packaging checks pass. -5. Verify install and import from a real consuming private repo using the README setup instructions. +4. Publish a new package version to npm after the packaging checks pass. +5. Verify install and import from a real consuming repo with a plain `npm`, `pnpm`, or `yarn` install and no private-registry setup. ## TypeScript Notes @@ -30,3 +30,4 @@ Optional follow-up: - Add `typesVersions` if you need compatibility with older TypeScript package resolution behavior. - Add a root barrel export if consumers should be able to write `import { ... } from '@epubknowledge/common'` instead of subpath imports. +- Add a local or CI check that fails early if the publishing account does not have access to the `@epubknowledge` npm scope. diff --git a/package.json b/package.json index c0433fa..542e065 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,7 @@ "node": ">=22.0.0" }, "publishConfig": { - "registry": "https://npm.pkg.github.com", + "registry": "https://registry.npmjs.org/", "access": "public" }, "repository": { From 31b749fae5f705629192a02a82997d01375f9d12 Mon Sep 17 00:00:00 2001 From: codingChewie Date: Fri, 17 Jul 2026 11:47:30 -0500 Subject: [PATCH 2/2] add action --- .github/workflows/release-package.yml | 74 +++++++++++++++++++++++---- README.md | 22 ++++++-- docs/importing.md | 13 +++-- package.json | 17 ++++-- 4 files changed, 100 insertions(+), 26 deletions(-) diff --git a/.github/workflows/release-package.yml b/.github/workflows/release-package.yml index ea5d388..3a07907 100644 --- a/.github/workflows/release-package.yml +++ b/.github/workflows/release-package.yml @@ -1,29 +1,85 @@ -name: Publish @epubknowledge/common package to npm +name: Publish @epubknowledge/common package on: - push: - branches: - - main + release: + types: + - published workflow_dispatch: jobs: publish: runs-on: ubuntu-latest permissions: contents: read + id-token: write + packages: write env: - NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true steps: - uses: actions/checkout@v4 - # Setup .npmrc file to publish to the public npm registry + with: + persist-credentials: false - uses: actions/setup-node@v4 with: node-version: '22.x' - registry-url: 'https://registry.npmjs.org' - scope: '@epubknowledge' - run: yarn install --frozen-lockfile - name: Run Vitest and capture results continue-on-error: true run: yarn test --reporter=json --outputFile=.test-results.json - name: Require 85% test pass rate run: node .github/scripts/verify-test-pass-rate.mjs .test-results.json 85 - - run: npm publish --access public + - name: Build package + run: npm run build + - name: Pack release artifact + id: pack + run: | + npm pack --json > pack-output.json + echo "filename=$(node -p 'JSON.parse(require(\"fs\").readFileSync(\"pack-output.json\", \"utf8\"))[0].filename')" >> "$GITHUB_OUTPUT" + - name: Verify packed dist assets + run: | + node -e "const pack = JSON.parse(require('fs').readFileSync('pack-output.json', 'utf8'))[0]; const files = pack.files.map(file => file.path); const hasJs = files.some(file => file.startsWith('dist/') && file.endsWith('.js')); const hasDts = files.some(file => file.startsWith('dist/') && file.endsWith('.d.ts')); if (!hasJs || !hasDts) { console.error('Packed tarball is missing compiled dist assets.'); process.exit(1); }" + - name: Consumer smoke test + run: | + tmp_dir="$(mktemp -d)" + npm init -y --prefix "$tmp_dir" >/dev/null + npm install --prefix "$tmp_dir" "$PWD/${{ steps.pack.outputs.filename }}" typescript + cat <<'EOF' > "$tmp_dir/runtime.mjs" + import { fileExists } from '@epubknowledge/common/file' + + if (typeof fileExists !== 'function') { + throw new Error('Expected fileExists export to be a function.') + } + EOF + cat <<'EOF' > "$tmp_dir/types.mts" + import type { EpubObj } from '@epubknowledge/common/types' + + const book: EpubObj | null = null + void book + EOF + cat <<'EOF' > "$tmp_dir/tsconfig.json" + { + "compilerOptions": { + "module": "nodenext", + "moduleResolution": "nodenext", + "noEmit": true + }, + "include": ["types.mts"] + } + EOF + node "$tmp_dir/runtime.mjs" + (cd "$tmp_dir" && ./node_modules/.bin/tsc -p tsconfig.json) + - name: Set up npm registry auth + uses: actions/setup-node@v4 + with: + node-version: '22.x' + registry-url: 'https://registry.npmjs.org' + - name: Publish to npm + run: npm publish "${{ steps.pack.outputs.filename }}" --provenance --access public + - name: Set up GitHub Packages auth + uses: actions/setup-node@v4 + with: + node-version: '22.x' + registry-url: 'https://npm.pkg.github.com' + scope: '@epubknowledge' + - name: Publish to GitHub Packages + run: npm publish "${{ steps.pack.outputs.filename }}" --registry=https://npm.pkg.github.com + env: + NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/README.md b/README.md index bac8bc8..dd75666 100644 --- a/README.md +++ b/README.md @@ -28,21 +28,24 @@ Requires Node.js `>= 22.0.0`. ## Publishing -Maintainers publish this package to npm, not GitHub Packages. +Maintainers publish this package to npm as the primary install target, and the release workflow mirrors the same version to GitHub Packages for authenticated consumers that still want it there. ### Publish prerequisites - The `@epubknowledge` scope must exist on npm and the publisher must have permission to publish under it. +- npm trusted publishing must be configured for the `release-package.yml` workflow on npmjs.com before CI publish will succeed. - Local publishing uses `npm login`. -- GitHub Actions publishing uses an `NPM_TOKEN` repository secret with permission to publish the package. +- GitHub Actions publishing uses GitHub OIDC trusted publishing for npm and the built-in `GITHUB_TOKEN` for the GitHub Packages mirror. ### Publish from CI -The release workflow publishes to `https://registry.npmjs.org` with: +The release workflow runs when a GitHub release is published or when it is started manually. Before any publish step, it runs tests, builds the package, verifies the tarball contains compiled `dist/*.js` and `dist/*.d.ts` assets, and smoke-tests a temporary consumer install for both runtime and type-only imports. It then publishes that tarball to `https://registry.npmjs.org` with provenance and mirrors the same tarball to `https://npm.pkg.github.com`. ```yaml -env: - NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} +on: + release: + types: [published] + workflow_dispatch: ``` ### Publish locally @@ -51,6 +54,15 @@ env: npm publish --access public ``` +### Optional GitHub Packages mirror install + +Most consumers should use the public npm install shown above. If a repo intentionally wants the GitHub Packages mirror instead, configure that consuming repo with: + +```ini +@epubknowledge:registry=https://npm.pkg.github.com +//npm.pkg.github.com/:_authToken=${GITHUB_TOKEN} +``` + ## Importing Import from the documented subpath exports only. There is currently no root barrel export, so prefer paths like `@epubknowledge/common/dir`. diff --git a/docs/importing.md b/docs/importing.md index 7376934..f928645 100644 --- a/docs/importing.md +++ b/docs/importing.md @@ -1,20 +1,19 @@ # Import Readiness Plan -This package is intended to be consumed from other repositories through the public npm registry. +This package is intended to be consumed from other repositories through the public npm registry. The release workflow also mirrors the same package version to GitHub Packages for authenticated consumers that still depend on that registry. ## Completed In This Repo - The build now emits `dist/` output instead of type-checking only. - The package export map matches the documented subpath modules. -- The README documents public npm install usage, npm publish prerequisites, supported import paths, and TypeScript usage. +- The release workflow now runs tests, builds the package, verifies packed `dist/*.js` and `dist/*.d.ts` assets, smoke-tests a temporary consumer install, publishes to npm with provenance, and mirrors the same tarball to GitHub Packages. +- The README documents public npm install usage, release-driven dual-registry publishing, supported import paths, and TypeScript usage. ## Remaining Checklist -1. Add a publish verification step in CI that runs `npm run build` and fails if `dist/` is missing. -2. Add a packaging smoke test that runs `npm pack` and verifies the tarball contains `dist/*.js` and `dist/*.d.ts`. -3. Add a consumer smoke test that installs the packed tarball into a temporary project and imports at least one runtime module plus one type-only module. -4. Publish a new package version to npm after the packaging checks pass. -5. Verify install and import from a real consuming repo with a plain `npm`, `pnpm`, or `yarn` install and no private-registry setup. +1. Publish a new package version to npm and mirror it to GitHub Packages after the packaging checks pass. +2. Verify install and import from a real consuming repo with a plain `npm`, `pnpm`, or `yarn` install and no private-registry setup. +3. Optionally verify the GitHub Packages mirror from a repo that already has authenticated `@epubknowledge` registry access configured. ## TypeScript Notes diff --git a/package.json b/package.json index 542e065..5bd4425 100644 --- a/package.json +++ b/package.json @@ -37,10 +37,6 @@ "engines": { "node": ">=22.0.0" }, - "publishConfig": { - "registry": "https://registry.npmjs.org/", - "access": "public" - }, "repository": { "type": "git", "url": "git+https://github.com/epubknowledge/common.git" @@ -131,5 +127,16 @@ "types": "./dist/resetMemory.d.ts", "import": "./dist/resetMemory.js" } - } + }, + "main": "index.js", + "directories": { + "doc": "docs" + }, + "keywords": [], + "author": "", + "license": "ISC", + "bugs": { + "url": "https://github.com/epubknowledge/common/issues" + }, + "homepage": "https://github.com/epubknowledge/common#readme" }