Jenkins release automation - maven

Is there a way to configure a single Jenkins job to perform the release of each newer version of my application?
i.e, I would like to know in detail if it's possible to do the following tasks without any human intervention. I'm using SVN as well as Artifactory.
Branch from the tag to be released
Change the snapshot versions in pom files to release versions (for each dependency defined in pom)
Take release build (EAR)
Deploy it in Weblogic instance.
Prepare release note
Tag the release
Thanks in advance.

It can be fully automated using Multijob plugin (Also with a regular single job, but using Multijob it will be easier and you can use Maven targets instead of some manual shell scripting ).
The workflow starts with:
commit and push to git
hook in git should trigger a job by http POST, so u need to configure your job to accept remote triggering. You can pass the branch name as parameter
job started, cloning the branch (git plugin)
start Maven project to mvn clean install and check unit tests (optional)
start Maven project to mvn release:prepare and mvn release:perform to omit the SNAPSHOT from pom.xml
tag the branch (using shell block and simple git commands)
merge to master branch (optionally)
start Maven project to mvn deploy to deploy to weblogic (weblogic should be configured in ~/.m2/settings.xml as the repository for deploying the artifacts
NOTE: all tasks can be also in 1 job with some shell scripting. the best practices is to use plugins but sometimes you will find it easier to use shell scripting for some tasks.

Related

How to split maven tasks between tasks and pipelines without running redundant maven tasks

I'm trying to set up a deployment pipeline using GoCD as follows:
Compile, test and deploy to Maven repo
Check out source code from SVN
Run mvn clean compile test install
Run mvn deploy to deploy the WAR artifact to Sonatype repo
Deploy to Tomcat server
Retrieve WAR artifact from Sonatype repo
Run mvn tomcat7:redeploy to deploy it to the Tomcat instance I have running
The thing is, I can't seem to split 1.2 and 1.3 (for example) without having to rerun the whole the entire source code checkout again in 1.3. This seems redundant to me as I had already gotten it up to the package stage and should be able to just continue to run from there.
Between 1.3 and 2.2, I can see that it can retrieve the WAR artifact from Sonatype, but I can't do much with it with maven because there's just no pom.xml for me to execute the maven task with. Of course, I can just add the source code material and run the entire mvn package tomcat7:redeploy cycle again, but I'm pretty sure that's not what this was designed for initially.
I can also write a shell script and ask Go to run it to copy the WAR file to the right location, but again, I could have done everything in one maven pass and save myself some effort but that would just reduce the entire pipeline to a single box which isn't much help to help visualize the deployment pipeline.
Can I get some advice on how I should be designing this pipeline if I wanted to split a maven task flow into different Go tasks / pipelines?
Thanks
Wong

Jenkins & Github, how to append a version number?

We have 2 branches in github,
master
release
In our jenkins we have a job for each of these branches.
We want to increment a version number programmatically for release each time jenkins builds the release. We want also to increment the version number in the github release branch. Can you give me some directions on how to do it and what jenkin plugins i need? Thanks
This can be performed using a simple command:
mvn release:prepare release:perform --batch-mode
Explanation:
release:prepare
Prepare for a release in SCM. Steps through several phases to ensure the POM is ready to be released and then prepares SCM to eventually contain a tagged version of the release and a record in the local copy of the parameters used. It will update your version number from e.g. "1.0.1-SNAPSHOT" to "1.0.1" and commit it to the tag. Also working version will be incremented and updated to "-SNAPSHOT" again, e.g. "1.0.2-SNAPSHOT".
This can be followed by a call to release:perform. For more info see example
release:perform
Perform a release from SCM, either from a specified tag, or the tag representing the previous release in the working copy created by release:prepare. For more info see example
--batch-mode allows a non-interactive script executeion. For details please read about maven-release-plugin
Use the maven release plugin to handle incrementing the version number. At that point all you have to do is have the Jenkins build run maven with the release plugin goals.
Here is a good article on it.
http://www.vineetmanohar.com/2009/10/how-to-automate-project-versioning-and-release-with-maven/
With that all you have to do in Jenkins is have it run the following command on the checked out repository.
mvn release:prepare release:perform -B

Releasing from Nexus staging repository via Jenkins/Maven

I have a Java project. Some parts are jar files, some are war files. I also have Jenkins and Nexus Pro, whereby when a developer on the team commits to SVN, the Jenkins build automatically kicks off.
Using the Maven versions plugin, I am able to mvn versions:set -DnewVersion=1.0.$SVN_REVISION as a pre-build step, and then mvn clean test deploy. At the end of this process, I've got a my-artifact-1.0.1234.jar uploaded to my Nexus Pro Staging Repository.
Since we're working in a CI-type of environment, we might have a hundred (or more) staging builds. When the time is right, the QA team wants to promote a certain build to a "later" environment (think QA, or SIT, or whatever. Environments are more of a locked-down state here.)
The workflow that I want to have happen is this:
Someone decides that Build 1.0.1357 should be Promoted to QA
They go into Jenkins, go to the "Promote to QA" job
They're presented with a list of all possible builds in the Nexus Staging Repository in a drop-down. They select one, and click the "Run" button.
That artifact is "released" from Nexus Staging to Nexus Releases, and further deployed to the QA environment. (I'm not as concerned about the "and deployed to QA" part -- I know how to do that already. It's included here for completeness-of-my-story sake.)
I already know that I can do this from the command-line, and it's working:
mvn nexus-staging:rc-list -DserverId=nexus -DnexusUrl=http://my.nexus.ip:8081/nexus
mvn nexus-staging:rc-release -DserverId=nexus -DnexusUrl=http://my.nexus.ip:8081/nexus -DstagingRepositoryId=abcd-1000 -Ddescription="Release from CLI."
The problem I'm having is that you have to specify the stagingRepositoryId on the command-line. How might I go about accomplishing this?
What I was doing is parsing the output of
mvn nexus-staging:rc-list -DserverId=nexus -DnexusUrl=http://my.nexus.ip:8081/nexus
and then just match the needed repository with your specifique logic. Using python for me was the best solution (but you can do it on your own with any language):
output = subprocess.check_output("mvn nexus-staging:rc-list -DserverId=nexus -DnexusUrl=http://my.nexus.ip:8081/nexus")
for line in output.split('\n'):
if "repo" in line:
stagingRepositoryId = "repo-" + line[8:23]
Considering output as
[INFO] repo_qa-3514 OPEN Implicitly created (auto staging).
[INFO] repo_qa-3518 Implicitly created (auto staging).
[INFO] repo_qa-3521 OPEN Implicitly created (auto staging).
[INFO] repo-2011 OPEN Implicitly created (auto staging).
You will run the second command after parsing as:
mvn nexus-staging:rc-release -DserverId=nexus -DnexusUrl=http://my.nexus.ip:8081/nexus -DstagingRepositoryId=repo-2011 -Ddescription="Release from CLI."
I think what you are trying to do can be achieved readily by using SNAPSHOT and release repository.
So you do your normal development in a SNAPSHOT build and once you are ready for testing, you can create a tag build which removes SNAPSHOT from version in POM. All this can be achieved using jenkins and Nexus.
Also you dont need SVN revision number in your version, instead an incremental build number will be sufficient which can be managed via release plugin.
So to summarise:
Lets say you are working on release 1.0.
So you take a initial branch with pom version as 1.0-0-SNAPSHOT . Here 1.0 represents release number, '-0' represents next tag build number which we plan to deploy.
Now once you are ready for deployment or want your QA team to test. You run a job or a script with maven release plugin to create a tag. A tag build will be created with version 1.0-0 [Snapshot is removed so it will go to release repository] and uploaded to repository also version in branch will be incremented to 1.0-1-SNAPSHOT [So now changes in branch will be made to release and deploy 1.0-1 if any changes are needed]
All the above steps are automated using Maven release plugin and run via jenkins job.
I have the above setup for my work.
OP stated that 'SNAPSHOT' is not in picture.
In that case this post answers the query : automate deployment to sonatype's oss maven repository [Look at the second answer]

Can I run integration tests from Mvn (Failsafe Plugin) against different versions of a branch easily?

Say my mvn Project has had a major version release.
So trunk is version 2, and I have a branch with Version 1. I want to allow developers to freely edit tests on trunk, But I would also like to maintain backwards compatibility from version 2 to 1. Is there an easy way to run version 1 branch integration tests against version 2 source code. I was thinking of compiling and moving the test jar (not sure if this would work), but that seems ugly.... Just to clarify, unit test classes are denoted with Test.java where as integration tests are denoted with IT.java. I only want to run the integration-tests
I would preferably be able to run something like
mvn integration-tests -Dfailsafe.plugin.src="branch/version1".
Alternatively, a Jenkins or Atlassian bamboo plugin would work.
Simply switch branch before executing mvn failsafe:integration-test. This is common pattern.
Maven Failsafe Plugin has no support for switching branches and no support for Version control systems (VCS) - and this is good, because this other plugin responsiblity.
This is easy to switch branch in tools like Jenkins. Create one job per branch, changes to code in branch should trigger jenkins build. Jenkis has support for private maven repositories, this will help with artifact collision. Also is possible to share workspace (results) from first job with second job.
In your case build job pipeline in jenkins, after first job from master execute job from branch to verify integration tests.
The best idea I've seen so far is to do a switch on the version control system and then just to run the integration tests.
Steps
svn co trunk
mvn clean install
svn switch branch
mvn failsafe:integration-test
If you run mvn integration-test in this stage you will rebuild the project and you will thus be testing your branch/the older version
I have coded this up and tested it against svn/mvn/jenkins stack

Continuous integration server beginner

I'm trying to setup a complete CI server, but I struggle on some points.
Currently, my system work as follow :
I commit local changes on my local GIT repository, then push to the GIT repository on the CI server
I then have a jenkins job triggered by the SCM change, who run a clean install and by doing so executes all my Junit and Jstestdriver test (via a local jstd server). This job deploy the snapshot artifact to a repository on my nexus repository
I installed M2-release-plugin for jenkins, and setup my pom.xml accordingly using maven-release-plugin. When i click on "Perform maven release" in jenkins job page, jenkins run mvn release:prepare release:perform, thus creating a tag in my git repo (say v000001) and deploying a versionned artifact on my nexus repository.
I don't really know if this process is fine, but i guess so...
My problem is that I want to deliver the versionned artifact in my nexus repo (say "artifact-v0000001.war") in my production tomcat. But I can't figure out how to do it.
When I do "mvn release:prepare release:perform tomcat:deploy" it deploys the new SNAPSHOT artifact built ... I don't want to do this, I want to reuse the artifact from the nexus repository.
Is there a way to doing this using a tool (maven/jenkins plugin, or external)?
Basically, I want to fetch the last release artifact on the repository, and send it to the tomcat manager for dereploying the webapp.
Do I need to setup a delivery job separated from the release job?
Jenkins, especially when combined with a tool like ANT, can do just about anything. It has a lot of plug-ins, and you can always write a script and incorporate it into a Jenkins build. Currently, I use Jenkins to deploy web applications to Windows IIS servers. What you could do here is have a Jenkins build that has your SVN path set in the source control section so that it fetches the latest version when you trigger the build. From there it should be fairly trivial to write an ANT script that copies it over the existing JAR in Tomcat, which will automatically restart it.
Your problem is that you are probably using the Jenkins release plugin, not the "m2 release plugin". The problem with the standard plugin is that it performs the regular build, saves the artifacts, then performs the release. It will then try to deploy the wrong artifacts that it created from the regular build.
The m2 release plugin solves this particular problem. There are some tricky workaround for this problem, but that's how it stands at the moment until this feature is implemented: https://issues.jenkins-ci.org/browse/JENKINS-11120 (log in and vote for it!)

Resources