How to stage sub-project in Play Activator from bash script? - bash

In my play project I have a separate akka module that I run stand-alone.
If I want to stage this module I usually do the following:
./activator
project akkaProject
compile
stage
I can stage the main project from a script using ./activator compile && ./activator stage, but I can't find the correct syntax to do this for a sub-project (without going inside the activator).

tl;dr activator akkaProject/stage
You need to scope the stage task to akkaProject project and since stage depends on compile you don't need to execute both -- let sbt do it for you.

Related

Why is there a difference between ./gradlew clean build and ./gradlew clean :build

I have the following situation:
I have a project with several subprojects. Today I tried to build the projects with gradle via command line.
The build was successful when I executed ./gradlew clean :build, but not with ./gradlew clean build. It causes different errors, depending on which subprojects are activated. Why is that? Shouldn't it be the same?
Both commands are executed directly after each other, without changes in the code, and from the same directory (the base-directory, where settings.gradle is located.
The gradle-refresh of Intellij works, the build is successful (but fails on our build server, if that is relevant).
According to the documentation https://docs.gradle.org/current/userguide/command_line_interface.html#executing_tasks_in_multi_project_builds I assumed that it would do the same, since no subproject is specified, and the build task is executed for all submodules. There is no folder called build in the root project, so this should not cause confusion. Am I interpreting it wrong?
I searched online, however, I could not find the result, since : is is not recognized by most search engines, and colon leads to not relevant results like What is the colon operator in Gradle?.
The gradle version is 4.10.2
If you need more information, please let me know.
There is a difference between ./gradlew clean :build and ./gradlew clean build, that's why you have a different behavior: in the first case you are using qualified task name, in the other case you are using simple task name. These documentations here and here explain these two approaches for executing tasks:
Using simple task name ( ./gradlew test) :
The first approach is similar to the single-project use case, but Gradle works slightly differently in the case of a multi-project build. The command gradle test will execute the test task in any subprojects, relative to the current working directory, that have that task. So if you run the command from the root project directory, you’ll run test in api, shared, services:shared and services:webservice. If you run the command from the services project directory, you’ll only execute the task in services:shared and services:webservice.
=> so executing ./gradlew build in the root project directory will trigger execution of build task for root project and all subprojects
Using qualified task name ( ./gradlew :build)
For more control over what gets executed, use qualified names (the second approach mentioned). These are paths just like directory paths, but use ‘:’ instead of ‘/’ or ‘\’. If the path begins with a ‘:’, then the path is resolved relative to the root project. In other words, the leading ‘:’ represents the root project itself. All other colons are path separators.
=> executing ./gradlew :build , you will execute "only" the build task for rootProject
As I said in comment, you migth have some issues in one or more of your subproject, but you will not see these errors if you execute only Root project build ( ./gradlew :build )

How to control the order of child project Gradle tasks from root build?

I have a Gradle project with two subprojects:
backend
frontend
I want to create a task in the parent project called stage which executes :backend:build but only after running :frontend:clean and :backend:clean.
I tried this but the mustRunAfter is ignored and the cleaning happens at the end of the build instead. What is wrong with it?
task stage(dependsOn: [':frontend:clean', ':backend:clean', ':backend:build'])
task(":backend:build").mustRunAfter(":frontend:clean", ":backend:clean")
I also tried replacing the second line with:
project("backend").build.mustRunAfter(":frontend:clean, ":backend:clean")
but still no luck.
I am still not sure why non of my tries work but here is a working approach:
task stage(dependsOn: [':frontend:clean', ':backend:clean', ':backend:build'])
tasks.getByPath(":backend:build").mustRunAfter(":frontend:clean", ":backend:clean")

Conditionally ordering tasks in Gradle

Consider a Gradle plugin that adds three tasks to a project - a buildZip task to create a distributable zip of the project, a publishZip task to publish that zip to a shared repository, and a cleanZip task to clean up any local version of the zip. For local development, cleanZip buildZip will be used frequently, but the automated build system will be running buildZip publishZip cleanZip.
One of the projects in which this plugin is being used wants to run their build using Gradle's parallel flag to allow the different parts of the project to be built in parallel. Unfortunately, this runs into a problem with the zip tasks - buildZip depends on the project actually building, but cleanZip doesn't have any dependencies so it can run right away, leading to the automated build system not being able to clean up.
Declaring any dependencies between these tasks isn't a good idea because they should be able to be run separately. Also, I can't specify mustRunAfter (at least between buildZip and cleanZip) because sometimes clean should be first and sometimes build should be first.
How can I tell Gradle what order to run these tasks in, in a way that will be honored by --parallel and isn't hardcoded to have a particular one always run before the other?
What you can do is: detect if gradle is run with --parallel and based on this configure dependencies between tasks appropriately. It can be done in the following way:
println project.gradle.startParameter.parallelProjectExecutionEnabled

Run all microservices in a multi-project gradle build

I have a multi-project gradle build that's roughly set up like this:
RootProject
- ServiceA
- ServiceB
- ServiceC
- UI
Each of these subprojects is using the Spark framework and runs an embedded web server. It's basically a microservices setup, so they all need to be up and running for the system as a whole to work.
They each have a task defined like this:
task runApp(type: JavaExec) {
main = 'App'
classpath = sourceSets.main.runtimeClasspath
}
I know I can manually start each service either through my IDE or by opening a different terminal for each sub-project and running gradlew ServiceA:runApp, but what I'd like to do is create a runSystem task at the root level that will fire up everything to make it easy to run the whole system during development.
How can I do this with Gradle?
If you run a task on the root project, Gradle invokes the same task (if it exists) on all the subprojects. Just execute runApp from the root folder.
In your case however, your runApp task might not exit because it starts a server, so execution will not move on to the next project. You can either enable parallel execution, or modify your tasks to run your server tasks in the background (using ProcessBuilder)

How to make gradle build script constants available in the built code?

I am building and running some unit tests from within a gradle build script. The tests need to access some resources located in gradle_project_dir/src/test/resources/fixtures which in gradle.build logic can be expressed as
apply plugin: 'java'
// ...
File fixturesDir = new File(sourceSets.test.resources.srcDirs[0], "fixtures")
What is the best way of pointing the test source to the file as seen in build.gradle?
I want to avoid hard-coding the path in the tests to keep them DRY.
The cleanest solution that currently comes to my mind is to make the gradle build script first build some .jar with BuildConstants class or similar which will contain the fixturesDir file and make the tests source depend on it.
Another option is to make both the build script and the tests depend on some external .jar (possibly built with yet another gradle build script).
Something tells me there should be a simpler way, though.

Resources