Tegami

CI Setup

Run Tegami in your release pipeline.

The tegami ci command is designed for a release pipeline on your main branch. It runs versioning first; only when there is nothing to version does it publish from the existing publish lock.

GitHub Actions

A minimal publish workflow:

.github/workflows/publish.yml
name: Publish

on:
  push:
    branches:
      - main

jobs:
  publish:
    runs-on: ubuntu-latest
    permissions:
      contents: write
      id-token: write
      pull-requests: write
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - uses: pnpm/action-setup@v6

      - uses: actions/setup-node@v6
        with:
          node-version: 24
          cache: pnpm

      - run: pnpm install --frozen-lockfile

      # see the "Build packages" section below for details
      - name: Build packages
        run: pnpm build

      - name: Version & publish packages
        run: pnpm tegami ci
        env:
          GITHUB_TOKEN: ${{ github.token }}

Set id-token: write so npm trusted publishing (OIDC) works without an NPM_TOKEN.

Set pull-requests: write so the GitHub plugin can open Version Packages pull requests. The same GITHUB_TOKEN is also used to create GitHub releases after publish.

Build packages

Tegami does not build your packages, registries publish whatever is on disk.

The example above runs pnpm build before every tegami ci invocation, this will always build all packages before they are published.

To build only packages that are about to be published, use a willPublish plugin. For example, using tinyexec and Turborepo:

scripts/tegami.mts
import { x } from "tinyexec";
import { tegami } from "tegami";
import type { TegamiPlugin } from "tegami";

function buildOnPublish(): TegamiPlugin {
  return {
    name: "build-on-publish",
    async willPublish({ pkg }) {
      const result = await x("turbo", ["run", "build", "--filter", pkg.name], {
        nodeOptions: { cwd: this.cwd },
      });

      if (result.exitCode !== 0) {
        throw new Error(`Failed to build ${pkg.name}`);
      }
    },
  };
}

const paper = tegami({
  // [!code +]
  plugins: [buildOnPublish()],
});

willPublish runs once per package right before it is published. Turborepo's --filter scopes the build to that package and its dependencies.

With this plugin, you can remove the standalone build step from your workflow and rely on tegami ci to build each package at publish time.

With the GitHub plugin enabled, CI follows a two-step flow:

  1. Changelogs committed
    • Maintainers push commits that add .tegami/*.md changelog files.
    • CI runs tegami ci, writes the publish lock.
    • CI opens a Version Packages pull request (at tegami/version-packages by default).
  2. Version PR merges
    • The merged commit contains bumped versions and .tegami/publish-lock.yaml.
    • The next CI run publishes packages and creates GitHub releases.

Because the publish lock lives in git, failed publish jobs can be retried safely without duplicating releases.

To run this flow on more than one branch, e.g. a canary channel, or maintenance branches for older majors, see Multiple Release Lines.

Pull request preview

Use tegami pr preview and tegami pr comment on pull requests to post a release preview comment. The preview renders markdown that:

  1. Introduces Tegami and tells contributors to add changelog files.
  2. Links to create a new changelog file on GitHub.
  3. Shows pending package bumps and changelogs added in the PR.

Split this into two workflows for a better security model.

.github/workflows/tegami-pr.yml
name: Tegami PR

on:
  pull_request:
    types: [opened, synchronize, reopened]

permissions:
  contents: read

jobs:
  preview:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - uses: pnpm/action-setup@v6

      - uses: actions/setup-node@v6
        with:
          node-version: 24
          cache: pnpm

      - run: pnpm install --frozen-lockfile

      - name: Release preview
        run: pnpm tegami pr preview --artifact tegami-pr-preview.md

      - uses: actions/upload-artifact@v4
        with:
          name: tegami-pr-preview
          path: tegami-pr-preview.md

The "Generate Comment" step must use pull_request over pull_request_target, it will run untrusted code.

Only "Post Comment" needs pull-requests: write, and it checks out your default branch instead of the pull request head, so pull requests from forks are commented on without running their code with a writable token.

Custom CLI hooks

runCli accepts optional hooks to replace the default draft() or publish() behavior:

await runCli(paper, {
  version: async () => {
    const draft = await paper.draft();
    // customize the draft before apply
    return draft;
  },
  publish: async () => {
    return paper.publish();
  },
});

See the programmatic API for lower-level control.

On this page