Adding custom command to gradle script - java

I'm using the shadowJar plugin for Gradle (4.2.1) to build the so-called fatJar or uberJar. This works as expected but I would like to to add some actions after the building is done. More precisely, I'd like to make the resulting file executable (in Unix terms, i.e. chmod +x) and then copy it to a certain directory. I've googled a lot and I know that both task are possible. I'd like to know whether I should write a script (task) that runs shadowJar and then does what I want, or I should change the shadowJar itself to embed the operations I need.

I think a good criteria to decide about such situation is to ask yourself if the new features are really part of the responsibility of the shoadowJar. If the answer is no, then it would be better to (as you mentioned) have another task that runs on top of that. By doing so you can reuse the shadowJar in much more different scenarios by combining it to other tasks. If you define the new one to be dependent on the shadowJar, then you would be sure that you can still call shadowJar task individually while calling the new task would always trigger the shadowJar. Your new task would be something like this:
task afterShadowJar (dependesOn: 'shadowJar') {
// manipulate file permissions, etc.
}

Related

Design Question - Gradle plugin for release packaging?

gradle newbie here,
I have began to implement a small gradle plugin. The goal of the plugin is to create a release zip for projects, with the intention of using across a couple of different projects.
Each project has a yaml file with a zipping structure loosely as such;
---
zip:
task:
- name:
zip:
task:
- name:
- name:
- name:
zip denotes that a given working directory should be zipped at this point
task denotes the name of a gradle task that should be executed preparing a particular directory in preparation of being zipped
The best pro that comes to mind is, with this approach I can reuse gradle tasks between projects and if needed include custom gradle tasks at a per project level and reference them here in the yml. Using a yaml also assists with creating release zips making them easy to build and read..
I have a manager gradle task that is called at runtime from cli ./gradlew myReleaseZipTask ( I think I achieve this by making it an exec task and putting the logic into the exec action). This manager task is responsible for parsing the yaml file into DTOs. Traversing from the lowest task I traverse up the graph executing each gradle task as defined preparing files into a specified directory and then once all tasks are completed zip the current workspace. Continue up the graph
Im halfway through my implementation and Im a little bit worried im abusing gradle in a way that its not intended. Some of my main concerns are;
I have one task that is orchestrating many other gradle tasks, I either find or create a task on the fly, then retrieve its actions and execute them from inside my manager task, this isnt something I see often in gradle examples. Everyone seems to have very static linear task dependencies and dont "reflectively" create or find tasks to execute..
When dealing with a task entry from the yml my manager task tries to lookup the gradle task by name, if it doesnt exist, it tries to create the task. Given a task is created/found I set the properties from the YmlTaskDTO onto the task and then call the task to execute. Will I run into issues with reusing the same tasks with different properties? For example if I have something like;
zip:
task:
- name: taskA
argA: A
argB: B
- name: taskA
argA: A
argB: C
Could anyone give me some feedback on my design and if its inline with correct standards of gradle use? Please raise any concerns you may have!
I think you have realised some of the answers your self.
The one guidance here is that 'plugins' are to create a new functionalities, that are not available in native gradle.
What you are doing here is composition of existing tasks in a specific order for your use case. Plugin for this is an overkill.
What you are looking for can be achieved with simple tasks and task chaining.

How do I make an alias for a Gradle task?

As a part of a TDD workflow, I want to be able to check if my Java codebase compiles, but not if the tests pass.
Currently, if I run gradle build it runs the compile tasks (for source and tests) and then also executes the test task (and returns a non-zero exit code since the tests fail).
So I find that I have to run gradle build -x test to exclude the test task, and get a successful zero exit code.
What do I add to my build.gradle to define a new task, say compile that is an alias for build x test?
So far I have this, but it doesn't seem like dependsOn takes any arguments to customize the build task I want to execute:
task compile {
dependsOn build
}
I've been reading the docs here, I see different kinds of dependency chaining mechanisms, but not to disable/exclude a particular task. How does the -x flag even work then? I assumed there would be a way to control it programmatically too.
Thanks to Bjørn Vester's answer and reading the docs, I have implemented my task as follows:
task compile {
dependsOn classes
dependsOn testClasses
}
There are lots of different tasks you can run individually. For instance:
gradle classes: Will compile your "main" code.
gradle testClasses: Will compile your "main" code as well as test code.
gradle jar: Will compile your "main" code and assemble it into a jar.
None of the above will run your unit tests. On the other hand, the build task depends on all of the above, as well as the test task and more.
In general, if you like to run a particular set of tasks, you do that by defining a new task and then make dependencies to those other tasks you like to run with it. You tried that already, but instead of build you should have used something like compileJava or classes whatever other tasks you need. But always check if there isn't one already that satisfies your needs, like there are in this case. You can read about what tasks are available in Java projects in the documentation for the Gradle java plugin.

File dependency Gradle

I am a gmake user transitioning to Gradle. I have a multi-project structure, where one sub-project is a Java project and the other a home-brewed language. The home-brewed language does not use any Gradle plugins. Now I want to add a task that runs a Java program to generate XML when any of my home-brewed source files have been modified. In make, I would just declare a dependency on inputFile.mine or *.mine next to the target name, but I could not easily find how to do this basic thing with Gradle. Currently, I force the task to always execute using the potentially ugly work-around below. I want to replace this with some dependsOn *.mine . The Gradle user guide has a whole chapter dedicated to explaining different ways of specifying files, but I did not see how to declare a dependency.
task generateXML(type: Exec) {
generateXML.getOutputs().upToDateWhen({false}) // Force it to execute always
executable("java.exe")
args("-jar", "resources/generateXml.jar", "src/inputFile.mine")
}
Thanks for helping a newbie out.
You can define task inputs and outputs in Gradle.
For example:
task generateXML(type: Exec) {
inputs.file ("src/inputFile.mine")
executable("java.exe")
args("-jar", "resources/generateXml.jar", "src/inputFile.mine")
}
See https://docs.gradle.org/current/userguide/more_about_tasks.html and https://docs.gradle.org/current/javadoc/org/gradle/api/tasks/TaskInputs.html for more information.
Side note: When you run your build with -i, Gradle will tell you what has happened during the up-to-date check.

Tuning Gradle startScripts in Application Plugin

I using Gradle with the Application plugin.
I am trying to tune the the startScripts task. I don't think that the tuning demands a lot of changes, so I would like to change the standard task:
The complete distribution includes its own JRE so I want the script to refer to that library instead of using JAVA_HOME
If possible, remove the UNIX start script. I only need the Windows script.
If possible I prefer understanding what variables in the task to change rather rewriting the task from scratch.
My question is how to do it. Looking at the documentation I saw accessors only for applicationName, classpath, defaultJvmOpts, exitEnvironmentVar, mainClassName, optsEnvironmentVar, outputDir, which all look irrelevant for me.
Can you guide me to a documentation describing how to do this?
To remove a UNIX script, you can configure the startScripts task as:
startScripts {
doLast {
delete unixScript
}
}
As for the script content, not really sure, whether it is possible to do with the custom script generator, which could be used in startScripts as the WindowsStartScriptGenerator. But any way, you are able to modify the content of the start scripts in doLast, just referring to it as windowsScript.text:
startScripts {
doLast {
windowsScript.text = windowsScript.text.replace("set JAVA_EXE=%JAVA_HOME%/bin/java.exe",
"set JAVA_EXE=../relative/path/to/java/bin/java.exe")
}
}

how to alias a task in buildr

I might be doing something wrong, cuz I'm using buildr for not so long, so all comments are welcome.
My project structure is:
define :proj do
define :web do
task :run do
# runs the web part of the project in a jetty
end
end
end
now if I want to start my project I have to type
buildr proj:web:run
I'd like to type simply
buildr run
instead. How do I achieve that?
At the top level of your buildfile (i.e., outside of any defines), add
task :run => 'proj:web:run'
This defines a task named run whose sole prerequisite is the proj:web:run task.
You can also make the task a 'local task',
Project.local_task 'run'
which means that whenever you are inside the web directory, typing buildr run will look for a locally-scoped that of that name.
Note that Buildr 1.4.3 added a standard run task so you typically wouldn't need to make run a local task; see http://buildr.apache.org/more_stuff.html#run for details.

Categories

Resources