Release and maintain safely

Production quality is a repeatable release process, not a one-time successful publish command.

Communicate change with semantic versions

Patch, 1.0.0 → 1.0.1
A backward-compatible bug fix. Existing documented calls keep working.
Minor, 1.0.0 → 1.1.0
A backward-compatible feature, such as a new optional input or export.
Major, 1.0.0 → 2.0.0
A breaking change, such as removing a field, renaming an export, changing an error type, or dropping a supported runtime.

npm recommends 1.0.0 for a first stable product. Versions below 1.0.0 communicate that the API is still settling. Even during 0.x, document breaking changes and avoid surprising users.

Treat types and schemas as versioned behavior

If contracts changes, run API, SDK, integration, type, tarball, and clean-consumer checks together. Shared contracts increase consistency, but they also make coordinated releases necessary.

Use the same release checklist every time

  1. Choose the next version from consumer-visible change.
  2. Update package versions and internal dependency ranges.
  3. Update README examples and changelog.
  4. Install with the frozen lockfile in CI.
  5. Run typecheck, unit tests, integration tests, and builds.
  6. Run pack dry runs and inspect packed manifests.
  7. Install tarballs in a clean consumer.
  8. Commit and tag the exact release source.
  9. Publish dependencies before dependents.
  10. Verify registry metadata and install from npm.

Automate verification before automating publication

Every pull request should run:

pnpm install --frozen-lockfile
pnpm typecheck
pnpm test
pnpm --filter @your-scope/quiz-contracts build
pnpm --filter @your-scope/quiz-sdk build
pnpm --filter @your-scope/quiz-contracts pack --dry-run
pnpm --filter @your-scope/quiz-sdk pack --dry-run

Only automate publishing after this pipeline is dependable. A fast automatic release of an unchecked tarball is still a bad release.

Prefer trusted publishing for CI

npm trusted publishing uses OpenID Connect to issue short-lived credentials to one approved cloud workflow. It avoids storing a long-lived write token in repository secrets. npm also generates provenance automatically for eligible public packages published this way.

Configure the exact repository and workflow filename in each npm package's Trusted Publisher settings. The workflow needs id-token: write:

name: Publish packages

on:
  push:
    tags:
      - "sdk-v*"

permissions:
  contents: read
  id-token: write

jobs:
  publish:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6
      - uses: actions/setup-node@v6
        with:
          node-version: "24"
          registry-url: "https://registry.npmjs.org"
          package-manager-cache: false
      - run: corepack enable
      - run: pnpm install --frozen-lockfile
      - run: pnpm typecheck
      - run: pnpm test
      - run: pnpm --filter @your-scope/quiz-contracts build
      - run: pnpm --filter @your-scope/quiz-sdk build
      - run: npm --version
      - run: npm publish --access public
        working-directory: packages/contracts
      - run: npm publish --access public
        working-directory: packages/sdk

Why the workflow publishes with npm CLI

As of September 2026, npm's trusted publishing documentation requires npm CLI 11.5.1 or later and Node.js 22.14.0 or later. Continue using pnpm for installation, workspace commands, tests, and builds. Use the supported npm CLI for the OIDC publish exchange, and verify its version in the job.

After trusted publishing works, set package publishing access to require 2FA and disallow traditional tokens. Revoke unused automation tokens.

Make releases traceable

Provenance links a package to its public source repository and build workflow. Configure an exact public repository URL in package.json. Trusted publishing from supported hosted CI generates the provenance attestation automatically for eligible public packages.

Provenance does not prove that code is good. It proves where and how the artifact was produced, which gives consumers evidence they can audit.

Recover without pretending a version can be replaced

Once npm accepts a name and version, publish a new version for the fix. Do not try to rebuild and overwrite the old number.

pnpm deprecate \
  @your-scope/quiz-sdk@1.2.0 \
  "Broken response validation. Upgrade to 1.2.1."

Deprecation leaves the version available but warns installers. npm permits unpublishing only under policy limits, including a broader window during the first 72 hours. Prefer a corrective release and deprecation because removal can break existing dependency graphs.

Production readiness test

A stranger should be able to install one documented package in an empty project, import its declared public API, receive validated runtime behavior, understand its errors, and trace the installed version back to tested source.

If any part of that sentence is false, the release process still has work to do.

Official references

Check your understanding

  1. A release removes an exported field. Is that patch, minor, or major?

    Show answer

    Major after 1.0.0. Existing consumers may compile or run against that field, so removal breaks compatibility.

  2. Why is trusted publishing safer than a long-lived npm write token?

    Show answer

    It issues short-lived credentials only to one approved workflow. There is no reusable write token to leak, copy, or forget to rotate.

  3. What should you do after publishing a broken immutable version?

    Show answer

    Publish a corrected new version and deprecate the broken version with a useful upgrade message. Use unpublish only when npm policy permits it and removal is the least harmful option.