diff --git a/1.10.2/build.gradle b/1.10.2/build.gradle index 129c5a2..52ab88c 100644 --- a/1.10.2/build.gradle +++ b/1.10.2/build.gradle @@ -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 { diff --git a/1.10.2/src/main/kotlin/matterlink/Constants.kt b/1.10.2/src/main/kotlin/matterlink/Constants.kt index 3aa1612..bd4dc94 100644 --- a/1.10.2/src/main/kotlin/matterlink/Constants.kt +++ b/1.10.2/src/main/kotlin/matterlink/Constants.kt @@ -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@ diff --git a/1.10.2/src/main/kotlin/matterlink/MatterLink.kt b/1.10.2/src/main/kotlin/matterlink/MatterLink.kt index 7b6eefa..5f24b6b 100644 --- a/1.10.2/src/main/kotlin/matterlink/MatterLink.kt +++ b/1.10.2/src/main/kotlin/matterlink/MatterLink.kt @@ -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() } diff --git a/1.11.2/build.gradle b/1.11.2/build.gradle index 91ea2fb..cb8497c 100644 --- a/1.11.2/build.gradle +++ b/1.11.2/build.gradle @@ -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 { diff --git a/1.11.2/src/main/kotlin/matterlink/Constants.kt b/1.11.2/src/main/kotlin/matterlink/Constants.kt index 31146a7..636198a 100644 --- a/1.11.2/src/main/kotlin/matterlink/Constants.kt +++ b/1.11.2/src/main/kotlin/matterlink/Constants.kt @@ -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@ diff --git a/1.11.2/src/main/kotlin/matterlink/MatterLink.kt b/1.11.2/src/main/kotlin/matterlink/MatterLink.kt index 22a7171..0b2fefe 100644 --- a/1.11.2/src/main/kotlin/matterlink/MatterLink.kt +++ b/1.11.2/src/main/kotlin/matterlink/MatterLink.kt @@ -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() } diff --git a/1.12.2/build.gradle b/1.12.2/build.gradle index f36af1b..787ddd3 100644 --- a/1.12.2/build.gradle +++ b/1.12.2/build.gradle @@ -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 { diff --git a/1.12.2/src/main/kotlin/matterlink/Constants.kt b/1.12.2/src/main/kotlin/matterlink/Constants.kt index 31146a7..636198a 100644 --- a/1.12.2/src/main/kotlin/matterlink/Constants.kt +++ b/1.12.2/src/main/kotlin/matterlink/Constants.kt @@ -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@ diff --git a/1.12.2/src/main/kotlin/matterlink/MatterLink.kt b/1.12.2/src/main/kotlin/matterlink/MatterLink.kt index 00c27a7..06e8409 100644 --- a/1.12.2/src/main/kotlin/matterlink/MatterLink.kt +++ b/1.12.2/src/main/kotlin/matterlink/MatterLink.kt @@ -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() } diff --git a/1.7.10/build.gradle b/1.7.10/build.gradle index 7f2bfda..307d3d4 100644 --- a/1.7.10/build.gradle +++ b/1.7.10/build.gradle @@ -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 { diff --git a/1.7.10/src/main/kotlin/matterlink/MatterLink.kt b/1.7.10/src/main/kotlin/matterlink/MatterLink.kt index be6dff7..1504cb1 100644 --- a/1.7.10/src/main/kotlin/matterlink/MatterLink.kt +++ b/1.7.10/src/main/kotlin/matterlink/MatterLink.kt @@ -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() } diff --git a/1.7.10/src/templates/kotlin/matterlink/Constants.kt b/1.7.10/src/templates/kotlin/matterlink/Constants.kt index a9fa955..ad1e302 100644 --- a/1.7.10/src/templates/kotlin/matterlink/Constants.kt +++ b/1.7.10/src/templates/kotlin/matterlink/Constants.kt @@ -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@ diff --git a/build.gradle b/build.gradle index 43f2e5c..bf44813 100644 --- a/build.gradle +++ b/build.gradle @@ -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" } diff --git a/core/build.gradle b/core/build.gradle index 723b254..0d4d029 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -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 } diff --git a/core/src/main/kotlin/matterlink/HttpClientUtil.kt b/core/src/main/kotlin/matterlink/HttpClientUtil.kt new file mode 100644 index 0000000..cb102fc --- /dev/null +++ b/core/src/main/kotlin/matterlink/HttpClientUtil.kt @@ -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): HttpGet = this.apply { + addHeader(pair.first, pair.second) +} + +fun HttpGet.responseString(): Triple { + 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() +} \ No newline at end of file diff --git a/core/src/main/kotlin/matterlink/IMatterLink.kt b/core/src/main/kotlin/matterlink/IMatterLink.kt index 63d0a02..8f9a9f3 100644 --- a/core/src/main/kotlin/matterlink/IMatterLink.kt +++ b/core/src/main/kotlin/matterlink/IMatterLink.kt @@ -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 diff --git a/core/src/main/kotlin/matterlink/jenkins/Artifact.kt b/core/src/main/kotlin/matterlink/jenkins/Artifact.kt new file mode 100644 index 0000000..7e24641 --- /dev/null +++ b/core/src/main/kotlin/matterlink/jenkins/Artifact.kt @@ -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 +) \ No newline at end of file diff --git a/core/src/main/kotlin/matterlink/jenkins/Build.kt b/core/src/main/kotlin/matterlink/jenkins/Build.kt new file mode 100644 index 0000000..5ac7e35 --- /dev/null +++ b/core/src/main/kotlin/matterlink/jenkins/Build.kt @@ -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() + } +} + diff --git a/core/src/main/kotlin/matterlink/jenkins/BuildWithDetails.kt b/core/src/main/kotlin/matterlink/jenkins/BuildWithDetails.kt new file mode 100644 index 0000000..69f5d11 --- /dev/null +++ b/core/src/main/kotlin/matterlink/jenkins/BuildWithDetails.kt @@ -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, +// @JsonFormat(shape=JsonFormat.Shape.NUMBER, pattern="s") + val timestamp: Date +) \ No newline at end of file diff --git a/core/src/main/kotlin/matterlink/jenkins/JenkinsServer.kt b/core/src/main/kotlin/matterlink/jenkins/JenkinsServer.kt new file mode 100644 index 0000000..5758847 --- /dev/null +++ b/core/src/main/kotlin/matterlink/jenkins/JenkinsServer.kt @@ -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() + } + +} \ No newline at end of file diff --git a/core/src/main/kotlin/matterlink/jenkins/Job.kt b/core/src/main/kotlin/matterlink/jenkins/Job.kt new file mode 100644 index 0000000..fb687e9 --- /dev/null +++ b/core/src/main/kotlin/matterlink/jenkins/Job.kt @@ -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?, + val lastSuccessfulBuild: Build?, + val lastStableBuild: Build? +) { + fun getBuildByNumber(build: Int, userAgent: String): BuildWithDetails? { + return builds?.find { it.number == build }?.details(userAgent) + } +} \ No newline at end of file diff --git a/core/src/main/kotlin/matterlink/update/UpdateChecker.kt b/core/src/main/kotlin/matterlink/update/UpdateChecker.kt index e9b5593..d73421c 100644 --- a/core/src/main/kotlin/matterlink/update/UpdateChecker.kt +++ b/core/src/main/kotlin/matterlink/update/UpdateChecker.kt @@ -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")) {