CI Extension
The @putnami/ci package provides CI/CD automation for Putnami workspaces. It includes git hooks, release orchestration, and provider integrations.
Scope: Git hooks are installed automatically. The release command is workspace-scoped.
External tools
- Git
- Conventional Commits
- GitHub CLI (for releases and PR labelling)
Enable the extension
Install the extension at the workspace root:
bun add @putnami/ciThe extension is auto-discovered from workspace dependencies.
Commands
release
Finalize a workspace release with changelog, git tag, and version bump.
Behavior:
- Waits for all project
publishjobs to complete (npm, docker, assets) - Generates changelog from conventional commits
- Creates git tag for the release version
- Creates GitHub Release with release notes
- Bumps version for next development cycle
Options:
--promote— Perform stable release (required for changelog/tag/bump)--skip-changelog— Skip changelog generation--skip-tag— Skip git tag creation--skip-bump— Skip version bump--dry-run— Preview what would happen
Example:
# Dry run (preview what will happen)
bunx putnami release --dry-run
# Stable release
bunx putnami release --promote
# Skip specific steps
bunx putnami release --promote --skip-changelogCommand Naming Scheme
| Command | Scope | Target | Description |
|---|---|---|---|
build |
project | artifacts | Compile, bundle |
test |
project | - | Run tests |
lint |
project | - | Lint code |
publish |
project | registry/assets | npm, docker registry, binary assets |
deploy |
project | environment | server, cloud, k8s |
release |
workspace | git | Changelog, tag, version bump |
Note: publish always pushes versioned artifacts. --stable additionally promotes mutable tags (latest for npm/docker) and updates binary tag manifests (tag.latest.json).
Installed Git Hooks
On dependency installation, @putnami/ci runs a postinstall script that sets up git hooks in .git/hooks/ (skipped in CI):
pre-commit— blocks commits onmain, runsbunx putnami lint --impactedpre-push— blocks pushes onmaincommit-msg— validates Conventional Commits via commitlint
Conventional Commits
Expected format:
<type>(<scope>): <subject>Common types: feat, fix, docs, style, refactor, test, chore, perf, ci, build, revert.
Automatic version bump detection:
| Commit type | Version bump |
|---|---|
fix: |
patch (0.0.x) |
feat: |
minor (0.x.0) |
feat!: or BREAKING CHANGE: |
major (x.0.0) |
Git Utilities
Provider detection
Detect the Git provider from a repository URL:
import { git } from '@putnami/ci';
const provider = git.detectProvider('git+https://github.com/user/repo.git');
// => 'github'Supported providers: github, gitlab, bitbucket.
Changelog generation
import { git } from '@putnami/ci';
const changelog = await git.generateChangelog('1.0.0');Git tag creation
import { git } from '@putnami/ci';
await git.createGitTag('1.0.0');
await git.pushTags();Release Utilities
import { release } from '@putnami/ci';
// Get workspace version
const version = release.getWorkspaceVersion();
// Bump version
const nextVersion = release.bumpVersion('1.0.0', 'minor');
// => '1.1.0'
// Detect bump type from commits
const bumpType = await release.detectBumpFromCommits();
// => 'patch' | 'minor' | 'major'GitHub Utilities
PR Labeller
The PR labeller adds/removes feat:* labels based on command arguments:
bun run node_modules/@putnami/ci/src/git/github/pr-labeller.ts 123 auth apiThis ensures the PR has feat:auth and feat:api labels.
GitHub Release
Automatically creates a GitHub Release with the generated changelog:
import { git } from '@putnami/ci';
await git.github.createGitHubRelease('1.0.0', changelog);Configuration
commitlint
To extend the default commitlint rules, add commitlint.config.js at the repository root:
module.exports = {
extends: ['@putnami/ci/commitlint.config.js'],
rules: {
// custom rules
},
};Manual hook installation
If hooks need to be reinstalled:
bun run node_modules/@putnami/ci/src/git/install-hooks.tsExamples
# CI workflow: build and publish pre-release (impacted packages only)
bunx putnami build --impacted
bunx putnami publish --impacted
# → npm: @putnami/pkg@1.0.0-abc1234 (canary tag on main, dev on branches)
# → Docker: registry/app:canary (or dev on branches)
# → Assets: gs://<bucket>/<prefix>/v1.0.0-abc1234
# → Manifests: gs://<bucket>/<prefix>/tag.1.0.0-abc1234.json + gs://<bucket>/<prefix>/tag.canary.json (or tag.dev.json)
# Stable release workflow (all packages with same version)
bunx putnami build --all
bunx putnami publish --all --stable
bunx putnami release --promote
# → npm: @putnami/pkg@1.0.0 (latest tag)
# → Docker: registry/app:latest
# → Assets: gs://<bucket>/<prefix>/v1.0.0
# → Manifests: gs://<bucket>/<prefix>/tag.1.0.0.json + gs://<bucket>/<prefix>/tag.latest.json
# → Changelog generated, git tag v1.0.0 created
# → .putnamirc.json version bumped to 1.0.1Next steps
- Previous: Docker