Skip to main content

Multi-Package Release Management (m release)

Framework M provides the m release command suite to automate the complex lifecycle of versioning, changelog generation, dependency pinning, and release tagging across multi-package monorepos and standalone applications.


1. How It Works​

The release system follows the Conventional Commits specification (feat:, fix:, chore:, etc.):

  1. Commit Inspection: Scans git commit messages affecting specific package directories.
  2. SemVer Calculation:
    • Commits with feat(...) trigger minor version bumps (0.1.0 -> 0.2.0).
    • Commits with fix(...) trigger patch version bumps (0.1.0 -> 0.1.1).
    • Breaking changes (feat!: or BREAKING CHANGE:) trigger major bumps (1.0.0 -> 2.0.0).
    • Commits with chore, docs, refactor, test do not trigger version bumps on their own.
  3. Workspace Dependency Sync: Automatically updates dependent packages to point to the newly bumped internal versions.
  4. Changelog Generation: Generates clean, grouped release notes prepended to each package's CHANGELOG.md.
  5. SBOM Generation: Produces a Software Bill of Materials (SBOM) using Syft.
  6. Tagging & Forge Release: Creates annotated git tags (e.g. package-name@v1.2.0) and GitLab/GitHub Releases with release notes.

2. Configuration: release-config.json​

Every project or monorepo using m release defines a release-config.json file in its root directory:

{
"packages": [
{
"name": "my-app-core",
"publish_name": "my-app-core",
"version_file": "packages/core/pyproject.toml",
"paths": ["packages/core"],
"scopes": ["core"],
"include_global": false
},
{
"name": "my-app-ui",
"publish_name": "@my-app/ui",
"version_file": "packages/ui/package.json",
"paths": ["packages/ui"],
"scopes": ["ui"],
"include_global": false
}
],
"sync": [
{
"file": "apps/**/package.json",
"package_name": "my-app-ui"
}
],
"target_branch": "main",
"release_branch": "release/next",
"enable_sbom": true,
"provider": "gitlab"
}

Key Properties​

  • packages: Array of managed packages.
    • name: Internal workspace name.
    • publish_name: Name used for package registry publication (PyPI / NPM).
    • version_file: Path to file holding version string (pyproject.toml or package.json).
    • paths: List of directory paths belonging to this package.
    • scopes: Conventional commit scope names associated with this package (e.g., feat(core): ...).
  • sync: Target files outside the package directory that need their dependency versions synchronized when a package is bumped.
  • provider: Default forge provider (gitlab or github).

3. CLI Commands​

The m release commands are available via framework-m-studio.

1. m release plan​

Preview which packages require version bumps and what those bumps will be without making any changes:

uv run m release plan

# Output as JSON
uv run m release plan --json

2. m release prepare​

Prepares the release branch locally or in CI:

  • Updates version numbers in pyproject.toml or package.json.
  • Synchronizes dependent workspace packages and sync targets.
  • Prepend entries to each package's CHANGELOG.md.
  • Generates SBOM files when enable_sbom is true.
uv run m release prepare --branch release/next

# Dry-run preview
uv run m release prepare --dry-run

3. m release mr​

Creates or updates a Merge Request / Pull Request from the release branch (e.g. release/next) targeting main:

uv run m release mr --branch release/next --target-branch main

4. m release tag​

Scans changelogs and commit history, creates annotated git tags (<package>@v<version>), pushes them to the remote origin, and publishes release entries on GitLab or GitHub:

uv run m release tag

# Preview tags without creating or pushing
uv run m release tag --dry-run

5. m release auto​

Runs the complete automated end-to-end pipeline (used in CI on push to main):

  1. Evaluates commit history.
  2. Checks out the release branch (release/next).
  3. Executes prepare.
  4. Pushes the release branch.
  5. Opens or updates the release Merge Request.
uv run m release auto --provider gitlab

6. m release lint-scopes​

Validates that all files modified in a commit or MR range belong to a known package scope defined in release-config.json:

uv run m release lint-scopes --base origin/main --head HEAD