Loading...
Loading...
Set up and review CI, artifact publishing, versioning, and release management for Minecraft 26.x or legacy 1.21.x mods and Paper plugins. Use for pipelines and releases, not gameplay implementation or server operations.
npx skill4agent add jahrome907/minecraft-agent-skills minecraft-ci-releaseUse whenDo not use whenminecraft-moddingminecraft-plugin-devminecraft-datapackDo not use whenminecraft-server-adminactions/checkout@v7.0.1 3d3c42e5aac5ba805825da76410c181273ba90b1
actions/setup-java@v6.0.0 dd06d9cba3e5552c54d9f8ea23572deb30010f7c
gradle/actions/setup-gradle@v6.3.0 9c971963bec38e04b3d30dcc455b5382be2fdbfb
actions/upload-artifact@v7.0.1 043fb46d1a93c77aae656e7c1c64a875d1fc6a0a
softprops/action-gh-release@v3.0.3 efb35369e0ad2afab669f228072c1b0d510eae64{mod_version}+{mc_version}1.0.0+26.3 ← mod 1.0.0 for MC 26.3
1.2.3+26.3
2.0.0+26.3mod_version: 1.2.3
project/artifact version: 1.2.3+26.3
tag: v1.2.3v1.2.3mod_version=1.2.3mod_versionBuild / Build (fabric)Build / Build (neoforge)Build / Test.github/workflows/build.ymlname: Build
on:
push:
branches: ["main", "develop"]
pull_request:
branches: ["main"]
permissions:
contents: read
jobs:
build:
name: Build (${{ matrix.platform }})
runs-on: ubuntu-latest
strategy:
matrix:
platform: [neoforge, fabric]
fail-fast: false
steps:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1
- name: Set up Java 25
uses: actions/setup-java@dd06d9cba3e5552c54d9f8ea23572deb30010f7c
with:
java-version: "25"
distribution: "temurin"
- name: Setup Gradle
uses: gradle/actions/setup-gradle@9c971963bec38e04b3d30dcc455b5382be2fdbfb
with:
cache-read-only: ${{ github.event_name == 'pull_request' }}
- name: Grant execute permission for gradlew
run: chmod +x gradlew
- name: Build (${{ matrix.platform }})
run: ./gradlew :${{ matrix.platform }}:build --no-daemon
- name: Upload artifacts
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a
with:
name: mod-${{ matrix.platform }}-${{ github.sha }}
path: ${{ matrix.platform }}/build/libs/*.jar
if-no-files-found: error
test:
name: Test
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1
- name: Set up Java 25
uses: actions/setup-java@dd06d9cba3e5552c54d9f8ea23572deb30010f7c
with:
distribution: temurin
java-version: "25"
- name: Set up Gradle
uses: gradle/actions/setup-gradle@9c971963bec38e04b3d30dcc455b5382be2fdbfb
- name: Run tests
run: ./gradlew test --no-daemon.github/workflows/release.ymlname: Release
on:
push:
tags:
- "v*"
permissions:
contents: write # for creating GitHub releases
jobs:
release:
name: Release
runs-on: ubuntu-latest
steps:
- name: Checkout tagged source
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1
- name: Set up Java 25
uses: actions/setup-java@dd06d9cba3e5552c54d9f8ea23572deb30010f7c
with:
java-version: "25"
distribution: "temurin"
- name: Setup Gradle
uses: gradle/actions/setup-gradle@9c971963bec38e04b3d30dcc455b5382be2fdbfb
- name: Grant execute permission for gradlew
run: chmod +x gradlew
- name: Validate tag and build
env:
MOD_VERSION: ${{ github.ref_name }}
run: |
MOD_VERSION="${MOD_VERSION#v}"
./gradlew verifyReleaseVersion build --no-daemon \
-PreleaseModVersion="$MOD_VERSION"
- name: Select release artifacts
env:
RELEASE_TAG: ${{ github.ref_name }}
run: |
mkdir -p release-artifacts
shopt -s nullglob
select_primary() {
local loader="$1"; shift
local matches=( "$@" )
if (( ${#matches[@]} != 1 )); then
printf 'Expected one %s primary JAR, found %s: %s\n' \
"$loader" "${#matches[@]}" "${matches[*]:-none}" >&2
exit 1
fi
cp "${matches[0]}" "release-artifacts/${loader}-${RELEASE_TAG}.jar"
}
select_primary fabric fabric/build/libs/*-fabric.jar
select_primary neoforge neoforge/build/libs/*-neoforge.jar
- name: Create GitHub Release
uses: softprops/action-gh-release@efb35369e0ad2afab669f228072c1b0d510eae64
with:
files: |
release-artifacts/fabric-${{ github.ref_name }}.jar
release-artifacts/neoforge-${{ github.ref_name }}.jar
fail_on_unmatched_files: true
generate_release_notes: true
prerelease: ${{ contains(github.ref_name, '-alpha') || contains(github.ref_name, '-beta') || contains(github.ref_name, '-rc') }}.github/workflows/build.ymlname: Build
on:
push:
branches: ["main"]
pull_request:
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1
- uses: actions/setup-java@dd06d9cba3e5552c54d9f8ea23572deb30010f7c
with:
java-version: "25"
distribution: "temurin"
- uses: gradle/actions/setup-gradle@9c971963bec38e04b3d30dcc455b5382be2fdbfb
- run: chmod +x gradlew
- run: ./gradlew build --no-daemon
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a
with:
name: plugin-${{ github.sha }}
path: build/libs/*.jar
if-no-files-found: error
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1
- uses: actions/setup-java@dd06d9cba3e5552c54d9f8ea23572deb30010f7c
with:
java-version: "25"
distribution: "temurin"
- uses: gradle/actions/setup-gradle@9c971963bec38e04b3d30dcc455b5382be2fdbfb
- run: ./gradlew test --no-daemonjarremapJargradle.properties# gradle.properties (committed)
mod_id=mymod
mod_version=1.0.0
minecraft_version=26.3
modrinth_project_id=AABBCCDD
curseforge_project_id=123456
# DO NOT commit tokens
# Set these as GitHub repo secrets:
# MODRINTH_TOKEN, CURSEFORGE_TOKEN| Change | Version bump |
|---|---|
| New features, no breaking changes | Minor: |
| Bug fixes only | Patch: |
| API/config breaking changes | Major: |
| Minecraft version update | Keep mod version, change the |
| Pre-release | |
# Changelog
## [1.1.0] — 2026-10-01
### Added
- New `/kit` command
- PDC-based kill tracker
### Fixed
- Death message not appearing on Paper 26.3
## [1.0.0] — 2026-09-01
### Added
- Initial releasemod_version.github/dependabot.ymlversion: 2
updates:
- package-ecosystem: "gradle"
directory: "/"
schedule:
interval: "weekly"
groups:
gradle-plugins:
patterns:
- "com.gradleup.shadow"
- "dev.architectury.loom"
- "com.modrinth.minotaur"
- "net.darkhax.curseforgegradle"
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"# In all workflow jobs:
- name: Setup Gradle
uses: gradle/actions/setup-gradle@9c971963bec38e04b3d30dcc455b5382be2fdbfb
with:
# Read-only cache on PRs, read-write on main
cache-read-only: ${{ github.event_name == 'pull_request' }}mainBuild / Build (fabric)Build / Build (neoforge)Build / Test#!/usr/bin/env bash
# scripts/release.sh <mod-version>
set -euo pipefail
VERSION="${1:?Usage: release.sh <mod-version>}"
REMOTE="${RELEASE_REMOTE:-origin}"
BRANCH="${RELEASE_BRANCH:-main}"
EXPECTED_REMOTE_URL="${RELEASE_REMOTE_URL:?Set RELEASE_REMOTE_URL to the expected push URL}"
git diff --check
[[ -z "$(git status --porcelain=v1 --untracked-files=all)" ]] \
|| { echo "Working tree contains staged, unstaged, or untracked files." >&2; exit 1; }
[[ "$(git branch --show-current)" == "$BRANCH" ]] \
|| { echo "Release must start from branch $BRANCH." >&2; exit 1; }
mapfile -t PUSH_URLS < <(git remote get-url --push --all "$REMOTE")
[[ ${#PUSH_URLS[@]} -eq 1 && "${PUSH_URLS[0]}" == "$EXPECTED_REMOTE_URL" ]] \
|| { echo "Remote $REMOTE must have one expected push URL." >&2; exit 1; }
! git rev-parse --verify --quiet "refs/tags/v${VERSION}" >/dev/null \
|| { echo "Local tag v${VERSION} already exists." >&2; exit 1; }
set +e
git ls-remote --exit-code --tags "$EXPECTED_REMOTE_URL" "refs/tags/v${VERSION}" >/dev/null
REMOTE_TAG_STATUS=$?
set -e
case "$REMOTE_TAG_STATUS" in
0) echo "Remote tag v${VERSION} already exists." >&2; exit 1 ;;
2) ;;
*) echo "Could not verify remote tag v${VERSION}." >&2; exit "$REMOTE_TAG_STATUS" ;;
esac
./gradlew verifyReleaseVersion --no-daemon -PreleaseModVersion="$VERSION"
git tag --annotate "v${VERSION}" --message "Release v${VERSION}"
git push "$REMOTE" "HEAD:refs/heads/${BRANCH}"
git push "$REMOTE" "refs/tags/v${VERSION}"RELEASE_BRANCHRELEASE_REMOTERELEASE_REMOTE_URLminecraft-ci-release# Run from the installed skill directory:
./scripts/validate-workflow-snippets.sh --root .
# Strict mode treats warnings as failures:
./scripts/validate-workflow-snippets.sh --root . --strict.agents/.codex/.claude/minecraft-ci-releasenode_modulesuses:./...docker://...SKILL.md.github/workflowsverifyReleaseVersion