Run all microservices in a multi-project gradle build - gradle

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)

Related

Gradle: Making JavaExec tasks incremental whilst debugging

I am working on a gradle project where I have a JavaExec task which runs as part of the build. When running the task normally it is incremental, i.e when the inputs/outputs haven't changed the task is skipped. As the project is built with gradle, when I run my application it builds the required modules before launching.
This works fine when using the standard 'Run' (I am using IntelliJ as my IDE), however if I launch it using 'Debug' (with the same run configuration), the JavaExec task always rebuilds, as the randomly assigned 'address' property in the jvmArgs has changed, despite no other changes to the inputs/outputs.
This turns the usual ~5s launch time (when all tasks are up-to-date) into 1min+, as it reruns the task.
Is there any way to force the address of the jvm that the child process uses, in order to retain the benefit of the incremental builds?
I have tried:
debugOptions closure, eg:
debugOptions {
enabled = true
port = 12995
server = true
suspend = false
}
Explicitly settings the jvmArgs, eg:
jvmArgs '-agentlib:jdwp=transport=dt_socket,server=n,suspend=y,address=12995'

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

Calling Gradle commands and tasks with parameters from Gradle Task

I have a current setup in my build.gradle that I'm trying to understand. I need a number of tasks to go off in a very specific order and execute all with one task call. The setup I want looks like this:
1.) Run liquibase changeset into predefined database
2.) Run a number of tests against database
3.) Rollback all changes made with the previous changeset
I want the database in a 'clean' state every time I test it. It should have only the changes I expect and nothing else. The liquibase is set up with the Gradle plugin for it and the changeset is applied/updated. However, I don't want to call the command manually. This will be something that needs to run in continuous integration, so I need to script it so I simply have our CI call one task and it then runs each task, in order, until the end. I'm unsure of how to call the Gradle command-line task from inside of itself (ie inside the build.gradle file) and then also pass parameters to it (since I'll need to call some type of rollback command task to get the database to be what it was before calling the update).
Right now, all I'm doing is calling the command line tasks like this:
$ gradle update
$ gradle test
$ gradle rollbackToDate -PliquibaseCommandValue=2016-05-25
Again, I can't call them by the command line alone. I need a custom task inside Gradle so that I could just call something like:
$ gradle runDatabaseTests
...And I would have it do everything I expect.
There is no gradle way to invoke/call a task from another task directly. What you can do instead is to use dependsOn or finalizedBy to setup task dependencies which will force the prereq tasks to run first.
If you declare a task:
task runDatabaseTests(dependsOn: [update, test, rollbackToDate]) << {
println "I depend on update, test and rollbackToDate"
}
when you call
gradle runDatabaseTests -PliquibaseCommandValue=2016-05-25
it will force update, test and rollbackToDate first. You can control the order in which they're run, if you care about that, by using mustRunAfter and/or shouldRunAfter

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

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.

Resources