Sign in

    moon-release

    Automated release management tool for MoonBit

    release
    changelog
    semver
    conventional-commits
    Download zip
    Author
    Version
    0.2.2
    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

    Create .github/workflows/release.yml. This base workflow creates release PRs and GitHub Releases (with Git tags):

    name: Release on: push: branches: [main] workflow_dispatch: permissions: contents: write pull-requests: write jobs: release-pr: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 with: fetch-depth: 0 - name: Setup MoonBit run: | curl -fsSL https://cli.moonbitlang.com/install/unix.sh | bash echo "$HOME/.moon/bin" >> $GITHUB_PATH - name: Download moon-release run: | curl -fsSL -o moon-release https://github.com/dijdzv/moon-release/releases/latest/download/moon-release-linux-x86_64 chmod +x moon-release - name: Configure Git run: | git config --global user.name "github-actions[bot]" git config --global user.email "github-actions[bot]@users.noreply.github.com" - name: Create Release PR env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: ./moon-release release-pr --verbose release: runs-on: ubuntu-latest if: github.event_name == 'push' && startsWith(github.event.head_commit.message, 'chore:') && contains(github.event.head_commit.message, 'release v') steps: - name: Checkout uses: actions/checkout@v4 with: fetch-depth: 0 - name: Setup MoonBit run: | curl -fsSL https://cli.moonbitlang.com/install/unix.sh | bash echo "$HOME/.moon/bin" >> $GITHUB_PATH - name: Download moon-release run: | curl -fsSL -o moon-release https://github.com/dijdzv/moon-release/releases/latest/download/moon-release-linux-x86_64 chmod +x moon-release - name: Create Release env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: ./moon-release release --verbose

    Key points:
    • fetch-depth: 0 - Required to analyze commit history
    • release-pr job - Runs on every push: creates/updates a release PR with version bump
    • release job - Runs only when a release PR is merged: creates Git tag + GitHub Release
    • GITHUB_TOKEN - Automatically provided by GitHub Actions

    With this base setup, merging a release PR will automatically create a Git tag and a GitHub Release with release notes. No additional secrets are needed.

    #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. Add Credentials Step to Workflow

    Add the following step to the release job, before the "Download moon-release" step:

    - name: Configure mooncakes credentials env: MOONCAKES_TOKEN: ${{ secrets.MOONCAKES_TOKEN }} MOONCAKES_USERNAME: ${{ secrets.MOONCAKES_USERNAME }} run: | mkdir -p ~/.moon jq -n --arg token "$MOONCAKES_TOKEN" --arg username "$MOONCAKES_USERNAME" \ '{"token": $token, "username": $username}' > ~/.moon/credentials.json

    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: '20' registry-url: 'https://registry.npmjs.org'

    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.

    #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, "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)

    #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

    #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/src/main/main.exe ~/.local/bin/moon-release

    #Quick Start

    # Initialize configuration file moon-release init # 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

    #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

    See DESIGN_DECISIONS.md for details.

    #License

    MIT