Update author email in package.json #7
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Publish | |
| # Publishes to npm. Provenance attestation (OIDC) is added when the repository | |
| # is public — npm cannot mint it from a private source. | |
| # Requires either npm Trusted Publishing configured for | |
| # SkyLink-API/SkyLink-API-TypeScript-SDK, or an NPM_ACCESS_TOKEN repository secret | |
| # as a fallback. | |
| # | |
| # Trusted publishing needs npm >= 11.5.1 on Node >= 22.14. Node 22 still bundles | |
| # npm 10, which cannot speak OIDC at all and quietly falls back to the token, so | |
| # this job runs on Node 24 and asserts the npm version before it publishes. | |
| # | |
| # Every push to main lints, tests and builds; when package.json holds a version | |
| # that is not on npm yet, it is published. Pushing a `v*` tag still works and | |
| # additionally asserts the tag matches the package version. | |
| on: | |
| push: | |
| branches: [main] | |
| tags: ["v*"] | |
| workflow_dispatch: | |
| permissions: | |
| contents: read | |
| concurrency: | |
| group: publish | |
| cancel-in-progress: false | |
| jobs: | |
| publish: | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| id-token: write | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - uses: actions/setup-node@v6 | |
| with: | |
| node-version: "24" | |
| cache: npm | |
| registry-url: "https://registry.npmjs.org" | |
| # Node 24 bundles npm 11.17, comfortably past the 11.5.1 trusted publishing | |
| # needs. Asserted rather than assumed: on an image carrying an older npm the | |
| # publish would authenticate with the token, skip OIDC, land without an | |
| # attestation — and still report success. | |
| - name: Ensure npm is new enough for OIDC | |
| run: | | |
| NEED=11.5.1 | |
| HAVE=$(npm --version) | |
| if [ "$({ echo "$NEED"; echo "$HAVE"; } | sort -V | head -n1)" != "$NEED" ]; then | |
| echo "npm $HAVE predates $NEED — upgrading so trusted publishing can engage." | |
| npm install -g "npm@^$NEED" | |
| fi | |
| echo "npm $(npm --version) on node $(node --version)" | |
| - run: npm ci | |
| - name: Verify the tag matches the package version | |
| if: startsWith(github.ref, 'refs/tags/') | |
| run: | | |
| TAG="${GITHUB_REF_NAME#v}" | |
| VERSION=$(node -p "require('./package.json').version") | |
| echo "tag=$TAG package=$VERSION" | |
| if [ "$TAG" != "$VERSION" ]; then | |
| echo "::error::Tag v$TAG does not match package version $VERSION" | |
| exit 1 | |
| fi | |
| - name: Verify src/version.ts matches package.json | |
| run: | | |
| PKG=$(node -p "require('./package.json').version") | |
| SRC=$(node -p "require('fs').readFileSync('src/version.ts','utf8').match(/\"([^\"]+)\"/)[1]") | |
| if [ "$PKG" != "$SRC" ]; then | |
| echo "::error::src/version.ts ($SRC) does not match package.json ($PKG)" | |
| exit 1 | |
| fi | |
| - run: npm run lint | |
| - run: npm run typecheck | |
| - run: npm test | |
| - run: npm run build | |
| - name: Check whether this version is already on npm | |
| id: npm | |
| run: | | |
| VERSION=$(node -p "require('./package.json').version") | |
| # Checked on the output, not just the exit status: older npm answers a | |
| # missing version of an existing package with success and an empty line, | |
| # which would mark the release as already published and skip it silently. | |
| if [ -n "$(npm view "skylink-api@$VERSION" version 2>/dev/null)" ]; then | |
| echo "unpublished=false" >> "$GITHUB_OUTPUT" | |
| echo "skylink-api@$VERSION already exists on npm — publish will be skipped." | |
| else | |
| echo "unpublished=true" >> "$GITHUB_OUTPUT" | |
| echo "skylink-api@$VERSION is not on npm yet — it will be published." | |
| fi | |
| - name: Publish to npm | |
| if: steps.npm.outputs.unpublished == 'true' | |
| # npm refuses to mint provenance from a private repository. The flag is | |
| # therefore added only when the source is public, so making the repo | |
| # public is the single action needed to get attestation back — nothing | |
| # here has to change. An unknown visibility is treated as private, which | |
| # costs the attestation rather than the release. | |
| run: | | |
| if [ "${{ github.event.repository.visibility }}" = "public" ]; then | |
| npm publish --provenance --access public | |
| else | |
| echo "::warning::Repository is not public — publishing without provenance." | |
| npm publish --access public | |
| fi | |
| env: | |
| NODE_AUTH_TOKEN: ${{ secrets.NPM_ACCESS_TOKEN }} | |
| # A publish that fell back to the token instead of OIDC still succeeds and | |
| # still reports green; it just lands without an attestation. Catch it here | |
| # rather than on the package page weeks later. Only meaningful once the | |
| # repository is public, since provenance is skipped by design before that. | |
| - name: Verify the published version carries provenance | |
| if: steps.npm.outputs.unpublished == 'true' && github.event.repository.visibility == 'public' | |
| run: | | |
| VERSION=$(node -p "require('./package.json').version") | |
| for attempt in 1 2 3 4 5; do | |
| if npm view "skylink-api@$VERSION" dist.attestations --json 2>/dev/null | grep -q provenance; then | |
| echo "provenance attestation present for $VERSION" | |
| exit 0 | |
| fi | |
| echo "not visible yet (attempt $attempt) — giving the registry a moment" | |
| sleep 5 | |
| done | |
| echo "::error::$VERSION was published without a provenance attestation — the OIDC path did not engage. Check the npm CLI version and the trusted publisher configuration." | |
| exit 1 |