Skip to main content
Version: Next

Core Concepts

This page explains the key ideas behind Cngpac: changenotes, the versioning pipeline, and the plugin architecture.

Changenotes​

A changenote is a small markdown file stored in the .changenotes/ directory at the root of your project. Each changenote describes a single change and specifies its semantic impact.

Format​

---
bump: minor
---

# feat: add dark mode support

Added a new dark mode toggle to the settings page. Users can now
switch between light and dark themes.

A changenote has three parts:

PartDescription
FrontmatterYAML block with a bump field — one of patch, minor, or major
TitleThe heading line (# ...) — used as the git commit message by cngpac commit
BodyOptional description included in the generated changelog

Naming​

Changenotes are automatically given human-readable random IDs like noble-sage-jay.md or brave-coral-fox.md. This avoids merge conflicts when multiple contributors add changenotes to the same branch.

Bump Types​

BumpWhen to useExample
patchBug fixes, docs, refactorsFix a typo in error messages
minorNew features (backwards compatible)Add a new CLI command
majorBreaking changesRename a config option

The highest bump across all changenotes determines the version increment. If you have five patch notes and one minor note, the release will be a minor bump.

The Versioning Pipeline​

Cngpac's release flow has four phases:

1. Setup​

Run cngpac init once to scaffold:

  • A cngpac.config.ts config file
  • A .github/workflows/version.yml CI workflow

2. Development​

For each change that deserves a changelog entry:

  1. cngpac change — Interactively create a changenote file
  2. cngpac commit — Stage and commit the changenote using its title as the commit message
  3. Push and merge your PR as usual

3. Release Prep​

When ready to release:

  1. cngpac prepare release — Reads all changenotes, calculates the next semantic version, and writes a prepare.json file
  2. Push prepare.json to the main branch — this triggers the CI workflow

For pre-releases, use prepare prerelease, prepatch, preminor, or premajor with an optional tag:

cngpac prepare prerelease beta # e.g., 1.3.0-beta.1

4. CI / Automated​

The CI workflow runs:

cngpac version --commit --tag --push --publish --release

This command:

  1. Reads prepare.json for the target version
  2. Bumps package.json
  3. Builds the package (if build is configured and --no-build is not passed)
  4. Generates a changelog via the changelog generator plugin
  5. Saves it via the changelog saver plugin (if configured)
  6. Deletes all consumed changenote files and prepare.json
  7. Runs formatters on changed files
  8. Commits, tags, and pushes
  9. Runs publisher plugins (e.g., npm publish)
  10. Runs releaser plugins (e.g., GitHub Release)

Plugin Architecture​

Cngpac is built around plugin system. Each plugin is a simple function you configure in cngpac.config.ts:

Changelog Generator​

Generates changelog markdown from changenotes. The built-in generator (createChangelogGenerator) fetches GitHub commit metadata and produces a rich changelog with commit links, PR references, and contributor mentions.

Changelog Saver​

Persists the generated changelog to disk. The built-in saver (createChangelogSaver) supports template variables in the filepath:

createChangelogSaver({ filepath: "changelogs/v{version}.md" });

Publisher​

Runs after git push. The built-in npm publisher (createNpmPublisher) publishes to the npm registry with optional provenance attestation. See Publishers for all options and custom publisher docs.

Releaser​

Runs after publishers. The built-in GitHub releaser (createGitHubReleaser) creates a GitHub Release with the changelog as the body. See Releasers for all options and custom releaser docs.

Formatter​

Formats files created or modified by CLI commands. The built-in formatter (createFormatter) delegates to any external tool:

createFormatter({ extensions: ["json", "md"], command: "oxfmt" });

Version​

Customizes the commit message and tag name produced by the version command. By default, Cngpac uses Release {name}@{version} for commits and {name}@{version} for tags. Override either or both via the version config option:

version: {
commitMessage: (bump) => `chore(release): ${bump.packageName}@${bump.newVersion}`,
tagName: (bump) => `v${bump.newVersion}`,
}

Build​

Compiles or bundles the package after the version is bumped in package.json. Configured via the build option as an npm script ({ script: "build" }), shell command ({ command: "npm run build" }), or custom plugin function.


Next: Quick Start →