//g;s/.*<\/td> | //g;s///g;s/<\/t.>//g'
+ assert 'default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline';' \
+ bash -c "curl -fsSL --user \"admin:$(get_jenkins_password)\" $(get_jenkins_url)/systemInfo | sed 's/<\/tr>/<\/tr>\'$'\n/g' | grep 'hudson.model.DirectoryBrowserSupport.CSP | ' | sed -e '${sed_expr}'"
+ assert 'Europe/Madrid' \
+ bash -c "curl -fsSL --user \"admin:$(get_jenkins_password)\" $(get_jenkins_url)/systemInfo | sed 's/<\/tr>/<\/tr>\'$'\n/g' | grep 'user.timezone | ' | sed -e '${sed_expr}'"
+}
+
+@test "clean test containers" {
+ cleanup $SUT_CONTAINER
+}
diff --git a/jenkins/tests/test_helpers.bash b/jenkins/tests/test_helpers.bash
new file mode 100644
index 0000000..eb67f45
--- /dev/null
+++ b/jenkins/tests/test_helpers.bash
@@ -0,0 +1,84 @@
+#!/bin/bash
+
+# check dependencies
+(
+ type docker &>/dev/null || ( echo "docker is not available"; exit 1 )
+ type curl &>/dev/null || ( echo "curl is not available"; exit 1 )
+)>&2
+
+# Assert that $1 is the outputof a command $2
+function assert {
+ local expected_output=$1
+ shift
+ local actual_output
+ actual_output=$("$@")
+ actual_output="${actual_output//[$'\t\r\n']}" # remove newlines
+ if ! [ "$actual_output" = "$expected_output" ]; then
+ echo "expected: \"$expected_output\""
+ echo "actual: \"$actual_output\""
+ false
+ fi
+}
+
+# Retry a command $1 times until it succeeds. Wait $2 seconds between retries.
+function retry {
+ local attempts=$1
+ shift
+ local delay=$1
+ shift
+ local i
+
+ for ((i=0; i < attempts; i++)); do
+ run "$@"
+ if [ "$status" -eq 0 ]; then
+ return 0
+ fi
+ sleep $delay
+ done
+
+ echo "Command \"$*\" failed $attempts times. Status: $status. Output: $output" >&2
+ false
+}
+
+function docker_build {
+ if [ -n "$JENKINS_VERSION" ]; then
+ docker build --build-arg JENKINS_VERSION=$JENKINS_VERSION --build-arg JENKINS_SHA=$JENKINS_SHA "$@"
+ else
+ docker build "$@"
+ fi
+}
+
+function get_jenkins_url {
+ if [ -z "${DOCKER_HOST}" ]; then
+ DOCKER_IP=localhost
+ else
+ DOCKER_IP=$(echo "$DOCKER_HOST" | sed -e 's|tcp://\(.*\):[0-9]*|\1|')
+ fi
+ echo "http://$DOCKER_IP:$(docker port "$SUT_CONTAINER" 8080 | cut -d: -f2)"
+}
+
+function get_jenkins_password {
+ docker logs "$SUT_CONTAINER" 2>&1 | grep -A 2 "Please use the following password to proceed to installation" | tail -n 1
+}
+
+function test_url {
+ run curl --user "admin:$(get_jenkins_password)" --output /dev/null --silent --head --fail --connect-timeout 30 --max-time 60 "$(get_jenkins_url)$1"
+ if [ "$status" -eq 0 ]; then
+ true
+ else
+ echo "URL $(get_jenkins_url)$1 failed" >&2
+ echo "output: $output" >&2
+ false
+ fi
+}
+
+function cleanup {
+ docker kill "$1" &>/dev/null ||:
+ docker rm -fv "$1" &>/dev/null ||:
+}
+
+function unzip_manifest {
+ local plugin=$1
+ local work=$2
+ bash -c "docker run --rm -v $work:/var/jenkins_home --entrypoint unzip $SUT_IMAGE -p /var/jenkins_home/plugins/$plugin META-INF/MANIFEST.MF | tr -d '\r'"
+}
diff --git a/jenkins/tests/upgrade-plugins/Dockerfile b/jenkins/tests/upgrade-plugins/Dockerfile
new file mode 100644
index 0000000..dfe81de
--- /dev/null
+++ b/jenkins/tests/upgrade-plugins/Dockerfile
@@ -0,0 +1,3 @@
+FROM bats-jenkins
+
+RUN /usr/local/bin/install-plugins.sh maven-plugin:2.13 ant:1.2
diff --git a/jenkins/update-official-library.sh b/jenkins/update-official-library.sh
new file mode 100644
index 0000000..07e3b1f
--- /dev/null
+++ b/jenkins/update-official-library.sh
@@ -0,0 +1,36 @@
+#!/bin/bash -eu
+
+# Generate the Docker official-images file
+
+sha() {
+ local branch=$1
+ git rev-parse $branch
+}
+
+version_from_dockerfile() {
+ local branch=$1
+ git show $branch:Dockerfile | grep JENKINS_VERSION: | sed -e 's/.*:-\(.*\)}/\1/'
+}
+
+master_sha=$(sha master)
+alpine_sha=$(sha alpine)
+
+master_version=$(version_from_dockerfile master)
+alpine_version=$(version_from_dockerfile alpine)
+
+if ! [ "$master_version" == "$alpine_version" ]; then
+ echo "Master version '$master_version' does not match alpine version '$alpine_version'"
+ exit 1
+fi
+
+cat << EOF > ../official-images/library/jenkins
+# maintainer: Nicolas De Loof (@ndeloof)
+# maintainer: Michael Neale (@michaelneale)
+# maintainer: Carlos Sanchez (@carlossg)
+
+latest: git://github.com/jenkinsci/jenkins-ci.org-docker@$master_sha
+$master_version: git://github.com/jenkinsci/jenkins-ci.org-docker@$master_sha
+
+alpine: git://github.com/jenkinsci/jenkins-ci.org-docker@$alpine_sha
+$alpine_version-alpine: git://github.com/jenkinsci/jenkins-ci.org-docker@$alpine_sha
+EOF
|