How to show the result of an SBT task in Console - sbt

In sbt console, it is possible to do show settingsKey to view the value of a setting for example:
> show resourceManaged
[info] /Users/code/my_project/target/scala-2.11/resource_managed
Is there a way to do this for tasks? That is to execute and view the result of a task in the console?

Yes, you can also print the results of a task in console with show. For example sbt 'show fullClasspath' or directly show fullClasspath in sbt interactive mode.
Remember that keys are scoped:
Examples of scoped key notation
fullClasspath specifies just a key, so the default scopes are used: current project, a key-dependent configuration, and global task scope.
test:fullClasspath specifies the configuration, so this is fullClasspath in the test configuration, with defaults for the other two scope axes.
*:fullClasspath specifies Global for the configuration, rather than the default configuration.
doc::fullClasspath specifies the fullClasspath key scoped to the doc task, with the defaults for the project and configuration axes.
{file:/home/hp/checkout/hello/}default-aea33a/test:fullClasspath specifies a project, {file:/home/hp/checkout/hello/}default-aea33a, where the project is identified with the build {file:/home/hp/checkout/hello/} and then a project id inside that build default-aea33a. Also specifies configuration test, but leaves the default task axis.
{file:/home/hp/checkout/hello/}/test:fullClasspath sets the project axis to “entire build” where the build is {file:/home/hp/checkout/hello/}.
{.}/test:fullClasspath sets the project axis to “entire build” where the build is {.}. {.} can be written ThisBuild in Scala code.
{file:/home/hp/checkout/hello/}/compile:doc::fullClasspath sets all three scope axes.
You can use inspect fullClasspath to see scopes for that task in your project in Related.

Related

Different mappings for stage and tarball

I want to produce different log configuration for my stage app and on the tarball that I'd use to distribute my application
I have a task to generate the configuration and want it to be called with different parameters on doing stage and packageZipTar. This is my config
mappings in Universal in stage += {
val f = generateLoggingConfigTask(LogType.ConsoleAndFiles).value
f -> ("conf/" + f.getName)
},
mappings in Universal in packageZipTarball += {
val f = generateLoggingConfigTask(LogType.Files).value
f -> ("conf/" + f.getName)
},
The first task fires only when doing stage but on packageZipTarball I get both tasks running, furthermore they run in an unpredictable order so sometimes I have one config sometimes another
Any hints on how to proceed?
The issue is that packageZipTarball depends on stage, which is how native-packager works. stage always creates a "ready to build" directory, which the packaging format uses to create the package. Diverging these two, would be confusing and inconsistent with native-packagers behavior.
I would recommend one of the following options
1. Create your app with stage and pass the configuration explicitly with a cli parameter
2. Create a bash script that adds the logging configuration parameter explicitly and you call this to start your app

sbt cross configuration dependencies

what is the reason SBT won't allow me to have dependencies between different configurations of different projects in a multi-project build?
consider the following setup in the main build.sbt file:
lazy val domain: Project = project in file("domain") dependsOn(testUtils % "test->test")
lazy val testUtils: Project = project in file("testUtils") dependsOn(domain % "compile->test")
...
I would want to write all my test helpers in testUtils, and have each of the other projects' test code to be clean test logic without the (sometimes duplicated among different projects) boilerplate of the aiding methods.
SBT is forcing me to put the : Project type, since it complains the value is "recursive". and upon reloading, I get:
...
at $281429c805669a7befa4$.domain(build.sbt:142)
at $281429c805669a7befa4$.testUtils$lzycompute(build.sbt:144)
at $281429c805669a7befa4$.testUtils(build.sbt:144)
at $281429c805669a7befa4$.domain$lzycompute(build.sbt:142)
at $281429c805669a7befa4$.domain(build.sbt:142)
[error] java.lang.StackOverflowError
[error] Use 'last' for the full log.
is there a way around this? or should I write test-related logic in each module test, even at the cost of getting the code less organize, many "test->test" dependencies, etc'...

SBT setting fallback search path

How are you doing?
I did the following in SBT console:
inspect version
And I get something like the following:
[info] Delegates:
[info] *:version
[info] {.}/*:version
[info] */*:version
So, actually, what's the difference between the last two??? I read and read the documentation but can't seem to make any difference to me. One is ThisBuild (a.k.a. entire build, a.k.a. {.}) while the other one is Global.
Why does {.} in the project axis has precedence over * in the project axis?
The values {.} and * looks pretty much the same to me..
Thanks!!!!
The order of the last two in:
*:version -> try current project
{.}/*:version -> try this build
*/*:version -> try global
says that whatever version you specified in this build, you want that to override anything that was possibly defined in Global.
Example: Key "version"
For Global scope it was defined in Defaults.scala with value "0.1-SNAPSHOT".
For your projects in this build you might want to overwrite that with:
version in ThisBuild := "3.0.1"
So, because {.}/*:version has precedence over /:version, whenever you get "version" in your projects, you fetch "3.0.1" instead of "0.1-SNAPSHOT".

How to set system properties for runMain on command line?

How can I set a system property for runMain upon executing it from command line on Windows?
I'd like to be able to run the following command:
sbt -Dconfig.resource=../application.conf "runMain akka.Main com.my.main.Actor"
Regardless of whether fork is true, whether I put it in SBT_OPTS, or how I pass it in I cannot accomplish this. I am familiar with both Setting value of setting on command line when no default value defined in build? and Setting system properties with "sbt run" but neither answer my question.
Other questions seem to indicate you can't even easily view the Java invocation arguments easily in SBT. Any help is appreciated.
This works:
sbt '; set javaOptions += "-Dconfig.resource=../application.conf" ; runMain akka.Main com.my.main.Actor'
If this isn't a "friendly" enough syntax, wrap it in a little shell script.
(Note this assumes you have fork set to true for running. If you don't, see akauppi's comment.)
You could use envVars setting. I'm unsure how idiomatic it is in SBT, though.
> help envVars
Environment variables used when forking a new JVM
The following (very minimalistic) build.sbt worked fine.
fork := true
envVars := Map("msg" -> "hello")
Once you get it running, setting envVars to any value with set does the trick.
> help set
set [every] <setting-expression>
Applies the given setting to the current project:
1) Constructs the expression provided as an argument by compiling and loading it.
2) Appends the new setting to the current project's settings.
3) Re-evaluates the build's settings.
This command does not rebuild the build definitions, plugins, or configurations.
It does not automatically persist the setting(s) either.
To persist the setting(s), run 'session save' or 'session save-all'.
If 'every' is specified, the setting is evaluated in the current context
and the resulting value is used in every scope. This overrides the value
bound to the key everywhere.
I've got a simple app to run.
$ sbt run
[info] Set current project to fork-testing (in build file:/C:/dev/sandbox/fork-testing/)
[info] Running Hello
[info] hello
With the envVars setting changed on the command line the output would change as follows:
$ sbt 'set envVars := Map("msg" -> "Hello, Chad")' run
[info] Set current project to fork-testing (in build file:/C:/dev/sandbox/fork-testing/)
[info] Defining *:envVars
[info] The new value will be used by *:runner, compile:run::runner and 1 others.
[info] Run `last` for details.
[info] Reapplying settings...
[info] Set current project to fork-testing (in build file:/C:/dev/sandbox/fork-testing/)
[info] Running Hello
[info] Hello, Chad
runMain is no different from run in this case.
$ sbt 'set envVars := Map("msg" -> "Hello, Chad")' 'runMain Hello'
[info] Set current project to fork-testing (in build file:/C:/dev/sandbox/fork-testing/)
[info] Defining *:envVars
[info] The new value will be used by *:runner, compile:run::runner and 1 others.
[info] Run `last` for details.
[info] Reapplying settings...
[info] Set current project to fork-testing (in build file:/C:/dev/sandbox/fork-testing/)
[info] Running Hello
[info] Hello, Chad
If you're trying to set SBT properties, like plugin settings, then the above won't work (AFAICT) as of 0.13+ in my experience. The following however did work, when trying to pass in Liquibase settings, like password, from our CI frameworks.
In your build.sbt
Ugly, but supplies defaults, and optionally grabs from System.properties. This way you've got your default and override cases covered.
def sysPropOrDefault(propName:String,default:String):String = Option(System.getProperty(propName)).getOrElse(default)
liquibaseUsername := sysPropOrDefault("liquibase.username","change_me")
liquibasePassword := sysPropOrDefault("liquibase.password","chuck(\)orris")
From the commandline
Now just override via -Dprop=value like you would with Maven or other JVM programs. Note props appear before SBT task.
sbt -Dliquibase.password="shh" -Dliquibase.username="bob" liquibase:liquibase-update

Pass an environment variable into SBT to use in a Specs2 test?

What is the correct way of passing in an environment variable into SBT so that it can be accessed using Specs2? (And then retrieving the value in Specs2.) The environment variable will contain an API key to use for testing.
It needs to be an environment variable to work with Travis CI's encrypted environment variable functionality[1]
My setup:
SBT 0.13.0
Specs2 2.3.4
Travis CI
Edit: bonus points if somebody can link to an open-source repo that does this. There must be a few!
[1] Using secret api keys on travis-ci
I guess that you can encrypt your key with the travis api and get:
xxxEncryptedxxx
Then you can use the CommandLineArguments trait to pass arguments from the command-line in SBT to your specification.
In .travis.yml
sbt ++$TRAVIS_SCALA_VERSION testOnly *MySpec* -- key xxxEncryptedxxx
In MySpec.scala
class MySpec extends mutable.Specification with CommandLineArguments {
"this is an API test" >> {
arguments.commandLine.value("key").map { k =>
callApi(k) must beOk
}.getOrElse(ko("you need to pass a key on the command line"))
}
}
From you questions, I presume you're looking to pass secure environment variables using Travis's built-in support for encryption?
If so the environment variable is set before SBT is run, so it should be available to all processes. I don't use Specs, but the standard JVM way to get environment variable is to use System.getenv(String). It's possible that sbt deletes the environment variables before running Specs; if that's true then fixing that has to be done in your build.sbt somehow, and isn't specific to Travis.

Resources