Run Jenkins Script Console Scripts from Command Line (Without Remoting)

If you’re like me, you generally enjoy using the command line, and want to make as much available to it as possible.

Jenkins has a decent CLI client, Jenkins CLI, that allows you to do a number of Jenkins things from the command line. It also seems to be steeped in history – at least judging from the number of deprecated protocols and options. The most relevant deprecation here is Remoting, which, among other things, allows the transfer of files to and from the server – so that is no longer possible. More on that later.

Setting up Jenkins CLI

Throughout this guide, replace my.jenkins.instance with the domain for your Jenkins instance.

Download the correct version of the CLI to match your Jenkins instance. Fortunately, all Jenkins instances host their matching version, so it is easy to download from your own instance:

curl 'https://my.jenkins.instance/jnlpJars/jenkins-cli.jar' > "$HOME/bin/jenkins-cli.jar"

Next, to use the Jenkins CLI, you need a token to be able to log in. To get the token, log in to your Jenkins instance, go to your user’s dropdown in the top-right corner of the screen > Configure > Show API Token…. Copy the User ID and API Token in to the following command, replacing <User ID> and <API Token> respectively, which will put them in to a file we’ll use shortly:

echo '<User ID>:<API Token>' > "$HOME/.jenkins-cli-auth"

You are now able to use the Jenkins CLI with your own commands!

java -jar "$HOME/bin/jenkins-cli.jar" -s 'https://my.jenkins.instance' -noKeyAuth -auth "@$HOME/.jenkins-cli-auth" <command...>

I recommend making an alias – future examples will use this alias:

jenkinsCli() {
    java -jar "$HOME/bin/jenkins-cli.jar" -s 'https://my.jenkins.instance' -noKeyAuth -auth "@$HOME/.jenkins-cli-auth" "$@"
}

Pro Tip: There’s nothing stopping you from downloading multiple JARs for different instances of Jenkins, and making multiple aliases to use them.

Getting an interactive shell

Once you have the CLI working, you can log on to Jenkins and get an interactive shell for scripting using:

jenkinsCli groovysh

For example, let’s say you want to clear the build queue of all of its jobs, something I’ve written about before. Entering the following code in to the shell will do that:

import jenkins.model.*
Jenkins.instance.queue.clear()

Note the import, which has been added to the code from the original post. This is because the web shell automatically imports import jenkins.model.* and import hudson.model.* for you, whereas the CLI’s interactive shell doesn’t. So we add it ourselves.

Running scripts from files without remoting

Now suppose that you like to clear the build queue quite regularly, and you get fed up of typing it or copying and pasting it. It is possible to place code in to re-usable scripts.

Following our example from earlier, let’s say we got fed up and copied the script (with imports) in to a new file, ~/jenkins-cli/clear-build-queue.groovy.

We can then run this script in Jenkins by running the following command:

jenkinsCli groovy = < ~/jenkins-cli/clear-build-queue.groovy

groovy is a subcommand that runs a Groovy script directly on the Jenkins master, without a wrapper shell. = instructs Jenkins CLI to expect stdin to provide a script to run. < feeds the contents of the Groovy file to jenkinsCli via stdin (where it is listening, thanks to =).

With that, you can now run scripts on Jenkins without leaving the comfort of your command line.

Currying vs Partial Function Application

While having a read in to the art of function programming, I stumbled upon a curious technicality. Those that know me know (perhaps wearily) I love talking about technical stuff.

Currying (wikipedia) builds a single function that, in effect, takes multiple arguments by composing a chain of functions that each take a single argument and eventually yield the final result:

f: (x, y, z) -> result
curry(f): x -> (y -> (z -> result))

So if you wanted to call a curried function, it would look something like:

f(first_arg)(second_arg)(third_arg)

Functional languages often compose multiple-argument functions using what appears to be currying.

But wait, that’s not what I just said! I must be an awful writer, spreading misinformation like that. After all, I’ve read plenty of blogs and articles that tell me that currying is where you “fix” some arguments in place ahead of final invocation. The result is creating a function with fewer arguments, like so:

f(x, y, z) -> result
g(z) -> f(1, 2, z)

It turns out that this is known as partial function application. How it came to be known as currying I am not sure, but it seems to be a very common misconception. I believed it too until recently! Yet another thing to remember.

Wikipedia contrasts currying and partial function application in detail if you want to compare them further.

Cancel All Queued Jenkins Jobs

I do not believe cancelling all queued Jenkins jobs is possible via the UI. Fortunately, it is possible if you have access to the Script Console.

Run this in Manage Jenkins > Script Console:

Jenkins.instance.queue.clear()

While this script is innocuous, always be careful when using the Script Console. Any script run inside it effectively has administrative permissions over Jenkins!

Update 2018-09-11: Use Jenkins instead of the deprecated Hudson.

Backup and restore a stock Android device

Overview

Taking regular backups of important devices is sensible advice. And backups themselves are no good unless you can restore them. This guide gives a brief overview on how to backup and restore a stock Android device – that is, a device that runs an uncustomised version of Android, that is unrooted. It may also work for non-stock Android devices.

One big caveat: While this is the best method I have found without root, I have not had consistent results across devices when restoring backups, even among Nexus devices. So I recommend that this method is not relied upon exclusively for backup.

Usage information

We will be using adb backup and adb restore to backup and restore device state.

To find out usage information for your device, connect it and run:

adb shell bu help

This info was found by simply running adb.

This guide assumes the backup and restore commands work like stock Android devices.

Backup

  1. Set up your computer and device so that your computer can access the device via USB. There are plenty of good guides out there, but in summary this’ll involve enabling USB debugging on the device and installing the Android SDK Platform Tools.

  2. Run the following command, authorising your computer to access the device if you have not already:

    adb backup -apk -obb -shared -all -system
    
  3. Follow the instructions. In my case, I needed to unlock the device and confirm the backup operation (optionally entering a password to encrypt the backup).

This will store a file in the current working directory.

Restore

  1. Ensure the device to restore to is connected.

  2. Run:

    adb restore <path_to_backup>
    

Using .netrc with curl for Automatic Authorisation

The ~/.netrc file can store credentials. This can include things like OAuth tokens and plain text passwords.

Warning: Be very careful if you decide to store passwords in this file. The file is not encrypted, so you’ll be storing your password in plain text on the disk. This is generally a bad idea!

First, create the file and make it readable by only yourself:

touch ~/.netrc
chmod go= ~/.netrc

Then edit the file to contain lines that look like the following (one line per machine):

machine the.address.tld login the-username password the-password

curl can then read this file by providing the --netrc option:

curl --netrc http://the.address.tld/classified

Ignore a Package Update When Using Fedora and KDE

Recently I wrote about Escaping a login loop when using Fedora. Well, once I had downgraded the package, I wanted to ensure that it would not get automatically updated again!

To ignore the package when performing updated via dnf, add an exclude=<package> line to /etc/dnf/dnf.conf. For example:

[main]
gpgcheck=1
installonly_limit=3
clean_requirements_on_remove=True
exclude=sddm

dnf no longer requests me to update SDDM.

Unfortunately, the built-in updater for KDE (which I blieve is PackageKit) does not honour the settings in dnf.conf. It will, however, honour exclude= lines in the repo files in /etc/yum.repos.d.

Since I wanted to block an update to SDDM, I edited /etc/yum.repos.d/fedora-updates.repo and added an exclude=sddm directive to the [updates] block:

[updates]
name=Fedora $releasever - $basearch - Updates
failovermethod=priority
#baseurl=http://download.fedoraproject.org/pub/fedora/linux/updates/$releasever/$basearch/
metalink=https://mirrors.fedoraproject.org/metalink?repo=updates-released-f$releasever&arch=$basearch
enabled=1
repo_gpgcheck=0
type=rpm
gpgcheck=1
metadata_expire=6h
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-fedora-$releasever-$basearch
skip_if_unavailable=False
exclude=sddm

After a while, KDE stopped pestering me to install the SDDM update.

I technically probably only have to add the exclude to the repo files, but this is the process that I went through. If you’re feeling adventurous, you may try only updating the repo files.

Escape Login Loop in Fedora

The problem seems to be caused by an update to SDDM (Simple Desktop Display Manager).

On Fedora it can be downgraded, but first you need an internet connection. I enabled my wireless internet connection by running:

nmcli connection up <wireless-network>

Where <wireless-network> is the SSID of my wireless network.

I then downgraded SDDM:

sudo dnf downgrade sddm

Logins should then work after a reboot.

Make kdesu use sudo (a.k.a. stop asking for root's password)

When I tried to start partitionmanager (KDE Partition Manager) on Fedora 26, it would always ask for the root user’s password, despite the fact that the root user was disabled in my setup.

The dialog box that popped up looked like it might be kdesu. kdesu,. a.k.a. KDE su, is a KDE version of su that allows a process to be run as another user, like root. When I tried running kdesu separately it asked for root’s password again. So I knew the problem lay within kdesu, not partitionmanager.

The ever-helpful Arch wiki contained just the golden nugget I was after: a command that would configure kdesu to use sudo:

kwriteconfig5 --file kdesurc --group super-user-command --key super-user-command sudo

This fixed the problem for me, as sudo requests your password, not root’s. Whether you’re allowed to run the command depends on the contents of the system’s sudoers file. Look that file up if you continue to have difficulty.

Re-use Commit Message in Git

To re-use a commit’s message verbatim, including authorship and timestamp information, use -C <commit>:

git commit --amend -C @

Pro Tip: @ is a synonym for HEAD, the currently checked-out commit.

To reset the date as well, use --date now; to reset the author too, use --reset-author:

git commit --amend -C @ --date now
git commit --amend -C @ --reset-author
git commit --amend -C @ --date now --reset-author

If you want to use an existing commit’s message and also want a chance to edit it, use -c <commit>:

git commit --amend -c @

-c is compatible with --date and --reset-author too:

git commit --amend -c @ --date now
git commit --amend -c @ --reset-author
git commit --amend -c @ --date now --reset-author

Added 2020-05-16: To re-use a commit message after a reset, try using @{1}:

git commit -C @{1}

If you’re wondering what commit @{1} refers to, run git reflog and look for the line near the top containing HEAD@{1}.