Sign in

    moon-release

    Automated release management tool for MoonBit

    release
    changelog
    semver
    conventional-commits
    Download zip
    Author
    Version
    0.3.1
    License
    MIT
    Last updated
    8 months ago
    Downloads
    48

    #moon-release

    Automated release management tool for MoonBit projects. Inspired by release-plz, optimized for the MoonBit ecosystem.

    #Features

    • Conventional Commits - Automatically determine semantic version from commits
    • GitHub Release - Automatic creation of tags and release notes
    • Release PR - Automatic creation and update of release pull requests
    • mooncakes.io - Automatic publishing to the MoonBit package registry
    • npm - Automatic publishing to the npm registry
    • API Compatibility Check - semver-checks for breaking change detection
    • Monorepo Support - Version synchronization via version_group

    #Table of Contents

    #GitHub Actions

    This is the primary way to use moon-release. Set up CI/CD to automatically create release PRs, create GitHub Releases with tags, and optionally publish to mooncakes.io / npm.

    #Required Setup

    #1. Repository Permissions

    Go to Settings → Actions → General → Workflow permissions:

    • Select "Read and write permissions"
    • Check "Allow GitHub Actions to create and approve pull requests"

    Without these settings, moon-release cannot create release PRs.

    #2. Workflow File Setup

    Copy templates/release.yml to .github/workflows/release.yml and change BINARY_NAME to your project's binary name.

    mkdir -p .github/workflows curl -fsSL -o .github/workflows/release.yml \ https://raw.githubusercontent.com/dijdzv/moon-release/main/templates/release.yml

    The template includes three jobs:

    JobTriggerDescription
    release-prPush to main (non-release commits)Creates/updates a release PR with version bump
    buildRelease PR mergedBuilds binaries for Linux, macOS, Windows
    releaseAfter build completesCreates Git tag + GitHub Release + uploads binaries + publishes to mooncakes.io

    Key points:
    • fetch-depth: 0 - Required to analyze commit history
    • GITHUB_TOKEN - Automatically provided by GitHub Actions
    • Supports dry-run and build-only modes via manual workflow dispatch

    With this setup, merging a release PR will automatically create a Git tag, a GitHub Release with release notes, and upload cross-platform binaries. No additional secrets are needed for the base workflow.

    #Publishing to mooncakes.io (Optional)

    To also publish to mooncakes.io when releasing, add mooncakes credentials to the release job.

    #1. Configure GitHub Secrets

    First, authenticate locally and register the credentials as GitHub Secrets:

    # Authenticate with mooncakes.io (creates ~/.moon/credentials.json) moon login

    If you have jq and gh installed, you can register the secrets in one step:

    #!/usr/bin/env bash set -euo pipefail CREDS="$HOME/.moon/credentials.json" if [ ! -f "$CREDS" ]; then echo "Error: $CREDS not found. Run 'moon login' first." exit 1 fi TOKEN=$(jq -r '.token' "$CREDS") USERNAME=$(jq -r '.username' "$CREDS") if [ -z "$TOKEN" ] || [ "$TOKEN" = "null" ]; then echo "Error: token not found in $CREDS" exit 1 fi if [ -z "$USERNAME" ] || [ "$USERNAME" = "null" ]; then echo "Error: username not found in $CREDS" exit 1 fi echo "Setting MOONCAKES_TOKEN..." echo "$TOKEN" | gh secret set MOONCAKES_TOKEN echo "Setting MOONCAKES_USERNAME..." echo "$USERNAME" | gh secret set MOONCAKES_USERNAME echo "Done! Mooncakes credentials registered as GitHub Secrets."

    Or set them manually at Settings → Secrets and variables → Actions → New repository secret:

    Secret NameValue
    MOONCAKES_TOKENThe token value from ~/.moon/credentials.json
    MOONCAKES_USERNAMEThe username value from ~/.moon/credentials.json

    #2. Workflow Configuration

    The template already includes the mooncakes credentials setup step. Just configure the GitHub Secrets above — no workflow changes are needed.

    No changes to release.json are needed — moon_publish is true by default.

    Warning: mooncakes.io does not currently provide limited-scope tokens for CI use. The token in ~/.moon/credentials.json may have full account permissions. Use at your own risk with this understanding.

    #Publishing to npm (Optional)

    moon-release uses npm Trusted Publishing (OIDC) for secure, tokenless authentication.

    #1. Configure Trusted Publishing on npmjs.com

    1. Go to npmjs.com → your package → Settings → Configure Trusted Publishing
    2. Add a new trusted publisher:
      • Repository owner: Your GitHub username or organization
      • Repository name: Your repository name
      • Workflow filename: release.yml (or your workflow file)
      • Environment: (leave empty or set if using environments)

    If this is a new package, you need to publish it once manually first:
    npm publish --access public

    #2. Update Configuration

    Enable npm publishing in release.json:

    { "npm_publish": true, "npm_build_command": "moon build --target js" }

    #3. Update Workflow

    Add id-token: write permission and a Node.js setup step to the release job:

    release: runs-on: ubuntu-latest permissions: contents: write id-token: write # Required for npm Trusted Publishing # ... steps: # ... (after Checkout, before Create Release) - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: '24'

    Trusted Publishing is more secure than access tokens:
    • No secrets to store or rotate
    • Short-lived tokens generated per-workflow
    • Scoped to specific repository and workflow

    #Execution Order

    When npm_publish is enabled, moon-release executes in this order:

    1. Build JS target - Runs npm_build_command (default: moon build --target js)
    2. Create Git tag
    3. Create GitHub Release
    4. Publish to mooncakes.io (if moon_publish: true)
    5. Publish to npm

    If the JS build fails, no tag or release is created (atomic operation).

    #Configuration Summary

    SettingRequiredWhere to Configure
    Repository write permissionsYesSettings → Actions → General
    Allow PR creationYesSettings → Actions → General
    GITHUB_TOKENYes (auto)Automatically provided
    MOONCAKES_TOKENFor mooncakes publishSettings → Secrets
    MOONCAKES_USERNAMEFor mooncakes publishSettings → Secrets
    id-token: writeFor npm publishWorkflow permissions
    Trusted PublishingFor npm publishnpmjs.com package settings

    #Workflow Template

    See templates/release.yml for a complete example.

    Recommended: Pin the moon-release version in your workflow to avoid unexpected breaking changes. The template uses minor version pinning (bash -s -- 0.2) which auto-updates patch releases. Check Releases for the latest version.

    To always use the latest version instead, remove the version argument:
    curl -fsSL https://raw.githubusercontent.com/dijdzv/moon-release/main/install.sh | bash

    #Configuration

    Customize behavior with release.json.

    { "pr_title": "chore: release v{{ version }}", "pr_draft": false, "pr_labels": ["release"], "pr_body": "## Release v{{ version }}", "pr_branch_prefix": "release/", "base_branch": "main", "allow_prerelease": false, "git_tag_enable": true, "git_tag_name": "v{{ version }}", "git_release_enable": true, "git_release_draft": false, "git_release_name": "Release v{{ version }}", "git_release_body": "{{ changelog }}", "git_release_latest": true, "moon_publish": true, "moon_publish_frozen": false, "moon_publish_timeout": 300, "npm_publish": false, "npm_build_command": null, "npm_publish_provenance": true, "npm_publish_timeout": 300, "semver_check": false, "registry_check": false, "allow_dirty": false, "custom_major_increment_regex": null, "custom_minor_increment_regex": null, "max_analyze_commits": null, "bump_all_packages": false, "bootstrap_sha": null, "packages": [] }

    #Configuration Options

    OptionDefaultDescription
    pr_title"chore: release v{{ version }}"PR title template
    pr_draftfalseCreate as draft PR
    pr_labels[]Labels to add to PR
    pr_body-PR body template
    pr_branch_prefix"release/"Release branch prefix
    base_branch"main"PR base branch
    allow_prereleasefalseAllow prerelease versions (e.g., --prerelease alpha)
    git_tag_enabletrueWhether to create Git tag
    git_tag_name"v{{ version }}"Tag name template
    git_release_enabletrueWhether to create GitHub Release
    git_release_draftfalseCreate as draft release
    git_release_name"Release v{{ version }}"Release name template
    git_release_bodynullRelease body template (null for auto-generate)
    git_release_latesttrueMark GitHub Release as latest
    moon_publishtrueWhether to publish to mooncakes.io
    moon_publish_frozenfalseUse moon publish --frozen
    moon_publish_timeout300Publish timeout in seconds
    npm_publishfalseWhether to publish to npm registry
    npm_build_commandnullCustom build command before npm publish (default: moon build --target js). Note: split by spaces, paths with spaces are not supported.
    npm_publish_provenancetrueUse --provenance flag for npm publish. Set to false for local or non-GitHub CI publishing.
    npm_publish_timeout300npm publish timeout in seconds
    semver_checkfalseRun API compatibility check
    registry_checkfalseCheck registry version before publish
    allow_dirtyfalseAllow uncommitted changes
    custom_major_increment_regexnullCustom substring pattern for major bump (matched against commit description)
    custom_minor_increment_regexnullCustom substring pattern for minor bump (matched against commit description)
    max_analyze_commitsnullMaximum number of commits to analyze
    bump_all_packagesfalseBump all packages uniformly in monorepo mode (fixed versioning)
    bootstrap_shanullStarting commit SHA for commit analysis (skips earlier history). Useful when migrating from another release tool. Once the first release is created, this setting is automatically ignored.

    #Template Variables

    VariableDescription
    {{ version }}New version number
    {{ changelog }}Auto-generated release notes (git_release_body only)

    #Conventional Commits

    moon-release parses Conventional Commits to automatically determine the version.

    Commit TypeBumpExample
    featMinorfeat: add new feature
    fixPatchfix: resolve bug
    feat! / fix!Majorfeat!: breaking change
    BREAKING CHANGE:MajorIn footer

    Other types (docs, style, refactor, perf, test, build, ci, chore) do not affect the version.

    #API Compatibility Check (semver_check)

    Setting semver_check: true detects breaking API changes before release.

    { "semver_check": true }

    #Detected Changes

    ChangeImpact
    Removal of pub type/function/methodBreaking (Major)
    Signature changeBreaking (Major)
    Struct field removal/changeBreaking (Major)
    Addition of new pub type/functionAddition (Minor)

    #How It Works

    1. Checkout latest tag → Generate API with moon doc
    2. Return to current code → Generate API with moon doc
    3. Compare the two package_data.json files
    4. Display warning if breaking changes are found

    #Monorepo Support

    For monorepos with multiple packages, configure each package individually with packages.

    { "packages": [ { "name": "core", "path": "packages/core", "moon_publish": true, "npm_publish": true, "version_group": "main" }, { "name": "utils", "path": "packages/utils", "moon_publish": true, "npm_publish": false, "version_group": "main" }, { "name": "internal", "path": "packages/internal", "moon_publish": false, "npm_publish": false } ] }

    #Versioning Strategies

    #Independent (default)

    Only packages with changes are bumped. Each package gets its own bump type based on its commits.

    # Only changed packages are bumped moon-release update # Force major bump on changed packages only moon-release update --bump major

    #Fixed (bump_all_packages or --bump-all)

    All packages are bumped uniformly using the highest bump type found across changed packages.

    { "bump_all_packages": true }

    Or use the CLI flag for one-time override:

    # Bump all packages (uses max bump type from changed packages) moon-release update --bump-all # Force major bump on ALL packages moon-release update --bump major --bump-all

    Config bump_all_packagesCLIBehavior
    false(none)Changed packages only, auto bump type
    false--bump majorChanged packages only, forced major
    false--bump-allAll packages, max bump type from changes
    false--bump major --bump-allAll packages, forced major
    true(none)All packages, max bump type from changes
    true--bump majorAll packages, forced major

    Note: --bump controls the bump type (major/minor/patch), while --bump-all controls the bump scope (changed-only vs all packages).

    #version_group

    Packages with the same version_group are aligned to the largest bump type within the group.

    Example: If core has a breaking change and utils has a feat, both will receive a major bump.

    #CLI Usage

    moon-release can also be used as a standalone CLI tool for local development and debugging.

    #Installation

    moon install dijdzv/moon-release

    #Install script

    curl -fsSL https://raw.githubusercontent.com/dijdzv/moon-release/main/install.sh | bash

    Pin to a specific version:

    # Pin to minor version (recommended: auto-updates patch releases) curl -fsSL https://raw.githubusercontent.com/dijdzv/moon-release/main/install.sh | bash -s -- 0.2 # Pin to exact version curl -fsSL https://raw.githubusercontent.com/dijdzv/moon-release/main/install.sh | bash -s -- 0.2.8

    Installs to ~/.local/bin by default. Override with INSTALL_DIR:

    INSTALL_DIR=/usr/local/bin curl -fsSL https://raw.githubusercontent.com/dijdzv/moon-release/main/install.sh | bash

    #Download binary

    Download pre-built binaries from GitHub Releases:

    # Linux (x86_64) curl -fsSL -o moon-release https://github.com/dijdzv/moon-release/releases/latest/download/moon-release-linux-x86_64 chmod +x moon-release # macOS (Apple Silicon) curl -fsSL -o moon-release https://github.com/dijdzv/moon-release/releases/latest/download/moon-release-macos-arm64 chmod +x moon-release

    #Build from source

    git clone https://github.com/dijdzv/moon-release cd moon-release moon build --target native --release cp _build/native/release/build/moon-release.exe ~/.local/bin/moon-release

    #Quick Start

    #Initial Setup (first time only)

    moon-release determines the next version by analyzing commits since the last release. When no tag or release commit exists yet, it analyzes all commits in the repository to compute the initial version — no manual setup is required.

    It is strongly recommended to create a Git tag as a baseline. This ensures only new commits are analyzed, producing more accurate and predictable version bumps:

    # Tag the commit that represents your latest release git tag v0.1.0 git push origin --tags

    If the release was made in a past commit, tag that specific commit:

    git tag v0.1.0 <commit-hash> git push origin --tags

    Recommended: Always create an initial tag. Without one, moon-release analyzes the entire commit history, which may produce unexpectedly large version bumps on repositories with a long history.

    Alternatively, if you are migrating from another release tool and cannot create a tag, you can set bootstrap_sha in release.json to specify the starting commit for analysis:

    { "bootstrap_sha": "<commit-hash>" }

    Once the first release is created, bootstrap_sha is automatically ignored (the release commit takes precedence), so you can leave it in the config without side effects.

    #Regular Usage

    After the initial setup, the typical workflow is:

    # Check current state moon-release check # Preview version update moon-release update --dry-run # Update version moon-release update # Create release PR moon-release release-pr # Create release (tag + GitHub Release + publish) moon-release release

    #Commands

    #moon-release check

    Check the current state and display recommended version bump.

    moon-release check moon-release check --verbose # Show commit details moon-release check -o json # Output in JSON format

    #moon-release update

    Update the version in moon.mod.json (no commit/push).

    moon-release update # Auto-determine moon-release update --bump major # Force major bump (changed packages only) moon-release update --bump-all # Bump all packages (monorepo) moon-release update --bump major --bump-all # Force major bump on all packages moon-release update --dry-run # Preview only moon-release update -o json # Output in JSON format

    #moon-release release-pr

    Create or update a release Pull Request.

    moon-release release-pr moon-release release-pr --bump major # Force major bump moon-release release-pr --bump-all # Include all packages moon-release release-pr --bump major --bump-all # Force major on all packages moon-release release-pr --dry-run

    #moon-release release

    Create Git tag and GitHub Release, and publish to mooncakes.io.

    moon-release release moon-release release --bump major # Force major bump moon-release release --bump-all # Include all packages moon-release release --bump major --bump-all # Force major on all packages moon-release release --prerelease alpha # Prerelease moon-release release --dry-run

    #moon-release set-version

    Manually set the version.

    moon-release set-version 1.0.0

    #moon-release init

    Create the configuration file release.json.

    moon-release init moon-release init --force # Overwrite

    #moon-release generate-completions

    Generate shell completion scripts.

    moon-release generate-completions bash > ~/.local/share/bash-completion/completions/moon-release moon-release generate-completions zsh > ~/.zfunc/_moon-release moon-release generate-completions fish > ~/.config/fish/completions/moon-release.fish

    #moon-release generate-schema

    Generate JSON Schema for the configuration file. Can be used for IDE autocompletion.

    moon-release generate-schema > release-schema.json

    #Planned Features

    • Per-package release PRs - Create separate release PRs for each package (or version_group) in a monorepo, instead of bundling all changes into a single PR
    • Per-package release - Create tags and publish each package independently when its release PR is merged
    • WebAssembly registry publishing - Publish to a Wasm component registry (e.g., warg, wa.dev)

    #Differences from release-plz

    Featurerelease-plzmoon-release
    PlatformGitHub, GitLab, GiteaGitHub only
    CHANGELOGAuto-generated with git-cliffNone (use GitHub Release instead)
    Dependency Updatecargo updateNone (MoonBit uses minimal version selection)
    API Compatibility Checkcargo-semver-checksBuilt-in (uses moon doc)
    Config FormatTOMLJSON
    Registrycrates.iomooncakes.io

    #License

    MIT