5

Take this basic build pipeline (with gradle tasks):

  1. Compile/Run Unit tests (gradle clean build)
  2. Integration tests (gradle integrationTest)
  3. Acceptance tests (gradle acceptanceTest)
  4. Deploy (gradle myCustomDeployTask)

According to Jez Humble's "Continuous Delivery" book, you should only build your binaries once. So in the above theoretical pipeline, in step 1 we clean, compile, and build the WAR, in step 2 we run the integration tests (using the compiled code from step 1), in step 3 we run the acceptance tests (using the compiled code from step 1), and in step 4 we deploy the WAR (that was built in step 1). So far so good.

I'm trying to implement this pipeline in Jenkins. Because each job has it's own workspace, steps 2, 3, & 4 end up recompiling the code and building the WAR, which violates the "Continuous Delivery" mantra of only building your binaries once.

To combat this, I used the "Clone Workspace SCM" Jenkins plugin, which will zip up the workspace from the first build and be the source of the workspace for builds 2, 3, & 4. However, gradle still recompiles the code in each step because it apparently uses the absolute path of the files to determine if a task needs to be executed. Since the plugin moved the files to a new workspace, the absolute path changed, which makes gradle think it needs to start from the beginning rather than executing an incremental build.

Now we could share workspaces in Jenkins, but that's frowned upon as well because of the possibility of two jobs running against the shared workspace.

So how does one implement the above pipeline using Jenkins and Gradle while adhering to the best practices of Continuous Delivery, Jenkins, and Gradle?

smgeorge99
  • 51
  • 1
  • 2

2 Answers2

0

First make sure that the later targets (integrationTest etc) don't depend on compile. Next, publish the war file generated in the first job as a jenkins artifact. Then use something like the copy artifact plugin to copy the war file over to your target workspace.

ottodidakt
  • 3,631
  • 4
  • 28
  • 34
  • But integrationTest is a Test task, and Test tasks depend on compile. – smgeorge99 Jul 17 '13 at 11:47
  • 1
    Bagheera's point is correct too. gradle integrationTest -x build -x clean – AKS Sep 11 '13 at 02:41
  • This is a valid answer given the circumstances, but wouldn't it be nice if the `gradle compile` task looked in Artifactory for the Jar and only compiled the code if the Jar was not found? – Taylor Nov 19 '15 at 00:07
0

I haven't tried it, but you could try adding the following to your project:

build.onlyIf { ! Boolean.getBoolean('skip.build') }

Run gradle with the -Dskip.build=true argument and the build tasks will be skipped.

Take a look at the Skipping Tasks section in the gradle docs.

This is similar to an answer in this Gradle build without tests question.

Community
  • 1
  • 1