I have a Jenkins job that use maven build goals 'clean package deploy' for the master git branch. However, due to the nexus repo not allowing redeploys, if the Jenkins job runs a second time without the version changing, it will fail with the expected 400 Bad Request error:
org.apache.maven.lifecycle.LifecycleExecutionException: Failed to execute goal
org.apache.maven.plugins:maven-deploy-plugin:2.7:deploy (default-deploy)
on project common-library:
Failed to deploy artifacts: Could not transfer artifact
net.bacon.common:common-library:pom:1.2.13 from/to bacon-releases
(https://maven.bacon.com/nexus/content/repositories/releases):
Failed to transfer file:
https://maven.bacon.com/nexus/content/repositories/releases/net/bacon/common/common-library/1.2.13/common-library-1.2.13.pom.
Return code is: 400, ReasonPhrase:Bad Request.
Can anyone suggest a different strategy, whereby the deploy goal can run without making the Jenkins job fail?
what we do is automatic snapshot builds. then, the version is automatically incremented.
for release build, we use the maven release plugin and enter the version manually. you can, however, let the release plugin do the work. it will remove the "-SNAPSHOT" build, deploy, and then, for the next release version increment the last digit and append the "-SNAPSHOT" again.
for the distribution management, you can have two repos, one for snapshots and one for releases, with different redeploy settings.
We apply a "double action" solution:
Increment version
Run mvn install
Run tests
If all passed, we run mvn deploy
This way, we do not try to deploy before we know all passed and we have a unique version deployed every time.
I hope this helps.
You should make sure, that each commit on master carries its own version number on the pom file. So you won't have redeploys.
There is a good reason for rejecting the "redeploys": The content of a released version should never change.
If you can't avoid commits for the same version number on master, consider changing the chained jenkins job to "clean install" (stores the artifacts only on the local repository) and create a new job with "clean deploy" that is only started manually.
This is an issue for our group as well.
We want maven to attempt a PASSIVE deploy, so if the deploy exists at nexus then it will acceptably move on with SUCCESS ALREADY DEPLOYED, and if the deploy does not exist at nexus, it will upload and deploy with SUCCESS.
We want jenkins to deploy after it builds and passes coverage check, but how to make it so that only the un-deployed will get deployed, and the already-deployed are ignored.
Our solution was a custom script.
You can use the release candidate concept. When you start the release you add -RC1 to the version (1.1.0-RC1 for example).
With the next redeploy you are increment the RC number. When the release is finished and you want to generate a new TAG, you only delete the RC for the version. before the TAG creation
Related
I am learning Jenkins. Can someone tell me if my understanding is correct?
To build the app:
I commit my code and push my branch to my remote repository.
Jenkins sees my commit and triggers off a build (possibly using maven install).
Jenkins runs all the tests and if all pass, a war/ear is created. This artefact is pushed to nexus.
To deploy to an environment:
A deploy script in my branch contains steps to deploy the app to, say, Tomcat.
Jenkins goes to Nexus, retrieves the latest artefact (built above), and deploys this app to Tomcat.
Other steps in the deploy file shutdown and restart Tomcat as necessary, possibly testing to make sure the app started and is ready to serve requests.
Am I right in saying that a deploy doesn't need to build the latest artefact, that it uses that last one pushed to Nexus, or is a fresh one built every deploy?
It's all according to how you set up your build on Jenkins and/or git.
Jenkins can be configured to monitor your repository (repo, for short) and to kick off a build when it detects a change.
Jenkins can be configured to run a build. You provide the Maven command-line arguments; Jenkins just orchestrates the commands you give it.
Some of the steps you provide Jenkins will be shell code. This is how you can run custom shell scripts, say to access Nexus. Things don't happen by themselves; if you tell Jenkins to deploy an artifact, say by using Maven, then Jenkins will invoke the deployment command as you told it to.
It is highly irregular for an app deployment to arrogate responsibility to start, restart, or shut down your server (Tomcat). That could be done via Jenkins, sure, but it's at a higher "pay grade" than an app deployment should have. Keep it simple; if your Jenkins build is managing an app for testing and deployment, keep its focus on the app and not on the server.
Jenkins is magical, but it's not a mind reader. It will do none of the things you said unless you tell it to. That said, the process you outlined is a reasonable one, whatever tool you use to enact it. Jenkins certainly can do those things, if you set it up accordingly.
I have configured maven surefire plugin with parameter:
<configuration>
<forkedProcessTimeoutInSeconds>60</forkedProcessTimeoutInSeconds>
</configuration>
So when test's working more then 60 seconds, the surefire plugin interrupts it.
Everything works perfectly on my local machine when I use mvn test or mvn install, but when I try to build project on Jenkins it just swallows exception, writes into log [ERROR] There was a timeout or other error in the fork and continues the build. As result I get a Finished: SUCCESS message.
Question: Have anyone got this problem? Does anyone know any solution?
One important difference between default options of a maven local build and a Jenkins maven job is that locally the maven.test.failure.ignore option of the Maven Surefire Plugin is set to false (reasonably) so that test failures will also fail the build.
From official documentation:
Set this to "true" to ignore a failure during testing. Its use is NOT RECOMMENDED, but quite convenient on occasion.
However, a Maven Jenkins job will always run setting the same option to true, as such making the Maven build successful even with test failing and turn the status of the Jenkins job to UNSTABLE (and not SUCCESSFUL or FAILED, which may be a point of debate indeed).
This behavior is also documented in an official Jenkins issue ticket
Following the Jenkins Terminology, when (surefire or failsafe) tests fail, the Jenkins build status must be UNSTABLE:
<< A build is unstable if it was built successfully and one or more publishers report it unstable. For example if the JUnit publisher is configured and a test fails then the build will be marked unstable. >>
So, in a Maven Jenkins job, if a test fails:
Maven build is SUCCESSFUL
Jenkins build is UNSTABLE
Instead, in a freestyle Jenkins job executing Maven, if a test fails:
Maven build is FAILED
Jenkins build is FAILED
Possible solutions:
Change the build to a freestyle Jenkins job running maven (which may be too much work though) or
Add the -Dmaven.test.failure.ignore=false option to your build (however, you would not have UNSTABLE builds any longer).
We are using the standard git flow branching model (develop, master, release-, hotfix-, etc).
As part of our workflow, we would like to set up a "one-click" release via jenkins.
I was looking at the jgitflow-maven-plugin. Can I set up this plugin to do a one-click release from jenkins? If so, what are the configuration options?
In particular, can I do something like this?
Jenkins Job
Maven goals: release-start release-finish -Dsomething -Delse
And is there a way tell it to automatically build from the latest -SNAPSHOT version, e.g. if the version is 1.2.3-SNAPSHOT it would build release-1.2.3.
Otherwise, is there a maven plugin that builds releases according the git flow branching model (i.e. build from develop and create a new release branch named release-x.y.z).
Although this answer is one year old I'd like point out that meanwhile the jgitflow (v1.0-m5.1) works with maven batch mode.
So to release an artifact with just one command you can execute:
mvn --batch-mode jgitflow:release-start jgitflow:release-finish
You don't need to set developmentVersion and releaseVersion.
JGitFlow will use the current version minus the -SNAPSHOT part as release version. Then it increments the least significant digit and adds -SNAPSHOT again for the next development version.
Example 1.0.0-SNAPSHOT --> Release: 1.0.0, next Development version: 1.0.1-SNAPSHOT
In order to configure a single click Jenkins release job you need to configure some things regarding Git.
Under Source Code Management > Git > Additional Behaviors select
Wipe out repository & force git clone: just to make sure the workspace is clean
Checkout to specific local branch: your develop branch.
Finally, the release happens locally on your Jenkins server, so you want to push back the changes to your Git remote server.
To accomplish this, the easiest way is to add a Post-build action which executes the following bash command (the branch names may vary, I've used the JGitFlow default values):
git push origin develop master --tags
Note If Jenkins is running on Windows you either have to execute a Batch script containing the same command (sometimes this doesn't work due to SSH issues with Windows) or configure the Git Publisher Post-build action accordingly.
You can simply use the jenkins plugin M2 Release Plugin with the release goals an options
-B -DautoVersionSubmodules=true jgitflow:release-start jgitflow:release-finish
We ended up with starting the release via CLI on the client (because in Jenkins there is a bug starting the release).
git flow release start -DautoVersionSubmodules=true
If you want to use the batch mode you need to specify developmentVersion and releaseVersion.
Created a new job in Jenkins to build the release branch and use the M2 Release Plugin to release it finally:
-B jgitflow:release-finish
If you use some custom profiles, you have to pass them additional via arguments caused by a bug.
-Darguments=-Pprofile
We never found a way to get this to work via a plugin or maven goal in Jenkins.
Our solution ended up with a bash script that did git flow release start <version>, maven release process, git flow release finish <version> and other things (git pull on develop and master at very start, git push and slack notification at very end).
When I execute mvn release:perform on a parent POM, the server is responding with this error about one of the child projects (filenames redacted):
[ERROR] Failed to execute goal
org.apache.maven.plugins:maven-deploy-plugin:2.7:deploy-file
(default-cli) on project: Failed to deploy artifacts: Could not
transfer artifact from/to repository: Failed to transfer file.
Return code is: 400, ReasonPhrase: Bad Request.
However, all the files for this child project are successfully uploaded! I see a new directory (named after the release version number) and it contains all the .jar, .pom, .md5, and .sha1 files one would expect.
I don't have access to the Nexus server, but I'm wondering what might cause this and how to fix it. Is it possible that Maven is trying to upload this particular child project twice? If so, why would Maven be doing this and how can I stop it?
UPDATE: If you're having the same problem, check out the answer with the most upvotes in this post. I ran mvn help:effective-pom and found that the project in question actually had two executions of the deploy phase. Removing one of those executions solved my problem.
I encountered the same issue, releasing a maven multi-module project. An error occured the first time but the deploy goal had already contact nexus and then create the appropriate path. Assuming that a "release" repo is a write-once one, the second time I trggered it, nexus refuse to overwrite the path.
So, in such a case, you might ask your admin to delete the repo ... or create a new release.
PS : better late than never ;)
I recently tried to use maven-release-plugin since it is apparently the recommended way of building and packages releases in the Maven universe.
However I wanted to use this within Eclipse, as the rest of my development workflow is Eclipse based. I normally run Maven commands via the m2eclipse plugin provided as part of Eclipse Juno (4.2)
I noticed a few oddities when I tried to run "release:prepare" within Eclipse:
Some extra files were created in the root project directory - "pom.xml.releaseBackup" and "release.properties". Do they really belong there? Have I got the release directories set up correctly? I wouldn't really consider these temporary artifacts as part of my source code tree......
The pom.xml gets manually overwritten with the updated release number. Eclipse warns you and is happy to reload the updated version - but is this generally safe?
The prepare ultimately fails giving the error [ERROR] Failed to execute goal org.apache.maven.plugins:maven-release-plugin:2.0:prepare (default-cli) on project clisk: Failed to invoke Maven build. Error configuring command-line. Reason: Maven executable not found at: C:\Users\Mike\git\clisk\EMBEDDED\bin\mvn.bat -> [Help 1] - presumably because I am using the built-in Maven excetable provided by m2eclipse rather than the command line. I guess I could install command line maven as well.... but is that sensible or will it just cause more problems?
Given these kind of issues, Is there a way to get maven-release-plugin to work smoothly within Eclipse, or should I just give up and continue to do releases manually?
I have been using release plugin, but only from command line.
Re. 1. The backup files that release plugin creates are needed if something goes wrong in time of preparing the release. You can always rollback the prepared release using release:rollback command. When you do release:perform they will be deleted.
Re. 2. The plugin changes the version number from snapshot version for example: 0.0.1-SNAPSHOT: to release version: 0.0.1. Then after release:perform release version is moved to the maven repository and release plugin changes version again to 0.0.2-SNAPSHOT. Now you can use you full released (tested) version in your testing or production enviornment and snapshot version for developping purposes.
Re. 3. I don't know what is causing the problem, but I don't see the problem by using release plugin from command line.
Also mvn 3.3.3 installs a mvn.cmd file, instead of a mvn.bat file in Windows.
You should copy mvn.cmd to mvn.bat
Well i know this link is OLD , but to help some on who reffers this link for the issue 3.
Install maven separately on to local Box and give the path of the installation under Windows->Preferences--> maven--> Installation. Also you have to define the same in the run configuration within the Eclipse.
Attached is a link that explains the same.
http://maven.40175.n5.nabble.com/Build-Failure-prepare-release-td510949.html
You might be able to overcome the error you mention by installing command line Maven and configure Eclipse to use that rather than the embedded one by choosing Window -> Preferences -> Maven -> Installations, but I agree with the advice of making your releases outside Eclipse.