Skip to content

Commit

Permalink
Merge pull request #413 from scalacenter/topic/expose-env-variables
Browse files Browse the repository at this point in the history
Use nailgun environment in forked processes
  • Loading branch information
jvican authored Apr 5, 2018
2 parents 09d685f + 79ed360 commit 0dbe10a
Show file tree
Hide file tree
Showing 17 changed files with 77 additions and 34 deletions.
1 change: 0 additions & 1 deletion build-integrations/sbt-1.0/build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ val GuardianFrontend = Integrations.GuardianFrontend
val MiniBetterFiles = Integrations.MiniBetterFiles
val WithResources = Integrations.WithResources
val WithTests = Integrations.WithTests

val integrations = List(SbtSbt, GuardianFrontend, MiniBetterFiles, WithResources, WithTests)

import bloop.build.integrations.PluginKeys
Expand Down
4 changes: 2 additions & 2 deletions build-integrations/sbt-1.0/project/Integrations.scala
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ object Integrations {
val MiniBetterFiles = RootProject(uri(
"git://github.com/scalacenter/mini-better-files.git#0ed848993a2fd5a36e4366b5efb9c68dce958fc2"))
val WithResources = RootProject(
uri("git://github.com/scalacenter/with-resources.git#7529b2c3ac455cbb1889d4791c4e0d4957e29306"))
uri("git://github.com/scalacenter/with-resources.git#f0a46830cae7ef6282d9bba64b6da34bae18f339"))
val WithTests = RootProject(
uri("git://github.com/scalacenter/with-tests.git#7a0c7f7d38efd53ca9ec3a347df3638932bd619e"))
uri("git://github.com/scalacenter/with-tests.git#3be26f4f21427c5bc0b83deb96d6e66973102eb2"))

}
11 changes: 9 additions & 2 deletions frontend/src/main/scala/bloop/Bloop.scala
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
package bloop

import bloop.cli.{CliOptions, Commands, ExitStatus}
import bloop.cli.CliParsers.{OptionsParser, inputStreamRead, pathParser, printStreamRead}
import bloop.cli.CliParsers.{
OptionsParser,
inputStreamRead,
pathParser,
printStreamRead,
propertiesParser
}
import bloop.engine.{Build, Exit, Interpreter, NoPool, Run, State}
import bloop.engine.tasks.Tasks
import bloop.io.AbsolutePath
Expand All @@ -17,7 +23,8 @@ object Bloop extends CaseApp[CliOptions] {
private val reader = consoleReader()

override def run(options: CliOptions, remainingArgs: RemainingArgs): Unit = {
val configDirectory = options.configDir.map(AbsolutePath.apply).getOrElse(AbsolutePath(".bloop"))
val configDirectory =
options.configDir.map(AbsolutePath.apply).getOrElse(AbsolutePath(".bloop"))
val logger = BloopLogger.default(configDirectory.syntax)
logger.warn("The Nailgun integration should be preferred over the Bloop shell.")
logger.warn(
Expand Down
1 change: 1 addition & 0 deletions frontend/src/main/scala/bloop/Cli.scala
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ object Cli {
ngout = server.out,
ngerr = server.err,
workingDirectory = ngContext.getWorkingDirectory,
env = ngContext.getEnv()
)
val command = ngContext.getCommand
val args = {
Expand Down
5 changes: 5 additions & 0 deletions frontend/src/main/scala/bloop/cli/CliParsers.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package bloop.cli

import java.io.{InputStream, PrintStream}
import java.nio.file.{Path, Paths}
import java.util.Properties

import caseapp.CommandParser
import caseapp.core.{ArgParser, DefaultBaseCommand}
Expand All @@ -27,6 +28,10 @@ object CliParsers {
}
}

implicit val propertiesParser: ArgParser[Properties] = ArgParser.instance("A properties parser") {
case whatever => Left("You cannot pass in properties through the command line.")
}

val BaseMessages: caseapp.core.Messages[DefaultBaseCommand] =
caseapp.core.Messages[DefaultBaseCommand]
val OptionsParser: caseapp.core.Parser[CliOptions] =
Expand Down
8 changes: 8 additions & 0 deletions frontend/src/main/scala/bloop/cli/CommonOptions.scala
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package bloop.cli

import java.io.{InputStream, PrintStream}
import java.util.Properties

import bloop.engine.ExecutionContext
import bloop.io.AbsolutePath
Expand All @@ -22,11 +23,18 @@ case class CommonOptions(
@Hidden err: PrintStream = System.err,
@Hidden ngout: PrintStream = System.out,
@Hidden ngerr: PrintStream = System.err,
@Hidden env: Properties = CommonOptions.currentProperties,
threads: Int = ExecutionContext.nCPUs
) {
def workingPath: AbsolutePath = AbsolutePath(workingDirectory)
}

object CommonOptions {
final val default = CommonOptions()
final val currentProperties: Properties = {
import scala.collection.JavaConverters._
System.getenv().asScala.foldLeft(new Properties()) {
case (props, (key, value)) => props.setProperty(key, value); props
}
}
}
3 changes: 2 additions & 1 deletion frontend/src/main/scala/bloop/engine/Interpreter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,8 @@ object Interpreter {
result
} catch {
case NonFatal(t) =>
previousState.logger.error(t.getMessage)
if (t.getMessage != null)
previousState.logger.error(t.getMessage)
previousState.logger.trace(t)
previousState
}
Expand Down
5 changes: 3 additions & 2 deletions frontend/src/main/scala/bloop/engine/tasks/Tasks.scala
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,8 @@ object Tasks {
DiscoveredTests(testLoader, includedTests.groupBy(_._1).mapValues(_.map(_._2)))
}

TestInternals.executeTasks(cwd, processConfig, discoveredTests, eventHandler, logger)
val env = state.commonOptions.env
TestInternals.executeTasks(cwd, processConfig, discoveredTests, eventHandler, logger, env)
}

// Return the previous state, test execution doesn't modify it.
Expand All @@ -303,7 +304,7 @@ object Tasks {
args: Array[String]): Task[State] = Task {
val classpath = project.classpath
val processConfig = ForkProcess(project.javaEnv, classpath)
val exitCode = processConfig.runMain(cwd, fqn, args, state.logger)
val exitCode = processConfig.runMain(cwd, fqn, args, state.logger, state.commonOptions.env)
val exitStatus = {
if (exitCode == ForkProcess.EXIT_OK) ExitStatus.Ok
else ExitStatus.UnexpectedError
Expand Down
10 changes: 8 additions & 2 deletions frontend/src/main/scala/bloop/exec/ForkProcess.scala
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
package bloop.exec

import java.io.File.{separator, pathSeparator}
import java.io.File.{pathSeparator, separator}
import java.lang.ClassLoader
import java.nio.file.Files
import java.net.URLClassLoader
import java.util.Properties
import java.util.concurrent.ConcurrentHashMap

import scala.util.control.NonFatal

import bloop.io.AbsolutePath
import bloop.logging.{Logger, ProcessLogger}

Expand Down Expand Up @@ -40,14 +40,17 @@ final case class ForkProcess(javaEnv: JavaEnv, classpath: Array[AbsolutePath]) {
* @param className The fully qualified name of the class to run.
* @param args The arguments to pass to the main method.
* @param logger Where to log the messages from execution.
* @param properties The environment properties to run the program with.
* @param extraClasspath Paths to append to the classpath before running.
* @return 0 if the execution exited successfully, a non-zero number otherwise.
*/
def runMain(cwd: AbsolutePath,
className: String,
args: Array[String],
logger: Logger,
env: Properties,
extraClasspath: Array[AbsolutePath] = Array.empty): Int = {
import scala.collection.JavaConverters.{propertiesAsScalaMap, mapAsJavaMapConverter}
val fullClasspath = classpath ++ extraClasspath

val java = javaEnv.javaHome.resolve("bin").resolve("java")
Expand All @@ -68,6 +71,9 @@ final case class ForkProcess(javaEnv: JavaEnv, classpath: Array[AbsolutePath]) {
} else {
val processBuilder = new ProcessBuilder(cmd: _*)
processBuilder.directory(cwd.toFile)
val processEnv = processBuilder.environment()
processEnv.clear()
processEnv.putAll(propertiesAsScalaMap(env).asJava)
val process = processBuilder.start()
val processLogger = new ProcessLogger(logger, process)
processLogger.start()
Expand Down
18 changes: 7 additions & 11 deletions frontend/src/main/scala/bloop/testing/TestInternals.scala
Original file line number Diff line number Diff line change
@@ -1,23 +1,17 @@
package bloop.testing

import java.util.Properties
import java.util.regex.Pattern

import bloop.DependencyResolution
import bloop.exec.{ForkProcess, JavaEnv}
import bloop.io.AbsolutePath
import bloop.logging.Logger
import sbt.testing.{
AnnotatedFingerprint,
EventHandler,
Fingerprint,
Framework,
SubclassFingerprint,
Task => TestTask
}
import sbt.testing.{AnnotatedFingerprint, EventHandler, Fingerprint, Framework, SubclassFingerprint, Task => TestTask}
import org.scalatools.testing.{Framework => OldFramework}
import sbt.internal.inc.Analysis
import sbt.internal.inc.classpath.{FilteredLoader, IncludePackagesFilter}
import sbt.testing.{Framework, Task => TestTask, TaskDef}
import sbt.testing.{Framework, TaskDef, Task => TestTask}
import xsbt.api.Discovered
import xsbti.api.ClassLike
import xsbti.compile.CompileAnalysis
Expand Down Expand Up @@ -74,12 +68,14 @@ object TestInternals {
* @param discoveredTests The tests that were discovered.
* @param eventHandler Handler that reacts on messages from the testing frameworks.
* @param logger Logger receiving test output.
* @param env The environment properties to run the program with.
*/
def executeTasks(cwd: AbsolutePath,
fork: ForkProcess,
discoveredTests: DiscoveredTests,
eventHandler: EventHandler,
logger: Logger): Unit = {
logger: Logger,
env: Properties): Unit = {
logger.debug("Starting forked test execution.")

val testLoader = fork.toExecutionClassLoader(Some(filteredLoader))
Expand All @@ -91,7 +87,7 @@ object TestInternals {
logger.debug("Test agent jars: " + testAgentFiles.mkString(", "))

val exitCode = server.whileRunning {
fork.runMain(cwd, forkMain, arguments, logger, testAgentJars)
fork.runMain(cwd, forkMain, arguments, logger, env, testAgentJars)
}

if (exitCode != 0) logger.error(s"Forked execution terminated with non-zero code: $exitCode")
Expand Down
18 changes: 12 additions & 6 deletions frontend/src/test/scala/bloop/engine/FileWatchingSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,9 @@ class FileWatchingSpec {
def watchTest(): Unit = {
val TestProjectName = "with-tests"
val testProject = s"$TestProjectName-test"
val state = ProjectHelpers.loadTestProject(TestProjectName)
val state0 = ProjectHelpers.loadTestProject(TestProjectName)
val commonOptions = state0.commonOptions.copy(env = ProjectHelpers.runAndTestProperties)
val state = state0.copy(commonOptions = commonOptions)

val workerAction: FileWatchingContext => Unit = {
case (state, project, bloopOut) =>
Expand All @@ -126,8 +128,8 @@ class FileWatchingSpec {
val loggerName = UUID.randomUUID().toString
val newLogger = BloopLogger.at(loggerName, newOut, newOut)
val newState = state.copy(logger = newLogger)
val commonOptions = cliOptions0.common.copy(out = newOut)
val cliOptions = cliOptions0.copy(common = commonOptions, verbose = true)
val commonOptions1 = commonOptions.copy(out = newOut)
val cliOptions = cliOptions0.copy(common = commonOptions1, verbose = true)
val cmd = Commands.Test(project.name, watch = true, cliOptions = cliOptions)
Interpreter.execute(Run(cmd), newState)
()
Expand All @@ -144,21 +146,25 @@ class FileWatchingSpec {

// Wait for #1 compilation to finish
readCompilingLines(1, "Compiling 1 Scala source to", bloopOut)
readCompilingLines(1, "Compiling 5 Scala sources to", bloopOut)
readCompilingLines(1, "Compiling 6 Scala sources to", bloopOut)
readCompilingLines(1, "+ is very personal", bloopOut)
readCompilingLines(1, "+ Greeting.is personal: OK", bloopOut)
readCompilingLines(1, "- should be very personal", bloopOut)
Thread.sleep(1500)
readCompilingLines(1, "Total for specification Specs2Test", bloopOut)
readCompilingLines(2, "Terminating test server.", bloopOut)
readCompilingLines(1, "File watching 8 directories.", bloopOut)

// Write the contents of a source back to the same source
Files.write(newSource, "object ForceRecompilation {}".getBytes("UTF-8"))

// Wait for #2 compilation to finish
readCompilingLines(2, "Compiling 1 Scala source to", bloopOut)
readCompilingLines(1, "Compiling 5 Scala sources to", bloopOut)
readCompilingLines(1, "Compiling 6 Scala sources to", bloopOut)
readCompilingLines(2, "+ is very personal", bloopOut)
readCompilingLines(2, "+ Greeting.is personal: OK", bloopOut)
readCompilingLines(2, "- should be very personal", bloopOut)
readCompilingLines(2, "Total for specification Specs2Test", bloopOut)
readCompilingLines(4, "Terminating test server.", bloopOut)

// Finish source file watching
workerThread.interrupt()
Expand Down
3 changes: 2 additions & 1 deletion frontend/src/test/scala/bloop/exec/ForkProcessSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ class ForkProcessSpec {
val classpath = project.classpath
val config = ForkProcess(env, classpath)
val logger = new RecordingLogger
val exitCode = config.runMain(cwdPath, s"$packageName.$mainClassName", args, logger)
val userEnv = ProjectHelpers.runAndTestProperties
val exitCode = config.runMain(cwdPath, s"$packageName.$mainClassName", args, logger, userEnv)
val messages = logger.getMessages
op(exitCode, messages)
}
Expand Down
6 changes: 4 additions & 2 deletions frontend/src/test/scala/bloop/nailgun/NailgunTest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,10 @@ abstract class NailgunTest {
val cmdBase =
if (BspServer.isWindows) "python" :: clientPath.toString :: Nil
else clientPath.toString :: Nil
new ProcessBuilder((cmdBase ++ (s"--nailgun-port=$port" +: cmd)): _*)
.directory(base.toFile)
val builder = new ProcessBuilder((cmdBase ++ (s"--nailgun-port=$port" +: cmd)): _*)
val env = builder.environment()
env.put("BLOOP_OWNER", "owner")
builder.directory(base.toFile)
}

/**
Expand Down
9 changes: 8 additions & 1 deletion frontend/src/test/scala/bloop/tasks/ProjectHelpers.scala
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,12 @@ object ProjectHelpers {
State.forTests(build, CompilationHelpers.getCompilerCache(logger), logger)
}

private[bloop] final val runAndTestProperties = {
val props = new java.util.Properties()
props.put("BLOOP_OWNER", "owner")
props
}

/**
* Compile the given sources and then run `cmd`. Log messages are then given to `check`.
*
Expand Down Expand Up @@ -119,7 +125,8 @@ object ProjectHelpers {
check: List[(String, String)] => Unit): Unit = {
val recordingLogger = new RecordingLogger
val recordingStream = ProcessLogger.toOutputStream(recordingLogger.info _)
val recordingState = state.copy(logger = recordingLogger)
val commonOptions = state.commonOptions.copy(env = runAndTestProperties)
val recordingState = state.copy(logger = recordingLogger).copy(commonOptions = commonOptions)
val project = getProject(cmd.project, recordingState)
val _ = Interpreter.execute(Run(cmd), recordingState)
check(recordingLogger.getMessages)
Expand Down
4 changes: 3 additions & 1 deletion frontend/src/test/scala/bloop/tasks/TestLoggingSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@ class TestLoggingSpec {
val beforeCompilation = state.copy(
build = build.copy(projects = build.projects.map(_.copy(javaEnv = inProcessEnv))))
val action = Run(Commands.Compile(moduleName))
Interpreter.execute(action, beforeCompilation)
val state0 = Interpreter.execute(action, beforeCompilation)
val commonOptions = state.commonOptions.copy(env = ProjectHelpers.runAndTestProperties)
state.copy(commonOptions = commonOptions)
}

val testAction = Run(Commands.Test(moduleName))
Expand Down
3 changes: 2 additions & 1 deletion frontend/src/test/scala/bloop/tasks/TestTaskTest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,8 @@ class TestTaskTest(framework: String) {
Seq(framework -> filteredDefs)
}.toMap
val discoveredTests = DiscoveredTests(classLoader, tests)
TestInternals.executeTasks(cwd, config, discoveredTests, Tasks.eventHandler, logger)
val env = ProjectHelpers.runAndTestProperties
TestInternals.executeTasks(cwd, config, discoveredTests, Tasks.eventHandler, logger, env)
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion project/BuildPlugin.scala
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ object BuildImplementation {
import ch.epfl.scala.sbt.release.ReleaseEarlyPlugin.{autoImport => ReleaseEarlyKeys}

final val globalSettings: Seq[Def.Setting[_]] = Seq(
BuildKeys.schemaVersion := "1.3-refresh2",
BuildKeys.schemaVersion := "1.3-refresh4",
Keys.testOptions in Test += sbt.Tests.Argument("-oD"),
Keys.onLoadMessage := Header.intro,
Keys.publishArtifact in Test := false,
Expand Down

0 comments on commit 0dbe10a

Please sign in to comment.