Sbt plugin run tasks before / after an other task










0















I know, I saw Run custom task automatically before/after standard task but it seems outdated. I also found SBT before/after hooks for a task but it does not have any code example.



I am on SBT 0.13.17.



So I want to run my task MyBeforeTask and MyAfterTask automatically after an other tasks, says Compile.



So when you do sbt compile I would like to see:



...log...
This is my before test text
...compile log...
This is my after test text


So I would need to have:



object MyPlugin extends AutoPlugin 
object autoImport
val MyBeforeTask = taskKey[Unit]("desc...")
val MyAfterTask = taskKey[Unit]("desc...")


import autoImport._

override def projectSettings: Seq[Def.Setting[_]] =
MyBeforeTask :=
println("This is my before test text")
,
MyAfterTask :=
println("This is my after test text")





So I think I need things like dependsOn and in but I am not sure how to set them up.










share|improve this question


























    0















    I know, I saw Run custom task automatically before/after standard task but it seems outdated. I also found SBT before/after hooks for a task but it does not have any code example.



    I am on SBT 0.13.17.



    So I want to run my task MyBeforeTask and MyAfterTask automatically after an other tasks, says Compile.



    So when you do sbt compile I would like to see:



    ...log...
    This is my before test text
    ...compile log...
    This is my after test text


    So I would need to have:



    object MyPlugin extends AutoPlugin 
    object autoImport
    val MyBeforeTask = taskKey[Unit]("desc...")
    val MyAfterTask = taskKey[Unit]("desc...")


    import autoImport._

    override def projectSettings: Seq[Def.Setting[_]] =
    MyBeforeTask :=
    println("This is my before test text")
    ,
    MyAfterTask :=
    println("This is my after test text")





    So I think I need things like dependsOn and in but I am not sure how to set them up.










    share|improve this question
























      0












      0








      0








      I know, I saw Run custom task automatically before/after standard task but it seems outdated. I also found SBT before/after hooks for a task but it does not have any code example.



      I am on SBT 0.13.17.



      So I want to run my task MyBeforeTask and MyAfterTask automatically after an other tasks, says Compile.



      So when you do sbt compile I would like to see:



      ...log...
      This is my before test text
      ...compile log...
      This is my after test text


      So I would need to have:



      object MyPlugin extends AutoPlugin 
      object autoImport
      val MyBeforeTask = taskKey[Unit]("desc...")
      val MyAfterTask = taskKey[Unit]("desc...")


      import autoImport._

      override def projectSettings: Seq[Def.Setting[_]] =
      MyBeforeTask :=
      println("This is my before test text")
      ,
      MyAfterTask :=
      println("This is my after test text")





      So I think I need things like dependsOn and in but I am not sure how to set them up.










      share|improve this question














      I know, I saw Run custom task automatically before/after standard task but it seems outdated. I also found SBT before/after hooks for a task but it does not have any code example.



      I am on SBT 0.13.17.



      So I want to run my task MyBeforeTask and MyAfterTask automatically after an other tasks, says Compile.



      So when you do sbt compile I would like to see:



      ...log...
      This is my before test text
      ...compile log...
      This is my after test text


      So I would need to have:



      object MyPlugin extends AutoPlugin 
      object autoImport
      val MyBeforeTask = taskKey[Unit]("desc...")
      val MyAfterTask = taskKey[Unit]("desc...")


      import autoImport._

      override def projectSettings: Seq[Def.Setting[_]] =
      MyBeforeTask :=
      println("This is my before test text")
      ,
      MyAfterTask :=
      println("This is my after test text")





      So I think I need things like dependsOn and in but I am not sure how to set them up.







      scala sbt






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Nov 14 '18 at 19:56









      WonayWonay

      394111




      394111






















          1 Answer
          1






          active

          oldest

          votes


















          1














          It is not possible to configure for a particular task to run after the given task, because that's not how the task dependencies model works - when you specify the task, its dependencies and itself will be executed, but there is no way to define an "after" dependency. However, you can simulate that with dynamic tasks.



          To run some task before another, you can use dependsOn:



          compile in Compile := (compile in Compile).dependsOn(myBeforeTask).value


          This establishes a dependency between two tasks, which ensures that myBeforeTask will be run before compile in Compile.




          Note that there is a more generic way to make multiple tasks run one after another:



          aggregateTask := Def.sequential(task1, task2, task3, task4).value


          Def.sequential relies on the dynamic tasks machinery, which sets up dependencies between tasks at runtime. However, there are some limitations to this mechanism, in particular, you cannot reference the task being defined in the list of tasks to execute, so you can't use Def.sequential to augment existing tasks:



          compile in Compile := Def.sequential(myBeforeTask, compile in Compile).value


          This definition will fail at runtime with a strange error message which basically means that you have a loop in your task dependencies graph. However, for some use cases it is extremely useful.




          To run some task after another, however, you have to resort to defining a dynamic task dependency using Def.taskDyn:



          compile in Compile := Def.taskDyn 
          val result = (compile in Compile).value
          Def.task
          val _ = myAfterTask.value
          result

          .value


          Def.taskDyn accepts a block which must return a Def.Initialize[Task[T]], which will be used to instantiate a task to be run later, after the main body of Def.taskDyn completes. This allows one to compute tasks dynamically, and establish dependencies between tasks at runtime. As I said above, however, this can result in very strange errors happening at runtime, which are usually caused by loops in the dependency graph.



          Therefore, the full example, with both "before" and "after" tasks, would look like this:



          compile in Compile := Def.taskDyn 
          val result = (compile in Compile).value
          Def.task
          val _ = myAfterTask.value
          result

          .dependsOn(myBeforeTask).value





          share|improve this answer

























          • What about doing something like compile in Compile := val r = (compile in Compile).value ; /* run after? */ ; r ? Sorry can't really do multi line in comments :/

            – Wonay
            Nov 14 '18 at 21:14







          • 1





            @Wonay, yes, indeed, this would work - it would run the original compile task before your code. This won't allow you to express your "run after" task as a real task though. That being said, maybe you can simulate that with careful Def.taskDyn application, with all potential issues dynamic tasks introduce.

            – Vladimir Matveev
            Nov 14 '18 at 21:31











          • @Wonay please see the updated answer.

            – Vladimir Matveev
            Nov 14 '18 at 21:39










          Your Answer






          StackExchange.ifUsing("editor", function ()
          StackExchange.using("externalEditor", function ()
          StackExchange.using("snippets", function ()
          StackExchange.snippets.init();
          );
          );
          , "code-snippets");

          StackExchange.ready(function()
          var channelOptions =
          tags: "".split(" "),
          id: "1"
          ;
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function()
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled)
          StackExchange.using("snippets", function()
          createEditor();
          );

          else
          createEditor();

          );

          function createEditor()
          StackExchange.prepareEditor(
          heartbeatType: 'answer',
          autoActivateHeartbeat: false,
          convertImagesToLinks: true,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: 10,
          bindNavPrevention: true,
          postfix: "",
          imageUploader:
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          ,
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          );



          );













          draft saved

          draft discarded


















          StackExchange.ready(
          function ()
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53307884%2fsbt-plugin-run-tasks-before-after-an-other-task%23new-answer', 'question_page');

          );

          Post as a guest















          Required, but never shown

























          1 Answer
          1






          active

          oldest

          votes








          1 Answer
          1






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes









          1














          It is not possible to configure for a particular task to run after the given task, because that's not how the task dependencies model works - when you specify the task, its dependencies and itself will be executed, but there is no way to define an "after" dependency. However, you can simulate that with dynamic tasks.



          To run some task before another, you can use dependsOn:



          compile in Compile := (compile in Compile).dependsOn(myBeforeTask).value


          This establishes a dependency between two tasks, which ensures that myBeforeTask will be run before compile in Compile.




          Note that there is a more generic way to make multiple tasks run one after another:



          aggregateTask := Def.sequential(task1, task2, task3, task4).value


          Def.sequential relies on the dynamic tasks machinery, which sets up dependencies between tasks at runtime. However, there are some limitations to this mechanism, in particular, you cannot reference the task being defined in the list of tasks to execute, so you can't use Def.sequential to augment existing tasks:



          compile in Compile := Def.sequential(myBeforeTask, compile in Compile).value


          This definition will fail at runtime with a strange error message which basically means that you have a loop in your task dependencies graph. However, for some use cases it is extremely useful.




          To run some task after another, however, you have to resort to defining a dynamic task dependency using Def.taskDyn:



          compile in Compile := Def.taskDyn 
          val result = (compile in Compile).value
          Def.task
          val _ = myAfterTask.value
          result

          .value


          Def.taskDyn accepts a block which must return a Def.Initialize[Task[T]], which will be used to instantiate a task to be run later, after the main body of Def.taskDyn completes. This allows one to compute tasks dynamically, and establish dependencies between tasks at runtime. As I said above, however, this can result in very strange errors happening at runtime, which are usually caused by loops in the dependency graph.



          Therefore, the full example, with both "before" and "after" tasks, would look like this:



          compile in Compile := Def.taskDyn 
          val result = (compile in Compile).value
          Def.task
          val _ = myAfterTask.value
          result

          .dependsOn(myBeforeTask).value





          share|improve this answer

























          • What about doing something like compile in Compile := val r = (compile in Compile).value ; /* run after? */ ; r ? Sorry can't really do multi line in comments :/

            – Wonay
            Nov 14 '18 at 21:14







          • 1





            @Wonay, yes, indeed, this would work - it would run the original compile task before your code. This won't allow you to express your "run after" task as a real task though. That being said, maybe you can simulate that with careful Def.taskDyn application, with all potential issues dynamic tasks introduce.

            – Vladimir Matveev
            Nov 14 '18 at 21:31











          • @Wonay please see the updated answer.

            – Vladimir Matveev
            Nov 14 '18 at 21:39















          1














          It is not possible to configure for a particular task to run after the given task, because that's not how the task dependencies model works - when you specify the task, its dependencies and itself will be executed, but there is no way to define an "after" dependency. However, you can simulate that with dynamic tasks.



          To run some task before another, you can use dependsOn:



          compile in Compile := (compile in Compile).dependsOn(myBeforeTask).value


          This establishes a dependency between two tasks, which ensures that myBeforeTask will be run before compile in Compile.




          Note that there is a more generic way to make multiple tasks run one after another:



          aggregateTask := Def.sequential(task1, task2, task3, task4).value


          Def.sequential relies on the dynamic tasks machinery, which sets up dependencies between tasks at runtime. However, there are some limitations to this mechanism, in particular, you cannot reference the task being defined in the list of tasks to execute, so you can't use Def.sequential to augment existing tasks:



          compile in Compile := Def.sequential(myBeforeTask, compile in Compile).value


          This definition will fail at runtime with a strange error message which basically means that you have a loop in your task dependencies graph. However, for some use cases it is extremely useful.




          To run some task after another, however, you have to resort to defining a dynamic task dependency using Def.taskDyn:



          compile in Compile := Def.taskDyn 
          val result = (compile in Compile).value
          Def.task
          val _ = myAfterTask.value
          result

          .value


          Def.taskDyn accepts a block which must return a Def.Initialize[Task[T]], which will be used to instantiate a task to be run later, after the main body of Def.taskDyn completes. This allows one to compute tasks dynamically, and establish dependencies between tasks at runtime. As I said above, however, this can result in very strange errors happening at runtime, which are usually caused by loops in the dependency graph.



          Therefore, the full example, with both "before" and "after" tasks, would look like this:



          compile in Compile := Def.taskDyn 
          val result = (compile in Compile).value
          Def.task
          val _ = myAfterTask.value
          result

          .dependsOn(myBeforeTask).value





          share|improve this answer

























          • What about doing something like compile in Compile := val r = (compile in Compile).value ; /* run after? */ ; r ? Sorry can't really do multi line in comments :/

            – Wonay
            Nov 14 '18 at 21:14







          • 1





            @Wonay, yes, indeed, this would work - it would run the original compile task before your code. This won't allow you to express your "run after" task as a real task though. That being said, maybe you can simulate that with careful Def.taskDyn application, with all potential issues dynamic tasks introduce.

            – Vladimir Matveev
            Nov 14 '18 at 21:31











          • @Wonay please see the updated answer.

            – Vladimir Matveev
            Nov 14 '18 at 21:39













          1












          1








          1







          It is not possible to configure for a particular task to run after the given task, because that's not how the task dependencies model works - when you specify the task, its dependencies and itself will be executed, but there is no way to define an "after" dependency. However, you can simulate that with dynamic tasks.



          To run some task before another, you can use dependsOn:



          compile in Compile := (compile in Compile).dependsOn(myBeforeTask).value


          This establishes a dependency between two tasks, which ensures that myBeforeTask will be run before compile in Compile.




          Note that there is a more generic way to make multiple tasks run one after another:



          aggregateTask := Def.sequential(task1, task2, task3, task4).value


          Def.sequential relies on the dynamic tasks machinery, which sets up dependencies between tasks at runtime. However, there are some limitations to this mechanism, in particular, you cannot reference the task being defined in the list of tasks to execute, so you can't use Def.sequential to augment existing tasks:



          compile in Compile := Def.sequential(myBeforeTask, compile in Compile).value


          This definition will fail at runtime with a strange error message which basically means that you have a loop in your task dependencies graph. However, for some use cases it is extremely useful.




          To run some task after another, however, you have to resort to defining a dynamic task dependency using Def.taskDyn:



          compile in Compile := Def.taskDyn 
          val result = (compile in Compile).value
          Def.task
          val _ = myAfterTask.value
          result

          .value


          Def.taskDyn accepts a block which must return a Def.Initialize[Task[T]], which will be used to instantiate a task to be run later, after the main body of Def.taskDyn completes. This allows one to compute tasks dynamically, and establish dependencies between tasks at runtime. As I said above, however, this can result in very strange errors happening at runtime, which are usually caused by loops in the dependency graph.



          Therefore, the full example, with both "before" and "after" tasks, would look like this:



          compile in Compile := Def.taskDyn 
          val result = (compile in Compile).value
          Def.task
          val _ = myAfterTask.value
          result

          .dependsOn(myBeforeTask).value





          share|improve this answer















          It is not possible to configure for a particular task to run after the given task, because that's not how the task dependencies model works - when you specify the task, its dependencies and itself will be executed, but there is no way to define an "after" dependency. However, you can simulate that with dynamic tasks.



          To run some task before another, you can use dependsOn:



          compile in Compile := (compile in Compile).dependsOn(myBeforeTask).value


          This establishes a dependency between two tasks, which ensures that myBeforeTask will be run before compile in Compile.




          Note that there is a more generic way to make multiple tasks run one after another:



          aggregateTask := Def.sequential(task1, task2, task3, task4).value


          Def.sequential relies on the dynamic tasks machinery, which sets up dependencies between tasks at runtime. However, there are some limitations to this mechanism, in particular, you cannot reference the task being defined in the list of tasks to execute, so you can't use Def.sequential to augment existing tasks:



          compile in Compile := Def.sequential(myBeforeTask, compile in Compile).value


          This definition will fail at runtime with a strange error message which basically means that you have a loop in your task dependencies graph. However, for some use cases it is extremely useful.




          To run some task after another, however, you have to resort to defining a dynamic task dependency using Def.taskDyn:



          compile in Compile := Def.taskDyn 
          val result = (compile in Compile).value
          Def.task
          val _ = myAfterTask.value
          result

          .value


          Def.taskDyn accepts a block which must return a Def.Initialize[Task[T]], which will be used to instantiate a task to be run later, after the main body of Def.taskDyn completes. This allows one to compute tasks dynamically, and establish dependencies between tasks at runtime. As I said above, however, this can result in very strange errors happening at runtime, which are usually caused by loops in the dependency graph.



          Therefore, the full example, with both "before" and "after" tasks, would look like this:



          compile in Compile := Def.taskDyn 
          val result = (compile in Compile).value
          Def.task
          val _ = myAfterTask.value
          result

          .dependsOn(myBeforeTask).value






          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Nov 14 '18 at 21:53

























          answered Nov 14 '18 at 21:10









          Vladimir MatveevVladimir Matveev

          70.5k15171214




          70.5k15171214












          • What about doing something like compile in Compile := val r = (compile in Compile).value ; /* run after? */ ; r ? Sorry can't really do multi line in comments :/

            – Wonay
            Nov 14 '18 at 21:14







          • 1





            @Wonay, yes, indeed, this would work - it would run the original compile task before your code. This won't allow you to express your "run after" task as a real task though. That being said, maybe you can simulate that with careful Def.taskDyn application, with all potential issues dynamic tasks introduce.

            – Vladimir Matveev
            Nov 14 '18 at 21:31











          • @Wonay please see the updated answer.

            – Vladimir Matveev
            Nov 14 '18 at 21:39

















          • What about doing something like compile in Compile := val r = (compile in Compile).value ; /* run after? */ ; r ? Sorry can't really do multi line in comments :/

            – Wonay
            Nov 14 '18 at 21:14







          • 1





            @Wonay, yes, indeed, this would work - it would run the original compile task before your code. This won't allow you to express your "run after" task as a real task though. That being said, maybe you can simulate that with careful Def.taskDyn application, with all potential issues dynamic tasks introduce.

            – Vladimir Matveev
            Nov 14 '18 at 21:31











          • @Wonay please see the updated answer.

            – Vladimir Matveev
            Nov 14 '18 at 21:39
















          What about doing something like compile in Compile := val r = (compile in Compile).value ; /* run after? */ ; r ? Sorry can't really do multi line in comments :/

          – Wonay
          Nov 14 '18 at 21:14






          What about doing something like compile in Compile := val r = (compile in Compile).value ; /* run after? */ ; r ? Sorry can't really do multi line in comments :/

          – Wonay
          Nov 14 '18 at 21:14





          1




          1





          @Wonay, yes, indeed, this would work - it would run the original compile task before your code. This won't allow you to express your "run after" task as a real task though. That being said, maybe you can simulate that with careful Def.taskDyn application, with all potential issues dynamic tasks introduce.

          – Vladimir Matveev
          Nov 14 '18 at 21:31





          @Wonay, yes, indeed, this would work - it would run the original compile task before your code. This won't allow you to express your "run after" task as a real task though. That being said, maybe you can simulate that with careful Def.taskDyn application, with all potential issues dynamic tasks introduce.

          – Vladimir Matveev
          Nov 14 '18 at 21:31













          @Wonay please see the updated answer.

          – Vladimir Matveev
          Nov 14 '18 at 21:39





          @Wonay please see the updated answer.

          – Vladimir Matveev
          Nov 14 '18 at 21:39



















          draft saved

          draft discarded
















































          Thanks for contributing an answer to Stack Overflow!


          • Please be sure to answer the question. Provide details and share your research!

          But avoid


          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.

          To learn more, see our tips on writing great answers.




          draft saved


          draft discarded














          StackExchange.ready(
          function ()
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53307884%2fsbt-plugin-run-tasks-before-after-an-other-task%23new-answer', 'question_page');

          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          這個網誌中的熱門文章

          How to read a connectionString WITH PROVIDER in .NET Core?

          In R, how to develop a multiplot heatmap.2 figure showing key labels successfully

          Museum of Modern and Contemporary Art of Trento and Rovereto