# Release

> Use this skill to publish a new version of @insforge/ui to npm from the InsForge/UI repository, or to diagnose a publish that failed. Publishing runs only through GitHub Actions with npm trusted publishing; there is no token to find.

- Skill: `insforge/release` (Agent Skill)
- Install (CLI): `npx skillmds@latest add insforge/release`
- Raw SKILL.md: https://api.skillmd.com/api/skills/insforge/release/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: insforge (https://skillmd.com/u/insforge)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/insforge/release

---


# Releasing @insforge/ui

A GitHub Release tagged `v<version>` triggers `.github/workflows/publish.yml`. The workflow authenticates with npm trusted publishing: GitHub issues an OIDC token for the run, npm checks it against the trusted publisher registered for the package, and the publish carries provenance. No npm token exists in this repository, its secrets, or any maintainer's environment, and none should be added.

## One-Time Setup on npmjs.com

Done once by a package maintainer, at https://www.npmjs.com/package/@insforge/ui/access → Trusted Publisher → GitHub Actions:

| Field | Value |
| --- | --- |
| Organization or user | `InsForge` |
| Repository | `UI` |
| Workflow filename | `publish.yml` |
| Environment name | leave empty |

The four values must match the workflow exactly. Renaming the repository or the workflow file breaks publishing until the npm side is updated. Creating a Release requires write access to the repository, and that is the whole access control for publishing.

## Cut a Release

1. On a branch, bump the version and the lockfile together:

   ```bash
   npm version <patch|minor|major> --no-git-tag-version
   ```

   Open a PR, merge to `main`, wait for the CI run on `main` to be green.

2. Create the Release. The tag is `v` plus the exact `package.json` version:

   ```bash
   gh release create v<version> --target main --generate-notes
   ```

   Tick pre-release only for a version with a prerelease suffix (`0.2.0-beta.1`); pre-releases publish under the `next` dist-tag instead of `latest`. Drafts do not trigger anything until published.

3. Watch the run and read the authoritative conclusion afterwards (`gh run watch` can exit non-zero for reasons other than failure):

   ```bash
   gh run list --workflow publish.yml --limit 1
   gh run watch <run-id> --exit-status
   gh run view <run-id>
   ```

4. Verify on npm:

   ```bash
   npm view @insforge/ui version dist-tags
   ```

   The package page shows a Provenance section linking back to the workflow run.

5. Move consumers forward: bump the `@insforge/ui` range in the InsForge monorepo (`packages/dashboard/package.json`) and in insforge-cloud (`package.json`), then run `npm install` there.

## When the Workflow Fails

- **"package.json is at X but the release tag is vY"** — tag and version disagree. Bump to a new version and cut a fresh release; do not reuse the tag.
- **"already on npm"** — that version exists. npm never accepts a republish, so bump.
- **`ENEEDAUTH`, `E401`, `E404`, or "Unable to authenticate" at `npm publish`** — the trusted publisher on npmjs.com does not match the run (owner, repository, workflow filename, environment), or npm on the runner is older than 11.5.1. The workflow prints `npm --version` right after upgrading; check it.
- **lint, typecheck, or test failed** — the release ran ahead of CI. Fix on `main`, bump, release again.
- A failed run leaves nothing on npm. Re-running the same release is safe until the publish step has succeeded once.

## Rules

- Publish only through the workflow. A laptop publish has no provenance and skips the checks.
- Never add an npm token to the repository, its secrets, or the workflow.
- Versions are immutable. To retract a bad release, publish a fixed version and deprecate the bad one:

  ```bash
  npm deprecate @insforge/ui@<bad-version> "use <fixed-version>"
  ```

  Deprecation is a manual maintainer action against npm and is the only step in this process that uses a personal login.

