Commit 03b9ba5

Anton Golub <antongolub@antongolub.com>
2025-08-18 11:10:55
ci: refactor build scripts, reduce jsr token permissions (#1320)
* ci: refactor build scripts, reduce jsr token permissions * test: update fixtures * test(size): update zx-lite paths
1 parent e2eb47b
.github/workflows/dev-publish.yml
@@ -21,8 +21,9 @@ jobs:
         env:
           FORCE_COLOR: 3
       - run: |
-          node scripts/build-jsr.mjs
-          node scripts/prepublish-clean.mjs
+          npm run build:jsr
+          npm run build:lite
+          npm run build:pkgjson
       - uses: actions/upload-artifact@v4
         with:
           name: build-${{ github.run_id }}
@@ -30,7 +31,7 @@ jobs:
             build
             jsr.json
             package.json
-            node_modules/depseek
+            package-lite.json
           retention-days: 1
 
   npm-publish:
@@ -83,11 +84,33 @@ jobs:
 
       - name: pushing lite snapshot to ${{ env.GOOGLE_NPM_REGISTRY }}
         run: |
-          cat <<< $(jq '.name="zx"' package.json) > package.json
-          node scripts/prepublish-lite.mjs
+          mv package-lite.json package.json
           cat <<< $(jq '.version="${{ env.ZX_LITE_DEV_VERSION }}"' package.json) > package.json
           npm publish --provenance --access=public --no-git-tag-version --tag dev --registry https://${{ env.GOOGLE_NPM_REGISTRY }}
 
+  jsr-publish:
+    needs: build
+    runs-on: ubuntu-latest
+    permissions:
+      contents: read
+      id-token: write
+    steps:
+      - uses: actions/checkout@v4
+        with:
+          persist-credentials: false
+      - uses: actions/setup-node@v4
+        with:
+          node-version: 22
+          cache: 'npm'
+      - uses: actions/download-artifact@v4
+        with:
+          name: build-${{ github.run_id }}
+      - name: Get zx version info
+        run: |
+          echo SHA_SHORT=$(git rev-parse --short HEAD) >> $GITHUB_ENV
+          echo ZX_VERSION=$(jq -r '.version' package.json) >> $GITHUB_ENV
+      - run: |
+          echo ZX_DEV_VERSION="${{ env.ZX_VERSION }}-dev.${{ env.SHA_SHORT }}" >> $GITHUB_ENV
       - name: pushing to jsr.io
         run: |
           cat <<< $(jq '.version="${{ env.ZX_DEV_VERSION }}"' jsr.json) > jsr.json
.github/workflows/publish.yml
@@ -23,16 +23,17 @@ jobs:
         env:
           FORCE_COLOR: 3
       - run: |
-          node scripts/build-jsr.mjs
-          node scripts/prepublish-clean.mjs
+          npm run build:jsr
+          npm run build:lite
+          npm run build:pkgjson
       - uses: actions/upload-artifact@v4
         with:
           name: build-${{ github.run_id }}
           path: |
             build
             package.json
+            package-lite.json
             jsr.json
-            node_modules/depseek
           retention-days: 1
 
   npm-publish:
@@ -77,10 +78,26 @@ jobs:
 
       - name: pushing lite snapshot to ${{ env.GOOGLE_NPM_REGISTRY }}
         run: |
-          cat <<< $(jq '.name="zx"' package.json) > package.json
-          node scripts/prepublish-lite.mjs
+          mv package-lite.json package.json
           npm publish --provenance --access=public --no-git-tag-version --tag lite --registry https://${{ env.GOOGLE_NPM_REGISTRY }}
 
+  jsr-publish:
+    needs: build
+    runs-on: ubuntu-latest
+    permissions:
+      contents: read
+      id-token: write
+    steps:
+      - uses: actions/checkout@v4
+        with:
+          persist-credentials: false
+      - uses: actions/setup-node@v4
+        with:
+          node-version: 22
+          cache: 'npm'
+      - uses: actions/download-artifact@v4
+        with:
+          name: build-${{ github.run_id }}
       - name: pushing to jsr.io
         run: npx jsr publish --allow-dirty
 
scripts/prepublish-lite.mjs → scripts/build-lite.mjs
@@ -40,8 +40,32 @@ for (const entry of entries) {
   }
 }
 
+const whitelist = new Set([
+  'name',
+  'version',
+  'description',
+  'type',
+  'main',
+  'types',
+  'typesVersions',
+  'exports',
+  'files',
+  'engines',
+  'optionalDependencies',
+  'publishConfig',
+  'keywords',
+  'repository',
+  'homepage',
+  'author',
+  'license',
+])
+
+const __pkgJson = Object.fromEntries(
+  Object.entries(_pkgJson).filter(([k]) => whitelist.has(k))
+)
+
 const pkgJson = {
-  ..._pkgJson,
+  ...__pkgJson,
   version: _pkgJson.version + '-lite',
   exports: {
     '.': {
@@ -59,10 +83,9 @@ const pkgJson = {
       '.': ['./build/core.d.ts'],
     },
   },
-  man: undefined,
   files: [...files].map((f) => path.join('build', f)).sort(),
 }
 
-fs.writeFileSync(pkgJsonFile, JSON.stringify(pkgJson, null, 2))
+fs.writeFileSync('package-lite.json', JSON.stringify(pkgJson, null, 2))
 
-console.log('package.json prepared for zx-lite publishing')
+console.log('package-lite.json prepared for zx-lite publishing')
scripts/prepublish-clean.mjs → scripts/build-pkgjson.mjs
File renamed without changes
test/it/build-npm.test.js
@@ -51,7 +51,7 @@ describe('npm artifact', () => {
         ])
 
         // pack / unpack
-        await $`node scripts/prepublish-clean.mjs`
+        await $`npm run build:pkgjson`
         const pack = await $`npm pack`
         await $`tar xf ${pack}`
         await $`rm ${pack}`.nothrow()
@@ -62,11 +62,22 @@ describe('npm artifact', () => {
         assert.match(stderr, /hello/)
 
         // contents
+        const pkgJson = await fs.readJson(
+          path.resolve(tmp, 'package/package.json')
+        )
         const files = await glob('**/*', {
           cwd: path.resolve(tmp, 'package'),
           absolute: false,
           onlyFiles: true,
         })
+
+        assert.equal(pkgJson.name, 'zx')
+        assert.equal(pkgJson.description, 'A tool for writing better scripts')
+        assert.equal(pkgJson.devDependencies, undefined)
+        assert.equal(pkgJson.prettier, undefined)
+        assert.equal(pkgJson.scripts, undefined)
+        assert.equal(pkgJson.volta, undefined)
+
         assert.deepEqual(
           files.sort(),
           [
@@ -126,8 +137,8 @@ describe('npm artifact', () => {
         ])
 
         // prepare package.json for lite
-        await $`node scripts/prepublish-lite.mjs`
-        await $`node scripts/prepublish-clean.mjs`
+        await $`npm run build:lite`
+        await $`mv package-lite.json package.json`
 
         // pack / unpack
         const pack = await $`npm pack`
@@ -140,18 +151,24 @@ describe('npm artifact', () => {
         assert.match(stderr, /hello/)
 
         // contents
+        const pkgJson = await fs.readJson(
+          path.resolve(tmp, 'package/package.json')
+        )
         const files = await glob('**/*', {
           cwd: path.resolve(tmp, 'package'),
           absolute: false,
           onlyFiles: true,
         })
+
+        assert.equal(pkgJson.name, 'zx')
+        assert.equal(pkgJson.devDependencies, undefined)
+        assert.equal(pkgJson.bin, undefined)
         assert.deepEqual(
           files.sort(),
           [
             'LICENSE',
             'README.md',
             'build/3rd-party-licenses',
-            'build/cli.js',
             'build/core.cjs',
             'build/core.d.ts',
             'build/core.js',
test/it/clean-package-json.test.js
@@ -1,55 +0,0 @@
-// Copyright 2024 Google LLC
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-import assert from 'node:assert'
-import { tempdir, $, path, fs } from '../../build/index.js'
-import { describe, before, after, it } from 'node:test'
-
-const __dirname = path.dirname(new URL(import.meta.url).pathname)
-const root = path.resolve(__dirname, '../../')
-
-describe('package.json artifact', () => {
-  let tmp
-  let t$
-
-  before(async () => {
-    tmp = tempdir()
-    t$ = $({ cwd: tmp, quiet: true })
-
-    await fs.copy(
-      path.resolve(root, 'package.json'),
-      path.resolve(tmp, 'package.json')
-    )
-    await fs.copy(
-      path.resolve(root, 'scripts/clean-package-json.mjs'),
-      path.resolve(tmp, 'scripts/clean-package-json.mjs')
-    )
-  })
-
-  after(() => fs.remove(tmp))
-
-  it('handle exist properties required for publishing', async () => {
-    await t$`node scripts/clean-package-json.mjs`
-    // to throw if manifest is not correct
-    const pkgJson = JSON.parse(
-      fs.readFileSync(path.resolve(tmp, 'package.json'))
-    )
-
-    assert.equal(pkgJson.name, 'zx')
-    assert.equal(pkgJson.description, 'A tool for writing better scripts')
-    assert.equal(pkgJson.prettier, undefined)
-    assert.equal(pkgJson.scripts, undefined)
-    assert.equal(pkgJson.volta, undefined)
-  })
-})
.gitignore
@@ -9,3 +9,4 @@ temp
 test/fixtures/ts-project/build/
 jsr.json
 .npmrc
+package-lite.json
.size-limit.json
@@ -4,10 +4,13 @@
     "path": [
       "build/3rd-party-licenses",
       "build/core.cjs",
-      "build/core.js",
       "build/core.d.ts",
+      "build/core.js",
       "build/deno.js",
+      "build/error.d.ts",
       "build/esblib.cjs",
+      "build/internals.cjs",
+      "build/log.d.ts",
       "build/util.cjs",
       "build/util.d.ts",
       "build/vendor-core.cjs",
@@ -15,7 +18,7 @@
       "README.md",
       "LICENSE"
     ],
-    "limit": "124.85 kB",
+    "limit": "127.60 kB",
     "brotli": false,
     "gzip": false
   },
package.json
@@ -78,6 +78,8 @@
     "build:dts": "tsc --project tsconfig.json && node scripts/build-dts.mjs",
     "build:dcr": "docker build -f ./dcr/Dockerfile . -t zx",
     "build:jsr": "node scripts/build-jsr.mjs",
+    "build:lite": "node scripts/build-lite.mjs",
+    "build:pkgjson": "node scripts/build-pkgjson.mjs",
     "postbuild": "node scripts/build-clean.mjs",
     "docs:dev": "vitepress dev docs",
     "docs:build": "vitepress build docs",