Skip to content

Seamless and automated release management with elegant changelog generation based on Conventional Commits, supporting both monorepos and single packages. Handles version bumping, changelog creation, Git tagging, and publishing to npm, GitHub & GitLab effortlessly.

License

Notifications You must be signed in to change notification settings

LouisMazel/relizy

Repository files navigation

Relizy Logo

Relizy

A tool to manage releases for monorepos and single packages.

Seamless and automated release manager with elegant changelog generation based on Conventional Commits, supporting both monorepos and single packages. Handles version bumping, changelog generation, Git tagging, and publishing to npm, GitHub & GitLab effortlessly.

🎯 Why use this tool?

Imagine you have multiple packages in your project (like a box with several toys). With one command, this tool helps you to:

  1. Update version numbers of your packages automatically
  2. Create changelogs to explain what changed
  3. Publish your packages to npm so others can use them
  4. Create releases on GitHub or GitLab

✨ Features

  • πŸš€ Built on top of changelogen
  • πŸ“¦ Monorepo support with glob pattern matching
  • πŸ”„ Three versioning modes: unified, selective, independent
  • πŸ“ Generate changelogs per package + root aggregate
  • 🏷️ Pre-release support (alpha, beta, rc)
  • πŸ“’ NPM publish with smart tag detection
  • πŸ”— Automatic dependency bumping for workspace dependencies
  • πŸ™ GitHub & GitLab release automation
  • πŸ” 2FA/OTP support for npm publishing
  • πŸŽ›οΈ Custom registry support (private registries, GitHub Packages, etc.)
  • βš™οΈ Multiple configuration files support for different release workflows
  • πŸ”§ Support for npm, yarn, pnpm, and bun (auto-detected)

πŸ“¦ Installation

pnpm add -D relizy

πŸ“¦ Package Manager Support

This tool automatically detects your package manager and uses the appropriate commands:

  • npm - Standard npm registry commands
  • yarn - Supports both Yarn Classic and Yarn Berry
  • pnpm - Optimized for pnpm workspaces
  • bun - Full support for bun package manager

Detection is automatic based on:

  1. packageManager field in package.json
  2. Lock file presence (pnpm-lock.yaml, yarn.lock, package-lock.json, bun.lockb)
  3. npm_config_user_agent environment variable

βš™οΈ Minimal configuration

Create a configuration file in the root of your project. The config file is loaded using c12, which supports multiple formats.

Supported Configuration Formats

You can use any of these formats for your configuration file:

  • JavaScript/TypeScript: .js, .ts, .mjs, .cjs, .mts, .cts
  • JSON: .json, .jsonc, .json5
  • YAML: .yaml, .yml
  • TOML: .toml

Examples:

  • relizy.config.ts (TypeScript - recommended)
  • relizy.config.js (JavaScript)
  • relizy.config.json (JSON)
  • relizy.config.yaml (YAML)

Minimal Configuration Example

TypeScript/JavaScript (recommended):

// relizy.config.ts
import { defineConfig } from 'relizy'

export default defineConfig({
  monorepo: {
    versionMode: 'selective', // 'unified', 'selective', 'independent'
    packages: ['packages/*'], // glob pattern matching
  },
})

JSON:

{
  "monorepo": {
    "versionMode": "selective",
    "packages": ["packages/*"]
  }
}

YAML:

monorepo:
  versionMode: selective
  packages:
    - packages/*

Check all options in the configuration section.

πŸš€ Usage

Available commands

The CLI uses the relizy command:

relizy <command> [options]

1. release - Complete release workflow

Executes the entire release workflow in one command:

  1. Bump versions
  2. Generate changelogs
  3. Commit changes
  4. Create git tag
  5. Push to remote
  6. Publish to npm
  7. Create GitHub/GitLab release
# Complete release
relizy release

# Release with pre-release
relizy release --prerelease --preid beta --tag beta

# Release with custom suffix (see bump --suffix)
relizy release --prerelease --preid beta --suffix abc123

# Without push to remote
relizy release --patch --no-push

# Without GitHub/GitLab release creation
relizy release --patch --no-provider-release

# Without npm publish
relizy release --patch --no-publish

# Without git verification (skip hooks)
relizy release --patch --no-verify

# With npm options
relizy release --patch --registry https://npm.pkg.github.com --access public --otp 123456

# Force even without commits
relizy release --patch --force

Available options:

All options from bump, changelog, publish and provider-release are available, and:

  • --no-push - Don't push changes and tags to remote
  • --no-provider-release - Don't create GitHub/GitLab release
  • --no-publish - Don't publish to npm
  • --no-verify - Skip git hooks during commit
  • --no-commit - Skip commit and tag creation
  • --no-changelog - Skip changelog generation
  • --no-clean - Skip working directory clean check
  • --token <token> - Git token (GitHub or GitLab)
  • --force - Force bump even without commits
  • --yes - Skip confirmation prompt
  • --build-cmd <cmd> - Command to build packages before publish
  • --suffix <suffix> - Custom suffix for prerelease versions (see bump --suffix)

2. bump - Update versions

Updates package version numbers.

# Auto-detect bump type from commits
relizy bump

# Specify bump type
relizy bump --patch    # 1.0.0 β†’ 1.0.1
relizy bump --minor    # 1.0.0 β†’ 1.1.0
relizy bump --major    # 1.0.0 β†’ 2.0.0

# Pre-releases
relizy bump --prerelease --preid beta     # 1.0.0 β†’ 1.0.1-beta.0
relizy bump --premajor --preid alpha      # 1.0.0 β†’ 2.0.0-alpha.0
relizy bump --preminor --preid rc         # 1.0.0 β†’ 1.1.0-rc.0
relizy bump --prepatch --preid beta       # 1.0.0 β†’ 1.0.1-beta.0

# Pre-releases with custom suffix
relizy bump --prepatch --preid beta --suffix abc123    # 1.0.0 β†’ 1.0.1-beta.abc123
relizy bump --prerelease --preid alpha --suffix 20241106  # 1.0.0-alpha.0 β†’ 1.0.0-alpha.20241106

# Options
relizy bump --force      # Force bump even without commits
relizy bump --yes        # Skip confirmation prompt
relizy bump --no-clean   # Skip working directory clean check

Available options:

  • --major - Bump major version
  • --minor - Bump minor version
  • --patch - Bump patch version
  • --prerelease - Bump prerelease version
  • --premajor - Bump premajor version
  • --preminor - Bump preminor version
  • --prepatch - Bump prepatch version
  • --preid <id> - Prerelease identifier (alpha, beta, rc, etc.)
  • --suffix <suffix> - Custom suffix for prerelease versions
  • --force - Force bump even without commits
  • --yes - Skip confirmation prompt
  • --no-clean - Skip working directory clean check
--suffix

The --suffix option allows you to customize the prerelease version number with a custom identifier instead of an auto-incremented number. This is particularly useful for CI/CD pipelines where you want to include build metadata in your version.

How it works:

When you use a prerelease bump type (prepatch, preminor, premajor, or prerelease) with the --suffix option, the version number's prerelease suffix will be replaced with your custom value instead of an auto-incremented number.

Examples:

# Without suffix (default behavior)
relizy bump --prepatch --preid beta
# 1.0.0 β†’ 1.0.1-beta.0

# With custom suffix
relizy bump --prepatch --preid beta --suffix abc123
# 1.0.0 β†’ 1.0.1-beta.abc123

# Incrementing an existing prerelease with suffix
relizy bump --prerelease --preid beta --suffix xyz789
# 1.0.1-beta.0 β†’ 1.0.1-beta.xyz789

# Common CI/CD use case: Git commit SHA
relizy bump --prerelease --preid alpha --suffix $(git rev-parse --short HEAD)
# 1.0.0-alpha.5 β†’ 1.0.0-alpha.a1b2c3d

# Common CI/CD use case: Build number
relizy bump --prepatch --preid rc --suffix ${CI_PIPELINE_ID}
# 2.5.0 β†’ 2.5.1-rc.12345

# Common CI/CD use case: Timestamp
relizy bump --preminor --preid beta --suffix $(date +%Y%m%d%H%M%S)
# 1.0.0 β†’ 1.1.0-beta.20241106153045

Important notes:

  • The --suffix option only works with prerelease bump types (prepatch, preminor, premajor, prerelease)
  • It has no effect on stable release types (patch, minor, major)
  • The suffix can contain letters, numbers, or hyphens
  • Suffix values follow semantic versioning rules for prerelease identifiers

Use cases:

  1. CI/CD Pipelines: Include build numbers, commit SHAs, or timestamps in your prerelease versions
  2. Feature Branches: Create unique prerelease versions for different branches
  3. Testing: Generate identifiable test releases
  4. Reproducible Builds: Track exact build metadata in version numbers

Example in CI/CD (GitHub Actions):

- name: Bump prerelease version
  run: |
    pnpm relizy bump --prerelease --preid beta --suffix ${{ github.sha }}

Example in CI/CD (GitLab CI):

bump:
  script:
    - pnpm relizy bump --prepatch --preid rc --suffix $CI_COMMIT_SHORT_SHA

3. changelog - Generate changelogs

Generates CHANGELOG.md files for each package and at the root.

# Generate all changelogs
relizy changelog

# Specify commit range
relizy changelog --from v1.0.0
relizy changelog --from v1.0.0 --to v1.1.0

# Format after generation
relizy changelog --format-cmd "pnpm lint:fix"

# Without root changelog
relizy changelog --no-root-changelog

Available options:

  • --from <ref> - Start commit reference
  • --to <ref> - End commit reference
  • --format-cmd <cmd> - Command to format CHANGELOGs after generation
  • --no-root-changelog - Skip root changelog generation

4. publish - Publish to npm

Publishes packages to npm registry (or other registry).

# Simple publish
relizy publish

# With custom registry
relizy publish --registry https://npm.pkg.github.com

# With custom tag
relizy publish --tag next

# For scoped packages (public access)
relizy publish --access public

# With 2FA
relizy publish --otp 123456

# Build before publish
relizy publish --build-cmd "pnpm build"

Available options:

  • --registry <url> - Custom npm registry URL
  • --tag <tag> - Publish tag (default: latest for stable, next for prerelease)
  • --access <type> - Access level (public or restricted)
  • --otp <code> - OTP code for 2FA
  • --build-cmd <cmd> - Command to build packages before publish

Automatic tag detection:

  • Stable version (e.g., 1.2.3) β†’ tag latest
  • Prerelease version (e.g., 1.2.3-beta.0) β†’ tag next

5. provider-release - Publish a release to git provider (github or gitlab)

Publishes a release for the latest tag.

# Publish release
relizy provider-release

# With custom token
relizy provider-release --token YOUR_GITHUB_TOKEN

# Force git provider
relizy provider-release --provider github

# Specify range
relizy provider-release --from v1.0.0 --to v1.1.0

Available options:

  • --from <ref> - Start commit reference
  • --to <ref> - End commit reference
  • --token <token> - Git provider token
  • --provider <provider> - Git provider (github or gitlab)

Token:

Multiple ways to provide the token:

  • Command line option (--token)
  • Configuration file (see tokens section)
  • Environment variables (checked in order):
    • GitHub: RELIZY_GITHUB_TOKEN, GITHUB_TOKEN, GH_TOKEN
    • GitLab: RELIZY_GITLAB_TOKEN, GITLAB_TOKEN, GITLAB_API_TOKEN, CI_JOB_TOKEN

Global options

All commands support these global options:

Config File

Use --config to specify a custom configuration file name (without the file extension):

# Use default config (relizy.config.{ts,js,json,yaml,...})
relizy bump --patch

# Use custom config (relizy.standalone.config.{ts,js,json,yaml,...})
relizy bump --config relizy.standalone --patch

# Use another config (relizy.experimental.config.{ts,js,json,yaml,...})
relizy release --config relizy.experimental --minor

Important:

  • The config file name must follow the pattern: <name>.config.<ext> (e.g., myconfig.config.ts, myconfig.config.json)
  • In the --config option, you only specify the <name> part (without .config.<ext>)
  • Supported extensions: .ts, .js, .mjs, .cjs, .mts, .cts, .json, .jsonc, .json5, .yaml, .yml, .toml

Dry Run

Use --dry-run to preview changes without writing files, creating tags, commits, or publishing:

# Preview bump
relizy bump --patch --dry-run

# Preview entire release workflow
relizy release --minor --dry-run

# Preview publish
relizy publish --dry-run

Log Level

Use --log-level to control verbosity:

# Default level (essential information)
relizy bump

# Debug level (detailed information)
relizy release --patch --log-level debug

# Silent level (errors only)
relizy publish --log-level silent

Available levels:

  • silent - Errors only
  • error - Errors and critical warnings
  • warning - Warnings and above
  • normal - Normal information
  • default - Essential information (default)
  • debug - Detailed debugging information
  • trace - Very detailed trace information
  • verbose - Show everything

Examples:

# Clean output with essential info
$ relizy bump --patch
β„Ή 4.2.0 β†’ 4.2.1 (unified mode)
βœ” All 3 package(s) bumped to 4.2.1

# Detailed output for debugging
$ relizy bump --patch --log-level debug
● Loading monorepo configuration
● Version mode: unified
● From: v4.2.0, To: HEAD
● Package patterns: packages/*
● Found 3 package(s)
● Starting bump in unified mode
● Fetching commits from v4.2.0 to HEAD
● Found 5 commits since v4.2.0
● Detected release type from commits: patch
β„Ή 4.2.0 β†’ 4.2.1 (unified mode)
● Writing version to 3 package(s)
● Updating lerna.json version
βœ” All 3 package(s) bumped to 4.2.1

βš™οΈ Configuration

This tool extends changelogen configuration with additional monorepo-specific options. Some options from changelogen are overridden to provide better monorepo support.

Create a relizy.config.ts file at the root of your project:

import { defineConfig } from 'relizy'

export default defineConfig({
  // Standard changelogen configuration
  types: {
    feat: { title: 'πŸš€ Features', semver: 'minor' },
    fix: { title: '🩹 Fixes', semver: 'patch' },
  },

  // Monorepo configuration
  monorepo: {
    versionMode: 'selective',
    packages: ['packages/*'],
    ignorePackageNames: [],
  },

  // Optional configuration
  changelog: {
    formatCmd: 'pnpm lint:fix',
    rootChangelog: true,
  },

  bump: {
    type: 'release',
    preid: undefined,
  },

  publish: {
    private: false,
    tag: 'latest',
    args: [],
  },

  release: {
    push: true,
    release: true,
    publish: true,
    noVerify: false,
  },
})

Configuration options

The configuration extends ChangelogConfig from changelogen with additional monorepo-specific options.

types

Type: Record<string, { title: string, semver?: 'major' | 'minor' | 'patch' } | false>

Description: Defines commit types and their impact on versioning.

  • With semver: Triggers a version bump
    • 'major': Breaking changes β†’ 1.0.0 β†’ 2.0.0
    • 'minor': New features β†’ 1.0.0 β†’ 1.1.0
    • 'patch': Bug fixes β†’ 1.0.0 β†’ 1.0.1
  • Without semver: Appears in changelog but doesn't trigger a bump
  • false: Completely ignored (no changelog, no bump)

Example:

export default defineConfig({
  types: {
    // Trigger a bump
    feat: { title: 'πŸš€ Features', semver: 'minor' },
    fix: { title: '🩹 Fixes', semver: 'patch' },
    perf: { title: 'πŸ”₯ Performance', semver: 'patch' },

    // Appear in changelog but no bump
    docs: { title: 'πŸ“– Documentation' },
    chore: { title: '🏑 Chore' },

    // Completely ignored
    ci: false,
    test: false,
  },
})

monorepo

Monorepo-specific configuration (required).

Property Type Default Description
versionMode 'unified' | 'selective' | 'independent' 'selective' How versions are managed across packages
packages string[] ['packages/*'] Glob patterns to locate packages
ignorePackageNames string[] [] Package names to ignore

Version modes:

Mode Version Scope Root & Lerna Best for
selective ⭐ Unified Only packages with commits βœ… Updated Most monorepos
unified Unified ALL packages βœ… Updated Keep all packages synchronized
independent Independent Only packages with commits ❌ Unchanged Collections of unrelated tools

Examples:

export default defineConfig({
  // Selective mode (recommended) - Only bump packages with commits
  monorepo: {
    versionMode: 'selective',
    packages: ['packages/*'],
  },

  // Unified mode - Bump ALL packages together
  // monorepo: {
  //   versionMode: 'unified',
  //   packages: ['packages/*', 'tools/*'],
  // },

  // Independent mode - Each package has its own version
  // monorepo: {
  //   versionMode: 'independent',
  //   packages: ['packages/*'],
  //   ignorePackageNames: ['@myorg/internal-utils'],
  // },
})

changelog

Changelog generation configuration.

Property Type Default Description
formatCmd string undefined Command to format changelogs after generation
rootChangelog boolean true Generate root CHANGELOG.md with aggregated changes
includeCommitBody boolean false Include full commit bodies in changelog entries

Example:

export default defineConfig({
  changelog: {
    formatCmd: 'pnpm lint:fix',
    rootChangelog: true,
    includeCommitBody: true,
  },
})

bump

Version bump configuration.

Property Type Default Description
type 'release' | 'major' | 'minor' | 'patch' | 'prerelease' | ... 'release' Default bump type ('release' auto-detects from commits)
preid string undefined Pre-release identifier (alpha, beta, rc, etc.)
clean boolean true Check if working directory is clean before bumping
dependencyTypes Array<'dependencies' | 'devDependencies' | 'peerDependencies'> ['dependencies'] Which dependency types trigger a version bump
yes boolean true Skip confirmation prompt

Dependency types: When a package is updated, this decides which dependent packages should also be bumped:

  • dependencies - Packages that need it to work
  • devDependencies - Packages that need it for building/testing
  • peerDependencies - Packages that work alongside it

Example:

export default defineConfig({
  bump: {
    type: 'release',
    dependencyTypes: ['dependencies', 'devDependencies'],
    clean: true,
    yes: true,
  },
})

publish

npm publishing configuration.

Property Type Default Description
private boolean false Don't publish packages
tag string 'latest' npm tag (auto: 'latest' for stable, 'next' for pre)
registry string undefined Custom registry URL
access 'public' | 'restricted' undefined Package access level
otp string undefined One-time password for 2FA
buildCmd string undefined Command to build packages before publish
args string[] [] Additional arguments for publish command

Example:

export default defineConfig({
  publish: {
    private: false,
    tag: 'latest',
    registry: 'https://registry.npmjs.org',
    access: 'public',
    buildCmd: 'pnpm build',
  },
})

release

Release workflow configuration.

Property Type Default Description
commit boolean true Commit changes and create tag
push boolean true Push changes and tags to remote
changelog boolean true Generate changelog files
release boolean true Create release on GitHub/GitLab
publish boolean true Publish to npm
clean boolean true Check if working directory is clean
noVerify boolean false Skip git hooks during commit
force boolean false Force bump even without commits

Example:

export default defineConfig({
  release: {
    commit: true,
    push: true,
    changelog: true,
    release: true,
    publish: true,
    noVerify: false,
  },
})

repo

Git repository configuration (auto-detected by default).

Property Type Default Description
provider 'github' | 'gitlab' Auto-detected Git provider (auto from remote URL)
domain string undefined Custom domain for self-hosted instance
repo string Auto-detected Repository in 'owner/repo' format
token string From env vars Authentication token

Auto-detection:

  • Provider: Detected from git remote URL (github.com β†’ GitHub, gitlab.com β†’ GitLab)
  • Repository: Parsed from git remote URL
  • Token: Read from environment variables (see tokens section)

Example:

export default defineConfig({
  // For self-hosted GitLab
  repo: {
    provider: 'gitlab',
    domain: 'gitlab.mycompany.com',
  },
})

tokens

Authentication tokens for git providers (read from environment variables by default).

Property Type Default Description
github string From env vars GitHub authentication token
gitlab string From env vars GitLab authentication token

Environment variables checked (in order):

  • GitHub: RELIZY_GITHUB_TOKEN, GITHUB_TOKEN, GH_TOKEN
  • GitLab: RELIZY_GITLAB_TOKEN, GITLAB_TOKEN, GITLAB_API_TOKEN, CI_JOB_TOKEN

Example:

export default defineConfig({
  tokens: {
    github: process.env.GITHUB_TOKEN,
    gitlab: process.env.GITLAB_TOKEN,
  },
})

templates

Templates for commit and tag messages.

Property Type Default Description
commitMessage string 'chore(release): bump version to {{newVersion}}' Commit message template
tagMessage string 'Bump version to v{{newVersion}}' Git tag message template
tagBody string 'v{{newVersion}}' Git tag body (not used in independent mode)
emptyChangelogContent string 'No relevant changes for this release' Changelog content when no changes

Available variables: {{newVersion}}, {{oldVersion}}, {{packageName}}

Example:

export default defineConfig({
  templates: {
    commitMessage: 'chore(release): v{{newVersion}} [skip ci]',
    tagMessage: 'Release {{newVersion}}',
    tagBody: 'Version {{newVersion}}',
  },
})

logLevel

Control verbosity of command output.

Type: 'silent' | 'error' | 'warning' | 'normal' | 'default' | 'debug' | 'trace' | 'verbose'

Default: 'default'

See Log Level section for details.

Inherited from Changelogen

The following options are inherited from changelogen configuration:

Property Type Default Description
cwd string process.cwd() Working directory
from string Last git tag Start reference for changelog
to string HEAD End reference for changelog
excludeAuthors string[] [] List of authors to exclude from changelog
noAuthors boolean false Don't include authors in changelog
scopeMap Record<string, string> {} Map scopes to custom names

Example:

export default defineConfig({
  cwd: process.cwd(),
  from: 'v1.0.0',
  to: 'HEAD',
  excludeAuthors: ['bot[bot]', 'dependabot'],
  noAuthors: false,
  scopeMap: {
    ui: 'User Interface',
    api: 'API',
  },
})

Configuration Examples

Simple configuration (selective mode)

import { defineConfig } from 'relizy'

export default defineConfig({
  types: {
    feat: { title: 'πŸš€ Features', semver: 'minor' },
    fix: { title: '🩹 Fixes', semver: 'patch' },
  },
  monorepo: {
    versionMode: 'selective',
    packages: ['packages/*'],
  },
})

Advanced configuration

import { defineConfig } from 'relizy'

export default defineConfig({
  types: {
    feat: { title: 'πŸš€ Features', semver: 'minor' },
    fix: { title: '🩹 Fixes', semver: 'patch' },
    perf: { title: 'πŸ”₯ Performance', semver: 'patch' },
    docs: { title: 'πŸ“– Documentation' },
    chore: { title: '🏑 Chore' },
    ci: false,
    test: false,
  },

  monorepo: {
    versionMode: 'selective',
    packages: ['packages/*', 'tools/*'],
    ignorePackageNames: ['@myorg/eslint-config'],
  },

  changelog: {
    formatCmd: 'pnpm lint:fix',
    rootChangelog: true,
  },

  bump: {
    type: 'release',
  },

  publish: {
    private: false,
    tag: 'latest',
  },

  release: {
    push: true,
    release: true,
    publish: true,
    noVerify: false,
  },

  templates: {
    commitMessage: 'chore(release): v{{newVersion}}',
  },
})

Configuration for self-hosted GitLab

import { defineConfig } from 'relizy'

export default defineConfig({
  repo: {
    domain: 'gitlab.mycompany.com',
    provider: 'gitlab',
  },
  monorepo: {
    versionMode: 'selective',
    packages: ['packages/*'],
  },
})

πŸ“ Multiple Configuration Files

You can create multiple configuration files to manage different release workflows in your monorepo. This is useful when you have packages with different versioning strategies or release cadences.

Use Cases

Common scenarios for multiple configs:

  1. Separate core packages from standalone utilities - Core UI packages use selective mode together, while standalone utilities use independent mode
  2. Different release cadences - Stable packages vs experimental packages
  3. Different registries - Public npm vs private registry
  4. Different package groups - Apps vs libraries vs tools

How to Create Multiple Configs

Create multiple configuration files following this naming pattern: <name>.config.<ext>

Example file structure:

/
β”œβ”€β”€ relizy.config.ts              # Main config (core packages)
β”œβ”€β”€ relizy.standalone.config.ts   # Standalone utilities config
└── relizy.experimental.config.json # Experimental packages config

You can use any supported format (.ts, .js, .json, .yaml, etc.) for each config file.

Example: Core UI Packages vs Standalone Utilities

This is a real-world example where you want to separate UI components (which should be released together) from standalone utilities (which can evolve independently).

relizy.config.ts - Core UI packages (selective mode):

import { defineConfig } from 'relizy'

export default defineConfig({
  types: {
    feat: { title: 'πŸš€ Features', semver: 'minor' },
    fix: { title: '🩹 Fixes', semver: 'patch' },
  },
  monorepo: {
    versionMode: 'selective',
    packages: [
      'packages/lib',
      'packages/icons',
      'packages/themes',
      'packages/nuxt',
      'packages/translations',
    ],
  },
  templates: {
    commitMessage: 'chore(release): v{{newVersion}}',
  },
})

relizy.standalone.config.ts - Standalone utilities (independent mode):

import { defineConfig } from 'relizy'

export default defineConfig({
  types: {
    feat: { title: 'πŸš€ Features', semver: 'minor' },
    fix: { title: '🩹 Fixes', semver: 'patch' },
  },
  monorepo: {
    versionMode: 'independent',
    packages: [
      'packages/utils',
      'packages/node',
      'packages/changelogen-monorepo',
      'packages/eslint-config',
    ],
  },
  templates: {
    commitMessage: 'chore(release): {{packageName}}@{{newVersion}}',
  },
  changelog: {
    rootChangelog: false, // No root changelog for independent packages
  },
})

Usage with Multiple Configs

# Release core UI packages together (selective mode)
pnpm relizy release --patch
# or explicitly
pnpm relizy release --config changelog --patch

# Release standalone utilities independently
pnpm relizy release --config changelog.standalone --patch

# You can also use different configs for different commands
pnpm relizy bump --config changelog.standalone --minor
pnpm relizy changelog --config changelog.standalone
pnpm relizy publish --config changelog.standalone

Example: Different Registries

relizy.config.ts - Public packages (npm registry):

import { defineConfig } from 'relizy'

export default defineConfig({
  monorepo: {
    versionMode: 'selective',
    packages: ['packages/public/*'],
  },
  publish: {
    registry: 'https://registry.npmjs.org',
    access: 'public',
  },
})

changelog.private.config.ts - Private packages (GitHub Packages):

import { defineConfig } from 'relizy'

export default defineConfig({
  monorepo: {
    versionMode: 'independent',
    packages: ['packages/private/*'],
  },
  publish: {
    registry: 'https://npm.pkg.github.com',
    access: 'restricted',
  },
})
# Publish public packages to npm
pnpm relizy publish

# Publish private packages to GitHub Packages
pnpm relizy publish --config changelog.private

Best Practices

  1. Use descriptive config names - relizy.standalone.config.ts is better than relizy.alt.config.ts
  2. Document your workflow - Add comments in your config files explaining the purpose
  3. Keep it simple - Don't create too many configs unless necessary
  4. Version control - Commit all config files to your repository
  5. CI/CD integration - Use different configs in different CI jobs if needed

Tips

  • The default config is relizy.config.<ext> where c12 will auto-detect the extension (you don't need --config flag)
  • Config files must follow the pattern <name>.config.<ext> (c12 requirement)
  • Supported formats: .ts, .js, .mjs, .cjs, .mts, .cts, .json, .jsonc, .json5, .yaml, .yml, .toml
  • All commands support the --config option
  • You can combine --config with --dry-run to preview different workflows

πŸ”— Dependency Management

The tool automatically detects and bumps packages that depend on other packages in the monorepo.

How it works

Automatic detection:

  • When package B is updated, all packages that depend on B are automatically identified
  • By default only dependencies are considered (not devDependencies or peerDependencies). You can change this behavior using the dependencyTypes option.
  • Transitive dependencies are handled: if Aβ†’Bβ†’C and C is updated, both B and A are bumped

Bump types by mode:

  • Selective/unified mode: Dependent packages get the same unified version as the root
  • Independent mode: Dependent packages get a minimum patch bump (can be higher if they also have commits)

Example:

Packages:
  - @maz-ui/utils@1.0.0
  - @maz-ui/components@2.0.0 (depends on @maz-ui/utils)
  - @maz-ui/forms@1.5.0 (depends on @maz-ui/components)

Commit: feat(utils): add new utility

Result in Independent mode:
  - @maz-ui/utils: 1.0.0 β†’ 1.1.0 (minor - from commit)
  - @maz-ui/components: 2.0.0 β†’ 2.0.1 (patch - dependency updated)
  - @maz-ui/forms: 1.5.0 β†’ 1.5.1 (patch - transitive dependency)

Result in Selective mode:
  - All 3 packages: bumped to unified version 2.1.0
  - Root version: 2.0.0 β†’ 2.1.0

πŸ”„ Lerna Integration

Automatic lerna.json updates

If a lerna.json file exists at the root, the tool automatically updates its version field during bump (in unified and selective modes only).

No lerna.json? No problem! The tool works perfectly without it.

Replacing Lerna commands

Lerna command relizy equivalent
lerna version patch relizy release --patch
lerna version minor relizy release --minor
lerna version major relizy release --major
lerna version prerelease --preid beta relizy release --prerelease --preid beta
lerna publish from-package Not needed (use pnpm publish -r)

Migration from Lerna

  1. Keep your existing lerna.json (optional)
  2. Create a relizy.config.ts with your versioning strategy
  3. Replace lerna version with relizy release
  4. Use your package manager to publish (e.g., pnpm publish -r)

🦊 GitLab CI/CD Configuration

Personal Access Token

  1. Go to GitLab β†’ Settings β†’ Access Tokens
  2. Create a token with api scope
  3. Set the environment variable:
GITLAB_TOKEN="your-token-here"

CI/CD Pipeline

GitLab CI automatically provides CI_JOB_TOKEN which can be used for releases:

release:
  stage: deploy
  script:
    - pnpm install
    - pnpm relizy release --yes
  only:
    - main

Programmatic Usage (API)

You can also use the tool programmatically:

import {
  bump,
  changelog,
  providerRelease,
  publish,
  release,
} from 'relizy'

// Bump versions
await bump({
  type: 'prerelease',
  preid: 'beta',
})

// Generate changelogs
await changelog({
  from: 'v1.0.0',
  to: 'v1.1.0',
})

// Publish to npm
await publish({
  registry: 'https://registry.npmjs.org',
  tag: 'beta',
})

// GitHub release
// Git provider is detected automatically but you can also specify it explicitly
await providerRelease({
  provider: 'github',
})

// Complete workflow
await release({
  type: 'prerelease',
  preid: 'beta',
  tag: 'beta',
  registry: 'https://registry.npmjs.org',
  push: true,
  release: true,
  publish: true,
})

License

MIT

About

Seamless and automated release management with elegant changelog generation based on Conventional Commits, supporting both monorepos and single packages. Handles version bumping, changelog creation, Git tagging, and publishing to npm, GitHub & GitLab effortlessly.

Topics

Resources

License

Code of conduct

Stars

Watchers

Forks

Packages

No packages published

Contributors 2

  •  
  •