Merge pull request #15 from avalon-vanguard/develop

📦 cereale is on npm — docs, badge, and trusted publishing
This commit is contained in:
Senrokai
2026-08-20 18:18:05 +02:00
committed by GitHub
4 changed files with 69 additions and 37 deletions
+54 -5
View File
@@ -4,10 +4,28 @@ name: Publish to npm
# not a decision to make it public and immutable, and npm's 72-hour unpublish window makes the # not a decision to make it public and immutable, and npm's 72-hour unpublish window makes the
# second one hard to take back. Run this workflow from the Actions tab when you mean it. # second one hard to take back. Run this workflow from the Actions tab when you mean it.
# #
# Before the first real run: # Authentication is by **trusted publishing** (OIDC): npm exchanges the workflow's
# 1. Create an npm automation token and add it as the NPM_TOKEN repository secret. # short-lived GitHub identity token for a publish token scoped to this package, so no
# 2. Run once with dry_run left as `true` and read the file list it prints. # long-lived npm token has to exist. To enable it, on npmjs.com → the cereale package →
# 3. Run again with dry_run set to `false`. # Settings → Trusted publisher → GitHub Actions, set:
#
# Organization or user: avalon-vanguard
# Repository: cereale
# Workflow filename: release.yml
# Environment: (leave blank — this workflow does not use one)
#
# The workflow filename must match this file's name, and the Environment field must be
# blank unless a matching `environment:` is added to the publish job; npm checks both
# against the OIDC claims and refuses the exchange if either disagrees.
#
# NPM_TOKEN is kept as a fallback. npm's OIDC step is deliberately non-throwing — if the
# trusted publisher is not configured, or the CLI is too old, it logs and falls through
# to token auth. That makes the switch safe to land before the registry side is set up.
# Once a real run shows OIDC working, the NPM_TOKEN secret can be deleted.
#
# Before a real run:
# 1. Run once with dry_run left as `true` and read the file list it prints.
# 2. Run again with dry_run set to `false`.
on: on:
workflow_dispatch: workflow_dispatch:
inputs: inputs:
@@ -18,7 +36,7 @@ on:
permissions: permissions:
contents: read contents: read
id-token: write # required for npm provenance id-token: write # the OIDC identity npm exchanges, and provenance
jobs: jobs:
publish: publish:
@@ -37,6 +55,21 @@ jobs:
cache: 'npm' cache: 'npm'
registry-url: 'https://registry.npmjs.org' registry-url: 'https://registry.npmjs.org'
# Node 22 bundles npm 10.x, which has no OIDC support at all — it would skip
# trusted publishing in silence and fall back to token auth. Trusted publishing
# landed in npm 11.5.0 (lib/utils/oidc.js), so the version is raised and then
# asserted rather than assumed.
- name: Use an npm that can do trusted publishing
run: |
npm install -g npm@latest
V=$(npm --version)
echo "npm $V"
MAJ=${V%%.*}; REST=${V#*.}; MIN=${REST%%.*}
if [ "$MAJ" -lt 11 ] || { [ "$MAJ" -eq 11 ] && [ "$MIN" -lt 5 ]; }; then
echo "::error::npm $V has no OIDC support; trusted publishing needs >= 11.5.0"
exit 1
fi
- name: Install dependencies - name: Install dependencies
run: npm ci run: npm ci
@@ -72,12 +105,28 @@ jobs:
run: npm run verify run: npm run verify
- name: Show exactly what would ship - name: Show exactly what would ship
# `npm publish --dry-run` performs the OIDC token exchange before it short-circuits
# (publish.js calls oidc() ahead of every dryRun branch), so this step is also the
# trusted-publishing smoke test — a dry run proves the exchange without publishing.
#
# verbose, because npm's OIDC step is non-throwing: at the default log level a
# successful exchange and a silent fallback to token auth look identical. Success
# prints `oidc Successfully retrieved and set token`; if that line is missing,
# trusted publishing did not engage. (The reasons it skips are logged at silly.)
env:
NPM_CONFIG_LOGLEVEL: verbose
run: npm publish --dry-run run: npm publish --dry-run
- name: Publish - name: Publish
if: ${{ inputs.dry_run == false }} if: ${{ inputs.dry_run == false }}
# --provenance stays explicit. Under OIDC npm would enable it on its own for a
# public repo, but only when the flag was left at its default; asking for it
# directly just skips that auto-enable and reaches the same place. On the token
# fallback path it is the only thing that produces an attestation at all.
run: npm publish --provenance --access public run: npm publish --provenance --access public
env: env:
# Fallback only. Ignored once the trusted publisher is configured, because npm
# sets its own short-lived token before reading credentials.
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
- name: Summary - name: Summary
+5 -11
View File
@@ -1,5 +1,6 @@
# Cereale # Cereale
[![npm](https://img.shields.io/npm/v/cereale?color=a0784a&label=npm)](https://www.npmjs.com/package/cereale)
[![CI](https://github.com/avalon-vanguard/cereale/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/avalon-vanguard/cereale/actions/workflows/ci.yml) [![CI](https://github.com/avalon-vanguard/cereale/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/avalon-vanguard/cereale/actions/workflows/ci.yml)
[![Docs](https://github.com/avalon-vanguard/cereale/actions/workflows/pages.yml/badge.svg)](https://avalon-vanguard.github.io/cereale/) [![Docs](https://github.com/avalon-vanguard/cereale/actions/workflows/pages.yml/badge.svg)](https://avalon-vanguard.github.io/cereale/)
[![Node ≥20](https://img.shields.io/badge/node-%E2%89%A520-a0784a)](https://github.com/avalon-vanguard/cereale/blob/main/package.json) [![Node ≥20](https://img.shields.io/badge/node-%E2%89%A520-a0784a)](https://github.com/avalon-vanguard/cereale/blob/main/package.json)
@@ -79,20 +80,13 @@ entity, anything with behaviour attached. Reach for Zod when you just want the d
## Installation ## Installation
Not on npm yet: `npm install cereale` does **not** resolve to this library — the name is
unclaimed on the registry. Installing straight from GitHub will not work either, because the
build output is not committed. Until the first publish, install from a clone:
```bash ```bash
git clone https://github.com/avalon-vanguard/cereale npm install cereale
cd cereale
npm install && npm run build
npm pack # → cereale-0.4.0.tgz
# then, from your own project
npm install ../cereale/cereale-0.4.0.tgz
``` ```
Published with [provenance](https://www.npmjs.com/package/cereale), so the registry carries a
verified attestation linking the tarball to the commit it was built from.
Cereale uses **TC39 standard decorators** (since 0.2.0), so no `experimentalDecorators` flag: Cereale uses **TC39 standard decorators** (since 0.2.0), so no `experimentalDecorators` flag:
```json ```json
+10 -15
View File
@@ -814,22 +814,15 @@ export default defineConfig({
</div> </div>
<div> <div>
<p class="compare-label"><span class="pill pill-bad">not on npm yet</span> installing it today</p> <p class="compare-label"><span class="pill pill-ok">on npm</span> installing it</p>
<div class="code"> <div class="code">
<div class="code-head"><span class="name">shell</span></div> <div class="code-head"><span class="name">shell</span></div>
<pre><code data-lang="text" id="install-shell">git clone https://github.com/avalon-vanguard/cereale <pre><code data-lang="text">npm install cereale</code></pre>
cd cereale
npm install &amp;&amp; npm run build
npm pack # → cereale-0.4.0.tgz
# then, from your own project
npm install ../cereale/cereale-0.4.0.tgz</code></pre>
</div> </div>
<p class="pg-note"> <p class="pg-note">
<code class="inline-code">npm install cereale</code> does <strong>not</strong> resolve to Published from CI with <strong>provenance</strong>, so the registry carries a verified
this library — the name is unclaimed on the registry. Installing straight from GitHub attestation linking the tarball to the commit it was built from — visible on the
will not work either: the build output is not committed, so the package would arrive <a href="https://www.npmjs.com/package/cereale">package page</a>.
without its <code class="inline-code">dist/</code>.
</p> </p>
</div> </div>
</div> </div>
@@ -998,9 +991,11 @@ npm install ../cereale/cereale-0.4.0.tgz</code></pre>
cannot reach. Both are errors rather than silent no-ops.</p> cannot reach. Both are errors rather than silent no-ops.</p>
</div> </div>
<div class="note-item"> <div class="note-item">
<h3>It is not on npm yet</h3> <h3>It is still 0.x</h3>
<p><span class="js-version">0.4.0</span> lives in the repository. <code class="inline-code">npm install cereale</code> does not <p><span class="js-version">0.4.0</span> is published, and under semver a 0.x minor bump
resolve to this library — build it from source until it is published.</p> is allowed to break you. Pin the version until 1.0; the
<a href="https://github.com/avalon-vanguard/cereale/blob/main/CHANGELOG.md">changelog</a>
says what moved and why.</p>
</div> </div>
</div> </div>
</div> </div>
-6
View File
@@ -43,12 +43,6 @@
Array.prototype.forEach.call(document.querySelectorAll('.js-version'), function (el) { Array.prototype.forEach.call(document.querySelectorAll('.js-version'), function (el) {
el.textContent = meta.version; el.textContent = meta.version;
}); });
// The install snippet names the tarball npm pack produces; keep it tied to the
// same package.json fact the badge uses instead of hand-bumping it each release.
var shell = document.getElementById('install-shell');
if (shell) {
shell.textContent = shell.textContent.replace(/cereale-[\d.]+\.tgz/g, 'cereale-' + meta.version + '.tgz');
}
} }
if (decoratorCount) { if (decoratorCount) {
Array.prototype.forEach.call(document.querySelectorAll('.js-dec-count'), function (el) { Array.prototype.forEach.call(document.querySelectorAll('.js-dec-count'), function (el) {