mirror of
https://github.com/SquidDev-CC/CC-Tweaked
synced 2024-06-27 15:43:23 +00:00
Move some more build logic to buildSrc
Look, I don't enjoy having 600 LOC long build.gradle files, it's just very easy to do! This at least moves some of the complexity elsewhere, so the build script is a little more declarative.
This commit is contained in:
parent
af5d816798
commit
0cfdd7b5e9
|
@ -83,7 +83,7 @@ ### Testing
|
||||||
- In-game (`./src/testMod/java/dan200/computercraft/ingame/`): These tests are run on an actual Minecraft server, using
|
- In-game (`./src/testMod/java/dan200/computercraft/ingame/`): These tests are run on an actual Minecraft server, using
|
||||||
the same system Mojang do][mc-test]. The aim of these is to test in-game behaviour of blocks and peripherals.
|
the same system Mojang do][mc-test]. The aim of these is to test in-game behaviour of blocks and peripherals.
|
||||||
|
|
||||||
These tests are run with `./gradlew testServer`.
|
These tests are run with `./gradlew runGametest`.
|
||||||
|
|
||||||
## CraftOS tests
|
## CraftOS tests
|
||||||
CraftOS's tests are written using a test system called "mcfly", heavily inspired by [busted] (and thus RSpec). Groups of
|
CraftOS's tests are written using a test system called "mcfly", heavily inspired by [busted] (and thus RSpec). Groups of
|
||||||
|
|
183
build.gradle
183
build.gradle
|
@ -1,6 +1,4 @@
|
||||||
plugins {
|
plugins {
|
||||||
id "checkstyle"
|
|
||||||
id "jacoco"
|
|
||||||
id "maven-publish"
|
id "maven-publish"
|
||||||
id "com.matthewprenger.cursegradle" version "1.4.0"
|
id "com.matthewprenger.cursegradle" version "1.4.0"
|
||||||
id "com.github.breadmoirai.github-release" version "2.2.12"
|
id "com.github.breadmoirai.github-release" version "2.2.12"
|
||||||
|
@ -12,9 +10,10 @@
|
||||||
id "com.github.johnrengelman.shadow" version "7.1.2"
|
id "com.github.johnrengelman.shadow" version "7.1.2"
|
||||||
id("cc-tweaked.illuaminate")
|
id("cc-tweaked.illuaminate")
|
||||||
id("cc-tweaked.java-convention")
|
id("cc-tweaked.java-convention")
|
||||||
|
id("cc-tweaked")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
import cc.tweaked.gradle.CheckChangelog
|
||||||
import cc.tweaked.gradle.ExtensionsKt
|
import cc.tweaked.gradle.ExtensionsKt
|
||||||
import cc.tweaked.gradle.IlluaminateExec
|
import cc.tweaked.gradle.IlluaminateExec
|
||||||
import cc.tweaked.gradle.IlluaminateExecToDir
|
import cc.tweaked.gradle.IlluaminateExecToDir
|
||||||
|
@ -25,16 +24,7 @@
|
||||||
group = "org.squiddev"
|
group = "org.squiddev"
|
||||||
archivesBaseName = "cc-tweaked-${mc_version}"
|
archivesBaseName = "cc-tweaked-${mc_version}"
|
||||||
|
|
||||||
def javaVersion = JavaLanguageVersion.of(8)
|
java.registerFeature("extraMods") { usingSourceSet(sourceSets.main) }
|
||||||
java {
|
|
||||||
toolchain {
|
|
||||||
languageVersion = javaVersion
|
|
||||||
}
|
|
||||||
|
|
||||||
withSourcesJar()
|
|
||||||
withJavadocJar()
|
|
||||||
registerFeature("extraMods") { usingSourceSet(sourceSets.main) }
|
|
||||||
}
|
|
||||||
|
|
||||||
sourceSets {
|
sourceSets {
|
||||||
main.resources {
|
main.resources {
|
||||||
|
@ -115,14 +105,6 @@ accessTransformer file('src/testMod/resources/META-INF/accesstransformer.cfg')
|
||||||
shadowJar {}
|
shadowJar {}
|
||||||
}
|
}
|
||||||
|
|
||||||
repositories {
|
|
||||||
mavenCentral()
|
|
||||||
maven {
|
|
||||||
name "SquidDev"
|
|
||||||
url "https://squiddev.cc/maven"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
configurations {
|
configurations {
|
||||||
shade { transitive = false }
|
shade { transitive = false }
|
||||||
implementation.extendsFrom shade
|
implementation.extendsFrom shade
|
||||||
|
@ -133,8 +115,6 @@ accessTransformer file('src/testMod/resources/META-INF/accesstransformer.cfg')
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
checkstyle "com.puppycrawl.tools:checkstyle:8.25"
|
|
||||||
|
|
||||||
minecraft "net.minecraftforge:forge:${mc_version}-${forge_version}"
|
minecraft "net.minecraftforge:forge:${mc_version}-${forge_version}"
|
||||||
annotationProcessor 'org.spongepowered:mixin:0.8.4:processor'
|
annotationProcessor 'org.spongepowered:mixin:0.8.4:processor'
|
||||||
|
|
||||||
|
@ -222,77 +202,21 @@ accessTransformer file('src/testMod/resources/META-INF/accesstransformer.cfg')
|
||||||
|
|
||||||
assemble.dependsOn("shadowJar")
|
assemble.dependsOn("shadowJar")
|
||||||
|
|
||||||
[
|
|
||||||
tasks.named("compileJava", JavaCompile.class),
|
|
||||||
tasks.named("compileTestJava", JavaCompile.class),
|
|
||||||
tasks.named("compileTestModJava", JavaCompile.class)
|
|
||||||
].forEach {
|
|
||||||
it.configure {
|
|
||||||
options.compilerArgs << "-Xlint" << "-Xlint:-processing"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
processResources {
|
processResources {
|
||||||
inputs.property "version", mod_version
|
inputs.property "version", mod_version
|
||||||
inputs.property "mcversion", mc_version
|
inputs.property "mcversion", mc_version
|
||||||
|
|
||||||
def hash = 'none'
|
inputs.property("gitHash", cct.gitHash)
|
||||||
Set<String> contributors = []
|
|
||||||
try {
|
|
||||||
hash = ["git", "-C", projectDir, "rev-parse", "HEAD"].execute().text.trim()
|
|
||||||
|
|
||||||
def blacklist = ['GitHub', 'Daniel Ratcliffe', 'Weblate']
|
filesMatching("data/computercraft/lua/rom/help/credits.txt") {
|
||||||
|
expand("gitContributors": cct.gitContributors.get().join("\n"))
|
||||||
// Extract all authors, commiters and co-authors from the git log.
|
|
||||||
def authors = ["git", "-C", projectDir, "log", "--format=tformat:%an <%ae>%n%cn <%ce>%n%(trailers:key=Co-authored-by,valueonly)"]
|
|
||||||
.execute().text.readLines().unique()
|
|
||||||
|
|
||||||
// We now pass this through git's mailmap to de-duplicate some authors.
|
|
||||||
def remapAuthors = ["git", "check-mailmap", "--stdin"].execute()
|
|
||||||
remapAuthors.withWriter { stdin ->
|
|
||||||
if (stdin !instanceof BufferedWriter) stdin = new BufferedWriter(stdin)
|
|
||||||
|
|
||||||
authors.forEach {
|
|
||||||
if (it == "") return
|
|
||||||
if (!it.endsWith(">")) it += ">" // Some commits have broken Co-Authored-By lines!
|
|
||||||
stdin.writeLine(it)
|
|
||||||
}
|
|
||||||
stdin.close()
|
|
||||||
}
|
|
||||||
|
|
||||||
// And finally extract out the actual name.
|
|
||||||
def emailRegex = ~/^([^<]+) <.+>$/
|
|
||||||
remapAuthors.text.readLines().forEach {
|
|
||||||
def matcher = it =~ emailRegex
|
|
||||||
matcher.find()
|
|
||||||
def name = matcher.group(1)
|
|
||||||
if (!blacklist.contains(name)) contributors.add(name)
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace()
|
|
||||||
}
|
|
||||||
inputs.property "commithash", hash
|
|
||||||
duplicatesStrategy = DuplicatesStrategy.INCLUDE
|
|
||||||
|
|
||||||
from(sourceSets.main.resources.srcDirs) {
|
|
||||||
include 'META-INF/mods.toml'
|
|
||||||
include 'data/computercraft/lua/rom/help/credits.txt'
|
|
||||||
|
|
||||||
expand 'version': mod_version,
|
|
||||||
'mcversion': mc_version,
|
|
||||||
'gitcontributors': contributors.sort(false, String.CASE_INSENSITIVE_ORDER).join('\n')
|
|
||||||
}
|
}
|
||||||
|
|
||||||
from(sourceSets.main.resources.srcDirs) {
|
filesMatching("META-INF/mods.toml") {
|
||||||
exclude 'META-INF/mods.toml'
|
expand("version": mod_version, "mcversion": mc_version)
|
||||||
exclude 'data/computercraft/lua/rom/help/credits.txt'
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sourcesJar {
|
|
||||||
duplicatesStrategy = DuplicatesStrategy.INCLUDE
|
|
||||||
}
|
|
||||||
|
|
||||||
// Web tasks
|
// Web tasks
|
||||||
|
|
||||||
List<String> mkCommand(String command) {
|
List<String> mkCommand(String command) {
|
||||||
|
@ -378,16 +302,6 @@ commandLine mkCommand('"node_modules/.bin/ts-node" -T --esm src/web/transform.ts
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
jacocoTestReport {
|
|
||||||
dependsOn('test')
|
|
||||||
reports {
|
|
||||||
xml.required = true
|
|
||||||
html.required = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
test.finalizedBy("jacocoTestReport")
|
|
||||||
|
|
||||||
def lintLua = tasks.register("lintLua", IlluaminateExec.class) {
|
def lintLua = tasks.register("lintLua", IlluaminateExec.class) {
|
||||||
group = JavaBasePlugin.VERIFICATION_GROUP
|
group = JavaBasePlugin.VERIFICATION_GROUP
|
||||||
description = "Lint Lua (and Lua docs) with illuaminate"
|
description = "Lint Lua (and Lua docs) with illuaminate"
|
||||||
|
@ -417,88 +331,29 @@ commandLine mkCommand('"node_modules/.bin/ts-node" -T --esm src/web/transform.ts
|
||||||
into "test-files/server"
|
into "test-files/server"
|
||||||
}
|
}
|
||||||
|
|
||||||
def testServerClassDumpDir = new File(buildDir, "jacocoClassDump/runTestServer")
|
def runGametest = tasks.register("runGametest", JavaExec.class) {
|
||||||
|
|
||||||
def testServer = tasks.register("testServer", JavaExec.class) {
|
|
||||||
group("In-game tests")
|
group("In-game tests")
|
||||||
description("Runs tests on a temporary Minecraft instance.")
|
description("Runs tests on a temporary Minecraft instance.")
|
||||||
dependsOn(setupServer, "cleanTestServer")
|
dependsOn(setupServer, "cleanRunGametest")
|
||||||
finalizedBy("jacocoTestServerReport")
|
|
||||||
|
|
||||||
// Copy from runTestServer. We do it in this slightly odd way as runTestServer
|
// Copy from runTestServer. We do it in this slightly odd way as runTestServer
|
||||||
// isn't created until the task is configured (which is no good for us).
|
// isn't created until the task is configured (which is no good for us).
|
||||||
ExtensionsKt.copyToFull(tasks.getByName("runTestServer"), it)
|
ExtensionsKt.copyToFull(tasks.getByName("runTestServer"), it)
|
||||||
|
|
||||||
// Jacoco and modlauncher don't play well together as the classes loaded in-game don't
|
|
||||||
// match up with those written to disk. We get Jacoco to dump all classes to disk, and
|
|
||||||
// use that when generating the report.
|
|
||||||
jacoco.applyTo(it)
|
|
||||||
it.jacoco.setIncludes(["dan200.computercraft.*"])
|
|
||||||
it.jacoco.setClassDumpDir(testServerClassDumpDir)
|
|
||||||
outputs.dir(testServerClassDumpDir)
|
|
||||||
// Older versions of modlauncher don't include a protection domain (and thus no code
|
|
||||||
// source). Jacoco skips such classes by default, so we need to explicitly include them.
|
|
||||||
it.jacoco.setIncludeNoLocationClasses(true)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.register("jacocoTestServerReport", JacocoReport.class) {
|
cct.jacoco(runGametest)
|
||||||
group("In-game tests")
|
|
||||||
description("Generate coverage reports for testServer")
|
|
||||||
dependsOn(testServer)
|
|
||||||
|
|
||||||
executionData(new File(buildDir, "jacoco/testServer.exec"))
|
tasks.check { dependsOn(runGametest) }
|
||||||
sourceDirectories.from(sourceSets.main.allJava.srcDirs)
|
|
||||||
classDirectories.from(testServerClassDumpDir)
|
|
||||||
|
|
||||||
reports {
|
|
||||||
xml.enabled true
|
|
||||||
html.enabled true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
check.dependsOn(testServer)
|
|
||||||
|
|
||||||
// Upload tasks
|
// Upload tasks
|
||||||
|
|
||||||
def checkRelease = tasks.register("checkRelease") {
|
def checkChangelog = tasks.register("checkChangelog", CheckChangelog.class) {
|
||||||
group "upload"
|
version.set(mod_version)
|
||||||
description "Verifies that everything is ready for a release"
|
whatsNew.set(file("src/main/resources/data/computercraft/lua/rom/help/whatsnew.md"))
|
||||||
|
changelog.set(file("src/main/resources/data/computercraft/lua/rom/help/changelog.md"))
|
||||||
inputs.property "version", mod_version
|
|
||||||
inputs.file("src/main/resources/data/computercraft/lua/rom/help/changelog.md")
|
|
||||||
inputs.file("src/main/resources/data/computercraft/lua/rom/help/whatsnew.md")
|
|
||||||
|
|
||||||
doLast {
|
|
||||||
def ok = true
|
|
||||||
|
|
||||||
// Check we're targetting the current version
|
|
||||||
def whatsnew = new File(projectDir, "src/main/resources/data/computercraft/lua/rom/help/whatsnew.md").readLines()
|
|
||||||
if (whatsnew[0] != "New features in CC: Tweaked $mod_version") {
|
|
||||||
ok = false
|
|
||||||
project.logger.error("Expected `whatsnew.md' to target $mod_version.")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check "read more" exists and trim it
|
|
||||||
def idx = whatsnew.findIndexOf { it == 'Type "help changelog" to see the full version history.' }
|
|
||||||
if (idx == -1) {
|
|
||||||
ok = false
|
|
||||||
project.logger.error("Must mention the changelog in whatsnew.md")
|
|
||||||
} else {
|
|
||||||
whatsnew = whatsnew.getAt(0..<idx)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check whatsnew and changelog match.
|
|
||||||
def versionChangelog = "# " + whatsnew.join("\n")
|
|
||||||
def changelog = new File(projectDir, "src/main/resources/data/computercraft/lua/rom/help/changelog.md").getText()
|
|
||||||
if (!changelog.startsWith(versionChangelog)) {
|
|
||||||
ok = false
|
|
||||||
project.logger.error("whatsnew and changelog are not in sync")
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!ok) throw new IllegalStateException("Could not check release")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
check.dependsOn(checkRelease)
|
|
||||||
|
tasks.check { dependsOn(checkChangelog) }
|
||||||
|
|
||||||
def isStable = true
|
def isStable = true
|
||||||
|
|
||||||
|
@ -595,7 +450,7 @@ commandLine mkCommand('"node_modules/.bin/ts-node" -T --esm src/web/transform.ts
|
||||||
}
|
}
|
||||||
|
|
||||||
def uploadTasks = ["publish", "curseforge", "modrinth", "githubRelease"]
|
def uploadTasks = ["publish", "curseforge", "modrinth", "githubRelease"]
|
||||||
uploadTasks.forEach { tasks.named(it) { dependsOn(checkRelease) } }
|
uploadTasks.forEach { tasks.named(it) { dependsOn(checkChangelog) } }
|
||||||
|
|
||||||
tasks.register("uploadAll") {
|
tasks.register("uploadAll") {
|
||||||
group = "upload"
|
group = "upload"
|
||||||
|
|
|
@ -14,6 +14,11 @@ dependencies {
|
||||||
|
|
||||||
gradlePlugin {
|
gradlePlugin {
|
||||||
plugins {
|
plugins {
|
||||||
|
register("cc-tweaked") {
|
||||||
|
id = "cc-tweaked"
|
||||||
|
implementationClass = "cc.tweaked.gradle.CCTweakedPlugin"
|
||||||
|
}
|
||||||
|
|
||||||
register("cc-tweaked.illuaminate") {
|
register("cc-tweaked.illuaminate") {
|
||||||
id = "cc-tweaked.illuaminate"
|
id = "cc-tweaked.illuaminate"
|
||||||
implementationClass = "cc.tweaked.gradle.IlluaminatePlugin"
|
implementationClass = "cc.tweaked.gradle.IlluaminatePlugin"
|
||||||
|
|
|
@ -4,11 +4,68 @@ import com.diffplug.spotless.LineEnding
|
||||||
import java.nio.charset.StandardCharsets
|
import java.nio.charset.StandardCharsets
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
java
|
`java-library`
|
||||||
jacoco
|
jacoco
|
||||||
|
checkstyle
|
||||||
id("com.diffplug.spotless")
|
id("com.diffplug.spotless")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
java {
|
||||||
|
toolchain {
|
||||||
|
languageVersion.set(JavaLanguageVersion.of(8))
|
||||||
|
}
|
||||||
|
|
||||||
|
withSourcesJar()
|
||||||
|
withJavadocJar()
|
||||||
|
}
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
mavenCentral()
|
||||||
|
maven("https://squiddev.cc/maven") {
|
||||||
|
name = "SquidDev"
|
||||||
|
content {
|
||||||
|
includeGroup("org.squiddev")
|
||||||
|
includeGroup("cc.tweaked")
|
||||||
|
// Things we mirror
|
||||||
|
includeGroup("com.blamejared.crafttweaker")
|
||||||
|
includeGroup("commoble.morered")
|
||||||
|
includeGroup("maven.modrinth")
|
||||||
|
includeGroup("mezz.jei")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
val libs = project.extensions.getByType<VersionCatalogsExtension>().named("libs")
|
||||||
|
checkstyle(libs.findLibrary("checkstyle").get())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Configure default JavaCompile tasks with our arguments.
|
||||||
|
sourceSets.all {
|
||||||
|
tasks.named(compileJavaTaskName, JavaCompile::class.java) {
|
||||||
|
// Processing just gives us "No processor claimed any of these annotations", so skip that!
|
||||||
|
options.compilerArgs.addAll(listOf("-Xlint", "-Xlint:-processing"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.withType(JavaCompile::class.java).configureEach {
|
||||||
|
options.encoding = "UTF-8"
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.test {
|
||||||
|
finalizedBy("jacocoTestReport")
|
||||||
|
|
||||||
|
useJUnitPlatform()
|
||||||
|
testLogging {
|
||||||
|
events("skipped", "failed")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.withType(JacocoReport::class.java).configureEach {
|
||||||
|
reports.xml.required.set(true)
|
||||||
|
reports.html.required.set(true)
|
||||||
|
}
|
||||||
|
|
||||||
spotless {
|
spotless {
|
||||||
encoding = StandardCharsets.UTF_8
|
encoding = StandardCharsets.UTF_8
|
||||||
lineEndings = LineEnding.UNIX
|
lineEndings = LineEnding.UNIX
|
||||||
|
|
124
buildSrc/src/main/kotlin/cc/tweaked/gradle/CCTweakedExtension.kt
Normal file
124
buildSrc/src/main/kotlin/cc/tweaked/gradle/CCTweakedExtension.kt
Normal file
|
@ -0,0 +1,124 @@
|
||||||
|
package cc.tweaked.gradle
|
||||||
|
|
||||||
|
import org.gradle.api.NamedDomainObjectProvider
|
||||||
|
import org.gradle.api.Project
|
||||||
|
import org.gradle.api.attributes.TestSuiteType
|
||||||
|
import org.gradle.api.file.FileSystemOperations
|
||||||
|
import org.gradle.api.provider.Provider
|
||||||
|
import org.gradle.api.reporting.ReportingExtension
|
||||||
|
import org.gradle.api.tasks.JavaExec
|
||||||
|
import org.gradle.api.tasks.SourceSetContainer
|
||||||
|
import org.gradle.configurationcache.extensions.capitalized
|
||||||
|
import org.gradle.kotlin.dsl.get
|
||||||
|
import org.gradle.language.base.plugins.LifecycleBasePlugin
|
||||||
|
import org.gradle.testing.jacoco.plugins.JacocoCoverageReport
|
||||||
|
import org.gradle.testing.jacoco.plugins.JacocoPluginExtension
|
||||||
|
import org.gradle.testing.jacoco.plugins.JacocoTaskExtension
|
||||||
|
import org.gradle.testing.jacoco.tasks.JacocoReport
|
||||||
|
import java.io.BufferedWriter
|
||||||
|
import java.io.IOException
|
||||||
|
import java.io.OutputStreamWriter
|
||||||
|
import java.util.regex.Pattern
|
||||||
|
|
||||||
|
abstract class CCTweakedExtension(
|
||||||
|
private val project: Project,
|
||||||
|
private val fs: FileSystemOperations,
|
||||||
|
) {
|
||||||
|
/** Get the hash of the latest git commit. */
|
||||||
|
val gitHash: Provider<String> = gitProvider(project) {
|
||||||
|
ProcessHelpers.captureOut("git", "-C", project.projectDir.absolutePath, "rev-parse", "HEAD")
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Get the current git branch. */
|
||||||
|
val gitBranch: Provider<String> = gitProvider(project) {
|
||||||
|
ProcessHelpers.captureOut("git", "-C", project.projectDir.absolutePath, "rev-parse", "--abbrev-ref", "HEAD")
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Get a list of all contributors to the project. */
|
||||||
|
val gitContributors: Provider<List<String>> = gitProvider(project) {
|
||||||
|
val authors: Set<String> = HashSet(
|
||||||
|
ProcessHelpers.captureLines(
|
||||||
|
"git", "-C", project.projectDir.absolutePath, "log",
|
||||||
|
"--format=tformat:%an <%ae>%n%cn <%ce>%n%(trailers:key=Co-authored-by,valueonly)",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
val process = ProcessHelpers.startProcess("git", "check-mailmap", "--stdin")
|
||||||
|
BufferedWriter(OutputStreamWriter(process.outputStream)).use { writer ->
|
||||||
|
for (authorName in authors) {
|
||||||
|
var author = authorName
|
||||||
|
|
||||||
|
if (author.isEmpty()) continue
|
||||||
|
if (!author.endsWith(">")) author += ">" // Some commits have broken Co-Authored-By lines!
|
||||||
|
writer.write(author)
|
||||||
|
writer.newLine()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val contributors: MutableSet<String> = HashSet()
|
||||||
|
for (authorLine in ProcessHelpers.captureLines(process)) {
|
||||||
|
val matcher = EMAIL.matcher(authorLine)
|
||||||
|
matcher.find()
|
||||||
|
val name = matcher.group(1)
|
||||||
|
if (!IGNORED_USERS.contains(name)) contributors.add(name)
|
||||||
|
}
|
||||||
|
|
||||||
|
contributors.sortedWith(String.CASE_INSENSITIVE_ORDER)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun jacoco(task: NamedDomainObjectProvider<JavaExec>) {
|
||||||
|
val classDump = project.buildDir.resolve("jacocoClassDump/${task.name}")
|
||||||
|
val reportTaskName = "jacoco${task.name.capitalized()}Report"
|
||||||
|
|
||||||
|
val jacoco = project.extensions.getByType(JacocoPluginExtension::class.java)
|
||||||
|
task.configure {
|
||||||
|
finalizedBy(reportTaskName)
|
||||||
|
|
||||||
|
doFirst("Clean class dump directory") { fs.delete { delete(classDump) } }
|
||||||
|
|
||||||
|
jacoco.applyTo(this)
|
||||||
|
extensions.configure(JacocoTaskExtension::class.java) {
|
||||||
|
includes = listOf("dan200.computercraft.*")
|
||||||
|
classDumpDir = classDump
|
||||||
|
|
||||||
|
// Older versions of modlauncher don't include a protection domain (and thus no code
|
||||||
|
// source). Jacoco skips such classes by default, so we need to explicitly include them.
|
||||||
|
isIncludeNoLocationClasses = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
project.tasks.register(reportTaskName, JacocoReport::class.java) {
|
||||||
|
group = LifecycleBasePlugin.VERIFICATION_GROUP
|
||||||
|
description = "Generates code coverage report for the ${task.name} task."
|
||||||
|
|
||||||
|
executionData(task.get())
|
||||||
|
classDirectories.from(classDump)
|
||||||
|
|
||||||
|
// Don't want to use sourceSets(...) here as we have a custom class directory.
|
||||||
|
val sourceSets = project.extensions.getByType(SourceSetContainer::class.java)
|
||||||
|
sourceDirectories.from(sourceSets["main"].allSource.sourceDirectories)
|
||||||
|
}
|
||||||
|
|
||||||
|
project.extensions.configure(ReportingExtension::class.java) {
|
||||||
|
reports.register("${task.name}CodeCoverageReport", JacocoCoverageReport::class.java) {
|
||||||
|
testType.set(TestSuiteType.INTEGRATION_TEST)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val EMAIL = Pattern.compile("^([^<]+) <.+>$")
|
||||||
|
private val IGNORED_USERS = setOf(
|
||||||
|
"GitHub", "Daniel Ratcliffe", "Weblate",
|
||||||
|
)
|
||||||
|
|
||||||
|
private fun <T> gitProvider(project: Project, supplier: () -> T): Provider<T> {
|
||||||
|
return project.provider {
|
||||||
|
try {
|
||||||
|
supplier()
|
||||||
|
} catch (e: IOException) {
|
||||||
|
project.logger.error("Cannot read Git Repository", e)
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
package cc.tweaked.gradle
|
||||||
|
|
||||||
|
import org.gradle.api.Plugin
|
||||||
|
import org.gradle.api.Project
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configures projects to match a shared configuration.
|
||||||
|
*/
|
||||||
|
class CCTweakedPlugin : Plugin<Project> {
|
||||||
|
override fun apply(project: Project) {
|
||||||
|
project.extensions.create("cct", CCTweakedExtension::class.java)
|
||||||
|
}
|
||||||
|
}
|
65
buildSrc/src/main/kotlin/cc/tweaked/gradle/CheckChangelog.kt
Normal file
65
buildSrc/src/main/kotlin/cc/tweaked/gradle/CheckChangelog.kt
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
package cc.tweaked.gradle
|
||||||
|
|
||||||
|
import org.gradle.api.DefaultTask
|
||||||
|
import org.gradle.api.GradleException
|
||||||
|
import org.gradle.api.file.RegularFileProperty
|
||||||
|
import org.gradle.api.provider.Property
|
||||||
|
import org.gradle.api.tasks.*
|
||||||
|
import org.gradle.language.base.plugins.LifecycleBasePlugin
|
||||||
|
import java.nio.charset.StandardCharsets
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks the `changelog.md` and `whatsnew.md` files are well-formed.
|
||||||
|
*/
|
||||||
|
@CacheableTask
|
||||||
|
abstract class CheckChangelog : DefaultTask() {
|
||||||
|
init {
|
||||||
|
group = LifecycleBasePlugin.VERIFICATION_GROUP
|
||||||
|
description = "Verifies the changelog and whatsnew file are consistent."
|
||||||
|
}
|
||||||
|
|
||||||
|
@get:Input
|
||||||
|
abstract val version: Property<String>
|
||||||
|
|
||||||
|
@get:InputFile
|
||||||
|
@get:PathSensitive(PathSensitivity.NONE)
|
||||||
|
abstract val changelog: RegularFileProperty
|
||||||
|
|
||||||
|
@get:InputFile
|
||||||
|
@get:PathSensitive(PathSensitivity.NONE)
|
||||||
|
abstract val whatsNew: RegularFileProperty
|
||||||
|
|
||||||
|
@TaskAction
|
||||||
|
fun check() {
|
||||||
|
val version = version.get()
|
||||||
|
|
||||||
|
var ok = true
|
||||||
|
|
||||||
|
// Check we're targetting the current version
|
||||||
|
var whatsNew = whatsNew.get().asFile.readLines()
|
||||||
|
if (whatsNew[0] != "New features in CC: Tweaked $version") {
|
||||||
|
ok = false
|
||||||
|
logger.error("Expected `whatsnew.md' to target $version.")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check "read more" exists and trim it
|
||||||
|
val idx = whatsNew.indexOfFirst { it == "Type \"help changelog\" to see the full version history." }
|
||||||
|
if (idx == -1) {
|
||||||
|
ok = false
|
||||||
|
logger.error("Must mention the changelog in whatsnew.md")
|
||||||
|
} else {
|
||||||
|
whatsNew = whatsNew.slice(0 until idx)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check whatsnew and changelog match.
|
||||||
|
val expectedChangelog = sequenceOf("# ${whatsNew[0]}") + whatsNew.slice(1 until whatsNew.size).asSequence()
|
||||||
|
val changelog = changelog.get().asFile.readLines()
|
||||||
|
val mismatch = expectedChangelog.zip(changelog.asSequence()).filter { (a, b) -> a != b }.firstOrNull()
|
||||||
|
if (mismatch != null) {
|
||||||
|
ok = false
|
||||||
|
logger.error("whatsnew and changelog are not in sync")
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ok) throw GradleException("Could not check release")
|
||||||
|
}
|
||||||
|
}
|
|
@ -25,7 +25,7 @@ fun create(api: File, main: File): FormatterStep = FormatterStep.createLazy(
|
||||||
)
|
)
|
||||||
|
|
||||||
private fun getTemplateText(file: File): String =
|
private fun getTemplateText(file: File): String =
|
||||||
file.readText(StandardCharsets.UTF_8).trim().replace("\${year}", "$YEAR")
|
file.readText().trim().replace("\${year}", "$YEAR")
|
||||||
|
|
||||||
private fun formatFile(licenses: Licenses, contents: String, file: File): String {
|
private fun formatFile(licenses: Licenses, contents: String, file: File): String {
|
||||||
val license = getLicense(contents)
|
val license = getLicense(contents)
|
||||||
|
@ -38,8 +38,8 @@ private fun formatFile(licenses: Licenses, contents: String, file: File): String
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getExpectedLicense(licenses: Licenses, file: File): String {
|
private fun getExpectedLicense(licenses: Licenses, root: File): String {
|
||||||
var file: File? = file
|
var file: File? = root
|
||||||
while (file != null) {
|
while (file != null) {
|
||||||
if (file.name == "api" && file.parentFile?.name == "computercraft") return licenses.api
|
if (file.name == "api" && file.parentFile?.name == "computercraft") return licenses.api
|
||||||
file = file.parentFile
|
file = file.parentFile
|
||||||
|
|
34
buildSrc/src/main/kotlin/cc/tweaked/gradle/ProcessHelpers.kt
Normal file
34
buildSrc/src/main/kotlin/cc/tweaked/gradle/ProcessHelpers.kt
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
package cc.tweaked.gradle
|
||||||
|
|
||||||
|
import org.codehaus.groovy.runtime.ProcessGroovyMethods
|
||||||
|
import java.io.BufferedReader
|
||||||
|
import java.io.IOException
|
||||||
|
import java.io.InputStreamReader
|
||||||
|
|
||||||
|
internal object ProcessHelpers {
|
||||||
|
fun startProcess(vararg command: String): Process {
|
||||||
|
// Something randomly passes in "GIT_DIR=" as an environment variable which clobbers everything else. Don't
|
||||||
|
// inherit the environment array!
|
||||||
|
return Runtime.getRuntime().exec(command, arrayOfNulls(0))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun captureOut(vararg command: String): String {
|
||||||
|
val process = startProcess(*command)
|
||||||
|
val result = ProcessGroovyMethods.getText(process)
|
||||||
|
if (process.waitFor() != 0) throw IOException("Command exited with a non-0 status")
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
fun captureLines(vararg command: String): List<String> {
|
||||||
|
return captureLines(startProcess(*command))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun captureLines(process: Process): List<String> {
|
||||||
|
val out = BufferedReader(InputStreamReader(process.inputStream)).use { reader ->
|
||||||
|
reader.lines().filter { it.isNotEmpty() }.toList()
|
||||||
|
}
|
||||||
|
ProcessGroovyMethods.closeStreams(process)
|
||||||
|
if (process.waitFor() != 0) throw IOException("Command exited with a non-0 status")
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
}
|
|
@ -10,6 +10,7 @@ jqwik = "1.7.0"
|
||||||
junit = "5.9.1"
|
junit = "5.9.1"
|
||||||
|
|
||||||
# Build tools
|
# Build tools
|
||||||
|
checkstyle = "8.25" # There's a reason we're pinned on an ancient version, but I can't remember what it is.
|
||||||
spotless = "6.8.0"
|
spotless = "6.8.0"
|
||||||
|
|
||||||
[libraries]
|
[libraries]
|
||||||
|
@ -26,7 +27,8 @@ junit-jupiter-api = { module = "org.junit.jupiter:junit-jupiter-api", version.re
|
||||||
junit-jupiter-engine = { module = "org.junit.jupiter:junit-jupiter-engine", version.ref = "junit" }
|
junit-jupiter-engine = { module = "org.junit.jupiter:junit-jupiter-engine", version.ref = "junit" }
|
||||||
junit-jupiter-params = { module = "org.junit.jupiter:junit-jupiter-params", version.ref = "junit" }
|
junit-jupiter-params = { module = "org.junit.jupiter:junit-jupiter-params", version.ref = "junit" }
|
||||||
|
|
||||||
# Gradle plugins
|
# Build tools
|
||||||
|
checkstyle = { module = "com.puppycrawl.tools:checkstyle", version.ref = "checkstyle" }
|
||||||
spotless = { module = "com.diffplug.spotless:spotless-plugin-gradle", version.ref = "spotless" }
|
spotless = { module = "com.diffplug.spotless:spotless-plugin-gradle", version.ref = "spotless" }
|
||||||
|
|
||||||
[bundles]
|
[bundles]
|
||||||
|
|
|
@ -12,4 +12,4 @@ Follow @DanTwoHundred on Twitter!
|
||||||
To help contribute to ComputerCraft, browse the source code at https://github.com/dan200/ComputerCraft.
|
To help contribute to ComputerCraft, browse the source code at https://github.com/dan200/ComputerCraft.
|
||||||
|
|
||||||
GitHub Contributors:
|
GitHub Contributors:
|
||||||
${gitcontributors}
|
${gitContributors}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user