CI: publish every push to the staging registry

main → latest (the package.json version, skipped if already published), next → next,
other branches → dev-<branch> as <version>-<tag>.<timestamp> prereleases.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017Qxbkp4tA7G5SCWjzWuxmE
This commit is contained in:
Claude
2026-10-23 13:43:51 +00:00
parent 631c75428b
commit ad517965ee
3 changed files with 69 additions and 1 deletions
+27 -1
View File
@@ -2,9 +2,12 @@ name: CI
on:
push:
branches: [main]
branches: ['**'] # not tags
pull_request:
env:
NPM_REGISTRY: https://verdaccio.harvmaster.com/
jobs:
check:
name: Node ${{ matrix.node }}
@@ -28,3 +31,26 @@ jobs:
run: npm run test:only
- name: Build
run: npm run build
# Pushes only (not pull requests): main → `latest`, next → `next`, other branches → `dev-<branch>`.
# See scripts/publish.mjs. Needs the NPM_REGISTRY_TOKEN secret.
staging:
name: Publish to staging registry
needs: check
if: github.event_name == 'push'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: npm
- run: npm ci
- name: Configure registry
run: |
host="${NPM_REGISTRY#https://}"
printf 'registry=%s\n//%s:_authToken=${NPM_REGISTRY_TOKEN}\n' "$NPM_REGISTRY" "$host" > .npmrc
- name: Publish
run: node scripts/publish.mjs "${{ github.ref_name }}"
env:
NPM_REGISTRY_TOKEN: ${{ secrets.NPM_REGISTRY_TOKEN }}
+4
View File
@@ -14,11 +14,15 @@
"import": "./dist/index.js"
}
},
"publishConfig": {
"registry": "https://verdaccio.harvmaster.com/"
},
"files": [
"dist"
],
"scripts": {
"build": "tsc -p tsconfig.build.json",
"prepack": "npm run build",
"typecheck": "tsc --noEmit",
"test": "tsc --noEmit && vitest run",
"test:watch": "vitest",
+38
View File
@@ -0,0 +1,38 @@
// Publishes the package for a branch: `main` → `latest`, `next` → `next`, any other branch →
// `dev-<branch>`. Usage: node scripts/publish.mjs <branch> [--dry-run]
//
// `main` publishes the version in package.json as is, and skips if it is already published (bump
// the version to release). Other branches publish a prerelease, `<version>-<tag>.<timestamp>`,
// so every push gets its own version. The registry and its token come from `.npmrc` / npm config.
import { execFileSync } from 'node:child_process'
import { readFileSync, writeFileSync } from 'node:fs'
const [branch, ...flags] = process.argv.slice(2)
if (!branch) throw new Error('Usage: node scripts/publish.mjs <branch> [--dry-run]')
const dryRun = flags.includes('--dry-run')
const npm = (...args) => execFileSync('npm', args, { encoding: 'utf8', stdio: ['ignore', 'pipe', 'inherit'] }).trim()
const pkg = JSON.parse(readFileSync('package.json', 'utf8'))
const base = pkg.version.replace(/\+.*/, '')
const tag = branch === 'main' ? 'latest' : branch === 'next' ? 'next' : `dev-${branch.replace(/[^0-9A-Za-z-]/g, '-')}`
if (tag === 'latest') {
let published = ''
try {
published = npm('view', `${pkg.name}@${base}`, 'version')
} catch {
// Not found (or the package doesn't exist yet): publish it.
}
if (published) {
console.log(`${pkg.name}@${base} is already published; bump the version in package.json to release.`)
process.exit(0)
}
} else {
const timestamp = new Date().toISOString().replace(/\D/g, '')
pkg.version = `${base}${base.includes('-') ? '.' : '-'}${tag}.${timestamp}`
writeFileSync('package.json', `${JSON.stringify(pkg, null, 2)}\n`)
}
console.log(`Publishing ${pkg.name}@${pkg.version} with tag "${tag}"`)
execFileSync('npm', ['publish', '--tag', tag, ...(dryRun ? ['--dry-run'] : [])], { stdio: 'inherit' })