From 8d2d52bed8b08a9e117ab527c5caf57e2ebc7acf Mon Sep 17 00:00:00 2001 From: Felix Kotschenreuther Date: Fri, 10 Jul 2026 14:47:04 +0200 Subject: [PATCH] ci(release): publish @eqrm/ct-cli to GitHub Packages so consumers need no PAT (#24) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ct-structure's CI can't 'npm install' ct-cli today: the git dependency ssh://git@github.com/eqrm/ct-cli.git needs a credential GITHUB_TOKEN can't provide across private repos in the same org (Permission denied (publickey)). The recent GitHub improvement — pulling private deps in CI with the built-in GITHUB_TOKEN, no PAT — applies to package REGISTRIES, not raw git deps. So publish ct-cli to GitHub Packages and let consumers depend on the package. - package.json: scope the name to @eqrm/ct-cli (GitHub Packages requires the owner scope); drop 'private: true' (it blocks 'npm publish'); pin publishConfig.registry to npm.pkg.github.com so a stray publish can never hit public npm; add the 'repository' field GitHub Packages links the package by. - .releaserc.json: add @semantic-release/npm before the github plugin — it bumps the in-workspace version and publishes, but ONLY when commit-analyzer finds a releasable feat/fix (no accidental republish). - release.yml: add 'packages: write'; run 'npm ci' + build in the release job (the package is published from this working tree, and the release-assets artifact carries only the binaries, not dist/); pass NPM_TOKEN=GITHUB_TOKEN to authenticate against GitHub Packages. Consumers (eqrm/ct-structure) then depend on @eqrm/ct-cli and install it in CI with just secrets.GITHUB_TOKEN + 'permissions: packages: read', after granting the consumer repo Actions access to the package — no personal PAT. Verified locally: 'npm pack' produces @eqrm/ct-cli with dist/ built via the prepare script; lint/typecheck/test/build all green. Note: this ci: commit is itself non-releasing, so the package first publishes on the next releasable feat/fix merged to main. --- .github/workflows/release.yml | 17 ++++++++++++++++- .releaserc.json | 1 + package.json | 10 ++++++++-- 3 files changed, 25 insertions(+), 3 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index df6abfc..602ce5d 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -18,7 +18,8 @@ on: workflow_dispatch: {} permissions: - contents: write + contents: write # semantic-release: create the tag + GitHub Release + packages: write # @semantic-release/npm: publish @eqrm/ct-cli to GitHub Packages (npm.pkg.github.com) jobs: # CI gate + build the release assets every job below needs. Binaries are cross- @@ -145,6 +146,12 @@ jobs: with: node-version: 22 + # @semantic-release/npm publishes the package from THIS working tree, so `dist/` + # must exist and devDependencies (tsup, via the `prepare` script) must be present + # here — the `release-assets` artifact only carries the binaries, not `dist/`. + - run: npm ci + - run: npm run build + - uses: actions/download-artifact@v4 with: name: release-assets @@ -154,13 +161,21 @@ jobs: # Pinned via npx rather than added as devDependencies (see #9) — this repo # doesn't otherwise need semantic-release, so keep it out of package.json. + # @semantic-release/npm bumps the in-workspace version and publishes + # @eqrm/ct-cli to GitHub Packages (registry from package.json publishConfig); + # NPM_TOKEN=GITHUB_TOKEN authenticates against npm.pkg.github.com (needs the + # packages:write permission above). It only publishes when commit-analyzer + # finds a releasable change, and never to public npm (publishConfig pins the + # registry). Consumers in the org install it with just GITHUB_TOKEN — no PAT. - name: Run semantic-release env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + NPM_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | npx --yes \ -p semantic-release@24 \ -p @semantic-release/commit-analyzer@13 \ -p @semantic-release/release-notes-generator@14 \ + -p @semantic-release/npm@12 \ -p @semantic-release/github@11 \ semantic-release diff --git a/.releaserc.json b/.releaserc.json index f19f1de..0583a93 100644 --- a/.releaserc.json +++ b/.releaserc.json @@ -3,6 +3,7 @@ "plugins": [ "@semantic-release/commit-analyzer", "@semantic-release/release-notes-generator", + "@semantic-release/npm", [ "@semantic-release/github", { diff --git a/package.json b/package.json index 4a4b18f..687b832 100644 --- a/package.json +++ b/package.json @@ -1,9 +1,15 @@ { - "name": "ct-cli", + "name": "@eqrm/ct-cli", "version": "0.1.0", - "private": true, "description": "ChurchTools structure-as-code CLI — declarative plan/apply for the overarching, rights-bearing structure (campuses, groups, hierarchies, permissions, auto-groups). Never manages people.", "type": "module", + "repository": { + "type": "git", + "url": "git+https://github.com/eqrm/ct-cli.git" + }, + "publishConfig": { + "registry": "https://npm.pkg.github.com" + }, "bin": { "ct": "./dist/index.js" },