As I mentioned in an earlier post I am doing the work required for Google Summer of Code within the Paddy Power offices. Due to this I am following their standards for delivering a project.
A big part of this is following a behavior driven development approach. This puts a great emphases on continuous testing and for this reason a build pipeline as developed within Jenkins.
The layout of the pipeline is as follows:
- Pull in non-oss dependencies
- Pull in the cloudstack branch I've been working on, move in the non-oss dependencies and build it executing unit tests
- Run static analysis on the code using sonar source
- Create a new Cloudstack Database, Start the simulator and run the pre-integration configuration
- Launch the integration tests
- Stop the simulator
- Build a RPM binary of the source
- Push the binary out onto a local repository
This setup was showcased in a screencast I did awhile back, if you are interested: http://imduffy15.blogspot.ie/2013/06/continuous-testing-environment.html
This post is going to go through the process of creating such a setup. It is assumed you have a clean version of jenkins installed. The configuration of sonar will be detailed in a separate post.
Plugins required:
- Install the following plugins from Manage Jenkins -> Plugin Manager
- Build pipeline
- Jenkins Build timeout
- Jenkins clone workspace SCM
- Jenkins GIT
- Jenkins Parameterized Trigger
- Jenkins Sonar
After installing these plugins you will need to do a small amount of configuration. Navigate to Manage Jenkins -> Configure System
- Configure JDK - Under the JDK heading set your java_home path
- Configure git - Under the git heading fill out the options as necessary
- Configure maven - Under the maven heading set the path to your Maven 3.0.5 Home
- Configure sonar - Set its URL, account login, account password, database url(matches the same url in your sonar config), database login, database pasword
- Job Configuration
Job Configuration
To create a new job simply git "new job" on the sidebar. For most of these jobs I will be using a build a free-style project, unless stated otherwise.
Update non-OSS libs:
- Configure git to pull git@github.com:vogxn/cloudstack-nonoss.git this is a github repository that contains the non-oss dependencies required for the non-oss build of cloudstack
- Set a Poll SCM of @hourly
- Set the build to abort if it's stuck. For this I used Elastic with the default value of 150%
- Create a post build action of "Trigger parameterized build on other projects". Set projects to build to "build-master-nonoss", set trigger when build is stable, finally check trigger build without parameters.
- Save the job
Build non-OSS components:
- Description > Build non-OSS components
- Discard old builds > Log Rotation
- Days to keep builds > 5
- Max # of builds to keep > 5
- This build is paramaterized > true
- String Parameter
- NAME > MAJOR_VERSION_NUMBER
- DEFAULT VALUE > 4.2
- String Parameter
- NAME > PROJECT_REPOSITORY
- DEFAULT VALUE > https://git-wip-us.apache.org/repos/asf/cloudstack.git
- String parameter
- NAME > GROUP_ID
- DEFAULT VALUE > org/apache/cloudstack
- Git Repository
- Url> $PROJECT_REPOSITORY
- Branch Specifier > master
- Build
- Invoke Maven 3
- Maven version > Maven
- Root pom > pom.xml
- Goals and options > clean install -P developer,systemvm -D simulator -D nonoss
- Execute shell
- git checkout -b build-$MAJOR_VERSION_NUMBER.$BUILD_NUMBER
- git commit -a -m 'Build $MAJOR_VERSION_NUMBER.$BUILD_NUMBER
- Execute Shell
echo "Getting nonoss patches" LIBS=$JENKINS_HOME/jobs/mgmt-update-nonoss-libs/workspace #Remove old jars rm -fr deps/*.jar deps/XenServerJava deps/awsapilib deps/*.mar #Replace with latest from https://github.com/vogxn/cloudstack-nonoss.git cloned into mgmt-update-nonoss-libs cp -r $LIBS/*.jar $LIBS/XenServerJava/ $LIBS/awsapi-lib/ $LIBS/*.mar deps #install the non-oss jars into .m2 cd deps bash -x install-non-oss.sh #now build the non-oss profile cd $WORKSPACE mkdir -p /var/lib/jenkins/jobs/CodeCommit/workspace/services/console-proxy/server/distmvn clean install -P developer,systemvm -D simulator -D nonoss
- Post build actions
- Archive for cloud workspace scm
- Files to include in cloned workspace > **
- Criteria for build to be archieved > Most recent completed build
- Archive method > Gzipped
- Trigger paramterized build on other projects
- Projects to build > static-analysis
- Trigger when build is > Stable
Static Analysis:
- Discard old builds > Log Rotation
- Days to keep builds > 5
- Max # of builds to keep > 5
- Source Code Management
- Clone workspace
- Parent project > build-master-nonoss
- Criteria for parent build > Most Recent Completed Build
- Post build actions
- Sonar
- Root pom > pom.xml
- MAVEN_OPTS > -Dsonar.profile=Cloudstack
- Trigger parameterized build on other projects
- Projects to build > start-simulator
- Trigger when build is > Stable
Start simulator:
- Discard old builds > Log Rotation
- Days to keep builds > 5
- Max # of builds to keep > 5
- Build
- Execute shell
mvn -Pdeveloper -pl developer -Ddeploydb mvn -Pdeveloper -pl developer -Ddeploydb-simulator export OLD_BUILD_ID=$BUILD_ID export BUILD_ID=dontKillMe daemonize -c . -o log.txt /opt/apache-maven-3.0.5/bin/mvn -pl client jetty:run export BUILD_ID=$OLD_BUILD_ID while ! nc -vz localhost 8096; do sleep 10; done export http_proxy="" nosetests -v --with-marvin --marvin-config=setup/dev/advanced.cfg -w /tmp
- Trigger paramaterized build on other projects
- Projects to build > integration-tests.
- Trigger when build is > stable
Integration tests:
Use a configuration matrix for this
- Discard old builds > Log Rotation
- Days to keep builds
- Max # of builds to keep
- Configuration Matrix
- User defined axis
- Name: suite
- Values
- test_affinity_groups
- test_deploy_vm
- test_deploy_vm_with_userdata
- test_disk_offerings
- test_global_settings
- test_guest_vlan_range
- test_internal_lb
- test_network_acl
- test_nic
- test_non_contigiousvlan
- test_portable_publicip
- test_privategw_acl
- test_public_ip_range
- test_pvlan
- test_regions
- test_resource_detail
- Execute touchstone builds first
- Filter > suite="test_vm_life_cycle"
- Required result > "Stable"
- Build environment
- Abort the build if its stuck > true
- Absolute
- Timeout minutes > 1440
- Build
- Execute shell
nosetests --with-xunit --xunit-file=$suite.xml --with-marvin --marvin-config=$WORKSPACE/../../setup/dev/advanced.cfg $WORKSPACE/../../test/integration/smoke/$suite.py --load -a tags=advanced
- Post Build Actions
- Trigger paramaterized build on other projects
- Projects to build > stop simulator
- Trigger when build is > Complete
Stop Simulator:
- Discard old builds > Log Rotation
- Days to keep builds > 5
- Max # of builds to keep > 5
- Build
- Execute shell
- mvn -pl :cloud-client-ui jetty:stop
- Post build actions
- Trigger paramaterized build on other projects
- Projects to build > package-rhel63-4.2-nonoss,
- Trigger when build is > Stable
Package Binary:
- Discard old builds > Log Rotation
- Days to keep builds > 5
- Max # of builds to keep > 5
- Source code management
- Clone workspace
- Parent project > build-master-nonoss
- Criteria for parent build > Most recent completed build
- Build
- Execute shell
set -x PACKAGE_VERSION=4.2.0 cd scripts/vm/hypervisor/xenserver/ if [ ! vhd-util ]; then wget http://download.cloud.com.s3.amazonaws.com/tools/vhd-util fi cd $WORKSPACE/packaging/centos63/ bash -x package.sh