I tried the following:
update := update.dependsOn(myTask)
But it runs myTask in parallel of update where myTask is needed to be finished before update starts.
I then tried the following that doesn't work at all:
update := myTask.runBefore(update).value
Any idea?
Cheers
I found out that myTask was defined after the dependsOn or runBefore declaration and it seems to not be able to resolve it.
So declaring the tasks before solves the issue.
Related
so as I stated in the title, I am working on Laravel 5.7 project and am making first tests in this application (big system). We did not make any tests in here yet, so this problem is the first time here.
For every test, this is how the controller uses the trait
use RefreshDatabase;
protected function setUp()
{
parent::setUp();
$this->withoutMiddleware(\App\Http\Middleware\VerifyCsrfToken::class);
$this->withoutExceptionHandling();
}
As you can see, I am just trying to use the trait to refresh the DB after the tests are done.
The problem arises when I call to execute the tests.
ErrorException: Trying to access array offset on value of type int
C:\laragon\www\demi\systems\damaro\vendor\symfony\console\Input\ArrayInput.php:135
C:\laragon\www\demi\systems\damaro\vendor\symfony\console\Input\Input.php:55
C:\laragon\www\demi\systems\damaro\vendor\symfony\console\Command\Command.php:214
C:\laragon\www\demi\systems\damaro\vendor\laravel\framework\src\Illuminate\Console\Command.php:170
C:\laragon\www\demi\systems\damaro\vendor\symfony\console\Application.php:886
C:\laragon\www\demi\systems\damaro\vendor\symfony\console\Application.php:262
C:\laragon\www\demi\systems\damaro\vendor\symfony\console\Application.php:145
C:\laragon\www\demi\systems\damaro\vendor\laravel\framework\src\Illuminate\Console\Application.php:89
C:\laragon\www\demi\systems\damaro\vendor\laravel\framework\src\Illuminate\Console\Application.php:188
C:\laragon\www\demi\systems\damaro\vendor\laravel\framework\src\Illuminate\Foundation\Console\Kernel.php:250
C:\laragon\www\demi\systems\damaro\vendor\laravel\framework\src\Illuminate\Foundation\Testing\PendingCommand.php:136
C:\laragon\www\demi\systems\damaro\vendor\laravel\framework\src\Illuminate\Foundation\Testing\PendingCommand.php:218
C:\laragon\www\demi\systems\damaro\vendor\laravel\framework\src\Illuminate\Foundation\Testing\Concerns\InteractsWithConsole.php:55
C:\laragon\www\demi\systems\damaro\vendor\laravel\framework\src\Illuminate\Foundation\Testing\RefreshDatabase.php:55
C:\laragon\www\demi\systems\damaro\vendor\laravel\framework\src\Illuminate\Foundation\Testing\RefreshDatabase.php:18
C:\laragon\www\demi\systems\damaro\vendor\laravel\framework\src\Illuminate\Foundation\Testing\TestCase.php:104
C:\laragon\www\demi\systems\damaro\vendor\laravel\framework\src\Illuminate\Foundation\Testing\TestCase.php:71
This is the whole trace.
Some solutions I found are:
composer update - not an option, because the project is in production
disable telescope package in phpunit.xml - did not work
I also tried installing telescope package - did not work as well
Do you have any idea?
So I have not found an answer to this question, but I have found a workaround.
Instead of using RefreshDatabase trait I decided to use DatabaseTransactions trait.
I have written custom task for my sbt project and placed it in build.sbt.
However I would like to put the task's code to separate file and import it from build.sbt. I have created mytask.sbt that contains something like this:
lazy val myTask = taskKey[Unit]("my task")
myTask := {
//doing task
}
but I don't know how can I import this task from within build.sbt so I could use something like this:
compile <<= (compile in Compile) dependsOn myTask
I'm aware that there is plugins concept but I think this is overkill for my needs. All I want is to separate some code.
You do not mention what sbt version your are using, so the following answer is based on version 0.13.12.
As far as I know, task has to be defined either in an sbt file, in a plugin, or inside a scala file object extending the Build trait.
I don't think its possibly to define anything in one sbt file, and use it in another, so from my point of view, your have these options:
Extending the Build trait
this way of doing things, has become deprecated in the later versions of sbt, so I will not go into that one.
Defining the logic of the task in an scala file.
You could split the declaration and the logic of the task up, so that your declare the task in the sbt build file, but move the logic of it into a scala file. Then your build file could be like this:
import CommonBuildCode._
val myTask = taskKey[Unit]("my task")
myTask := {
myTaskPerform()
}
compile := {
myTask.value
(compile in Compile).value
}
And you logic for the task could be in the file project/CommonBuildCode.scala
import sbt._
object CommonBuildCode {
def myTaskPerform(): Unit = {
println("-------------------------- myTask called --------------------------")
}
}
I do not know it this would be enough for your, but it would keep the number of lines concerning the myTask task in your build.sbt file to a minimum.
Creating a simple plugin
Its pretty easy to create a plugin with sbt, and this will give a result very close to what your asking for. First create the file project/MyTaskPlugin.scala like this:
import sbt._
object MyTaskPlugin extends AutoPlugin {
object autoImport {
val myTask = taskKey[Unit]("my task")
}
import autoImport._
override def projectSettings = Seq(
myTask := {
println("--------------- myTask called from a plugin------------------")
}
)
}
When the project is enabled, anything under the autoImport project will be auto imported and available to use in your sbt build file, and all the settings set in the projectSettings method will apply. So now the only thing you need to do in you build.sbt file, is to activate the plugin:
enablePlugins(MyTaskPlugin)
compile := {
myTask.value
(compile in Compile).value
}
An extra bonus of using a plugin, is that it will be pretty easy to refactor the plugin into its own project, where it can publish a jar, that will be easily activated by other projects. This could be relly handy, in case myTask turns out to be a common build task among your project.
I am unsatisfied with ~ ;task1; task2; so I want to implement my very own task that watches for changes and executes tasks. I.e. I need an sbt task that watches for some files and runs some tasks depending on what is changed.
e.g.
val task1: Initialize[Task[Int]] = ....
val task2: Initialize[Task[Int]] = ....
myTask := {
log.info("Press Enter to stop watching...")
while(isEnterNotPressedYet) {
if (someFilesChanged)
execute(task1) //start task1 and wait for its termination
else if (someOtherFilesChanged)
execute(task2)
Thread.sleep(watchDuration.value)
}
}
task1.value will not work because it will execute task1 BEFORE the body and only once. dynTask will not work because I want to execute tasks multiple times and without leaving the loop. Precisely, question is how to implement following:
def execute[T](task: Initialize[Task[T]]): T
def isEnterNotPressedYet: Boolean
Background:
I have web application that uses JS, Scala, sbt-revolver. Some resources support hot reloading (but still require compilation!), some does not. I.e. if *.js files change, I want to invoke compileJs task. If .scala files change, I want to invoke re-start task. But sbt watch has only one set of watched resources per project...
Had to dive into SBT sources and implement it on my own.
There are quite a bit workarounds around strange SBT behavior but it works!
https://github.com/scf37/sbt-overwatch
I want to set a SettingKey[Seq[Tuple2[String, String]]] called IzPack.variables of a 3rd party plugin called sbt-izpack.
The documentation tells how to set this setting:
IzPack.variables in IzPack.Config <+= name {name => ("projectName", name)}
I think that the <+= syntax is old. There is no explanation about it in the 0.13.5 SBT documentation.
How can I append values that depends on tasks?
This is the syntax I'm using now:
IzPack.variables in IzPack.Config ++= Seq(
("appVersion", mySetting1.value),
("cocoonXconf", mySetting2.value),
)
but it complains when trying to use a task value with this message:
A setting cannot depend on a task
If it's a Setting it must be known at project load as Settings are only computed once. Tasks on the other hand are computed each time. A Setting can not depend on a Task but a Task can depend on a Setting.
See http://www.scala-sbt.org/0.13/tutorial/More-About-Settings.html#Tasks+with+dependencies.
The solution I've finally done is to refactor my own code, so that a task that generates a file, is split in a setting that defines the output file, and a task that creates the file contents.
The setting is used for initializing the setting IzPack.variables, whereas my custom task is made dependant of the task that uses IzPack.variables.
we need to run some code after the compile step. Making things happen after the compile step seems easy:
compile in Compile <<= (compile in Compile) map{x=>
// post-compile work
doFoo()
x
}
but how do you run something in the freshly compiled code?
More info on the scenario: we are using less for css in a lift project. We wanted lift to compile less into css on the fly (if needed) to help dev, but produce less using the same code, during the build, before tests etc run. less-sbt may help but we are interested in how to solve this generally.
You can use the triggeredBy method like this:
yourTask <<= (fullClasspath in Runtime) map {classpath =>
val loader: ClassLoader = ClasspathUtilities.toLoader(classpath.map(_.data).map(_.getAbsoluteFile))
loader.loadClass("your.class.Here").newInstance()
} triggeredBy(compile in Compile)
This will instantiate your class that has just been compiled, using the runtime classpath for your application, after any compile.
It would probably help if you explained your use scenario for this, since there are some different possible solution paths here and choosing between them might involve considerations that you haven't told us.
You won't be able to just write down an ordinary method call into the compiled code. That would be impossible since at the time your build definition is compiled, sbt hasn't looked at your project code yet.
Warning: rambling and thinking out loud ahead.
One trick I can suggest is to access testLoader in Test to get a classloader in which your compiled classes are loaded, and then use reflection to call methods there. For example, in my own build I have:
val netlogoVersion = taskKey[String]("...")
netlogoVersion := {
(testLoader in Test).value
.loadClass("org.nlogo.api.Version")
.getMethod("version")
.invoke(null).asInstanceOf[String]
}
I'm not sure whether accessing testLoader in Test will actually work in your case because testLoader loads your test classes as well as your regular classes, so you might get a circular dependency between compile in Compile and compile in Test.
If you want to try to make a classloader that just has your regular classes loaded, well, hmm. You could look in the sbt source code at the implementation of createTestLoader and use it for inspiration, modifying the arguments that are passed to ClasspathUtilities.makeLoader. (You might also look at the similar code in Run.run0. It calls makeLoader as part of the implementation of the run task.)
A different path you might consider is to reuse the machinery behind the run task to run your code. You won't be able to call an arbitrary method in your compiled code this way, only a main method, but perhaps you can live with that, if you don't need a return value back.
The fullRunTask method exists for creating entire run-like tasks. See "How can I create a custom run task, in addition to run?" from http://www.scala-sbt.org/0.13.1/docs/faq.html . fullRunTask makes it very easy to create a separate task that runs something in your compiled code, but by itself it won't get you all the way to a solution because you need a way of attaching that task to the existing compile in Compile task. If you go this route, I'd suggest asking it that last piece as a separate question.
Consider bypassing fullRunTask and just assembling your own call to Run.run. They use the same machinery. In my own build, I currently use fullRunTask, but back before fullRunTask was added by sbt, here was what my equivalent Run.run-based code looked like:
(..., fullClasspath in Compile, runner, streams, ...) map {
(..., cp, runner, s, ...) =>
Run.run("name.of.my.MainClass",
cp.map(_.data), Seq(), s.log)(runner)
}
Pardon the sbt 0.12, pre-macro syntax; this would look nicer if redone with the 0.13 macros.
Anyway, hopefully something in this brain dump proves useful.