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:
Navigate to Repository Settings
Go to your repository → Settings → Secrets and variables → Actions
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)
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:
- Use draft releases: Set
-DgithubDraft="true" for testing
- Use beta channels: Set version type to
beta or alpha
- Test with a single platform: Use
-Dplatforms="github" first
- 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