add update checks to jenkins builds

This commit is contained in:
nikky 2018-07-15 17:18:06 +02:00
parent 619e0541d7
commit 43d6589572
22 changed files with 220 additions and 7 deletions

View File

@ -78,6 +78,7 @@ minecraft {
replace '@MCVERSION@', project.mc_version
replace '@FORGELIN-VERSION@', project.forgelin_version
replace '@FORGE-VERSION@', project.forge_version
replace '-1//@BUILD_NUMBER@', System.env.BUILD_NUMBER ?: -1
}
processResources {

View File

@ -5,3 +5,4 @@ const val NAME = "MatterLink"
const val MODVERSION = "@MODVERSION@"
const val MCVERSION = "@MCVERSION@"
const val DEPENDENCIES = "required-after:forgelin@[@FORGELIN-VERSION@,);"
const val BUILD_NUMBER = -1//@BUILD_NUMBER@

View File

@ -118,5 +118,6 @@ object MatterLink : IMatterLink() {
override val mcVersion: String = MCVERSION
override val modVersion: String = MODVERSION
override val buildNumber = BUILD_NUMBER
override val forgeVersion = ForgeVersion.getVersion()
}

View File

@ -80,6 +80,7 @@ minecraft {
replace '@MCVERSION@', project.mc_version
replace '@FORGELIN-VERSION@', project.forgelin_version
replace '@FORGE-VERSION@', project.forge_version
replace '-1//@BUILD_NUMBER@', System.env.BUILD_NUMBER ?: -1
}
processResources {

View File

@ -5,4 +5,4 @@ const val NAME = "MatterLink"
const val MODVERSION = "@MODVERSION@"
const val MCVERSION = "@MCVERSION@"
const val DEPENDENCIES = "required-after:forgelin@[@FORGELIN-VERSION@,);required-after:forge@[@FORGE-VERSION@,);"
const val BUILD_NUMBER = -1//@BUILD_NUMBER@

View File

@ -120,5 +120,6 @@ object MatterLink : IMatterLink() {
override val mcVersion: String = MCVERSION
override val modVersion: String = MODVERSION
override val buildNumber = BUILD_NUMBER
override val forgeVersion = ForgeVersion.getVersion()
}

View File

@ -59,6 +59,7 @@ minecraft {
replace '@MCVERSION@', project.mc_version
replace '@FORGELIN-VERSION@', project.forgelin_version
replace '@FORGE-VERSION@', project.forge_version
replace '-1//@BUILD_NUMBER@', System.env.BUILD_NUMBER ?: -1
}
processResources {

View File

@ -5,4 +5,4 @@ const val NAME = "MatterLink"
const val MODVERSION = "@MODVERSION@"
const val MCVERSION = "@MCVERSION@"
const val DEPENDENCIES = "required-after:forgelin@[@FORGELIN-VERSION@,);required-after:forge@[@FORGE-VERSION@,);"
const val BUILD_NUMBER = -1//@BUILD_NUMBER@

View File

@ -123,5 +123,6 @@ object MatterLink : IMatterLink() {
override val mcVersion: String = MCVERSION
override val modVersion: String = MODVERSION
override val buildNumber = BUILD_NUMBER
override val forgeVersion = ForgeVersion.getVersion()
}

View File

@ -65,6 +65,9 @@ compileKotlin.doFirst {
ant.replaceregexp(match: '@FORGE-VERSION@', replace: project.forge_version, flags: 'g', byline: true) {
fileset(dir: target, includes: 'Constants.kt')
}
ant.replaceregexp(match: '@BUILD_NUMBER@', replace: System.env.BUILD_NUMBER ?: -1, flags: 'g', byline: true) {
fileset(dir: target, includes: 'Constants.kt')
}
}
processResources {

View File

@ -17,8 +17,6 @@ import net.minecraft.server.MinecraftServer
import net.minecraft.util.ChatComponentText
import net.minecraftforge.common.ForgeVersion
import net.minecraftforge.common.MinecraftForge
import org.apache.logging.log4j.Level
import org.apache.logging.log4j.Logger
import java.util.*
@Mod(
@ -122,5 +120,6 @@ class MatterLink : IMatterLink() {
override val mcVersion: String = MCVERSION
override val modVersion: String = MODVERSION
override val buildNumber = BUILD_NUMBER
override val forgeVersion = ForgeVersion.getVersion()
}

View File

@ -4,4 +4,4 @@ const val MODID = "matterlink"
const val NAME = "MatterLink"
const val MODVERSION = "@MODVERSION@"
const val MCVERSION = "@MCVERSION@"
const val BUILD_NUMBER = @BUILD_NUMBER@

View File

@ -18,6 +18,7 @@ subprojects {
if (System.env.BUILD_NUMBER) {
mod_version += "-${System.env.BUILD_NUMBER}"
} else if (!project.hasProperty('release')) {
// mod_version += "-dev"
mod_version += "-dev"
}

View File

@ -25,6 +25,8 @@ dependencies {
compile group: 'com.google.code.gson', name: 'gson', version: '+'
compile group: 'com.google.guava', name: 'guava', version: '+'
compile group: 'org.apache.httpcomponents', name: 'httpclient', version: '+'
compile group: 'org.jetbrains.kotlin', name: 'kotlin-stdlib-jdk8', version: project.kotlin_version
}

View File

@ -0,0 +1,42 @@
package matterlink
import matterlink.HttpClientUtil.client
import org.apache.http.HttpResponse
import org.apache.http.client.methods.HttpGet
import org.apache.http.client.methods.HttpRequestBase
import org.apache.http.impl.client.HttpClientBuilder
/**
* Created by nikky on 15/07/18.
* @author Nikky
*/
object HttpClientUtil {
val client = HttpClientBuilder.create().build()
}
fun String.httpGet(): HttpGet =
HttpGet(this)
fun HttpGet.header(pair: Pair<String, String>): HttpGet = this.apply {
addHeader(pair.first, pair.second)
}
fun HttpGet.responseString(): Triple<HttpRequestBase, HttpResponse, Result> {
val response = client.execute(this)
val result = response.entity.content.bufferedReader().use { it.readText() }
return Triple(this, response, Result.Success(result))
}
sealed class Result {
class Success(
val value: String
) : Result()
class Failure(
val error: Throwable
) : Result()
}

View File

@ -16,6 +16,7 @@ lateinit var logger: Logger
abstract class IMatterLink {
abstract val mcVersion: String
abstract val modVersion: String
abstract val buildNumber: Int
abstract val forgeVersion: String
abstract fun commandSenderFor(user: String, env: IBridgeCommand.CommandEnvironment, op: Boolean): IMinecraftCommandSender

View File

@ -0,0 +1,15 @@
package matterlink.jenkins
import com.google.gson.annotations.SerializedName
/**
* Created by nikky on 03/02/18.
* @author Nikky
*/
//@JsonIgnoreProperties(ignoreUnknown = true)
data class Artifact(
val displayPath: String,
val fileName: String,
val relativePath: String
)

View File

@ -0,0 +1,40 @@
package matterlink.jenkins
import com.google.gson.Gson
import matterlink.*
import matterlink.Result
import matterlink.header
import matterlink.httpGet
import matterlink.responseString
/**
* Created by nikky on 03/02/18.
* @author Nikky
*/
//@JsonIgnoreProperties(ignoreUnknown = true)
data class Build(
val number: Int,
val url: String
) {
fun details(userAgent: String): BuildWithDetails? {
val (request, response, result) = "$url/api/json"
.httpGet()
.header("User-Agent" to userAgent)
.responseString()
return when(result) {
is Result.Success -> {
gson.fromJson(result.value, BuildWithDetails::class.java)
}
is Result.Failure -> {
logger.error(result.error.toString())
null
}
}
}
companion object {
val gson = Gson()
}
}

View File

@ -0,0 +1,12 @@
package matterlink.jenkins
import java.util.*
//@JsonIgnoreProperties(ignoreUnknown = true)
data class BuildWithDetails(
val number: Int,
val url: String,
val artifacts: List<Artifact>,
// @JsonFormat(shape=JsonFormat.Shape.NUMBER, pattern="s")
val timestamp: Date
)

View File

@ -0,0 +1,43 @@
package voodoo.util.jenkins
import com.google.gson.Gson
import matterlink.Result
import matterlink.header
import matterlink.httpGet
import matterlink.responseString
import matterlink.jenkins.Job
import matterlink.logger
/**
* Created by nikky on 03/02/18.
* @author Nikky
*/
class JenkinsServer(val url: String) {
fun getUrl(job: String) = url + "/job/" + job.replace("/", "/job/")
fun getJob(job: String, userAgent: String): Job? {
val requestURL = getUrl(job) + "/api/json"
val (_, _, result) = requestURL
.httpGet()
.header("User-Agent" to userAgent)
.responseString()
return when (result) {
is Result.Success -> {
gson.fromJson(result.value, Job::class.java)
}
is Result.Failure -> {
logger.error(result.error.toString())
null
}
}
}
companion object {
val gson = Gson()
}
}

View File

@ -0,0 +1,22 @@
package matterlink.jenkins;
/**
* Created by nikky on 03/02/18.
* @author Nikky
*/
//@JsonIgnoreProperties(ignoreUnknown = true)
data class Job(
val url: String,
val name: String,
val fullName: String,
val displayName: String,
val fullDisplayName: String,
val builds: List<Build>?,
val lastSuccessfulBuild: Build?,
val lastStableBuild: Build?
) {
fun getBuildByNumber(build: Int, userAgent: String): BuildWithDetails? {
return builds?.find { it.number == build }?.details(userAgent)
}
}

View File

@ -7,6 +7,7 @@ import matterlink.bridge.MessageHandlerInst
import matterlink.config.cfg
import matterlink.instance
import matterlink.logger
import voodoo.util.jenkins.JenkinsServer
import java.io.BufferedReader
import java.net.HttpURLConnection
import java.net.URL
@ -25,8 +26,33 @@ class UpdateChecker : Thread() {
}
override fun run() {
if (instance.modVersion.contains("-build")) {
logger.debug("Not checking updates on Jenkins build")
if (instance.buildNumber > 0) {
val server = JenkinsServer("https://ci.elytradev.com")
val job = server.getJob("elytra/MatterLink/master", "MatterLink/${instance.modVersion}")
?: run {
logger.error("failed obtaining job: elytra/MatterLink/master")
return
}
//TODO: add job name to constants at build time
val build = job.lastSuccessfulBuild ?: run {
logger.error("no successful build found")
return
}
with(build) {
when {
number > instance.buildNumber -> {
logger.warn("Mod out of date! New build $number available at $url")
val difference = number - build.number
MessageHandlerInst.transmit(
ApiMessage(
text = "MatterLink out of date! You are $difference builds behind! Please download new version from $url"
)
)
}
number < instance.buildNumber -> logger.error("lastSuccessfulBuild: $number is older than installed build: ${instance.buildNumber}")
else -> logger.info("you are up to date")
}
}
return
}
if (instance.modVersion.contains("-dev")) {