Skip to main content
The GithubPlatform class implements the Platform interface to upload artifacts to GitHub Releases using the GitHub API.

Package

me.hsgamer.mcreleaser.github.GithubPlatform

Class Declaration

public class GithubPlatform implements Platform {
    private final Logger logger = LoggerFactory.getLogger(getClass());
}

Constructor

GithubPlatform()

Creates a new GitHub platform instance and automatically sets version and name from Git ref if available.
public GithubPlatform() {
    if (GithubPropertyKey.REF.isPresent()) {
        String version = getVersionFromRef(GithubPropertyKey.REF.getValue());
        if (CommonPropertyKey.VERSION.isAbsent()) {
            CommonPropertyKey.VERSION.setValue(version);
        }
        if (CommonPropertyKey.NAME.isAbsent()) {
            CommonPropertyKey.NAME.setValue(version);
        }
    }
}
Automatic Version Extraction:
  • Extracts version from Git ref (e.g., refs/tags/v1.0.0v1.0.0)
  • Sets VERSION and NAME if not already configured

Methods

createUploadRunnable

Creates a batch runnable that uploads files to a GitHub Release.
fileBundle
FileBundle
required
The bundle of files to upload as release assets
runnable
Optional<BatchRunnable>
Returns a BatchRunnable if all required properties are present, otherwise empty
@Override
public Optional<BatchRunnable> createUploadRunnable(FileBundle fileBundle) {
    if (PropertyKeyUtil.isAbsentAndAnnounce(logger, 
        GithubPropertyKey.TOKEN, 
        GithubPropertyKey.REPOSITORY, 
        GithubPropertyKey.REF)) {
        return Optional.empty();
    }
    // Create upload tasks...
}

Upload Process

The upload is executed in three phases:

Phase 0: Preparation

  1. Create GitHub Instance
    GitHub gitHub = new GitHubBuilder()
        .withOAuthToken(GithubPropertyKey.TOKEN.getValue())
        .build();
    
  2. Get Repository
    GHRepository repository = gitHub.getRepository(
        GithubPropertyKey.REPOSITORY.getValue()
    );
    

Phase 1: Release Creation

Creates or retrieves the GitHub Release:
GHRelease release = repository.getReleaseByTagName(
    GithubPropertyKey.REF.getValue()
);

if (release == null) {
    release = repository.createRelease(GithubPropertyKey.REF.getValue())
        .draft(GithubPropertyKey.DRAFT.asBoolean(false))
        .prerelease(GithubPropertyKey.PRERELEASE.asBoolean(false))
        .name(CommonPropertyKey.NAME.getValue())
        .body(CommonPropertyKey.DESCRIPTION.getValue())
        .create();
}

Phase 2: File Upload

Uploads all files from the bundle:
for (File file : fileBundle.allFiles()) {
    release.uploadAsset(file, "application/octet-stream");
    logger.info("File uploaded: {}", file.getName());
}
logger.info("Release URL: {}", release.getHtmlUrl());

Required Properties

GITHUB_TOKEN
String
required
GitHub personal access token or OAuth token with repo scope
GITHUB_REPOSITORY
String
required
Repository in format owner/repo (e.g., user/my-plugin)
GITHUB_REF
String
required
Git reference for the release (e.g., refs/tags/v1.0.0 or v1.0.0)

Optional Properties

GITHUB_DRAFT
boolean
default:"false"
Create release as draft (not published)
GITHUB_PRERELEASE
boolean
default:"false"
Mark release as pre-release

Common Properties

These properties are shared across platforms:
NAME
String
required
Release name/title (auto-set from ref if not provided)
VERSION
String
required
Version number (auto-set from ref if not provided)
DESCRIPTION
String
required
Release description/changelog (supports Markdown)

Configuration Examples

Basic Release

export GITHUB_TOKEN="ghp_1234567890abcdef"
export GITHUB_REPOSITORY="user/my-plugin"
export GITHUB_REF="refs/tags/v1.0.0"
export DESCRIPTION="Initial release"

java -jar mcreleaser-cli.jar

Draft Release

export GITHUB_TOKEN="ghp_..."
export GITHUB_REPOSITORY="user/my-plugin"
export GITHUB_REF="v2.0.0-beta"
export GITHUB_DRAFT="true"
export GITHUB_PRERELEASE="true"
export NAME="My Plugin v2.0.0-beta"
export DESCRIPTION="Beta release for testing"

GitHub Actions Integration

name: Release

on:
  push:
    tags:
      - 'v*'

jobs:
  release:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      
      - name: Build
        run: ./gradlew build
      
      - name: Release to GitHub
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          GITHUB_REPOSITORY: ${{ github.repository }}
          GITHUB_REF: ${{ github.ref }}
          DESCRIPTION: ${{ github.event.head_commit.message }}
          FILES: "build/libs/*.jar"
        run: java -jar mcreleaser-cli.jar

Multiple Files Upload

export GITHUB_TOKEN="ghp_..."
export GITHUB_REPOSITORY="user/my-plugin"
export GITHUB_REF="v1.5.0"
export FILES="build/libs/*.jar build/libs/*-sources.jar"

# All matched files will be uploaded as release assets
java -jar mcreleaser-cli.jar

Property Keys Source

Defined in GithubPropertyKey:
public interface GithubPropertyKey {
    PropertyPrefix GITHUB = new PropertyPrefix("github");
    PropertyKey TOKEN = GITHUB.key("token");
    PropertyKey REPOSITORY = GITHUB.key("repository");
    PropertyKey REF = GITHUB.key("ref");
    PropertyKey DRAFT = GITHUB.key("draft");
    PropertyKey PRERELEASE = GITHUB.key("prerelease");
}
Property Name Mapping:
  • Property: githubToken → Environment: GITHUB_TOKEN
  • Property: githubRepository → Environment: GITHUB_REPOSITORY
  • Property: githubRef → Environment: GITHUB_REF
  • Property: githubDraft → Environment: GITHUB_DRAFT
  • Property: githubPrerelease → Environment: GITHUB_PRERELEASE

Error Handling

Missing Required Properties

If required properties are missing, returns empty Optional:
if (PropertyKeyUtil.isAbsentAndAnnounce(logger, 
    GithubPropertyKey.TOKEN, 
    GithubPropertyKey.REPOSITORY, 
    GithubPropertyKey.REF)) {
    return Optional.empty();
}

GitHub API Errors

API errors are logged and the process is stopped:
try {
    GitHub gitHub = new GitHubBuilder()
        .withOAuthToken(token)
        .build();
} catch (Exception e) {
    logger.error("Failed to create GitHub instance", e);
    process.complete();
}

Release Already Exists

If a release with the tag already exists, it’s reused:
GHRelease release = repository.getReleaseByTagName(ref);
if (release == null) {
    // Create new release
} else {
    logger.info("Release already exists");
}

API Permissions

The GitHub token requires the following permissions:
  • repo - Full repository access
    • repo:status - Read commit status
    • repo_deployment - Read deployment status
    • public_repo - Access public repositories
    • repo:invite - Access repository invitations
For public repositories, public_repo scope is sufficient.

Build docs developers (and LLMs) love