Skip to content

Commit

Permalink
Setup CICD (#4)
Browse files Browse the repository at this point in the history
Add CICD pipeline via Travis for publishing builds to GitHub and CurseForge
  • Loading branch information
NotMyWing authored Dec 29, 2020
1 parent 5061579 commit 6b85bd9
Show file tree
Hide file tree
Showing 4 changed files with 260 additions and 4 deletions.
37 changes: 37 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
language: java
jdk:
- openjdk8

before_cache:
- rm -f $HOME/.gradle/caches/modules-2/modules-2.lock
- rm -fr $HOME/.gradle/caches/*/plugin-resolution/
cache:
directories:
- $HOME/.gradle/caches/
- $HOME/.gradle/wrapper/
- ./build/tmp/

git:
depth: false

deploy:
# Deploy release to CurseForge
- provider: script
edge: true
skip_cleanup: true
script: ./gradlew deployCurseForge
on:
all_branches: true
condition: $TRAVIS_BRANCH =~ ^(master|([0-9]+\.?){3}-[0-9]+\.[0-9]+)$

# Deploy release to GitHub (release)
- provider: releases
edge: true
skip_cleanup: true
file_glob: true
file: build/libs/**/*
token: "$GITHUB_TOKEN"
release_notes_file: build/tmp/changelog.md
overwrite: true
on:
tags: true
205 changes: 204 additions & 1 deletion build.gradle
Original file line number Diff line number Diff line change
@@ -1,16 +1,28 @@
import java.util.regex.Pattern
import groovy.json.JsonSlurper

import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.entity.mime.content.StringBody;
import groovyx.net.http.ContentType
import groovyx.net.http.HTTPBuilder
import groovyx.net.http.Method

buildscript {
repositories {
jcenter()
maven { url = "http://files.minecraftforge.net/maven" }
}
dependencies {
classpath 'net.minecraftforge.gradle:ForgeGradle:2.3-SNAPSHOT'
classpath "org.codehaus.groovy.modules.http-builder:http-builder:0.7"
classpath "org.apache.httpcomponents:httpmime:4.5.1"
}
}
apply plugin: 'net.minecraftforge.gradle.forge'

version = "${mc_version}-${mod_version}"
group = "jackyy.dimensionaledibles"
version = getRewrittenVersion()
archivesBaseName = "DimensionalEdibles"

sourceCompatibility = targetCompatibility = "1.8"
Expand All @@ -23,6 +35,7 @@ minecraft {
runDir = "run"
mappings = "${mappings_version}"

replace "GRADLE:VERSION", project.version
replace '@FINGERPRINT@', project.findProperty('signSHA1')
replaceIn "DimensionalEdibles.java"
}
Expand Down Expand Up @@ -82,3 +95,193 @@ task deobfJar(type: Jar) {
artifacts {
archives deobfJar
}


/*
Fetches the last tag associated with the current branch.
*/
def getLastTag() {
return run("git describe --abbrev=0 --tags " +
(System.env["TRAVIS_TAG"] ? run("git rev-list --tags --skip=1 --max-count=1") : "")
)
}

/*
Runs a command and returns the output.
*/
def run(command) {
def process = command.execute()
def outputStream = new StringBuffer();
def errorStream = new StringBuffer();
process.waitForProcessOutput(outputStream, errorStream)

errorStream.toString().with {
if (it) {
throw new GradleException("Error executing ${command}:\n> ${it}")
}
}

return outputStream.toString().trim()
}

/*
Rewrites the version.
*/
def getRewrittenVersion () {
def lastTag = getLastTag()

if (System.env['TRAVIS_TAG']) {
return System.env['TRAVIS_TAG'] + ".0"
} else {
def commitNo = run "git rev-list ${lastTag}..HEAD --count"

return lastTag + "." + commitNo
}
}

task generateChangelog {
onlyIf {
System.env['TRAVIS']
}

doLast {
/*
Create a comprehensive changelog.
*/
def lastTag = getLastTag()

def changelog = (run([
"git"
, "log"
, "--date=format:%d %b %Y"
, "--pretty=%s - **%an** (%ad)"
, "${lastTag}..HEAD"
].plus(
/*
Collect relevant directories only, them being:
* ./src/main/java
* ./src/main/resources
*/
sourceSets.main.java.srcDirs
.plus(sourceSets.main.resources.srcDirs)
.collect { [ "--", it ] }
).flatten()))

if (changelog) {
changelog = "Changes since ${lastTag}:\n${("\n" + changelog).replaceAll("\n", "\n* ")}"
}

def f = new File("build/tmp/changelog.md")
f.write(changelog ?: "", "UTF-8")
}
}

compileJava.dependsOn generateChangelog

task deployCurseForge {
doLast {
def final CURSEFORGE_ENDPOINT = "https://minecraft.curseforge.com/"

/*
Helper function for checking environmental variables.
*/
def final checkVariables = { variables ->
for (vari in variables) {
if (!System.env[vari]) {
throw new GradleException("Environmental variable ${vari} is unset")
}
}
}

checkVariables([
'CURSEFORGE_API_TOKEN', 'CURSEFORGE_PROJECT_ID'
])

/*
Helper function for fetching JSON data.
*/
def final fetch = { url, headers = null ->
def connection = new URL(url).openConnection();
connection.setRequestProperty("X-Api-Token", System.env["CURSEFORGE_API_TOKEN"])
if (headers != null) {
for (header in headers) {
connection.setRequestProperty(headers[1], headers[2])
}
}

def code = connection.getResponseCode()
if (code == 200) {
return new JsonSlurper().parseText(connection.getInputStream().getText())
} else {
throw new GradleException("Fetch failed with code ${code} (${url})")
}
}

/*
Fetch the list of Minecraft versions from CurseForge.
*/
def targetVersion = project.minecraft.version
def version = fetch(CURSEFORGE_ENDPOINT + "api/game/versions").with {
def v = it.find { it.name == targetVersion }

if (!v) {
throw new GradleException("Version ${project.minecraft.version} not found on CurseForge")
}

return v
}

/*
Fill the papers for CurseForge.
*/
def metadata = new groovy.json.JsonBuilder().with {
def versions = [ version.id ]

/*
CurseForge is dumb, so we'll have to prepend two spaces
to each newline. This is disgusting, but it works.
*/
def log = new File("build/tmp/changelog.md")
.getText("UTF-8")
.replaceAll("\n", " \n")
.replaceAll("\n\\*", "\n")

def root = it {
changelog log
changelogType "markdown"

releaseType System.env['TRAVIS_TAG'] ? "release" : "beta"
gameVersions versions

// Defined in gradle.properties
displayName "${project_fancy_name} ${project.version}"
}

if (project_curseforge_dependencies) {
def data = new JsonSlurper().parseText(project_curseforge_dependencies)

root << [relations: [ projects: data ]]
}

return it.toString()
}

/*
Upload the artifact to CurseForge.
*/
new HTTPBuilder(CURSEFORGE_ENDPOINT).request(Method.POST) { req ->
requestContentType = "multipart/form-data"
headers["X-Api-Token"] = System.env["CURSEFORGE_API_TOKEN"]
uri.path = "api/projects/${System.env["CURSEFORGE_PROJECT_ID"]}/upload-file"

req.entity = new MultipartEntityBuilder().with {
addPart("file", new FileBody(
new File("${project.jar.destinationDir}/${project.jar.archiveName}")
))
addPart("metadata", new StringBody(metadata))

return it.build()
}
}
}
}
20 changes: 18 additions & 2 deletions gradle.properties
Original file line number Diff line number Diff line change
@@ -1,7 +1,23 @@
# Sets default memory used for gradle commands. Can be overridden by user or command line properties.
# This is required to provide enough memory for the Minecraft decompilation process.
org.gradle.jvmargs=-Xmx4G
mc_version=1.12.2
forge_version=1.12.2-14.23.5.2825
mod_version=1.3.1
mappings_version=stable_39

# Deployment
project_fancy_name = Dimensional Edibles: Omnifactory Edition
project_curseforge_dependencies = [\
{\
"slug": "hwyla",\
"type": "optionalDependency"\
},{\
"slug": "jei",\
"type": "optionalDependency"\
},{\
"slug": "the-one-probe",\
"type": "optionalDependency"\
},{\
"slug": "waila",\
"type": "optionalDependency"\
}\
]
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
@Mod(modid = DimensionalEdibles.MODID, name = DimensionalEdibles.MODNAME, version = DimensionalEdibles.VERSION, acceptedMinecraftVersions = DimensionalEdibles.MCVERSION, dependencies = DimensionalEdibles.DEPENDS, certificateFingerprint = "@FINGERPRINT@", useMetadata = true)
public class DimensionalEdibles {

public static final String VERSION = "1.3.1";
public static final String VERSION = "GRADLE:VERSION";
public static final String MCVERSION = "[1.12,1.13)";
public static final String MODID = "dimensionaledibles";
public static final String MODNAME = "Dimensional Edibles";
Expand Down

0 comments on commit 6b85bd9

Please sign in to comment.