How to set name of the artifacts produced from Gradle to values passed from Jenkins pipeline - gradle

I am trying to setup a Jenkins pipeline to trigger builds using gradle for multiple environments.My requirement is that the artifacts produced when I run gradlew clean build should produce artifacts with name indicating the environment for which the pipeline was run. Example my-application-dev.jar
The value of the environment would be selected by the user when build will be triggered.
What is the optimal way to achieve this ? Does build allow to configure any such property via command line or do I need to define a task in my build.gradle and define properties within that task for which I will pass value from command line

There are basically two ways.
The first one is to pass these naming-relevant pieces of information to the gradlew process, e.g. via -D or -P properties.
Then you need the Gradle build to be aware of these parameters and craft the artifact names it produces accordingly.
The second one is arguably better and more contained. You simply rename the artifacts produced by the gradlew command after it completes, in the Jenkinsfile. This works well if the pipeline decides what to do with these artifacts (e.g. publish to a repository) as opposed to the gradle script doing it (in which case you would most likely be better off using the first method).

Related

Pass a file as a property while calling a maven goal in Jenkins v2.263.1

I am migrating all my jobs from Jenkins v1.651.3 to Jenkins v2.263.1.
Currently I am passing a file stored in my Linux server as a property under Invoke top-level maven targets build step in Jenkins.
e.g. property.a=/home/user1/props/a.properties and property.b=/home/user1/props/b.properties
In Jenkins v2.263.1, I am running all my jobs in a docker container which is created dynamically.
Where and how can I store this file so that I can pass this as a property to maven build like -Dproperty.a=/home/user1/props/a.properties and -Dproperty.b=/home/user1/props/b.properties
I tried adding these files in Managed Files section under Manage Jenkins option and passing these as -Dproperty.a=a.properties to maven build through Jenkinsfile, however, it did not work. Not sure if it's the right way.
Please let me now if there's a way to handle this.
Thanks in advance!

How can I configure Gradle google-java-format plugin to run goJF in the build step?

We wired https://github.com/sherter/google-java-format-gradle-plugin into our project per the readme.
We also wired in a pre-commit hook to run the plugin before committing, which ensures that all of the code in a changelist is formatted before pushing it, which avoids errors in Jenkins when we run the verGJF task.
But we have to keep remembering to run goJF locally before running ./gradlew build, or the build fails with formatting errors.
We worked around this by adding the https://plugins.jetbrains.com/plugin/8527-google-java-format and https://plugins.jetbrains.com/plugin/7642-save-actions plugins for IntelliJ, enabling the google-java-format plugin, and configuring the save-actions plugin to format on save.
But that's a lot of extra configuration a developer has to remember to go through, plus it means they can't format code the way they want while working on it, and only have it be reformatted at the point of build or commit.
We'd prefer an all-Gradle solution, so that the goJF task is run before the build task (and before the verGJF task, which is already bound to the build task by the google-java-format Gradle plugin).
We couldn't figure out how to do that. Does someone else know?
It sounds like you want to essentially always ensure that the code is properly formatted before the verifyGoogleJavaFormat task is run (and could complain). In that case, I’d simply make the googleJavaFormat task a dependency of the verifyGoogleJavaFormat task. In your build.gradle file, after you have applied the google-java-format plugin, simply add the following:
verifyGoogleJavaFormat.dependsOn(tasks.googleJavaFormat)
Alternatively, if you really only want to run the code formatter when the build task is run (as opposed to when the verifyGoogleJavaFormat task is run only), you could add this instead:
build.dependsOn(tasks.googleJavaFormat)
verifyGoogleJavaFormat.mustRunAfter(tasks.googleJavaFormat)

Set task properties (or command line args) using Gradle Tooling API

I want to use the Gradle Tooling API to invoke Gradle from an Eclipse plugin through the Buildship plug-ins. I am able to run basic tasks without problems.
One of my use cases is to execute the gradle init task in a new project folder, but to work non-interactively I have to pass the --type command line argument (or set the type property) on the init task. I can't find any way in the tooling API to set the properties of a task or to pass a task-specific command line argument.
I have tried BuildLauncher.addArgument("--type", "plain") but this is interpreted as an argument to Gradle itself, which is invalid.
How can I pass the --type plain argument to the init task?
After reading the docs here, I discovered you can set the task arguments via the Gradle command line build arguments. The important bit in the docs is:
Also, the task names configured by BuildLauncher.forTasks(String...) can be overridden if you happen to specify other tasks via the build arguments.
In my case I wanted to run gradle tasks --all via the tooling api. To get this working, I don't specify the task to run via forTasks(), I simply do not call that method. I set the task to run as part of the arguments via withArguments(). (In this case the arguments will be tasks --all).
I assume this should work the same for the init task.

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

Get Artifactory artifact by Jenkins build number

I'm investigating a Maven/Jenkins/Artifactory set up as a possible solution for a CI/Release process.
I have a job in Jenkins - call it MYJOB - that builds and deploys an artifact to Artifactory. Now, I want another job that I can run manually that will copy the artifact of a particular build of MYJOB from Artifactory and put it somewhere (not too bothered where right now, but eventually it'll be another server).
For example, let's say build #123 went green, and now my QA team want to deploy the built artifact to their environment for further testing (the idea being to keep this artifact intact and unchanged throughout the testing process, before marking it as releasable). I want them to be able to enter '123' into Jenkins as a job parameter and then kick off the build.
So, I figure I need a free-style job that uses a script to do this.
My question is: How can I pass the number of a previous MYJOB build to the job, so that it will get the correct artifact from artifactory?
Alternative methods of achieving my goal are welcomed :)
So I got it working. I put the following code in the Build Step section of a Jenkins Freestyle Build Configuration after defining a parameter called 'REQ_BUILD_NUMBER':
SOMETHING=$(curl "http://MYARTIFACTORYLOCATION/artifactory/api/search/prop?build.number=$REQ_BUILD_NUMBER" | jq --raw-output '.results[0].uri')
echo $SOMETHING
SOMETHING_ELSE=$(curl $SOMETHING | jq --raw-output '.downloadUri')
echo $SOMETHING_ELSE
wget -N --directory-prefix=/var/lib/jenkins/artifacts/ $SOMETHING_ELSE
(NB: I'm barely competent at shell scripting. I'm sure it can be done in a better way)
EDIT: This requires installing 'jq' for the command line.
Create a Parameterized build for the second job. The QA team can put the build number when they start the build. This build number will be available as an environment variable which can be accessed in the scripts which can then retrieve the packages from the repository.

Resources