summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakob Odersky <jakob@odersky.com>2017-03-06 01:47:50 -0800
committerJakob Odersky <jakob@odersky.com>2017-03-06 01:47:50 -0800
commitbd7083167c1a0899f722971fb90ce41c96de252f (patch)
treee0bcad925419f1801caa2d2cd8270417c7a5b2e8
parent374ac0ce8c10e9063c263ecf9c708f9ee6772973 (diff)
downloadcrashbox-ci-bd7083167c1a0899f722971fb90ce41c96de252f.tar.gz
crashbox-ci-bd7083167c1a0899f722971fb90ce41c96de252f.tar.bz2
crashbox-ci-bd7083167c1a0899f722971fb90ce41c96de252f.zip
scalafmt
-rw-r--r--crashbox-server/src/main/scala/io/crashbox/ci/Builders.scala124
-rw-r--r--crashbox-server/src/main/scala/io/crashbox/ci/Core.scala5
-rw-r--r--crashbox-server/src/main/scala/io/crashbox/ci/Main.scala6
-rw-r--r--crashbox-server/src/main/scala/io/crashbox/ci/Parsers.scala16
-rw-r--r--crashbox-server/src/main/scala/io/crashbox/ci/Schedulers.scala68
-rw-r--r--crashbox-server/src/main/scala/io/crashbox/ci/Source.scala11
-rw-r--r--crashbox-server/src/main/scala/io/crashbox/ci/StateStore.scala6
-rw-r--r--crashbox-server/src/main/scala/io/crashbox/ci/StreamStore.scala15
-rw-r--r--crashbox-server/src/test/scala/io/crashbox/ci/SourceSpec.scala5
-rw-r--r--crashbox-server/src/test/scala/io/crashbox/ci/TestUtil.scala5
10 files changed, 153 insertions, 108 deletions
diff --git a/crashbox-server/src/main/scala/io/crashbox/ci/Builders.scala b/crashbox-server/src/main/scala/io/crashbox/ci/Builders.scala
index 7e55640..6bd4816 100644
--- a/crashbox-server/src/main/scala/io/crashbox/ci/Builders.scala
+++ b/crashbox-server/src/main/scala/io/crashbox/ci/Builders.scala
@@ -1,11 +1,18 @@
package io.crashbox.ci
-import com.spotify.docker.client.DockerClient.{ AttachParameter, ListContainersParam }
+import com.spotify.docker.client.DockerClient.{
+ AttachParameter,
+ ListContainersParam
+}
import com.spotify.docker.client.LogStream
import com.spotify.docker.client.exceptions.ContainerNotFoundException
-import com.spotify.docker.client.messages.{ ContainerConfig, HostConfig, LogConfig }
+import com.spotify.docker.client.messages.{
+ ContainerConfig,
+ HostConfig,
+ LogConfig
+}
import com.spotify.docker.client.messages.HostConfig.Bind
-import java.io.{ File, OutputStream }
+import java.io.{File, OutputStream}
import scala.concurrent.Future
import scala.concurrent.duration._
import scala.collection.JavaConverters._
@@ -13,9 +20,10 @@ import com.spotify.docker.client.DefaultDockerClient
trait Builders { core: Core =>
- val dockerClient = DefaultDockerClient.builder().uri("unix:///run/docker.sock").build()
+ val dockerClient =
+ DefaultDockerClient.builder().uri("unix:///run/docker.sock").build()
- core.system.registerOnTermination{
+ core.system.registerOnTermination {
dockerClient.close()
}
@@ -27,60 +35,66 @@ trait Builders { core: Core =>
override def toString = id
}
- def startBuild(
- image: String,
- script: String,
- dir: File,
- out: OutputStream
- ): Future[ContainerId] = Future {
- val volume = Bind.builder().from(dir.getAbsolutePath).to(containerWorkDirectory).build()
- val hostConfig = HostConfig.builder().binds(volume).build()
- val containerConfig = ContainerConfig.builder()
- .labels(Map("crashbox" -> "build").asJava)
- .hostConfig(hostConfig)
- .tty(true) // combine stdout and stderr into stdout
- .image(image)
- .user(containerUser)
- .workingDir(containerWorkDirectory)
- .entrypoint("/bin/sh", "-c")
- .cmd(script)
- .build()
- val container = dockerClient.createContainer(containerConfig).id
+ def startBuild(image: String,
+ script: String,
+ dir: File,
+ out: OutputStream): Future[ContainerId] =
+ Future {
+ val volume = Bind
+ .builder()
+ .from(dir.getAbsolutePath)
+ .to(containerWorkDirectory)
+ .build()
+ val hostConfig = HostConfig.builder().binds(volume).build()
+ val containerConfig = ContainerConfig
+ .builder()
+ .labels(Map("crashbox" -> "build").asJava)
+ .hostConfig(hostConfig)
+ .tty(true) // combine stdout and stderr into stdout
+ .image(image)
+ .user(containerUser)
+ .workingDir(containerWorkDirectory)
+ .entrypoint("/bin/sh", "-c")
+ .cmd(script)
+ .build()
+ val container = dockerClient.createContainer(containerConfig).id
- log.debug(s"Starting container $container")
- dockerClient.startContainer(container)
+ log.debug(s"Starting container $container")
+ dockerClient.startContainer(container)
- log.debug(s"Attaching log stream of container $container")
- blockingDispatcher execute new Runnable {
- override def run() = {
- var stream: LogStream = null
- try {
- stream = dockerClient.attachContainer(
- container,
- AttachParameter.LOGS,
- AttachParameter.STDOUT,
- AttachParameter.STREAM
- )
- stream.attach(out, null, true)
- } finally {
- if (stream != null) stream.close()
+ log.debug(s"Attaching log stream of container $container")
+ blockingDispatcher execute new Runnable {
+ override def run() = {
+ var stream: LogStream = null
+ try {
+ stream = dockerClient.attachContainer(
+ container,
+ AttachParameter.LOGS,
+ AttachParameter.STDOUT,
+ AttachParameter.STREAM
+ )
+ stream.attach(out, null, true)
+ } finally {
+ if (stream != null) stream.close()
+ }
}
}
- }
- ContainerId(container)
- }(blockingDispatcher)
+ ContainerId(container)
+ }(blockingDispatcher)
- def waitBuild(id: ContainerId): Future[Int] = Future {
- log.debug(s"Waiting for container $id to exit")
- val res: Int = dockerClient.waitContainer(id.id).statusCode()
- cancelBuild(id)
- res
- }(blockingDispatcher)
+ def waitBuild(id: ContainerId): Future[Int] =
+ Future {
+ log.debug(s"Waiting for container $id to exit")
+ val res: Int = dockerClient.waitContainer(id.id).statusCode()
+ cancelBuild(id)
+ res
+ }(blockingDispatcher)
def cancelBuild(id: ContainerId): Unit = {
log.debug(s"Stopping container $id")
try {
- dockerClient.stopContainer(id.id, containerKillTimeout.toUnit(SECONDS).toInt)
+ dockerClient.stopContainer(id.id,
+ containerKillTimeout.toUnit(SECONDS).toInt)
dockerClient.removeContainer(id.id)
} catch {
case _: ContainerNotFoundException => // build already cancelled
@@ -88,10 +102,12 @@ trait Builders { core: Core =>
}
def reapDeadBuilds(): Unit = {
- val stale = dockerClient.listContainers(
- ListContainersParam.withLabel("crashbox"),
- ListContainersParam.withStatusExited()
- ).asScala
+ val stale = dockerClient
+ .listContainers(
+ ListContainersParam.withLabel("crashbox"),
+ ListContainersParam.withStatusExited()
+ )
+ .asScala
stale.foreach { container =>
dockerClient.removeContainer(container.id())
}
diff --git a/crashbox-server/src/main/scala/io/crashbox/ci/Core.scala b/crashbox-server/src/main/scala/io/crashbox/ci/Core.scala
index 8342293..5a30df0 100644
--- a/crashbox-server/src/main/scala/io/crashbox/ci/Core.scala
+++ b/crashbox-server/src/main/scala/io/crashbox/ci/Core.scala
@@ -2,13 +2,14 @@ package io.crashbox.ci
import akka.actor.ActorSystem
import scala.concurrent.duration.Duration
-import scala.concurrent.{ Await, ExecutionContext }
+import scala.concurrent.{Await, ExecutionContext}
trait Core {
implicit val system: ActorSystem = ActorSystem("crashbox")
implicit val executionContext: ExecutionContext = system.dispatcher
- val blockingDispatcher: ExecutionContext = system.dispatchers.lookup("crashbox.blocking-dispatcher")
+ val blockingDispatcher: ExecutionContext =
+ system.dispatchers.lookup("crashbox.blocking-dispatcher")
def log = system.log
def config = system.settings.config
diff --git a/crashbox-server/src/main/scala/io/crashbox/ci/Main.scala b/crashbox-server/src/main/scala/io/crashbox/ci/Main.scala
index 5b58875..0187751 100644
--- a/crashbox-server/src/main/scala/io/crashbox/ci/Main.scala
+++ b/crashbox-server/src/main/scala/io/crashbox/ci/Main.scala
@@ -2,8 +2,8 @@ package io.crashbox.ci
import java.net.URL
-
-object Main extends Core
+object Main
+ extends Core
with Schedulers
with Builders
with Parsers
@@ -21,6 +21,6 @@ object Main extends Core
)
Thread.sleep(15000)
System.exit(0)
- }
+ }
}
diff --git a/crashbox-server/src/main/scala/io/crashbox/ci/Parsers.scala b/crashbox-server/src/main/scala/io/crashbox/ci/Parsers.scala
index 6f43380..20221cb 100644
--- a/crashbox-server/src/main/scala/io/crashbox/ci/Parsers.scala
+++ b/crashbox-server/src/main/scala/io/crashbox/ci/Parsers.scala
@@ -9,8 +9,8 @@ trait Parsers {
def defaultImage = "crashbox/default"
case class BuildDef(
- image: String,
- script: String
+ image: String,
+ script: String
)
case class ParseError(message: String)
@@ -18,19 +18,23 @@ trait Parsers {
def parseBuild(workdir: File): Either[BuildDef, ParseError] = {
val file = new File(workdir, ".crashbox.txt")
if (!file.exists()) {
- return Right(ParseError("No build configuration file .crashbox.txt found."))
+ return Right(
+ ParseError("No build configuration file .crashbox.txt found."))
}
val lines = Files.readAllLines(file.toPath).asScala.map(_.trim)
val Pattern = """(\w+)\s*:\s*(.+)""".r
- val image = lines.collectFirst{case Pattern("image", s) => s}.getOrElse(defaultImage)
- val script = lines.collectFirst{case Pattern("script", s) => s}
+ val image = lines
+ .collectFirst { case Pattern("image", s) => s }
+ .getOrElse(defaultImage)
+ val script = lines.collectFirst { case Pattern("script", s) => s }
script match {
case Some(s) => Left(BuildDef(image, s))
- case None => Right(ParseError("No build script defined in configuration."))
+ case None =>
+ Right(ParseError("No build script defined in configuration."))
}
}
}
diff --git a/crashbox-server/src/main/scala/io/crashbox/ci/Schedulers.scala b/crashbox-server/src/main/scala/io/crashbox/ci/Schedulers.scala
index c860932..e9f2a82 100644
--- a/crashbox-server/src/main/scala/io/crashbox/ci/Schedulers.scala
+++ b/crashbox-server/src/main/scala/io/crashbox/ci/Schedulers.scala
@@ -1,24 +1,31 @@
package io.crashbox.ci
-import akka.actor.{ Actor, ActorLogging, ActorRef, OneForOneStrategy, Props, Terminated }
+import akka.actor.{
+ Actor,
+ ActorLogging,
+ ActorRef,
+ OneForOneStrategy,
+ Props,
+ Terminated
+}
import akka.stream.stage.GraphStageLogic
-import akka.stream.{ Attributes, Outlet, SourceShape }
+import akka.stream.{Attributes, Outlet, SourceShape}
import akka.stream.stage.GraphStage
-import java.io.{ File, OutputStream }
+import java.io.{File, OutputStream}
import java.net.URL
import java.nio.file.Files
import java.util.Base64
import scala.collection.mutable.HashMap
-import scala.concurrent.{ Await, Future }
+import scala.concurrent.{Await, Future}
import scala.concurrent.duration._
import scala.util.control.NonFatal
import akka.actor.SupervisorStrategy._
-import scala.util.{ Failure, Success }
-
+import scala.util.{Failure, Success}
trait Schedulers extends { self: Core with Source with Builders with Parsers =>
- private def newTempDir: File = Files.createTempDirectory("crashbox-run").toFile()
+ private def newTempDir: File =
+ Files.createTempDirectory("crashbox-run").toFile()
sealed trait BuildState
case class Cloning(url: URL) extends BuildState
@@ -31,10 +38,11 @@ trait Schedulers extends { self: Core with Source with Builders with Parsers =>
case class Failed(message: String) extends EndBuildState
class BuildManager(
- url: URL,
- openOut: () => OutputStream,
- update: BuildState => Unit
- ) extends Actor with ActorLogging {
+ url: URL,
+ openOut: () => OutputStream,
+ update: BuildState => Unit
+ ) extends Actor
+ with ActorLogging {
var buildDir: Option[File] = None
var out: Option[OutputStream] = None
@@ -53,7 +61,7 @@ trait Schedulers extends { self: Core with Source with Builders with Parsers =>
override def receive: Receive = {
- case state@Cloning(url) =>
+ case state @ Cloning(url) =>
log.debug("Update build state: cloning")
update(state)
fetchSource(url, newTempDir) onComplete {
@@ -63,7 +71,7 @@ trait Schedulers extends { self: Core with Source with Builders with Parsers =>
self ! Failed(s"Error fetching source from $url")
}
- case state@Parsing(src) =>
+ case state @ Parsing(src) =>
log.debug("Update build state: parsing")
update(state)
buildDir = Some(src)
@@ -74,7 +82,7 @@ trait Schedulers extends { self: Core with Source with Builders with Parsers =>
self ! Failed(s"Failed to parse build $err")
}
- case state@Starting(src, bd) =>
+ case state @ Starting(src, bd) =>
log.debug("Update build state: starting")
update(state)
val so = openOut()
@@ -86,7 +94,7 @@ trait Schedulers extends { self: Core with Source with Builders with Parsers =>
self ! Failed(s"Failed to start build $err")
}
- case state@Running(id) =>
+ case state @ Running(id) =>
log.debug("Update build state: running")
update(state)
containerId = Some(id)
@@ -97,25 +105,31 @@ trait Schedulers extends { self: Core with Source with Builders with Parsers =>
self ! Failed(s"Error waiting for build to complete")
}
- case state@Finished(status) =>
+ case state @ Finished(status) =>
log.debug("Update build state: finished")
update(state)
context stop self
- case state@Failed(message) =>
+ case state @ Failed(message) =>
log.debug("Update build state: failed")
update(state)
context stop self
}
}
object BuildManager {
- def apply(buildId: String, url: URL, out: () => OutputStream, update: BuildState => Unit) =
+ def apply(buildId: String,
+ url: URL,
+ out: () => OutputStream,
+ update: BuildState => Unit) =
Props(new BuildManager(url, out, update))
}
private sealed trait SchedulerCommand
private case class ScheduleBuild(
- buildId: String, url: URL, out: () => OutputStream, update: BuildState => Unit
+ buildId: String,
+ url: URL,
+ out: () => OutputStream,
+ update: BuildState => Unit
) extends SchedulerCommand
class Scheduler extends Actor {
@@ -128,8 +142,9 @@ trait Schedulers extends { self: Core with Source with Builders with Parsers =>
runningBuilds.get(sb.buildId) match {
case Some(_) => //already running
case None =>
- val buildManager = context.actorOf(BuildManager(
- sb.buildId, sb.url, sb.out, sb.update), s"build-${sb.buildId}")
+ val buildManager = context.actorOf(
+ BuildManager(sb.buildId, sb.url, sb.out, sb.update),
+ s"build-${sb.buildId}")
context watch buildManager
runningBuilds += sb.buildId -> buildManager
}
@@ -142,13 +157,14 @@ trait Schedulers extends { self: Core with Source with Builders with Parsers =>
}
}
- private val scheduler = system.actorOf(Props(new Scheduler()), "crashbox-scheduler")
+ private val scheduler =
+ system.actorOf(Props(new Scheduler()), "crashbox-scheduler")
def start(
- buildId: String,
- url: URL,
- out: () => OutputStream,
- update: BuildState => Unit
+ buildId: String,
+ url: URL,
+ out: () => OutputStream,
+ update: BuildState => Unit
): Unit = {
scheduler ! ScheduleBuild(buildId, url, out, update)
}
diff --git a/crashbox-server/src/main/scala/io/crashbox/ci/Source.scala b/crashbox-server/src/main/scala/io/crashbox/ci/Source.scala
index 720b809..335e59c 100644
--- a/crashbox-server/src/main/scala/io/crashbox/ci/Source.scala
+++ b/crashbox-server/src/main/scala/io/crashbox/ci/Source.scala
@@ -7,10 +7,11 @@ import scala.concurrent.Future
trait Source { self: Core =>
- def fetchSource(from: URL, to: File): Future[File] = Future {
- log.debug(s"Cloning git repo from $from to $to")
- Git.cloneRepository.setURI(from.toURI.toString).setDirectory(to).call()
- to
- }(blockingDispatcher)
+ def fetchSource(from: URL, to: File): Future[File] =
+ Future {
+ log.debug(s"Cloning git repo from $from to $to")
+ Git.cloneRepository.setURI(from.toURI.toString).setDirectory(to).call()
+ to
+ }(blockingDispatcher)
}
diff --git a/crashbox-server/src/main/scala/io/crashbox/ci/StateStore.scala b/crashbox-server/src/main/scala/io/crashbox/ci/StateStore.scala
index 94f51d0..3474407 100644
--- a/crashbox-server/src/main/scala/io/crashbox/ci/StateStore.scala
+++ b/crashbox-server/src/main/scala/io/crashbox/ci/StateStore.scala
@@ -1,7 +1,3 @@
package io.crashbox.ci
-trait StateStore {
-
-}
-
-
+trait StateStore {}
diff --git a/crashbox-server/src/main/scala/io/crashbox/ci/StreamStore.scala b/crashbox-server/src/main/scala/io/crashbox/ci/StreamStore.scala
index 5fd3769..bba3cdf 100644
--- a/crashbox-server/src/main/scala/io/crashbox/ci/StreamStore.scala
+++ b/crashbox-server/src/main/scala/io/crashbox/ci/StreamStore.scala
@@ -1,15 +1,24 @@
package io.crashbox.ci
-import java.io.{ File, FileInputStream, FileOutputStream, InputStream, OutputStream }
+import java.io.{
+ File,
+ FileInputStream,
+ FileOutputStream,
+ InputStream,
+ OutputStream
+}
import java.security.MessageDigest
trait StreamStore { self: Core =>
- val streamsDirectory: File = new File(config.getString("crashbox.streams.directory"))
+ val streamsDirectory: File = new File(
+ config.getString("crashbox.streams.directory"))
private def logFile(id: String): File = {
val bytes = MessageDigest.getInstance("SHA-256").digest(id.getBytes)
- val str = bytes.map{byte => Integer.toString((byte & 0xff) + 0x100, 16)}.mkString
+ val str = bytes.map { byte =>
+ Integer.toString((byte & 0xff) + 0x100, 16)
+ }.mkString
val (head, tail) = str.splitAt(2)
new File(streamsDirectory, s"$head/$tail")
}
diff --git a/crashbox-server/src/test/scala/io/crashbox/ci/SourceSpec.scala b/crashbox-server/src/test/scala/io/crashbox/ci/SourceSpec.scala
index 9bef01d..a03e476 100644
--- a/crashbox-server/src/test/scala/io/crashbox/ci/SourceSpec.scala
+++ b/crashbox-server/src/test/scala/io/crashbox/ci/SourceSpec.scala
@@ -23,10 +23,11 @@ class SourceSpec extends FlatSpec with Matchers with Source with Core {
}
"GitFetchers" should "be able to clone a local repository" in {
- TestUtil.withTempDir{ remote =>
+ TestUtil.withTempDir { remote =>
makeRepo(remote)
TestUtil.withTempDir { local =>
- val cloned = Await.result(fetchSource(remote.toURI().toURL(), local), Timeout)
+ val cloned =
+ Await.result(fetchSource(remote.toURI().toURL(), local), Timeout)
assert(cloned.listFiles().length == 3)
}
}
diff --git a/crashbox-server/src/test/scala/io/crashbox/ci/TestUtil.scala b/crashbox-server/src/test/scala/io/crashbox/ci/TestUtil.scala
index eb177f8..a7e7ae6 100644
--- a/crashbox-server/src/test/scala/io/crashbox/ci/TestUtil.scala
+++ b/crashbox-server/src/test/scala/io/crashbox/ci/TestUtil.scala
@@ -1,13 +1,14 @@
package io.crashbox.ci
-import java.io.{ File, OutputStream }
+import java.io.{File, OutputStream}
import java.nio.file.Files
object TestUtil {
def withTempDir[A](f: File => A): A = {
val dir = Files.createTempDirectory("crashbox-test").toFile
- try f(dir) finally dir.delete()
+ try f(dir)
+ finally dir.delete()
}
}