You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
133 lines
3.8 KiB
133 lines
3.8 KiB
package de.joshavg
|
|
|
|
import org.slf4j.Logger
|
|
import org.slf4j.LoggerFactory
|
|
import java.io.File
|
|
import java.nio.file.Paths
|
|
import java.util.concurrent.TimeUnit
|
|
import javax.enterprise.context.ApplicationScoped
|
|
import javax.inject.Inject
|
|
|
|
@ApplicationScoped
|
|
class GitRunner(
|
|
@Inject
|
|
val builds: Builds,
|
|
@Inject
|
|
val handles: Handles
|
|
) {
|
|
|
|
fun run(buildId: BuildId, rev: String): ProcessInfo {
|
|
val config = builds.buildConfig(buildId)
|
|
val logFile = builds.createLogFile(buildId)
|
|
|
|
logger.info("preparing process for build $buildId with config ${config.asPublic()}")
|
|
logger.info("log file: $logFile")
|
|
|
|
logFileHeader(logFile, buildId, rev)
|
|
|
|
assertEmptyWorkspace(config)
|
|
|
|
Thread {
|
|
try {
|
|
clone(config, logFile, config.gitRepo!!, rev, buildId)
|
|
execScripts(config, logFile, rev, buildId)
|
|
} finally {
|
|
cleanupWorkspace(config, buildId)
|
|
}
|
|
}.start()
|
|
|
|
return ProcessInfo(-1, logFile)
|
|
}
|
|
|
|
private fun clone(
|
|
config: BuildConfig,
|
|
logFile: File,
|
|
gitRepo: String,
|
|
rev: String,
|
|
buildId: BuildId
|
|
) {
|
|
logger.info("build $buildId: cloning ${config.gitRepo} into ${config.workspace}")
|
|
|
|
val process = processBuilder(config, logFile, "")
|
|
.command("git", "clone", config.gitRepo, ".")
|
|
.start()
|
|
handles.add(Handle(process.toHandle(), buildId))
|
|
val cloneSuccess = process.waitFor(30, TimeUnit.SECONDS)
|
|
|
|
logger.info("build $buildId: checkout rev $rev")
|
|
processBuilder(config, logFile, "")
|
|
.command("git", "checkout", rev)
|
|
.start()
|
|
.waitFor()
|
|
|
|
if (!cloneSuccess) {
|
|
throw FailedToClone(buildId, gitRepo)
|
|
}
|
|
}
|
|
|
|
private fun execScripts(config: BuildConfig, logFile: File, rev: String, buildId: BuildId) {
|
|
val scriptFiles = listOf("pre.sh", "job.sh", "post.sh")
|
|
|
|
logger.info("build $buildId: looking for scripts $scriptFiles in .alfred/")
|
|
|
|
scriptFiles.forEach { script ->
|
|
if (Paths.get(config.workspace, ".alfred", script).toFile().exists()) {
|
|
logger.info("build $buildId: found script $script, running it")
|
|
|
|
val scriptProcess = processBuilder(config, logFile, rev)
|
|
.command(".alfred/$script")
|
|
.start()
|
|
handles.add(Handle(scriptProcess.toHandle(), buildId))
|
|
|
|
val ret = scriptProcess.waitFor()
|
|
logger.info("build $buildId: script $script returned $ret")
|
|
|
|
logFile.appendText("\n$script returned $ret\n")
|
|
}
|
|
}
|
|
}
|
|
|
|
private fun cleanupWorkspace(config: BuildConfig, buildId: BuildId) {
|
|
val wsList = File(config.workspace).list()
|
|
if (wsList != null && wsList.isNotEmpty()) {
|
|
logger.info("build $buildId: cleaning up workspace ${config.workspace}")
|
|
|
|
val ws = File(config.workspace)
|
|
ws.deleteRecursively()
|
|
ws.mkdirs()
|
|
}
|
|
}
|
|
|
|
private fun assertEmptyWorkspace(config: BuildConfig) {
|
|
val workspace = File(config.workspace)
|
|
|
|
if (!workspace.exists()) {
|
|
workspace.mkdirs()
|
|
}
|
|
|
|
val wsList = workspace.list()
|
|
if (wsList != null && wsList.isNotEmpty()) {
|
|
throw WorkspaceIsNotEmpty(config.workspace)
|
|
}
|
|
}
|
|
|
|
val logger: Logger = LoggerFactory.getLogger(this::class.java)
|
|
|
|
}
|
|
|
|
|
|
class WorkspaceIsNotEmpty(
|
|
private val ws: String
|
|
) : RuntimeException() {
|
|
override fun toString() =
|
|
"${this::class}: workspace $ws is not empty"
|
|
}
|
|
|
|
class FailedToClone(
|
|
private val buildId: BuildId,
|
|
private val gitRepo: String
|
|
) : RuntimeException() {
|
|
override fun toString() =
|
|
"${this::class}: failed to clone $gitRepo for build id $buildId"
|
|
}
|