Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Notify & enable users to stay in the warm shell #2996

Merged
merged 4 commits into from
Mar 7, 2017

Conversation

dwijnand
Copy link
Member

@dwijnand dwijnand commented Mar 7, 2017

Notify & enable users to stay in sbt's shell on the warm JVM by hitting
[ENTER] while sbt is running.

Looks like this; first I run 'sbt about', then I hit [ENTER]:

$ sbt about
[info] !!! Executing in batch mode !!! For better performance, hit [ENTER] to remain in the sbt shell

[info] Loading global plugins from /Users/dnw/.dotfiles/.sbt/0.13/plugins
[info] Loading project definition from /s/t/project
[info] Set current project to t (in build file:/s/t/)
[info] This is sbt 0.13.14-SNAPSHOT
[info] The current project is {file:/s/t/}t 0.1.0-SNAPSHOT
[info] The current project is built against Scala 2.12.1
[info] Available Plugins: sbt.plugins.IvyPlugin, sbt.plugins.JvmPlugin, sbt.plugins.CorePlugin, sbt.plugins.JUnitXmlReportPlugin, sbt.plugins.Giter8TemplatePlugin
[info] sbt, sbt plugins, and build definitions are using Scala 2.10.6
>
>

Fixes #2987

image

Notify & enable users to stay in sbt's shell on the warm JVM by hitting
[ENTER] while sbt is running.

Looks like this; first I run 'sbt about', then I hit [ENTER]:

    $ sbt about
    [info] !!! Executing in batch mode !!! For better performance, hit [ENTER] to remain in the sbt shell

    [info] Loading global plugins from /Users/dnw/.dotfiles/.sbt/0.13/plugins
    [info] Loading project definition from /s/t/project
    [info] Set current project to t (in build file:/s/t/)
    [info] This is sbt 0.13.14-SNAPSHOT
    [info] The current project is {file:/s/t/}t 0.1.0-SNAPSHOT
    [info] The current project is built against Scala 2.12.1
    [info] Available Plugins: sbt.plugins.IvyPlugin, sbt.plugins.JvmPlugin, sbt.plugins.CorePlugin, sbt.plugins.JUnitXmlReportPlugin, sbt.plugins.Giter8TemplatePlugin
    [info] sbt, sbt plugins, and build definitions are using Scala 2.10.6
    >
    >

Fixes sbt#2987
@fommil
Copy link
Contributor

fommil commented Mar 7, 2017

the concept is really great, I'm tired of telling people to stay in shell mode. The hint here suggests that hitting return is the only way to get into script mode, can you think of wording that captures how to start in script mode?

"BATCH MODE: for better performance use the sbt shell by not passing commands, or by pressing [ENTER] to upgrade."

def isInteractive = System.console() != null
def hasShell = state.remainingCommands contains "shell"
if (isInteractive && !hasShell)
state.log info "!!! Executing in batch mode !!! For better performance, hit [ENTER] to remain in the sbt shell"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(bikeshedding) Should this not be a warning instead? I believe this would make it more likely for people to pay attention instead of the triple exclamation marks.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Much better. Thanks.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not so sure if warning is the right level here. sbt is able to reduce the log level using --warn (This could get rid of Resolving etc.), and I feel like "tip of the day" message sits squarely on the "info" level. Yes, your build is going to compile slower, but it's not like it's destroying your code.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I found that without my "!!!" even I who implemented the feature couldn't see it.

That's why I agreed with Lars that the issue was in the choice of using info. Move it to warn allowed me to drop the !!! workaround, make the message shorter, and also (as you can see from the screenshots below) benefit from [warn] being in yellow.

We have only 1 axis (error/warn/info/debug) on which to attribute semantics. I don't know you, but if I IRL see someone run sbt compile I would want to warn them.

Yes, your build is going to compile slower, but it's not like it's destroying your code.

It's not an error, just a warning.

@dwijnand
Copy link
Member Author

dwijnand commented Mar 7, 2017

@fommil I agree, having a little trouble thinking of a good, not-too-verbose way to communicate that.

There so many parts to the message:

  • the current status "executing in batch mode"
  • the reason for the message "for better performance"
  • and the 3 different options: pass no commands, pass 'shell', or hit [ENTER]

WDYT?

[warn] BATCH MODE: for better performance hit [ENTER] to switch to interactive mode
[warn]   consider launching sbt without any commands, or explicitly passing 'shell'

@dwijnand
Copy link
Member Author

dwijnand commented Mar 7, 2017

image

Copy link
Member

@eed3si9n eed3si9n left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is a run-on is a sentence. (bike shedding)

How about:

Executing command(s) 'about' in batch mode.
For faster compilation, hit [ENTER] to switch to interactive mode, or
consider launching sbt without any commands.

@dwijnand
Copy link
Member Author

dwijnand commented Mar 7, 2017

@eed3si9n

  • I avoided printing out the commands as I CBA to deal with quoting, etc; and I don't think it's required
  • I stuck to "for better performance" because this is not just specific to compilation
  • I kept the "or explicitly pass 'shell'" part, as it's the 3rd option some might be interested in

@dwijnand
Copy link
Member Author

dwijnand commented Mar 7, 2017

image

f(x, s.copy(remainingCommands = xs, history = x :: s.history))
}
def isInteractive = System.console() != null
def hasInput = System.console().reader().ready()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens if someone runs sbt run that asks user for text input?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or more likely sbt +publishSigned

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

src/main/scala/t/T.scala

package t

object T {
  def main(args: Array[String]): Unit = {
    val con = System.console()
    val x = con readLine "Give me something: "
    con printf ("You gave me: %s\n", x)
  }
}

->

$ sbt run
[warn] Executing in batch mode.
[warn]   For better performance, hit [ENTER] to switch to interactive mode, or
[warn]   consider launching sbt without any commands, or explicitly passing 'shell'

[info] Loading global plugins from /Users/dnw/.dotfiles/.sbt/0.13/plugins
[info] Loading project definition from /s/t/project
[info] Set current project to t (in build file:/s/t/)
[info] Running t.T
Give me something: You gave me:
[success] Total time: 0 s, completed 07-Mar-2017 14:24:09

project/plugins.sbt

addSbtPlugin("com.jsuereth" % "sbt-pgp" % "1.0.0")

->

$ sbt +publishLocalSigned
[warn] Executing in batch mode.
[warn]   For better performance, hit [ENTER] to switch to interactive mode, or
[warn]   consider launching sbt without any commands, or explicitly passing 'shell'

[info] Loading global plugins from /Users/dnw/.dotfiles/.sbt/0.13/plugins
[info] Loading project definition from /s/t/project
[info] Updating {file:/s/t/project/}t-build...
[info] Resolving org.fusesource.jansi#jansi;1.4 ...
[info] Done updating.
[info] Set current project to t (in build file:/s/t/)
[info] Setting version to 2.12.1
[info] Reapplying settings...
[info] Set current project to t (in build file:/s/t/)
[info] Packaging /s/t/target/scala-2.12/t_2.12-0.1.0-SNAPSHOT-sources.jar ...
[info] Done packaging.
[info] Main Scala API documentation to /s/t/target/scala-2.12/api...
[info] Wrote /s/t/target/scala-2.12/t_2.12-0.1.0-SNAPSHOT.pom
[info] :: delivering :: com.dwijnand#t_2.12;0.1.0-SNAPSHOT :: 0.1.0-SNAPSHOT :: integration :: Tue Mar 07 14:28:17 GMT 2017
[info] 	delivering ivy file to /s/t/target/scala-2.12/ivy-0.1.0-SNAPSHOT.xml
[info] Packaging /s/t/target/scala-2.12/t_2.12-0.1.0-SNAPSHOT.jar ...
[info] Done packaging.
model contains 3 documentable templates
[info] Main Scala API documentation successful.
[info] Packaging /s/t/target/scala-2.12/t_2.12-0.1.0-SNAPSHOT-javadoc.jar ...
[info] Done packaging.
Please enter PGP passphrase (or ENTER to abort):
java.lang.RuntimeException: Empty passphrase. aborting...
	at scala.sys.package$.error(package.scala:27)
	at com.typesafe.sbt.pgp.SbtPgpCommandContext.inputPassphrase(SbtPgpCommandContext.scala:27)
	at com.typesafe.sbt.pgp.SbtPgpCommandContext$$anonfun$1$$anonfun$apply$1$$anonfun$apply$2.apply(SbtPgpCommandContext.scala:34)
	at com.typesafe.sbt.pgp.SbtPgpCommandContext$$anonfun$1$$anonfun$apply$1$$anonfun$apply$2.apply(SbtPgpCommandContext.scala:34)
	at scala.Option.getOrElse(Option.scala:120)
	at com.typesafe.sbt.pgp.SbtPgpCommandContext$$anonfun$1$$anonfun$apply$1.apply(SbtPgpCommandContext.scala:34)
	at com.typesafe.sbt.pgp.SbtPgpCommandContext$$anonfun$1$$anonfun$apply$1.apply(SbtPgpCommandContext.scala:34)
	at com.typesafe.sbt.pgp.Cache$$anonfun$withValue$1.apply(SbtHelpers.scala:39)
	at scala.Option.getOrElse(Option.scala:120)
	at com.typesafe.sbt.pgp.Cache$class.withValue(SbtHelpers.scala:38)
	at com.typesafe.sbt.pgp.PasswordCache$.withValue(SbtHelpers.scala:55)
	at com.typesafe.sbt.pgp.SbtPgpCommandContext$$anonfun$1.apply(SbtPgpCommandContext.scala:34)
	at com.typesafe.sbt.pgp.SbtPgpCommandContext.retry(SbtPgpCommandContext.scala:42)
	at com.typesafe.sbt.pgp.SbtPgpCommandContext.withPassphrase(SbtPgpCommandContext.scala:31)
	at com.typesafe.sbt.pgp.BouncyCastlePgpSigner.sign(PgpSigner.scala:37)
	at com.typesafe.sbt.pgp.PgpSettings$$anonfun$signingSettings$1$$anonfun$apply$1.apply(PgpSettings.scala:120)
	at com.typesafe.sbt.pgp.PgpSettings$$anonfun$signingSettings$1$$anonfun$apply$1.apply(PgpSettings.scala:117)
	at scala.collection.TraversableLike$$anonfun$flatMap$1.apply(TraversableLike.scala:251)
	at scala.collection.TraversableLike$$anonfun$flatMap$1.apply(TraversableLike.scala:251)
	at scala.collection.immutable.Map$Map4.foreach(Map.scala:181)
	at scala.collection.TraversableLike$class.flatMap(TraversableLike.scala:251)
	at scala.collection.AbstractTraversable.flatMap(Traversable.scala:105)
	at com.typesafe.sbt.pgp.PgpSettings$$anonfun$signingSettings$1.apply(PgpSettings.scala:117)
	at com.typesafe.sbt.pgp.PgpSettings$$anonfun$signingSettings$1.apply(PgpSettings.scala:115)
	at scala.Function4$$anonfun$tupled$1.apply(Function4.scala:35)
	at scala.Function4$$anonfun$tupled$1.apply(Function4.scala:34)
	at scala.Function1$$anonfun$compose$1.apply(Function1.scala:47)
	at sbt.$tilde$greater$$anonfun$$u2219$1.apply(TypeFunctions.scala:40)
	at sbt.std.Transform$$anon$4.work(System.scala:63)
	at sbt.Execute$$anonfun$submit$1$$anonfun$apply$1.apply(Execute.scala:228)
	at sbt.Execute$$anonfun$submit$1$$anonfun$apply$1.apply(Execute.scala:228)
	at sbt.ErrorHandling$.wideConvert(ErrorHandling.scala:17)
	at sbt.Execute.work(Execute.scala:237)
	at sbt.Execute$$anonfun$submit$1.apply(Execute.scala:228)
	at sbt.Execute$$anonfun$submit$1.apply(Execute.scala:228)
	at sbt.ConcurrentRestrictions$$anon$4$$anonfun$1.apply(ConcurrentRestrictions.scala:159)
	at sbt.CompletionService$$anon$2.call(CompletionService.scala:28)
	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
	at java.lang.Thread.run(Thread.java:745)
[error] (*:signedArtifacts) Empty passphrase. aborting...
[error] Total time: 3 s, completed 07-Mar-2017 14:28:20

@dwijnand
Copy link
Member Author

dwijnand commented Mar 7, 2017

Testing the behaviour of System.console() on Travis CI:

package t

object T {
  def main(args: Array[String]): Unit = {
    def isInteractive = System.console() != null
    if (isInteractive)
      println("interactive: TRUE")
    else
      println("interactive: FALSE")
  }
}
language: scala
jdk: oraclejdk8
scala: 2.12.2
script:
  - sbt package
  - scala target/scala-*/*.jar
  - scala target/scala-*/*.jar < /dev/null
  - scala target/scala-*/*.jar | cat
  - scala target/scala-*/*.jar < /dev/null | cat

https://travis-ci.org/dwijnand/l2travis/builds/208656785

I'm expecting the output:

interactive: FALSE
interactive: FALSE
interactive: FALSE
interactive: FALSE

@dwijnand
Copy link
Member Author

dwijnand commented Mar 7, 2017

No scala binary on Travis CI. Switched to sbt-assembly and java: https://travis-ci.org/dwijnand/l2travis/builds/208672634

@dwijnand
Copy link
Member Author

dwijnand commented Mar 7, 2017

$ java -jar target/scala-*/*-assembly-*.jar
interactive: TRUE

So when Travis CI invokes things it's technically in "interactive" mode. So unless the invocation does something like < /dev/null/| cat (or use -batch which is a sbt-extras' feature), then they'll see these extra 3 lines of warning..

I think we should merge, and if anyone wants to make the out-the-box experience with Travis CI or similar better, they're very welcome to contribute an enhancement.

@eed3si9n eed3si9n merged commit a3d776c into sbt:0.13 Mar 7, 2017
@dwijnand dwijnand deleted the stay-in-shell branch March 7, 2017 22:03
@ScalaWilliam
Copy link
Contributor

Wouldn't it be enough to just indicate this warning, and NOT do the Enter thing?

How can I disable this feature if I don't want to see the warning every time I'm intentionally in batch mode?

When I see a warning my alarm bells go off to get ready to investigate a problem but this non-problem is going to be appearing all the time.

@dwijnand
Copy link
Member Author

Wouldn't it be enough to just indicate this warning, and NOT do the Enter thing?

You could. The Enter thing was added for convenience.

How can I disable this feature if I don't want to see the warning every time I'm intentionally in batch mode?

When I see a warning my alarm bells go off to get ready to investigate a problem but this non-problem is going to be appearing all the time.

Using sbt-extras if you can pass the -batch flag you indicate to sbt that you're not an interactive shell. Then it won't tell you how to switch to interactive mode.

I wonder, do you think the length of the message, i.e the fact that it's 3 lines long, part of the reason your alarm bells are going off?

@eed3si9n
Copy link
Member

Note that currently the warning is displayed incorrectly, which will be fixed soon - #3004

When I see a warning my alarm bells go off to get ready to investigate a problem but this non-problem is going to be appearing all the time.

Are we talking about literal or figurative/mental alarm bells here?
The purpose of this is to let the user community know that using batch mode is slower, so to some degree if it's catching your attention, it's doing its job. Another idea might be to display a large ASCII art at "info" level when you run the batch mode.

btw, what would be the reason for using batch mode intentionally besides CI?

@ScalaWilliam
Copy link
Contributor

ScalaWilliam commented Mar 12, 2017

I find seeing this message all the time a bit redundant, would like to disable it permanently without specifying extra flags. I understood the message the first time I saw it, why keep on repeating it. So suggestion would be to have an SBT option in ~/.sbt that helps disable this thing.

[warn] Executing in batch mode.
[warn]   For better performance, hit [ENTER] to switch to interactive mode, or
[warn]   consider launching sbt without any commands, or explicitly passing 'shell'

The 'warn' part captures attention very quickly, especially when it's highlighted very visibly in the terminal.


I just saw @eed3si9n's comment that this is actually a bug so I guess my comment above is not relevant any more.


I do use batch mode typically to execute multiple commands locally to do test & build sequences - before going to CI.

It's more convenient to just type sbt clean stage docker:publishLocal && doSomethingElse in one line.

We also call into SBT from Makefiles, I'm not sure how this will affect things (will it think interactive mode & also 'warn' users when they try to build via make?). Some projects use sbt as one of several build tools.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants