Continuous integration server beginner - maven

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!)

Related

What maven command can I use to revert deployments or "Builds?

I have created pipelines which will clean, compile, test, & deploy the code every time we update it. But in case of a technical issue/or error I want to add a step which allows me to revert/rollback the "build" or deployment.
Is there a maven command that can be used to revert/rollback builds/deployments?
No.
If you just run clean package, then another clean will erase the results of package, but if you have run install or deploy the artifact is send to the local repository or remote repository. This cannot be "rolled back" by Maven.
The Maven Release Plugin has a rollback goal that rolls back the changes that it made to version control:
version changes in POMs are reverted
created tag is deleted
created branch is deleted
However, this rollback does not delete files that were uploaded to the remote repository! If the remote repository does not allow artifacts with final versions to get deleted or modified, then you would end up with a problem, because your next attempt would fail to re-upload.
The Maven Release Plugin internally uses the Maven Deploy Plugin to upload files, and the latter has an experimental deployAtEnd feature. Unfortunately, I did not manage to get it to work for my build (using the suggestion from this SO comment) - I still had a build in which the Maven Release Plugin uploaded files before exiting with a failure.

Jenkins release automation

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.

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]

Jenkins CI server and Nexus Server on the same Box

I am in a situation where I have one Build Server box which is to carry out all continuous integration and manage our maven repository. The box works as follows:
There is one maven repository which is hosted through Apache Server as a URL for developers to use
All Jenkins jobs (including release jobs) run mvn install so that artifacts are kept in this one repository.
I would like to get rid of the Apache server and run Nexus on this same box to manage and host repositories, however I have the following questions/ideas:
With Nexus and Jenkins on the same box, will it mean that I will have to manage two repositories, one where maven installs an artifact to a local repository, and one where maven deploys an artifact to nexus? Would it be possible to have Nexus manage the "mvn install" repository also? How can I make sure we don't run out of disk space on the server very very quickly all the time?
Thanks
Added as response to comments: Thank you both, I am thinking I will just set the Jenkins jobs and release plugin goals to mvn package deploy:deploy in order to skip the install phase, that way, artifacts go directly from the target directory to Nexus. However I guess the Jenkins job will require a local repository from which to use depedencies which will get copied from Nexus to the maven local repository during the build, I am not sure if this can be avoided though.
mvn install installs in the local repository
mvn deploy installs to the remote repository
these semantics are defined in the lifecycle and map to different plugins. Their implementations are different.
You don't have to manage the local repository. Actually for some if not most jobs you might even want to define it localized to the job (with the 'Use private Maven repository' option) instead of to the user who is running the job, especially that you plan to use nexus for repository.
You will have to change your jobs to use mvn deploy instead.
How can I make sure we don't run out of disk space on the server very
very quickly all the time?
Configure Jenkins/Nexus. Discard old builds and disable automatic artifact archiving. Both settings can be found in the Jenkins job-configuration. Also you could delete old artifacts automatically from Nexus using Scheduling Tasks.
There is no need to install the artifacts into the local maven repository when using Jenkins/Nexus on a dedicated server.

How to block local release of the eclipse made for artifactory repository

I´m working with Maven 3, eclipse Helios and Jenkins e Artifactory. During the execution of release plugin one of the steps that this plugin is doing, is publish in artifactory the generated release. In my organization, we have the following issue:
Only the manage of configuration can run the release through Jenkins with release-plugin, but any developer can run the release plugin through console and this execution will overwrite the release published in artifactory.
I´m looking around artifactory configurations and all developer users are with read permissions but they can update release local in artifactory.
There are any solution to block or disable the execution of local release from eclipse through Jenkins?
Thanks if anyone can help me!
I would suggets using Artifactory's release management for Jenkins, which is part of the Jenkins Artifactory plugin.
This will allow you to run release management purely from Jenkins, possibly with a dedicated user, and also run staging and promotion on releases.
Releasing/staging would typically be done to a dedicated repo in Artifactory which only the Jenkins release user has write permissions for.
The release management functionality in the Jenkins Artifactory plugin is a complete replacement for the maven release plugin (and for the Jenkins m2release plugin which is based on the latter), that is:
Faster and involves less (unnecessary) rebuild cycles
Integrates your existing Maven and SCM Jenkins configs
More flexible in how versions can be applied
Offers robust rollbacks
Also works for non-Maven build types
Move release plugin to profile (it should not be activate by default). Activate profile only when you run build on jenkins. (for profile name jenkins use mvn <goals> -Pjenkins)
http://wiki.jfrog.org/confluence/display/RTF/Managing+Permissions

Resources