Skip to main content

Overview

MCReleaser supports configuration through both environment variables and Java system properties via a unified property key system. Understanding the conversion mechanism is essential for proper configuration.

Property Key System

All configuration in MCReleaser uses the PropertyKey class, which automatically handles:
  1. Environment variable lookup
  2. System property fallback
  3. CamelCase to CONSTANT_CASE conversion

Naming Convention

CamelCase to CONSTANT_CASE

MCReleaser automatically converts camelCase property names to CONSTANT_CASE for environment variables:
// From PropertyKey.java:18-27
private static String camelToConstant(String camel) {
    StringBuilder constant = new StringBuilder();
    for (char c : camel.toCharArray()) {
        if (Character.isUpperCase(c)) {
            constant.append('_');
        }
        constant.append(Character.toUpperCase(c));
    }
    return constant.toString();
}

Conversion Examples

Property Key (camelCase)Environment Variable (CONSTANT_CASE)
nameNAME
versionVERSION
gameVersionsGAME_VERSIONS
gameVersionTypeGAME_VERSION_TYPE
announceMissingKeyANNOUNCE_MISSING_KEY
syncSYNC

Configuration Priority

MCReleaser follows this resolution order:
  1. Environment Variable (checked first)
  2. System Property (fallback)
// From PropertyKey.java:45-51
public String getValue() {
    String value = System.getenv(env);  // 1. Check environment variable
    if (value == null) {
        value = System.getProperty(key);  // 2. Fallback to system property
    }
    return value;
}

Example Priority

# Environment variable takes precedence
export VERSION=2.0.0
java -Dversion=1.0.0 -jar mcreleaser.jar
# Result: VERSION=2.0.0 (from environment)

# System property used when env var is absent
java -Dversion=1.0.0 -jar mcreleaser.jar
# Result: VERSION=1.0.0 (from system property)

Common Properties

Core Properties

Defined in CommonPropertyKey.java:
PropertyEnvironment VariableDescription
nameNAMEProject/artifact name
versionVERSIONRelease version
descriptionDESCRIPTIONRelease description
gameVersionsGAME_VERSIONSMinecraft versions (comma/space-separated)
gameVersionTypeGAME_VERSION_TYPEVersion type filter (release, snapshot, all)
announceMissingKeyANNOUNCE_MISSING_KEYShow missing property warnings (boolean)

CLI Properties

Defined in CLIPropertyKey.java:
PropertyEnvironment VariableDescription
platformsPLATFORMSPlatforms to upload to (comma/space-separated)
syncSYNCSequential upload mode (boolean)
filesFILESFile globs to upload

Platform-Specific Properties

Property Prefixes

Platform-specific properties use the PropertyPrefix system, which adds a platform prefix to property keys:
// From PropertyPrefix.java:12-16
public PropertyKey key(String key) {
    key = key.substring(0, 1).toUpperCase() + key.substring(1);
    return new PropertyKey(prefix + key);
}

Modrinth Properties

PropertyEnvironment VariableExample Value
modrinthTokenMODRINTH_TOKENmrp_xxxxx
modrinthProjectMODRINTH_PROJECTmy-mod
modrinthVersionTypeMODRINTH_VERSION_TYPErelease
modrinthGameVersionsMODRINTH_GAME_VERSIONS1.20.1,1.20.2
modrinthLoadersMODRINTH_LOADERSfabric,forge
modrinthFeaturedMODRINTH_FEATUREDtrue
modrinthDependenciesMODRINTH_DEPENDENCIESfabric-api:required
modrinthEndpointMODRINTH_ENDPOINThttps://api.modrinth.com

GitHub Properties

PropertyEnvironment VariableExample Value
githubTokenGITHUB_TOKENghp_xxxxx
githubRepositoryGITHUB_REPOSITORYowner/repo
githubRefGITHUB_REFmain
githubDraftGITHUB_DRAFTfalse
githubPrereleaseGITHUB_PRERELEASEfalse

CurseForge Properties

PropertyEnvironment Variable
curseforgeTokenCURSEFORGE_TOKEN
curseforgeProjectCURSEFORGE_PROJECT
curseforgeGameVersionsCURSEFORGE_GAME_VERSIONS
curseforgeReleaseTypeCURSEFORGE_RELEASE_TYPE

Hangar Properties

PropertyEnvironment Variable
hangarTokenHANGAR_TOKEN
hangarProjectHANGAR_PROJECT
hangarChannelHANGAR_CHANNEL

Polymart Properties

PropertyEnvironment Variable
polymartTokenPOLYMART_TOKEN
polymartProjectPOLYMART_PROJECT

Configuration Methods

Method 1: Environment Variables

Recommended for CI/CD
export NAME="My Mod"
export VERSION="1.0.0"
export DESCRIPTION="A cool Minecraft mod"
export PLATFORMS="modrinth,curseforge"
export MODRINTH_TOKEN="mrp_xxxxx"
export MODRINTH_PROJECT="my-mod"
export CURSEFORGE_TOKEN="xxxxx"
export CURSEFORGE_PROJECT="123456"

java -jar mcreleaser.jar

Method 2: System Properties

Recommended for local development
java -Dname="My Mod" \
     -Dversion="1.0.0" \
     -Ddescription="A cool Minecraft mod" \
     -Dplatforms="modrinth,curseforge" \
     -DmodrinthToken="mrp_xxxxx" \
     -DmodrinthProject="my-mod" \
     -DcurseforgeToken="xxxxx" \
     -DcurseforgeProject="123456" \
     -jar mcreleaser.jar

Method 3: Mixed Configuration

Combine both for flexibility
# Secrets via environment (secure)
export MODRINTH_TOKEN="mrp_xxxxx"
export CURSEFORGE_TOKEN="xxxxx"

# Public config via system properties (visible)
java -Dname="My Mod" \
     -Dversion="1.0.0" \
     -Dplatforms="modrinth,curseforge" \
     -jar mcreleaser.jar

Type Conversion

MCReleaser automatically converts property values to appropriate types:

Boolean Properties

// From PropertyKey.java:75-78
public boolean asBoolean(boolean defaultValue) {
    String value = getValue();
    return value == null ? defaultValue : Boolean.parseBoolean(value);
}
Valid boolean values: true, false (case-insensitive)
export SYNC=true
export GITHUB_DRAFT=false
export MODRINTH_FEATURED=TRUE  # Also valid

Number Properties

// From PropertyKey.java:66-73
public Number asNumber(Number defaultValue) {
    String value = getValue();
    try {
        return value == null ? defaultValue : Double.parseDouble(value);
    } catch (NumberFormatException e) {
        return defaultValue;
    }
}
export TIMEOUT=30
export RETRY_COUNT=3

String Properties

No conversion needed - used directly:
export NAME="My Mod"
export VERSION="1.0.0"

Missing Properties

MCReleaser can announce missing required properties:
export ANNOUNCE_MISSING_KEY=true
java -jar mcreleaser.jar
Output:
ERROR: The following keys are missing: name, version, description
Required properties like name, version, and description must be set, or MCReleaser will exit early.

Best Practices

1. Use Environment Variables for Secrets

# Good: Secrets in environment
export MODRINTH_TOKEN="mrp_xxxxx"
export GITHUB_TOKEN="ghp_xxxxx"

# Bad: Secrets in command line (visible in process list)
java -DmodrinthToken="mrp_xxxxx" -jar mcreleaser.jar

2. Document Required Properties

Create a .env.example file:
# Required
NAME=
VERSION=
DESCRIPTION=
FILES=

# Platform selection
PLATFORMS=modrinth,curseforge

# Modrinth
MODRINTH_TOKEN=
MODRINTH_PROJECT=

# CurseForge
CURSEFORGE_TOKEN=
CURSEFORGE_PROJECT=

3. Use Consistent Naming

Always use either camelCase (system properties) or CONSTANT_CASE (environment variables):
# Good: Consistent
export MODRINTH_TOKEN="mrp_xxxxx"
java -DmodrinthToken="mrp_xxxxx" -jar mcreleaser.jar

# Bad: Mixed case (won't work)
export modrinth_token="mrp_xxxxx"

4. Validate Configuration

Enable missing key announcements during development:
export ANNOUNCE_MISSING_KEY=true

Programmatic Access

If extending MCReleaser, access properties via PropertyKey:
// Define property
PropertyKey MY_PROPERTY = new PropertyKey("myProperty");

// Read value
String value = MY_PROPERTY.getValue();
String valueWithDefault = MY_PROPERTY.getValue("default");
boolean boolValue = MY_PROPERTY.asBoolean(false);

// Set value (updates system property only)
MY_PROPERTY.setValue("newValue");

// Check presence
if (MY_PROPERTY.isPresent()) {
    // Property is set
}
When creating custom platform integrations, follow the existing naming conventions: use PropertyPrefix for platform-specific properties and camelCase for property keys.

Build docs developers (and LLMs) love