# GitHub Actions Publishing

> Automatically publish your Kore datapacks using GitHub Actions with mc-publish.

Updated 2026-10-21. Canonical: https://kore.ayfri.com/docs/advanced/github-actions-publishing

This guide shows you how to automatically publish your Kore-generated datapacks to various platforms using GitHub Actions and the
`mc-publish` action.

## Prerequisites

- A GitHub repository containing your Kore project
- Accounts on target platforms (Modrinth, CurseForge, etc.)
- API tokens for each platform you want to publish to

## What is mc-publish?

[mc-publish](https://github.com/Kira-NT/mc-publish) is a GitHub Action that simplifies publishing Minecraft projects across multiple platforms including Modrinth, CurseForge, and GitHub Releases. It automatically detects project metadata and handles the complex publication process with minimal configuration.

## Setting Up GitHub Secrets

Before configuring your workflow, you'll need to add your platform tokens as GitHub secrets:

1. Go to your repository's **Settings** → **Secrets and variables** → **Actions**
2. Add the following secrets:
	- `MODRINTH_TOKEN`: Your Modrinth API token
	- `CURSEFORGE_TOKEN`: Your CurseForge API token
	- `GITHUB_TOKEN` is automatically provided by GitHub

> **Note:** Only add secrets for platforms you plan to publish to.

## Basic Workflow Setup

Create `.github/workflows/publish.yml` in your repository:

```yaml
name: Publish Datapack

on:
  release:
    types: [ published ]
  workflow_dispatch: # Allow manual triggering

jobs:
  publish:
    runs-on: ubuntu-latest
    permissions:
      contents: write

    steps:
      - name: Checkout repository
        uses: actions/checkout@v5

      - name: Set up JDK 25
        uses: actions/setup-java@v5
        with:
          cache: gradle
          distribution: 'temurin'
          java-version: 25

      - name: Ensure Gradle is executable
        run: chmod +x gradlew

      - name: Setup Gradle
        uses: gradle/actions/setup-gradle@v4

      - name: Generate datapack
        run: ./gradlew run

      - name: Publish to platforms
        uses: Kir-Antipov/mc-publish@v3.3
        with:
          # Modrinth configuration
          modrinth-id: YOUR_PROJECT_ID
          modrinth-token: ${{ secrets.MODRINTH_TOKEN }}

          # CurseForge configuration
          curseforge-id: YOUR_PROJECT_ID
          curseforge-token: ${{ secrets.CURSEFORGE_TOKEN }}

          # GitHub Releases
          github-token: ${{ secrets.GITHUB_TOKEN }}
```

Ensure to use `datapack.generateZip()` in your build script to generate a zip file containing your datapack.

## Advanced Configuration

For more control over the publishing process, you can customize various aspects:

```yaml
- name: Publish to platforms
  uses: Kir-Antipov/mc-publish@v3.3
  with:
    # Project identification
    modrinth-id: AANobbMI
    modrinth-token: ${{ secrets.MODRINTH_TOKEN }}
    curseforge-id: 394468
    curseforge-token: ${{ secrets.CURSEFORGE_TOKEN }}
    github-token: ${{ secrets.GITHUB_TOKEN }}

    # Version configuration
    name: "My Datapack v${{ github.ref_name }}"
    version: ${{ github.ref_name }}
    version-type: release # alpha, beta, or release

    # File selection
    files: |
      out/*.zip
      !out/*-unfinished.zip

    # Supported game versions
    game-versions: |
      26.3

    # Mod loaders (if exporting to Jars)
    loaders: |
      fabric
      forge

    # Release configuration
    changelog-file: CHANGELOG.md
    dependencies: |
      fabric-api(required){modrinth:P7dR8mSH}{curseforge:306612}

    # Platform-specific settings
    modrinth-featured: true
    curseforge-java-versions: |
      Java 25
    github-prerelease: ${{ contains(github.ref_name, 'beta') || contains(github.ref_name, 'alpha') }}
    github-draft: false
```

## Kore-Specific Configuration

Kore generates your datapack from Kotlin code, so the workflow needs a build step that runs your `main()` and produces a
zip. Make sure your
entry point calls `datapack.generateZip()` (Kore writes the archive to the `out/` directory by default), then point
`mc-publish`'s `files` input
at it:

```yaml
files: out/*.zip
```

Kore projects come in two flavours depending on the build tool you started from. Use the matching build step.

### Gradle (Kore-Template)

The default [Kore-Template](https://github.com/Ayfri/Kore-Template) is a Gradle project, so the build step uses the
Gradle wrapper:

```yaml
      - name: Set up JDK 25
        uses: actions/setup-java@v5
        with:
          distribution: 'temurin'
          java-version: 25

      - name: Ensure Gradle is executable
        run: chmod +x gradlew

      - name: Generate datapack
        run: ./gradlew run
```

### Kotlin Toolchain (formerly Amper)

Projects configured with the [Kotlin Toolchain](https://kotlinlang.org/docs/multiplatform/amper.html) (the
`module.yaml` / `project.yaml`
setup, previously called Amper) ship a `kotlin` wrapper script instead of `gradlew`. The wrapper downloads the toolchain
and a JDK on first run,
so you don't need a separate `setup-java` step:

```yaml
      - name: Make the Kotlin wrapper executable
        run: chmod +x kotlin

      - name: Generate datapack
        env:
          CI: "true"
        run: ./kotlin run
```

For a multi-module project (several datapacks in one repository), target a specific module with `-m`:

```yaml
        run: ./kotlin run -m my-datapack
```

Gate `generateZip()` behind an environment variable so local runs still emit loose files while CI produces the
publishable zip:

```kotlin
val isCI get() = System.getenv("CI") != null

fun main() {
	dataPack("my_datapack") {
		// ... your content ...
	}.run { if (isCI) generateZip() else generate() }
}
```

## Workflow Triggers

You can configure when the publishing workflow runs:

```yaml
on:
  # Trigger on new releases
  release:
    types: [ published ]

  # Trigger on version tags
  push:
    tags:
      - 'v*'

  # Allow manual triggering
  workflow_dispatch:
    inputs:
      version-type:
        description: 'Release type'
        required: true
        default: 'release'
        type: choice
        options:
          - release
          - beta
          - alpha
```

## Platform-Specific Features

### Modrinth

- Supports featured projects
- Automatic dependency resolution
- Rich markdown changelog support

```yaml
modrinth-featured: true
modrinth-unfeature-mode: subset
```

### CurseForge

- Java version specification
- Custom display name support

```yaml
curseforge-java-versions: |
  Java 25
curseforge-display-name: "My Awesome Datapack"
```

### GitHub Releases

- Draft and prerelease support
- Asset management

```yaml
github-draft: false
github-prerelease: ${{ contains(github.ref_name, 'pre') }}
github-tag: ${{ github.ref_name }}
```

This helps mc-publish automatically detect project metadata.

## Best Practices

### 1. Version Management

Use semantic versioning and Git tags:

```bash
git tag v1.0.0
git push origin v1.0.0
```

### 2. Changelog Management

Maintain a `CHANGELOG.md` file following [Keep a Changelog](https://keepachangelog.com/) format:

```markdown
# Changelog

## [1.0.0] - 2025-09-30

### Added

- Initial release with basic functionality
- Support for Minecraft 26.2

### Changed

- Improved performance of item generation

### Fixed

- Fixed issue with advancement rewards
```

### 3. Testing Before Publishing

Add a test job before publishing:

```yaml
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v5
      - name: Set up JDK 25
        uses: actions/setup-java@v5
        with:
          java-version: '25'
          distribution: 'temurin'
      - name: Run tests
        run: ./gradlew test

  publish:
    needs: test
    runs-on: ubuntu-latest
    # ... publishing steps
```

## Troubleshooting

### Common Issues

1. **Missing files**: Ensure you exported the datapack to the correct directory
2. **Invalid tokens**: Verify your secrets are correctly set in GitHub
3. **Permission errors**: Ensure the workflow has `contents: write` permission

### Debugging

Enable debug logging by adding:

```yaml
env:
  ACTIONS_RUNNER_DEBUG: true
  ACTIONS_STEP_DEBUG: true
```

## Complete Example

Here's a complete workflow for a Kore datapack project:

```yaml
name: Publish Datapack

on:
  release:
    types: [ published ]
  workflow_dispatch:

jobs:
  publish:
    runs-on: ubuntu-latest
    permissions:
      contents: write

    steps:
      - name: Checkout repository
        uses: actions/checkout@v5

      - name: Set up JDK 25
        uses: actions/setup-java@v5
        with:
          cache: gradle
          distribution: 'temurin'
          java-version: 25

      - name: Ensure Gradle is executable
        run: chmod +x gradlew

      - name: Setup Gradle
        uses: gradle/actions/setup-gradle@v4

      - name: Generate datapack
        run: ./gradlew run

      - name: Publish to platforms
        uses: Kir-Antipov/mc-publish@v3.3
        with:
          name: "${{ github.event.repository.name }} ${{ github.ref_name }}"
          version: ${{ github.ref_name }}
          version-type: release

          files: out/*.zip

          game-versions: |
            26.3

          modrinth-id: YOUR_MODRINTH_ID
          modrinth-token: ${{ secrets.MODRINTH_TOKEN }}
          modrinth-featured: true

          curseforge-id: YOUR_CURSEFORGE_ID
          curseforge-token: ${{ secrets.CURSEFORGE_TOKEN }}

          github-token: ${{ secrets.GITHUB_TOKEN }}
          github-tag: ${{ github.ref_name }}

          changelog-file: CHANGELOG.md
```

## See Also

- [Creating a Datapack](https://kore.ayfri.com/docs/guides/creating-a-datapack.md)
- [Configuration](https://kore.ayfri.com/docs/guides/configuration.md)
- [mc-publish Documentation](https://github.com/Kir-Antipov/mc-publish)
- [GitHub Actions Documentation](https://docs.github.com/en/actions)
