Change axises and delete action in API (#2792)
This commit is contained in:
@@ -82,7 +82,7 @@ private def uploadBenchmarkResultToBintray(String fileName) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
task registerBuild(type: BuildRegister) {
|
task registerBuild(type: BuildRegister) {
|
||||||
onlyBranch = project.findProperty('kotlin.register.only.branch')
|
onlyBranch = project.findProperty('kotlin.register.branch')
|
||||||
// Get bundle size.
|
// Get bundle size.
|
||||||
bundleSize = null
|
bundleSize = null
|
||||||
if (project.findProperty('kotlin.bundleBuild') != null) {
|
if (project.findProperty('kotlin.bundleBuild') != null) {
|
||||||
|
|||||||
@@ -91,7 +91,10 @@ open class BuildRegister : DefaultTask() {
|
|||||||
val teamCityUser = buildProperties.getProperty("teamcity.auth.userId")
|
val teamCityUser = buildProperties.getProperty("teamcity.auth.userId")
|
||||||
val teamCityPassword = buildProperties.getProperty("teamcity.auth.password")
|
val teamCityPassword = buildProperties.getProperty("teamcity.auth.password")
|
||||||
val buildNumber = buildProperties.getProperty("build.number")
|
val buildNumber = buildProperties.getProperty("build.number")
|
||||||
val branch = buildProperties.getProperty("teamcity.build.branch")
|
|
||||||
|
// Get branch.
|
||||||
|
val currentBuild = getBuild("id:$buildId", teamCityUser, teamCityPassword)
|
||||||
|
val branch = getBuildProperty(currentBuild,"branchName")
|
||||||
|
|
||||||
// Get summary information.
|
// Get summary information.
|
||||||
val output = arrayOf("$analyzer", "summary", "-exec-samples", "all", "-compile", "samples",
|
val output = arrayOf("$analyzer", "summary", "-exec-samples", "all", "-compile", "samples",
|
||||||
|
|||||||
@@ -24,34 +24,6 @@ import java.net.URL
|
|||||||
import java.util.Base64
|
import java.util.Base64
|
||||||
import java.util.Properties
|
import java.util.Properties
|
||||||
|
|
||||||
data class Commit(val revision: String, val developer: String, val webUrlWithDescription: String)
|
|
||||||
|
|
||||||
// List of commits.
|
|
||||||
class CommitsList(data: JsonElement): ConvertedFromJson {
|
|
||||||
|
|
||||||
val commits: List<Commit>
|
|
||||||
|
|
||||||
init {
|
|
||||||
if (data !is JsonObject) {
|
|
||||||
error("Commits description is expected to be a json object!")
|
|
||||||
}
|
|
||||||
val changesElement = data.getOptionalField("change")
|
|
||||||
commits = changesElement?.let {
|
|
||||||
if (changesElement !is JsonArray) {
|
|
||||||
error("Change field is expected to be an array. Please, check source.")
|
|
||||||
}
|
|
||||||
changesElement.jsonArray.map {
|
|
||||||
with(it as JsonObject) {
|
|
||||||
Commit(elementToString(getRequiredField("version"), "version"),
|
|
||||||
elementToString(getRequiredField("username"), "username"),
|
|
||||||
elementToString(getRequiredField("webUrl"), "webUrl")
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} ?: listOf<Commit>()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Task to produce regressions report and send it to slack. Requires a report with current benchmarks result
|
* Task to produce regressions report and send it to slack. Requires a report with current benchmarks result
|
||||||
* and path to analyzer tool
|
* and path to analyzer tool
|
||||||
@@ -65,7 +37,7 @@ class CommitsList(data: JsonElement): ConvertedFromJson {
|
|||||||
*/
|
*/
|
||||||
open class RegressionsReporter : DefaultTask() {
|
open class RegressionsReporter : DefaultTask() {
|
||||||
|
|
||||||
val teamCityUrl = "http://buildserver.labs.intellij.net"
|
|
||||||
val slackUsers = mapOf(
|
val slackUsers = mapOf(
|
||||||
"olonho" to "nikolay.igotti",
|
"olonho" to "nikolay.igotti",
|
||||||
"nikolay.igotti" to "nikolay.igotti",
|
"nikolay.igotti" to "nikolay.igotti",
|
||||||
@@ -107,41 +79,12 @@ open class RegressionsReporter : DefaultTask() {
|
|||||||
private fun testReportUrl(buildId: String, buildTypeId: String) =
|
private fun testReportUrl(buildId: String, buildTypeId: String) =
|
||||||
tabUrl(buildId, buildTypeId, "testsInfo")
|
tabUrl(buildId, buildTypeId, "testsInfo")
|
||||||
|
|
||||||
private fun buildsUrl(buildLocator: String) =
|
|
||||||
"$teamCityUrl/app/rest/builds/?locator=$buildLocator"
|
|
||||||
|
|
||||||
private fun previousBuildLocator(buildTypeId: String, branchName: String) =
|
private fun previousBuildLocator(buildTypeId: String, branchName: String) =
|
||||||
"buildType:id:$buildTypeId,branch:name:$branchName,status:SUCCESS,state:finished,count:1"
|
"buildType:id:$buildTypeId,branch:name:$branchName,status:SUCCESS,state:finished,count:1"
|
||||||
|
|
||||||
private fun changesListUrl(buildLocator: String) =
|
private fun changesListUrl(buildLocator: String) =
|
||||||
"$teamCityUrl/app/rest/changes/?locator=build:$buildLocator"
|
"$teamCityUrl/app/rest/changes/?locator=build:$buildLocator"
|
||||||
|
|
||||||
private fun sendGetRequest(url: String, username: String? = null, password: String? = null) : String {
|
|
||||||
val connection = URL(url).openConnection() as HttpURLConnection
|
|
||||||
if (username != null && password != null) {
|
|
||||||
val auth = Base64.getEncoder().encode((username + ":" + password).toByteArray()).toString(Charsets.UTF_8)
|
|
||||||
connection.addRequestProperty("Authorization", "Basic $auth")
|
|
||||||
}
|
|
||||||
connection.setRequestProperty("Accept", "application/json");
|
|
||||||
connection.connect()
|
|
||||||
return connection.inputStream.use { it.reader().use { reader -> reader.readText() } }
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getBuild(buildLocator: String, user: String, password: String) =
|
|
||||||
try {
|
|
||||||
sendGetRequest(buildsUrl(buildLocator), user, password)
|
|
||||||
} catch (t: Throwable) {
|
|
||||||
error("Try to get build! TeamCity is unreachable!")
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getBuildProperty(buildJsonDescription: String, property: String) =
|
|
||||||
with(JsonTreeParser.parse(buildJsonDescription) as JsonObject) {
|
|
||||||
if (getPrimitive("count").int == 0) {
|
|
||||||
error("No build information on TeamCity for $buildJsonDescription!")
|
|
||||||
}
|
|
||||||
(getArray("build").getObject(0).getPrimitive(property) as JsonLiteral).unquoted()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getCommits(buildLocator: String, user: String, password: String): CommitsList {
|
private fun getCommits(buildLocator: String, user: String, password: String): CommitsList {
|
||||||
val changes = try {
|
val changes = try {
|
||||||
sendGetRequest(changesListUrl(buildLocator), user, password)
|
sendGetRequest(changesListUrl(buildLocator), user, password)
|
||||||
|
|||||||
@@ -7,6 +7,10 @@ import java.io.FileInputStream
|
|||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
|
import java.net.HttpURLConnection
|
||||||
|
import java.net.URL
|
||||||
|
import java.util.Base64
|
||||||
|
import org.jetbrains.report.json.*
|
||||||
|
|
||||||
// Run command line from string.
|
// Run command line from string.
|
||||||
fun Array<String>.runCommand(workingDir: File = File("."),
|
fun Array<String>.runCommand(workingDir: File = File("."),
|
||||||
@@ -24,3 +28,62 @@ fun Array<String>.runCommand(workingDir: File = File("."),
|
|||||||
error("Couldn't run command $this")
|
error("Couldn't run command $this")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
data class Commit(val revision: String, val developer: String, val webUrlWithDescription: String)
|
||||||
|
|
||||||
|
val teamCityUrl = "http://buildserver.labs.intellij.net"
|
||||||
|
|
||||||
|
// List of commits.
|
||||||
|
class CommitsList(data: JsonElement): ConvertedFromJson {
|
||||||
|
|
||||||
|
val commits: List<Commit>
|
||||||
|
|
||||||
|
init {
|
||||||
|
if (data !is JsonObject) {
|
||||||
|
error("Commits description is expected to be a json object!")
|
||||||
|
}
|
||||||
|
val changesElement = data.getOptionalField("change")
|
||||||
|
commits = changesElement?.let {
|
||||||
|
if (changesElement !is JsonArray) {
|
||||||
|
error("Change field is expected to be an array. Please, check source.")
|
||||||
|
}
|
||||||
|
changesElement.jsonArray.map {
|
||||||
|
with(it as JsonObject) {
|
||||||
|
Commit(elementToString(getRequiredField("version"), "version"),
|
||||||
|
elementToString(getRequiredField("username"), "username"),
|
||||||
|
elementToString(getRequiredField("webUrl"), "webUrl")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} ?: listOf<Commit>()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun buildsUrl(buildLocator: String) =
|
||||||
|
"$teamCityUrl/app/rest/builds/?locator=$buildLocator"
|
||||||
|
|
||||||
|
fun getBuild(buildLocator: String, user: String, password: String) =
|
||||||
|
try {
|
||||||
|
sendGetRequest(buildsUrl(buildLocator), user, password)
|
||||||
|
} catch (t: Throwable) {
|
||||||
|
error("Try to get build! TeamCity is unreachable!")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun sendGetRequest(url: String, username: String? = null, password: String? = null) : String {
|
||||||
|
val connection = URL(url).openConnection() as HttpURLConnection
|
||||||
|
if (username != null && password != null) {
|
||||||
|
val auth = Base64.getEncoder().encode((username + ":" + password).toByteArray()).toString(Charsets.UTF_8)
|
||||||
|
connection.addRequestProperty("Authorization", "Basic $auth")
|
||||||
|
}
|
||||||
|
connection.setRequestProperty("Accept", "application/json");
|
||||||
|
connection.connect()
|
||||||
|
return connection.inputStream.use { it.reader().use { reader -> reader.readText() } }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getBuildProperty(buildJsonDescription: String, property: String) =
|
||||||
|
with(JsonTreeParser.parse(buildJsonDescription) as JsonObject) {
|
||||||
|
if (getPrimitive("count").int == 0) {
|
||||||
|
error("No build information on TeamCity for $buildJsonDescription!")
|
||||||
|
}
|
||||||
|
(getArray("build").getObject(0).getPrimitive(property) as JsonLiteral).unquoted()
|
||||||
|
}
|
||||||
|
|||||||
@@ -64,6 +64,28 @@ object LocalCache {
|
|||||||
fun buildExists(target: String, buildNumber: String) =
|
fun buildExists(target: String, buildNumber: String) =
|
||||||
buildsInfo[target][buildNumber]?.let { true } ?: false
|
buildsInfo[target][buildNumber]?.let { true } ?: false
|
||||||
|
|
||||||
|
fun delete(target: String, builds: Iterable<String>, bintrayUser: String, bintrayPassword: String): Boolean {
|
||||||
|
// Delete from bintray.
|
||||||
|
val buildsDescription = getBuildsInfoFromBintray(target).lines()
|
||||||
|
val initialBuildsNumber = buildsDescription.size
|
||||||
|
buildsDescription.filter {
|
||||||
|
val buildNumber = it.substringBefore(',')
|
||||||
|
buildNumber !in builds
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buildsDescription.size < initialBuildsNumber) {
|
||||||
|
// Upload new version of file.
|
||||||
|
val uploadUrl = "$uploadBintrayUrl/$bintrayPackage/latest/$target/$buildsFileName?publish=1&override=1"
|
||||||
|
sendUploadRequest(uploadUrl, buildsDescription.joinToString("\n"), bintrayUser, bintrayPassword)
|
||||||
|
|
||||||
|
// Reload values.
|
||||||
|
clean(target)
|
||||||
|
fill(target)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
private fun getBuilds(target: String, buildNumber: String? = null) =
|
private fun getBuilds(target: String, buildNumber: String? = null) =
|
||||||
buildsInfo[target]?.let { buildsList ->
|
buildsInfo[target]?.let { buildsList ->
|
||||||
buildNumber?.let {
|
buildNumber?.let {
|
||||||
@@ -125,12 +147,12 @@ data class BuildRegister(val buildId: String, val teamCityUser: String, val team
|
|||||||
val currentTime = Date()
|
val currentTime = Date()
|
||||||
val timeZone = currentTime.getTimezoneOffset() / -60 // Convert to hours.
|
val timeZone = currentTime.getTimezoneOffset() / -60 // Convert to hours.
|
||||||
// Get finish time as current time, because buid on TeamCity isn't finished.
|
// Get finish time as current time, because buid on TeamCity isn't finished.
|
||||||
val finishTime = "${format(currentTime.getFullYear())}" +
|
val finishTime = "${format(currentTime.getUTCFullYear())}" +
|
||||||
"${format(currentTime.getMonth() + 1)}" +
|
"${format(currentTime.getUTCMonth() + 1)}" +
|
||||||
"${format(currentTime.getDate())}" +
|
"${format(currentTime.getUTCDate())}" +
|
||||||
"T${format(currentTime.getHours())}" +
|
"T${format(currentTime.getUTCHours())}" +
|
||||||
"${format(currentTime.getMinutes())}" +
|
"${format(currentTime.getUTCMinutes())}" +
|
||||||
"${format(currentTime.getSeconds())}" +
|
"${format(currentTime.getUTCSeconds())}" +
|
||||||
"${if (timeZone > 0) "+" else "-"}${format(timeZone)}${format(0)}"
|
"${if (timeZone > 0) "+" else "-"}${format(timeZone)}${format(0)}"
|
||||||
return BuildInfo(buildNumber, branch, startTime, finishTime)
|
return BuildInfo(buildNumber, branch, startTime, finishTime)
|
||||||
}
|
}
|
||||||
@@ -217,6 +239,9 @@ fun router() {
|
|||||||
val uploadUrl = "$uploadBintrayUrl/$bintrayPackage/latest/${register.target}/${buildsFileName}?publish=1&override=1"
|
val uploadUrl = "$uploadBintrayUrl/$bintrayPackage/latest/${register.target}/${buildsFileName}?publish=1&override=1"
|
||||||
sendUploadRequest(uploadUrl, buildsDescription, register.bintrayUser, register.bintrayPassword)
|
sendUploadRequest(uploadUrl, buildsDescription, register.bintrayUser, register.bintrayPassword)
|
||||||
|
|
||||||
|
LocalCache.clean(register.target)
|
||||||
|
LocalCache.fill(register.target)
|
||||||
|
|
||||||
// Send response.
|
// Send response.
|
||||||
response.sendStatus(200)
|
response.sendStatus(200)
|
||||||
})
|
})
|
||||||
@@ -242,6 +267,15 @@ fun router() {
|
|||||||
response.sendStatus(200)
|
response.sendStatus(200)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
router.get("/delete/:target", { request, response ->
|
||||||
|
val buildsToDelete: List<String> = request.query.builds.toString().split(",").map { it.trim() }
|
||||||
|
val result = LocalCache.delete(request.params.target, buildsToDelete, request.query.user, request.query.key)
|
||||||
|
if (result) {
|
||||||
|
response.sendStatus(200)
|
||||||
|
}
|
||||||
|
response.sendStatus(404)
|
||||||
|
})
|
||||||
|
|
||||||
// Main page.
|
// Main page.
|
||||||
router.get("/", { request, response ->
|
router.get("/", { request, response ->
|
||||||
response.render("index")
|
response.render("index")
|
||||||
|
|||||||
@@ -94,6 +94,7 @@
|
|||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/chartist/0.11.0/chartist.min.js"></script>
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/chartist/0.11.0/chartist.min.js"></script>
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/chartist-plugin-legend/0.6.2/chartist-plugin-legend.js"></script>
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/chartist-plugin-legend/0.6.2/chartist-plugin-legend.js"></script>
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.devbridge-autocomplete/1.4.9/jquery.autocomplete.min.js"></script>
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.devbridge-autocomplete/1.4.9/jquery.autocomplete.min.js"></script>
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/chartist-plugin-axistitle@0.0.4/dist/chartist-plugin-axistitle.min.js"></script>
|
||||||
<script src="lib/kotlin/kotlin.js"></script>
|
<script src="lib/kotlin/kotlin.js"></script>
|
||||||
<script src="js/main.js"></script>
|
<script src="js/main.js"></script>
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import org.w3c.dom.*
|
|||||||
// API for interop with JS library Chartist.
|
// API for interop with JS library Chartist.
|
||||||
external class ChartistPlugins {
|
external class ChartistPlugins {
|
||||||
fun legend(data: dynamic): dynamic
|
fun legend(data: dynamic): dynamic
|
||||||
|
fun ctAxisTitle(data: dynamic): dynamic
|
||||||
}
|
}
|
||||||
|
|
||||||
external object Chartist {
|
external object Chartist {
|
||||||
@@ -73,7 +74,7 @@ fun getChartData(labels: List<String>, valuesList: Collection<List<*>>): dynamic
|
|||||||
return chartData
|
return chartData
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getChartOptions(samples: Array<String>): dynamic {
|
fun getChartOptions(samples: Array<String>, yTitle: String): dynamic {
|
||||||
val chartOptions: dynamic = object{}
|
val chartOptions: dynamic = object{}
|
||||||
chartOptions["fullWidth"] = true
|
chartOptions["fullWidth"] = true
|
||||||
val paddingObject: dynamic = object{}
|
val paddingObject: dynamic = object{}
|
||||||
@@ -83,11 +84,22 @@ fun getChartOptions(samples: Array<String>): dynamic {
|
|||||||
axisXObject["offset"] = 40
|
axisXObject["offset"] = 40
|
||||||
chartOptions["axisX"] = axisXObject
|
chartOptions["axisX"] = axisXObject
|
||||||
val axisYObject: dynamic = object{}
|
val axisYObject: dynamic = object{}
|
||||||
axisYObject["offset"] = 70
|
axisYObject["offset"] = 90
|
||||||
chartOptions["axisY"] = axisYObject
|
chartOptions["axisY"] = axisYObject
|
||||||
val legendObject: dynamic = object{}
|
val legendObject: dynamic = object{}
|
||||||
legendObject["legendNames"] = samples
|
legendObject["legendNames"] = samples
|
||||||
chartOptions["plugins"] = arrayOf(Chartist.plugins.legend(legendObject))
|
val titleObject: dynamic = object{}
|
||||||
|
val axisYTitle: dynamic = object{}
|
||||||
|
axisYTitle["axisTitle"] = yTitle
|
||||||
|
axisYTitle["axisClass"] = "ct-axis-title"
|
||||||
|
val titleOffset: dynamic = {}
|
||||||
|
titleOffset["x"] = 15
|
||||||
|
titleOffset["y"] = 15
|
||||||
|
axisYTitle["offset"] = titleOffset
|
||||||
|
axisYTitle["textAnchor"] = "middle"
|
||||||
|
axisYTitle["flipTitle"] = true
|
||||||
|
titleObject["axisY"] = axisYTitle
|
||||||
|
chartOptions["plugins"] = arrayOf(Chartist.plugins.legend(legendObject), Chartist.plugins.ctAxisTitle(titleObject))
|
||||||
return chartOptions
|
return chartOptions
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -168,9 +180,7 @@ fun main(args: Array<String>) {
|
|||||||
val parsedParameter = it.split("=", limit = 2)
|
val parsedParameter = it.split("=", limit = 2)
|
||||||
if (parsedParameter.size == 2) {
|
if (parsedParameter.size == 2) {
|
||||||
val (key, value) = parsedParameter
|
val (key, value) = parsedParameter
|
||||||
if (parameters.containsKey(key)) {
|
parameters[key] = value
|
||||||
parameters[key] = value
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -251,23 +261,31 @@ fun main(args: Array<String>) {
|
|||||||
}
|
}
|
||||||
separateValues(it.executionTime, executionTime) { value -> value.toDouble() }
|
separateValues(it.executionTime, executionTime) { value -> value.toDouble() }
|
||||||
separateValues(it.compileTime, compileTime) { value -> value.toDouble() }
|
separateValues(it.compileTime, compileTime) { value -> value.toDouble() }
|
||||||
separateValues(it.codeSize, codeSize) { value -> value.toDouble() }
|
separateValues(it.codeSize, codeSize) { value -> value.toDouble() / 1024.0 }
|
||||||
bundleSize.add(it.bundleSize?.toInt())
|
bundleSize.add(it.bundleSize?.toInt()?. let { it / 1024 / 1024 })
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw charts.
|
// Draw charts.
|
||||||
val execChart = Chartist.Line("#exec_chart", getChartData(labels, executionTime.values),
|
val execChart = Chartist.Line("#exec_chart", getChartData(labels, executionTime.values),
|
||||||
getChartOptions(executionTime.keys.toTypedArray()))
|
getChartOptions(executionTime.keys.toTypedArray(), "Time, microseconds"))
|
||||||
val compileChart = Chartist.Line("#compile_chart", getChartData(labels, compileTime.values),
|
val compileChart = Chartist.Line("#compile_chart", getChartData(labels, compileTime.values),
|
||||||
getChartOptions(compileTime.keys.toTypedArray()))
|
getChartOptions(compileTime.keys.toTypedArray(), "Time, microseconds"))
|
||||||
val codeSizeChart = Chartist.Line("#codesize_chart", getChartData(labels, codeSize.values),
|
val codeSizeChart = Chartist.Line("#codesize_chart", getChartData(labels, codeSize.values),
|
||||||
getChartOptions(codeSize.keys.toTypedArray()))
|
getChartOptions(codeSize.keys.toTypedArray(), "Size, KB"))
|
||||||
val bundleSizeChart = Chartist.Line("#bundlesize_chart", getChartData(labels, listOf(bundleSize)),
|
val bundleSizeChart = Chartist.Line("#bundlesize_chart", getChartData(labels, listOf(bundleSize)),
|
||||||
getChartOptions(arrayOf("Bundle size")))
|
getChartOptions(arrayOf("Bundle size"), "Size, MB"))
|
||||||
|
|
||||||
// Tooltips and higlights.
|
// Tooltips and higlights.
|
||||||
customizeChart(execChart, "exec_chart", js("$(\"#exec_chart\")"), builds, parameters)
|
customizeChart(execChart, "exec_chart", js("$(\"#exec_chart\")"), builds, parameters)
|
||||||
customizeChart(compileChart, "compile_chart", js("$(\"#compile_chart\")"), builds, parameters)
|
customizeChart(compileChart, "compile_chart", js("$(\"#compile_chart\")"), builds, parameters)
|
||||||
customizeChart(codeSizeChart, "codesize_chart", js("$(\"#codesize_chart\")"), builds, parameters)
|
customizeChart(codeSizeChart, "codesize_chart", js("$(\"#codesize_chart\")"), builds, parameters)
|
||||||
customizeChart(bundleSizeChart, "bundlesize_chart", js("$(\"#bundlesize_chart\")"), builds, parameters)
|
customizeChart(bundleSizeChart, "bundlesize_chart", js("$(\"#bundlesize_chart\")"), builds, parameters)
|
||||||
|
|
||||||
|
// Auto reload.
|
||||||
|
parameters["refresh"]?.let {
|
||||||
|
// Set event.
|
||||||
|
window.setInterval({
|
||||||
|
window.location.reload()
|
||||||
|
}, it.toInt() * 1000)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user