Replay a Pipeline with script edits
This is a cross-post of an article authored by Pipeline plugin maintainer Jesse Glick on the CloudBees blog. |
For those of you not checking their Updates tab obsessively, Pipeline 1.14 [up
to 2.1 now] was
released
a couple of weeks ago and I wanted to highlight the major feature in this
release: JENKINS-32727,
or replay. Some folks writing "Jenkinsfiles" in the field had grumbled that it
was awkward to develop the script incrementally, especially compared to jobs
using inline scripts stored in the Jenkins job configuration: to try a change to
the script, you had to edit Jenkinsfile
in SCM, commit it (perhaps to a
branch), and then go back to Jenkins to follow the output. Now this is a little
easier. If you have a Pipeline build which did not proceed exactly as you
expected, for reasons having to do with Jenkins itself (say, inability to find &
publish test results, as opposed to test failures you could reproduce locally),
try clicking the Replay link in the build’s sidebar. The quickest way to try
this for yourself is to run the
stock CD demo in its
latest release:
$ docker run --rm -p 2222:2222 -p 8080:8080 -p 8081:8081 -p 9418:9418 -ti jenkinsci/workflow-demo:1.14-3
When you see the page Replay
#1, you are shown two
(Groovy) editor boxes: one for the main
Jenkinsfile
, one for a library script
it loaded
(servers.groovy
, introduced to help demonstrate this feature). You
can make edits to either or both. For example, the original demo allocates a
temporary web application with a random name like
9c89e9aa-6ca2-431c-a04a-6599e81827ac
for the duration of the functional tests.
Perhaps you wished to prefix the application name with tmp-
to make it obvious
to anyone encountering the Jetty index page that these
URLs are transient. So in the second text area, find the line
def id = UUID.randomUUID().toString()
and change it to read
def id = "tmp-${UUID.randomUUID()}"
then click Run. In the new build’s log you will now see
Replayed #1
and later something like
… test -Durl=http://localhost:8081/tmp-812725bb-74c6-41dc-859e-7d9896b938c3/ …
with the improved URL format. Like the result? You will want to make it permanent. So jump to the [second build’s index page](http://localhost:8080/job/cd/branch/master/2/) where you will see a note that this build > Replayed #1 (diff) If you click on diff you will see:
--- old/Script1
+++ new/Script1
@@ -8,7 +8,7 @@
}
def runWithServer(body) {
- def id = UUID.randomUUID().toString()
+ def id = "tmp-${UUID.randomUUID()}"
deploy id
try {
body.call id
so you can know exactly what you changed from the last-saved version. In fact if you replay #2 and change tmp
to temp
in the loaded script, in the diff view for #3 you will see the diff from the first build, the aggregate diff:
--- old/Script1
+++ new/Script1
@@ -8,7 +8,7 @@
}
def runWithServer(body) {
- def id = UUID.randomUUID().toString()
+ def id = "temp-${UUID.randomUUID()}"
deploy id
try {
body.call id
At this point you could touch up the patch to refer to servers.groovy
(JENKINS-31838), git
apply
it to a clone of your repository, and commit. But why go to the trouble
of editing Groovy in the Jenkins web UI and then manually copying changes back
to your IDE, when you could stay in your preferred development environment from
the start?
$ git clone git://localhost/repo
Cloning into 'repo'...
remote: Counting objects: 23, done.
remote: Compressing objects: 100% (12/12), done.
remote: Total 23 (delta 1), reused 0 (delta 0)
Receiving objects: 100% (23/23), done.
Resolving deltas: 100% (1/1), done.
Checking connectivity... done.
$ cd repo
$ $EDITOR servers.groovy
# make the same edit as previously described
$ git diff
diff --git a/servers.groovy b/servers.groovy
index 562d92e..63ea8d6 100644
--- a/servers.groovy
+++ b/servers.groovy
@@ -8,7 +8,7 @@ def undeploy(id) {
}
def runWithServer(body) {
- def id = UUID.randomUUID().toString()
+ def id = "tmp-${UUID.randomUUID()}"
deploy id
try {
body.call id
$ ssh -p 2222 -o StrictHostKeyChecking=no localhost replay-pipeline cd/master -s Script1 < servers.groovy
Warning: Permanently added '[localhost]:2222' (RSA) to the list of known hosts.
# follow progress in Jenkins (see JENKINS-33438)
$ git checkout -b webapp-naming
M servers.groovy
Switched to a new branch 'webapp-naming'
$ git commit -a -m 'Adjusted transient webapp name.'
[webapp-naming …] Adjusted transient webapp name.
1 file changed, 1 insertion(+), 1 deletion(-)
$ git push origin webapp-naming
Counting objects: 3, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 330 bytes | 0 bytes/s, done.
Total 3 (delta 2), reused 0 (delta 0)
To git://localhost/repo
* [new branch] webapp-naming -> webapp-naming
Using the replay-pipeline
CLI command (in this example via
SSH)
you can prepare, test, and commit changes to your Pipeline script code without
copying anything to or from a browser. That is all for now. Enjoy!