Clean the slaves

In my current project we’re generating jobs for each branch of each project with the help of the Jenkins Job DSL. Branches are created for each feature and bugfix – hotfixes are branched from release branches but these are treated a little differently. Anyway, as you can imagine we tend to have a lot of branches even though we delete them once they’re merged back into the master. Since we also have a lot of different jobs for building/testing/deploying, the amount of jobs explodes quite quickly ;)
Also, to have acceptable job execution times and fast feedback for the developers, we’re using multiple slaves.

Problem

When deleting a job, e.g. because the branch is removed, its workspace on the slave is not deleted. This is a little annoying since it’s wasting a lot of space on the slaves’ disks and in the past required some manual effort to clean them up. Luckily, Jenkins provides some nice APIs :)

Solution

We created a job which is executing a “system groovy script” (important!) and must be run on the Jenkins master. It simply runs through all slaves, checks if their workspace contains a folder which is orphaned and deletes it. And yes, it is as simple as it sounds. Just a few lines of code which are run after the job generation and all orphaned workspaces are removed :mrgreen:

import hudson.model.*
import hudson.node_monitors.*
import jenkins.model.*

for (node in Jenkins.instance.nodes) {
    computer = node.toComputer()
    if (computer.getChannel() == null) {
        continue
    }

    def rootPath = node.getWorkspaceRoot()
    def space = DiskSpaceMonitor.DESCRIPTOR.get(computer)

    println "Checking node ${node.name}..."
    println "Got path ${rootPath} and remaining space ${space}"

    rootPath.list().sort().each { dir ->
        if (!Jenkins.instance.getItem(dir.name)) {
            println "${dir} orphaned. Deleting..."
            dir.deleteRecursive()
        } else {
            println "${dir} still in use. Skipping."
        }
    }
}

Using your MacBook as Jenkins slave and thereby avoid any sleeping

As a requirement in my current project, we have to support IE11 and Safari 9 & 10. Since running Mac OS X virtualized comes with some legal issues, we decided to simply use a MacBookPro (El Capitan) as our Jenkins slave of choice. This works out of the box until the MacBook decides to hibernate, suspend or simply start any energy saving feature Mac OS offers. For normal usage, these are some great features but as a Jenkins slave, they are pretty annoying. So here are some hints you can follow to disable the annoying sleeping features:

At first, simply go to the energy preferences and set them up as shown here:
Energy System Settings

This is not enough though. To disable hibernation, you have to execute the following command:

sudo pmset -a autopoweroff 0

And again, this is not enough, as closing the lid will put the MacBook asleep… Therefore you should install a tool like NoSleep and configure it like this:
nosleep

…but, Apple was pretty busy trying to avoid any kind of energy consuming background task. Since we want to test within Safari, we have to disable Safari’s background sleeping as well. So you have to run the following command:

sudo defaults write com.apple.Safari NSAppSleepDisabled -bool YES

Watch out with running this on your own machine though. Safari will drain your battery from now on ;)

From now on, your device will silently run and wait for work :mrgreen:

Update:

You can also set this globally:

defaults write NSGlobalDomain NSAppSleepDisabled -bool YES

Also, when using Safari for automated tests, you might want to set the following, to prevent Safari from reopening the latest windows:

defaults write com.apple.Safari ApplePersistenceIgnoreState YES

By the way, if you want to be notified for new posts, just sign up with your email address on the right :)