Skip to main content
MCReleaser is designed to work seamlessly with CI/CD pipelines. This guide shows you how to automate your release process.

GitHub Actions Integration

The most common way to use MCReleaser is through GitHub Actions, which automatically publishes releases when you create a tag.

Basic GitHub Actions Workflow

Create .github/workflows/release.yml:
name: Publish Release

on:
  push:
    tags:
      - 'v*.*.*'

jobs:
  publish:
    runs-on: ubuntu-latest
    
    steps:
      - name: Checkout repository
        uses: actions/checkout@v4
      
      - name: Set up JDK 17
        uses: actions/setup-java@v4
        with:
          distribution: 'temurin'
          java-version: '17'
      
      - name: Build with Gradle
        run: ./gradlew build
      
      - name: Download MCReleaser
        run: |
          curl -L -o mcreleaser.jar https://github.com/HSGamer/MCReleaser/releases/latest/download/mcreleaser.jar
      
      - name: Publish to Platforms
        run: |
          java \
            -Dname="My Minecraft Mod" \
            -Dversion="${{ github.ref_name }}" \
            -Ddescription="Release ${{ github.ref_name }}" \
            -DgameVersions="1.20.1,1.20.2" \
            -Dplatforms="all" \
            -Dfiles="build/libs/*-[0-9]*.jar" \
            -DgithubToken="${{ secrets.GITHUB_TOKEN }}" \
            -DgithubRepository="${{ github.repository }}" \
            -DgithubRef="${{ github.ref }}" \
            -DmodrinthToken="${{ secrets.MODRINTH_TOKEN }}" \
            -DmodrinthProject="${{ secrets.MODRINTH_PROJECT_ID }}" \
            -DmodrinthLoaders="fabric" \
            -DcurseforgeToken="${{ secrets.CURSEFORGE_TOKEN }}" \
            -DcurseforgeProject="${{ secrets.CURSEFORGE_PROJECT_ID }}" \
            -jar mcreleaser.jar
The GITHUB_TOKEN is automatically provided by GitHub Actions. You don’t need to create it manually.

Advanced Workflow with Changelog

Extract changelog from Git tags and use it as the release description:
name: Publish Release with Changelog

on:
  push:
    tags:
      - 'v*.*.*'

jobs:
  publish:
    runs-on: ubuntu-latest
    
    steps:
      - name: Checkout repository
        uses: actions/checkout@v4
        with:
          fetch-depth: 0  # Fetch all history for changelog
      
      - name: Set up JDK 17
        uses: actions/setup-java@v4
        with:
          distribution: 'temurin'
          java-version: '17'
      
      - name: Build with Gradle
        run: ./gradlew build
      
      - name: Generate Changelog
        id: changelog
        run: |
          # Get commits since last tag
          PREVIOUS_TAG=$(git describe --abbrev=0 --tags $(git rev-list --tags --skip=1 --max-count=1) 2>/dev/null || echo "")
          if [ -z "$PREVIOUS_TAG" ]; then
            CHANGELOG=$(git log --pretty=format:"- %s" ${{ github.ref_name }})
          else
            CHANGELOG=$(git log --pretty=format:"- %s" $PREVIOUS_TAG..${{ github.ref_name }})
          fi
          echo "changelog<<EOF" >> $GITHUB_OUTPUT
          echo "$CHANGELOG" >> $GITHUB_OUTPUT
          echo "EOF" >> $GITHUB_OUTPUT
      
      - name: Download MCReleaser
        run: |
          curl -L -o mcreleaser.jar https://github.com/HSGamer/MCReleaser/releases/latest/download/mcreleaser.jar
      
      - name: Publish to Platforms
        run: |
          java \
            -Dname="${{ github.event.repository.name }}" \
            -Dversion="${{ github.ref_name }}" \
            -Ddescription="${{ steps.changelog.outputs.changelog }}" \
            -DgameVersions="1.20.1,1.20.2,1.20.3" \
            -Dplatforms="modrinth,curseforge,github" \
            -Dfiles="build/libs/*-[0-9]*.jar build/libs/*-sources.jar" \
            -DgithubToken="${{ secrets.GITHUB_TOKEN }}" \
            -DgithubRepository="${{ github.repository }}" \
            -DgithubRef="${{ github.ref }}" \
            -DmodrinthToken="${{ secrets.MODRINTH_TOKEN }}" \
            -DmodrinthProject="${{ secrets.MODRINTH_PROJECT_ID }}" \
            -DmodrinthLoaders="fabric" \
            -DmodrinthVersionType="release" \
            -DcurseforgeToken="${{ secrets.CURSEFORGE_TOKEN }}" \
            -DcurseforgeProject="${{ secrets.CURSEFORGE_PROJECT_ID }}" \
            -DcurseforgeReleaseType="release" \
            -jar mcreleaser.jar

Multi-Loader Workflow

Publish different files for Fabric and Forge:
name: Multi-Loader Release

on:
  push:
    tags:
      - 'v*.*.*'

jobs:
  publish-fabric:
    runs-on: ubuntu-latest
    
    steps:
      - name: Checkout repository
        uses: actions/checkout@v4
      
      - name: Set up JDK 17
        uses: actions/setup-java@v4
        with:
          distribution: 'temurin'
          java-version: '17'
      
      - name: Build Fabric
        run: ./gradlew :fabric:build
      
      - name: Download MCReleaser
        run: |
          curl -L -o mcreleaser.jar https://github.com/HSGamer/MCReleaser/releases/latest/download/mcreleaser.jar
      
      - name: Publish Fabric Version
        run: |
          java \
            -Dname="My Mod (Fabric)" \
            -Dversion="${{ github.ref_name }}" \
            -Ddescription="Fabric version for ${{ github.ref_name }}" \
            -DgameVersions="1.20.1,1.20.2" \
            -Dplatforms="modrinth,curseforge" \
            -Dfiles="fabric/build/libs/*-[0-9]*.jar" \
            -DmodrinthToken="${{ secrets.MODRINTH_TOKEN }}" \
            -DmodrinthProject="${{ secrets.MODRINTH_PROJECT_ID }}" \
            -DmodrinthLoaders="fabric" \
            -DcurseforgeToken="${{ secrets.CURSEFORGE_TOKEN }}" \
            -DcurseforgeProject="${{ secrets.CURSEFORGE_PROJECT_ID }}" \
            -DcurseforgeModLoaders="Fabric" \
            -jar mcreleaser.jar
  
  publish-forge:
    runs-on: ubuntu-latest
    
    steps:
      - name: Checkout repository
        uses: actions/checkout@v4
      
      - name: Set up JDK 17
        uses: actions/setup-java@v4
        with:
          distribution: 'temurin'
          java-version: '17'
      
      - name: Build Forge
        run: ./gradlew :forge:build
      
      - name: Download MCReleaser
        run: |
          curl -L -o mcreleaser.jar https://github.com/HSGamer/MCReleaser/releases/latest/download/mcreleaser.jar
      
      - name: Publish Forge Version
        run: |
          java \
            -Dname="My Mod (Forge)" \
            -Dversion="${{ github.ref_name }}" \
            -Ddescription="Forge version for ${{ github.ref_name }}" \
            -DgameVersions="1.20.1,1.20.2" \
            -Dplatforms="modrinth,curseforge" \
            -Dfiles="forge/build/libs/*-[0-9]*.jar" \
            -DmodrinthToken="${{ secrets.MODRINTH_TOKEN }}" \
            -DmodrinthProject="${{ secrets.MODRINTH_PROJECT_ID_FORGE }}" \
            -DmodrinthLoaders="forge" \
            -DcurseforgeToken="${{ secrets.CURSEFORGE_TOKEN }}" \
            -DcurseforgeProject="${{ secrets.CURSEFORGE_PROJECT_ID_FORGE }}" \
            -DcurseforgeModLoaders="Forge" \
            -jar mcreleaser.jar

Using the Official GitHub Action

For even simpler integration, use the action-mcreleaser action:
name: Publish with Action

on:
  push:
    tags:
      - 'v*.*.*'

jobs:
  publish:
    runs-on: ubuntu-latest
    
    steps:
      - name: Checkout
        uses: actions/checkout@v4
      
      - name: Build
        run: ./gradlew build
      
      - name: Publish
        uses: HSGamer/action-mcreleaser@v1
        with:
          name: 'My Minecraft Mod'
          version: ${{ github.ref_name }}
          description: 'Release ${{ github.ref_name }}'
          game-versions: '1.20.1,1.20.2'
          platforms: 'all'
          files: 'build/libs/*-[0-9]*.jar'
          modrinth-token: ${{ secrets.MODRINTH_TOKEN }}
          modrinth-project: ${{ secrets.MODRINTH_PROJECT_ID }}
          modrinth-loaders: 'fabric'
          curseforge-token: ${{ secrets.CURSEFORGE_TOKEN }}
          curseforge-project: ${{ secrets.CURSEFORGE_PROJECT_ID }}
The official action handles downloading and running MCReleaser for you, making the workflow cleaner and easier to maintain.

Docker-Based CI/CD

MCReleaser is also available as a Docker image, perfect for any CI/CD platform that supports Docker:

GitLab CI Example

release:
  stage: deploy
  image: ghcr.io/hsgamer/mcreleaser:master
  only:
    - tags
  script:
    - |
      java -jar /app/mcreleaser.jar \
        -Dname="My Mod" \
        -Dversion="${CI_COMMIT_TAG}" \
        -Ddescription="Release ${CI_COMMIT_TAG}" \
        -DgameVersions="1.20.1,1.20.2" \
        -Dplatforms="modrinth,curseforge" \
        -Dfiles="build/libs/*.jar" \
        -DmodrinthToken="${MODRINTH_TOKEN}" \
        -DmodrinthProject="${MODRINTH_PROJECT_ID}" \
        -DmodrinthLoaders="fabric" \
        -DcurseforgeToken="${CURSEFORGE_TOKEN}" \
        -DcurseforgeProject="${CURSEFORGE_PROJECT_ID}"

Jenkins Pipeline Example

pipeline {
    agent any
    
    stages {
        stage('Build') {
            steps {
                sh './gradlew build'
            }
        }
        
        stage('Publish') {
            when {
                tag pattern: "v.*", comparator: "REGEXP"
            }
            steps {
                script {
                    docker.image('ghcr.io/hsgamer/mcreleaser:master').inside {
                        sh '''
                            java -jar /app/mcreleaser.jar \
                              -Dname="My Mod" \
                              -Dversion="${TAG_NAME}" \
                              -Ddescription="Release ${TAG_NAME}" \
                              -DgameVersions="1.20.1" \
                              -Dplatforms="all" \
                              -Dfiles="build/libs/*.jar" \
                              -DmodrinthToken="${MODRINTH_TOKEN}" \
                              -DmodrinthProject="${MODRINTH_PROJECT_ID}" \
                              -DmodrinthLoaders="fabric"
                        '''
                    }
                }
            }
        }
    }
}

Setting Up Secrets

For GitHub Actions, you need to configure repository secrets:
1

Navigate to Repository Settings

Go to your repository → Settings → Secrets and variables → Actions
2

Add Required Secrets

Click “New repository secret” and add:
  • MODRINTH_TOKEN - Your Modrinth API token
  • MODRINTH_PROJECT_ID - Your Modrinth project ID
  • CURSEFORGE_TOKEN - Your CurseForge API token
  • CURSEFORGE_PROJECT_ID - Your CurseForge project ID
  • HANGAR_KEY - Your Hangar API key (if needed)
  • POLYMART_KEY - Your Polymart API key (if needed)
3

Use Secrets in Workflow

Reference secrets using ${{ secrets.SECRET_NAME }} syntax
Never commit API tokens or keys to your repository. Always use CI/CD secrets management.

Testing Your Workflow

Before creating a real release, test your workflow:
  1. Use draft releases: Set -DgithubDraft="true" for testing
  2. Use beta channels: Set version type to beta or alpha
  3. Test with a single platform: Use -Dplatforms="github" first
  4. Enable verbose logging: Check CI logs for errors
# Test workflow on pull requests
on:
  pull_request:
    branches: [ main ]

jobs:
  test-release:
    runs-on: ubuntu-latest
    steps:
      # ... build steps ...
      
      - name: Test Release (Draft)
        if: github.event_name == 'pull_request'
        run: |
          java \
            -Dname="My Mod" \
            -Dversion="test-${{ github.event.pull_request.number }}" \
            -Ddescription="Test release for PR #${{ github.event.pull_request.number }}" \
            -Dplatforms="github" \
            -DgithubDraft="true" \
            -DgithubPrerelease="true" \
            # ... other properties
            -jar mcreleaser.jar

Common CI/CD Patterns

Release on Tag Push

Trigger releases only when tags are pushed:
on:
  push:
    tags:
      - 'v*.*.*'  # Matches v1.0.0, v2.1.3, etc.

Beta Releases from Branch

Automatic beta releases from a development branch:
on:
  push:
    branches:
      - beta

jobs:
  publish-beta:
    runs-on: ubuntu-latest
    steps:
      # ... build steps ...
      
      - name: Publish Beta
        run: |
          java \
            -Dversion="beta-${{ github.run_number }}" \
            -DmodrinthVersionType="beta" \
            -DcurseforgeReleaseType="beta" \
            -DgithubPrerelease="true" \
            # ... other properties
            -jar mcreleaser.jar

Manual Workflow Dispatch

Allow manual triggering with custom inputs:
on:
  workflow_dispatch:
    inputs:
      version:
        description: 'Release version'
        required: true
      platforms:
        description: 'Platforms to publish to'
        required: true
        default: 'all'

jobs:
  publish:
    runs-on: ubuntu-latest
    steps:
      # ... build steps ...
      
      - name: Publish
        run: |
          java \
            -Dversion="${{ github.event.inputs.version }}" \
            -Dplatforms="${{ github.event.inputs.platforms }}" \
            # ... other properties
            -jar mcreleaser.jar

Next Steps

Game Versions

Configure Minecraft version compatibility

File Handling

Learn about file globs and multiple file uploads

Build docs developers (and LLMs) love