I have a bunch of interrelated jobs that do Maven releases.  For various
reasons, they're not using the Jenkins release plugin, but rather invoke mvn
release:prepare release:perform as one of a sequence of steps.  I have all
the jobs linked together using build triggers, so if you run one of these
release jobs, it knows which others depend on it and need to be run
afterward.  Before doing the release, each job updates its pom.xml with the
latest versions released by the previous upstream jobs.

So far so good, that all works perfectly.  But, I wanted to automate one
more piece.  Currently, you have to know which parts of the project have
been updated since the last release, and manually start those releases.  It
seems like all the information is available to Jenkins to figure that out
for me, though.  It knows when each job ran, it has hooks to talk to the SCM
to find out if new changes have been checked in, so a simple Groovy script
should suffice.  But there's a catch.

Maybe this would work with other SCMs, but I'm using svn, and here's what
happens.  When I run one of my release jobs, Jenkins first does an SCM
update to pull down all the changes.  Then it does the release, which checks
in two changes to the pom.xml file.  The state of the workspace has now
changed - the SCM revision that Jenkins originally pulled down isn't the
latest any more, it's been bumped twice.  The workspace knows this, but I
think Jenkins doesn't.  The svn plugin keeps a file around called
revision.txt, and this file appears to be a cache of what revision the
workspace is at.  So, in my Groovy script, when I ask Jenkins whether that
job has SCM changes, and therefore needs to be run, Jenkins always answers
yes.  This is because it's looking at revision.txt to figure out if the
workspace needs updating, and revision.txt is out of date -- it still thinks
the workspace doesn't have the two changes committed during the release.  My
Groovy script looks like this:

job = <passed to my function>
def latestBuild = job.getLastCompletedBuild();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
def listener = new hudson.model.StreamBuildListener(baos);
def launcher = new hudson.Launcher.LocalLauncher(listener);
def scmrev = job.scm.calcRevisionsFromBuild(latestBuild, launcher,
listener);
def pollingResult = job.scm.compareRemoteRevisionWith(job, launcher,
job.workspace, listener, scmrev);
return pollingResult.hasChanges();

I've tried to force the workspace to do a checkout, to update revision.txt,
but ironically, that takes the workspace backward in time.  Here's the
script I'm using:

job = <passed to my function>
def latestBuild = job.getLastCompletedBuild();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
def listener = new hudson.model.StreamBuildListener(baos);
def launcher = new hudson.Launcher.LocalLauncher(listener);
job.scm.checkout(latestBuild, launcher, job.workspace, listener,
File.createTempFile("tempcheckout", "txt"));

When it runs, it decides for some reason to refresh the workspace to the
state described in revision.txt, rather than the state in the depot.

So, I'm hoping someone can tell me that I'm just looking at this the wrong
way, and there's a simple thing I can do to force revision.txt to get
updated after the mvn release finishes.  Or maybe there's some other way to
invoke checkout so that it updates revision.txt to match the workspace,
rather than the other way around.  Thanks.

-Joel


--
View this message in context: 
http://jenkins.361315.n4.nabble.com/From-Groovy-script-SCM-polling-reports-incorrect-info-if-job-makes-its-own-checkins-tp4628884.html
Sent from the Jenkins issues mailing list archive at Nabble.com.

Reply via email to