Jenkins Integration¶
Changes integrates extremely with Jenkins as a build manager, however it will require you to have a very specialized job for running a build.
Creating the Job¶
This changes rapidly and documentation is not maintained for the internals of the generic job.
<?xml version='1.0' encoding='UTF-8'?>
<project>
<actions/>
<description></description>
<logRotator class="hudson.tasks.LogRotator">
<daysToKeep>7</daysToKeep>
<numToKeep>1000</numToKeep>
<artifactDaysToKeep>-1</artifactDaysToKeep>
<artifactNumToKeep>100</artifactNumToKeep>
</logRotator>
<keepDependencies>false</keepDependencies>
<properties>
<hudson.model.ParametersDefinitionProperty>
<parameterDefinitions>
<hudson.model.StringParameterDefinition>
<name>REVISION</name>
<description>A commit, branch name, or something else recognizable as a tree.
</description>
<defaultValue></defaultValue>
</hudson.model.StringParameterDefinition>
<hudson.model.StringParameterDefinition>
<name>PATCH_URL</name>
<description></description>
<defaultValue></defaultValue>
</hudson.model.StringParameterDefinition>
<hudson.model.StringParameterDefinition>
<name>REPO_URL</name>
<description></description>
<defaultValue></defaultValue>
</hudson.model.StringParameterDefinition>
<hudson.model.ChoiceParameterDefinition>
<name>REPO_VCS</name>
<description></description>
<choices class="java.util.Arrays$ArrayList">
<a class="string-array">
<string>git</string>
<string>hg</string>
</a>
</choices>
</hudson.model.ChoiceParameterDefinition>
<hudson.model.StringParameterDefinition>
<name>SCRIPT</name>
<description></description>
<defaultValue></defaultValue>
</hudson.model.StringParameterDefinition>
<hudson.model.StringParameterDefinition>
<name>RESET_SCRIPT</name>
<description>Cleanup tasks to run after the generic job completes. Intended for use by reset-generic jobs.
</description>
<defaultValue></defaultValue>
</hudson.model.StringParameterDefinition>
<hudson.model.StringParameterDefinition>
<name>CHANGES_PID</name>
<description>Changes Project Slug</description>
<defaultValue></defaultValue>
</hudson.model.StringParameterDefinition>
<hudson.model.StringParameterDefinition>
<name>CHANGES_BID</name>
<description>Changes Job ID (DO NOT ENTER MANUALLY)</description>
<defaultValue></defaultValue>
</hudson.model.StringParameterDefinition>
<org.jvnet.jenkins.plugins.nodelabelparameter.LabelParameterDefinition plugin="nodelabelparameter@1.5.1">
<name>CLUSTER</name>
<description></description>
<defaultValue></defaultValue>
<allNodesMatchingLabel>false</allNodesMatchingLabel>
<triggerIfResult>allCases</triggerIfResult>
<nodeEligibility class="org.jvnet.jenkins.plugins.nodelabelparameter.node.AllNodeEligibility"/>
</org.jvnet.jenkins.plugins.nodelabelparameter.LabelParameterDefinition>
<hudson.model.StringParameterDefinition>
<name>WORK_PATH</name>
<description>Working directory to run SCRIPT from. Relative to REPO_ROOT.</description>
<defaultValue></defaultValue>
</hudson.model.StringParameterDefinition>
<hudson.model.StringParameterDefinition>
<name>C_WORKSPACE</name>
<description>Custom workspace directory.</description>
<defaultValue></defaultValue>
</hudson.model.StringParameterDefinition>
</parameterDefinitions>
</hudson.model.ParametersDefinitionProperty>
<com.sonyericsson.rebuild.RebuildSettings plugin="rebuild@1.20">
<autoRebuild>true</autoRebuild>
</com.sonyericsson.rebuild.RebuildSettings>
</properties>
<scm class="hudson.scm.NullSCM"/>
<canRoam>true</canRoam>
<disabled>false</disabled>
<blockBuildWhenDownstreamBuilding>false</blockBuildWhenDownstreamBuilding>
<blockBuildWhenUpstreamBuilding>false</blockBuildWhenUpstreamBuilding>
<authToken/>
<triggers/>
<concurrentBuild>true</concurrentBuild>
<builders>
<hudson.tasks.Shell>
<command>#!/bin/bash -ex
/var/lib/jenkins/build-steps/generic-build
</command>
</hudson.tasks.Shell>
</builders>
<publishers>
<hudson.tasks.ArtifactArchiver>
<artifacts>**/junit.xml,**/coverage.xml,**/tests.json,**/jobs.json</artifacts>
<latestOnly>false</latestOnly>
<allowEmptyArchive>true</allowEmptyArchive>
</hudson.tasks.ArtifactArchiver>
<hudson.tasks.BuildTrigger>
<childProjects>reset-generic</childProjects>
<threshold>
<name>FAILURE</name>
<ordinal>2</ordinal>
<color>RED</color>
<completeBuild>true</completeBuild>
</threshold>
</hudson.tasks.BuildTrigger>
</publishers>
</project>
Example scripts based on git are included for reference. Note that REPO_PATH is a global variable that is assumed to exist. The reset-generic job here is an optional, sample downstream job that can be run to execute cleanup tasks passed through the RESET_SCRIPT parameter. Running cleanup tasks outside the generic job has the advantage of not delaying build results from the generic job being posted back to Changes.
Master Build Step¶
#!/bin/bash -ex
echo `whoami`@$HOSTNAME
uname -a
# nothing works without ssh keys, so let's straight up error
# out of theres no keys/agent present
ssh-agent -s
ssh-add -l
REPO_PATH=$WORKSPACE/$CHANGES_PID
if [ -z $REVISION ]; then
if [ "$REPO_VCS" = "hg" ]; then
REVISION=default
else
REVISION=master
fi
fi
if [ "$REPO_VCS" = "git" ]; then
git-clone $REPO_PATH $REPO_URL $REVISION
git-patch $REPO_PATH $PATCH_URL
else
hg-clone $REPO_PATH $REPO_URL $REVISION
hg-patch $REPO_PATH $PATCH_URL
fi
# clean up any artifacts which might be present
for artifact_name in "junit.xml coverage.xml jobs.json tests.json"; do
find . -name $artifact_name -delete
done
SCRIPT_PATH=/tmp/$(mktemp build-step.XXXXXXXXXX)
echo "$SCRIPT" | tee $SCRIPT_PATH
chmod +x $SCRIPT_PATH
pushd $REPO_PATH
if [ ! -z $WORK_PATH ]; then
pushd $WORK_PATH
fi
$SCRIPT_PATH
Fetching the Revision¶
#!/bin/bash -eux
if [ ! -d $REPO_PATH/.git ]; then
git clone $REPO_URL $REPO_PATH
pushd $REPO_PATH
else
pushd $REPO_PATH && git fetch --all
git remote prune origin
fi
git clean -fdx
if ! git reset --hard $REVISION ; then
git reset --hard origin/master
echo "Failed to update to $REVISION, falling back to master"
fi
Applying the Patch¶
#!/bin/bash -eux
WORKSPACE_DIR=$(pwd)
pushd $REPO_PATH
if [ ! -z "${PATCH_URL:-}" ]; then
curl -o ${WORKSPACE_DIR}/PATCH $PATCH_URL
git apply ${WORKSPACE_DIR}/PATCH
fi
Running Tests¶
This step is arbitrary based on your platform. In Python this might be something like:
py.test --junit=junit.xml