blob: 12aa7b49090b86bee5612ff38c16ca735b4661db [file] [log] [blame]
Carlos Sanchez7d165ac2016-08-14 11:13:12 +02001#!/bin/bash -eu
Nicolas De Loof0ef5a622016-05-27 19:14:29 +02002
Sýlvan Heuserb20f3882016-06-01 15:47:38 +02003# Resolve dependencies and download plugins given on the command line
4#
5# FROM jenkins
6# RUN install-plugins.sh docker-slaves github-branch-source
7
Carlos Sanchez3a83b9d2016-08-08 09:36:28 +02008set -o pipefail
9
apotterebbd13d02016-06-23 12:24:15 -040010REF_DIR=${REF:-/usr/share/jenkins/ref/plugins}
Denis Egorenko6ddff322018-11-08 16:44:02 +040011DEPS_PINNING_FILE=${DEPS_PINNING_FILE:-/usr/share/jenkins/ref/jenkins-plugins-deps}
apotterebbd13d02016-06-23 12:24:15 -040012FAILED="$REF_DIR/failed-plugins.txt"
Sýlvan Heuserb20f3882016-06-01 15:47:38 +020013
Vincent Latombec14af952016-07-18 10:20:12 +020014. /usr/local/bin/jenkins-support
15
Charles Duffy3eec42c2016-09-20 12:11:33 -050016getLockFile() {
17 printf '%s' "$REF_DIR/${1}.lock"
apotterebbd13d02016-06-23 12:24:15 -040018}
19
Charles Duffy3eec42c2016-09-20 12:11:33 -050020getArchiveFilename() {
21 printf '%s' "$REF_DIR/${1}.jpi"
apotterebbd13d02016-06-23 12:24:15 -040022}
Sýlvan Heuserb20f3882016-06-01 15:47:38 +020023
Charles Duffy3eec42c2016-09-20 12:11:33 -050024download() {
Carlos Sanchezc0f63792016-08-15 10:30:16 +020025 local plugin originalPlugin version lock ignoreLockFile
26 plugin="$1"
27 version="${2:-latest}"
28 ignoreLockFile="${3:-}"
29 lock="$(getLockFile "$plugin")"
Nicolas De Loof0ef5a622016-05-27 19:14:29 +020030
Carlos Sanchezc0f63792016-08-15 10:30:16 +020031 if [[ $ignoreLockFile ]] || mkdir "$lock" &>/dev/null; then
32 if ! doDownload "$plugin" "$version"; then
33 # some plugin don't follow the rules about artifact ID
34 # typically: docker-plugin
35 originalPlugin="$plugin"
36 plugin="${plugin}-plugin"
37 if ! doDownload "$plugin" "$version"; then
38 echo "Failed to download plugin: $originalPlugin or $plugin" >&2
39 echo "Not downloaded: ${originalPlugin}" >> "$FAILED"
40 return 1
41 fi
42 fi
Nicolas De Loofa7a34c32016-05-30 09:10:58 +020043
Carlos Sanchezc0f63792016-08-15 10:30:16 +020044 if ! checkIntegrity "$plugin"; then
45 echo "Downloaded file is not a valid ZIP: $(getArchiveFilename "$plugin")" >&2
46 echo "Download integrity: ${plugin}" >> "$FAILED"
47 return 1
48 fi
apotterebbd13d02016-06-23 12:24:15 -040049
Carlos Sanchezc0f63792016-08-15 10:30:16 +020050 resolveDependencies "$plugin"
51 fi
Nicolas De Loof0ef5a622016-05-27 19:14:29 +020052}
53
Charles Duffy3eec42c2016-09-20 12:11:33 -050054doDownload() {
Carlos Sanchezc0f63792016-08-15 10:30:16 +020055 local plugin version url jpi
56 plugin="$1"
57 version="$2"
58 jpi="$(getArchiveFilename "$plugin")"
apotterebbd13d02016-06-23 12:24:15 -040059
Carlos Sanchezc0f63792016-08-15 10:30:16 +020060 # If plugin already exists and is the same version do not download
61 if test -f "$jpi" && unzip -p "$jpi" META-INF/MANIFEST.MF | tr -d '\r' | grep "^Plugin-Version: ${version}$" > /dev/null; then
62 echo "Using provided plugin: $plugin"
63 return 0
64 fi
apotterebbd13d02016-06-23 12:24:15 -040065
Carlos Sanchez0d167af2016-08-29 11:02:57 +020066 JENKINS_UC_DOWNLOAD=${JENKINS_UC_DOWNLOAD:-"$JENKINS_UC/download"}
Jean-Louis Boudartad0ff9c2016-08-22 09:00:30 +020067
68 url="$JENKINS_UC_DOWNLOAD/plugins/$plugin/$version/${plugin}.hpi"
apotterebbd13d02016-06-23 12:24:15 -040069
Carlos Sanchezc0f63792016-08-15 10:30:16 +020070 echo "Downloading plugin: $plugin from $url"
Carlos Sanchez21b0f372016-10-06 13:26:17 -070071 curl --connect-timeout ${CURL_CONNECTION_TIMEOUT:-20} --retry ${CURL_RETRY:-5} --retry-delay ${CURL_RETRY_DELAY:-0} --retry-max-time ${CURL_RETRY_MAX_TIME:-60} -s -f -L "$url" -o "$jpi"
Carlos Sanchezc0f63792016-08-15 10:30:16 +020072 return $?
apotterebbd13d02016-06-23 12:24:15 -040073}
74
Charles Duffy3eec42c2016-09-20 12:11:33 -050075checkIntegrity() {
Carlos Sanchezc0f63792016-08-15 10:30:16 +020076 local plugin jpi
77 plugin="$1"
78 jpi="$(getArchiveFilename "$plugin")"
apotterebbd13d02016-06-23 12:24:15 -040079
Gareth Harcombe-Minsond6a75122016-09-26 09:59:36 -050080 unzip -t -qq "$jpi" >/dev/null
Carlos Sanchezc0f63792016-08-15 10:30:16 +020081 return $?
apotterebbd13d02016-06-23 12:24:15 -040082}
83
Denis Egorenko6ddff322018-11-08 16:44:02 +040084getPluginDepsPinnedVersion() {
85 local plugin
86 plugin="$1"
87 pinnedPlugin=$(cat $DEPS_PINNING_FILE | grep "^${plugin}:")
88 if [ -n "$pinnedPlugin" ]; then
89 pinnedPluginVersion="$(echo "$pinnedPlugin" | cut -d':' -f2 | tr -d ' ')"
90 printf '%s' "$pinnedPluginVersion"
91 fi
92}
93
Charles Duffy3eec42c2016-09-20 12:11:33 -050094resolveDependencies() {
Carlos Sanchezc0f63792016-08-15 10:30:16 +020095 local plugin jpi dependencies
96 plugin="$1"
97 jpi="$(getArchiveFilename "$plugin")"
Nicolas De Loof0ef5a622016-05-27 19:14:29 +020098
Carlos Sanchezc0f63792016-08-15 10:30:16 +020099 dependencies="$(unzip -p "$jpi" META-INF/MANIFEST.MF | tr -d '\r' | tr '\n' '|' | sed -e 's#| ##g' | tr '|' '\n' | grep "^Plugin-Dependencies: " | sed -e 's#^Plugin-Dependencies: ##')"
Nicolas De Loof0ef5a622016-05-27 19:14:29 +0200100
Carlos Sanchezc0f63792016-08-15 10:30:16 +0200101 if [[ ! $dependencies ]]; then
102 echo " > $plugin has no dependencies"
103 return
104 fi
Nicolas De Loof0ef5a622016-05-27 19:14:29 +0200105
Carlos Sanchezc0f63792016-08-15 10:30:16 +0200106 echo " > $plugin depends on $dependencies"
Nicolas De Loof0ef5a622016-05-27 19:14:29 +0200107
Charles Duffy3eec42c2016-09-20 12:11:33 -0500108 IFS=',' read -r -a array <<< "$dependencies"
apotterebbd13d02016-06-23 12:24:15 -0400109
Carlos Sanchezc0f63792016-08-15 10:30:16 +0200110 for d in "${array[@]}"
111 do
112 plugin="$(cut -d':' -f1 - <<< "$d")"
113 if [[ $d == *"resolution:=optional"* ]]; then
114 echo "Skipping optional dependency $plugin"
115 else
116 local pluginInstalled
Denis Egorenko6ddff322018-11-08 16:44:02 +0400117 local pluginVersion; pluginVersion=$(getPluginDepsPinnedVersion "${plugin}")
Carlos Sanchezc0f63792016-08-15 10:30:16 +0200118 if pluginInstalled="$(echo "${bundledPlugins}" | grep "^${plugin}:")"; then
119 pluginInstalled="${pluginInstalled//[$'\r']}"
120 local versionInstalled; versionInstalled=$(versionFromPlugin "${pluginInstalled}")
Denis Egorenko6ddff322018-11-08 16:44:02 +0400121 local minVersion="$pluginVersion"
122 if [ -z "$minVersion" ]; then
123 minVersion=$(versionFromPlugin "${d}")
124 fi
Carlos Sanchez119703c2016-08-15 10:59:54 +0200125 if versionLT "${versionInstalled}" "${minVersion}"; then
126 echo "Upgrading bundled dependency $d ($minVersion > $versionInstalled)"
Denis Egorenko6ddff322018-11-08 16:44:02 +0400127 download "$plugin" "$pluginVersion" &
Carlos Sanchezc0f63792016-08-15 10:30:16 +0200128 else
Carlos Sanchez119703c2016-08-15 10:59:54 +0200129 echo "Skipping already bundled dependency $d ($minVersion <= $versionInstalled)"
Carlos Sanchezc0f63792016-08-15 10:30:16 +0200130 fi
131 else
Denis Egorenko6ddff322018-11-08 16:44:02 +0400132 download "$plugin" "$pluginVersion" &
Carlos Sanchezc0f63792016-08-15 10:30:16 +0200133 fi
134 fi
135 done
136 wait
Nicolas De Loof0ef5a622016-05-27 19:14:29 +0200137}
138
Charles Duffy3eec42c2016-09-20 12:11:33 -0500139bundledPlugins() {
Carlos Sanchezc0f63792016-08-15 10:30:16 +0200140 local JENKINS_WAR=/usr/share/jenkins/jenkins.war
141 if [ -f $JENKINS_WAR ]
142 then
143 TEMP_PLUGIN_DIR=/tmp/plugintemp.$$
144 for i in $(jar tf $JENKINS_WAR | egrep '[^detached-]plugins.*\..pi' | sort)
145 do
146 rm -fr $TEMP_PLUGIN_DIR
147 mkdir -p $TEMP_PLUGIN_DIR
148 PLUGIN=$(basename "$i"|cut -f1 -d'.')
149 (cd $TEMP_PLUGIN_DIR;jar xf "$JENKINS_WAR" "$i";jar xvf "$TEMP_PLUGIN_DIR/$i" META-INF/MANIFEST.MF >/dev/null 2>&1)
150 VER=$(egrep -i Plugin-Version "$TEMP_PLUGIN_DIR/META-INF/MANIFEST.MF"|cut -d: -f2|sed 's/ //')
151 echo "$PLUGIN:$VER"
152 done
153 rm -fr $TEMP_PLUGIN_DIR
154 else
155 rm -f "$TEMP_ALREADY_INSTALLED"
156 echo "ERROR file not found: $JENKINS_WAR"
157 exit 1
158 fi
Carlos Sancheze1b99f42016-07-06 14:22:39 +0200159}
160
Charles Duffy3eec42c2016-09-20 12:11:33 -0500161versionFromPlugin() {
Carlos Sanchezc0f63792016-08-15 10:30:16 +0200162 local plugin=$1
163 if [[ $plugin =~ .*:.* ]]; then
164 echo "${plugin##*:}"
165 else
166 echo "latest"
167 fi
Carlos Sancheze1b99f42016-07-06 14:22:39 +0200168
169}
170
Charles Duffy3eec42c2016-09-20 12:11:33 -0500171installedPlugins() {
Carlos Sanchezb5ae0c52016-08-15 11:38:24 +0200172 for f in "$REF_DIR"/*.jpi; do
173 echo "$(basename "$f" | sed -e 's/\.jpi//'):$(get_plugin_version "$f")"
174 done
175}
176
apotterebbd13d02016-06-23 12:24:15 -0400177main() {
Carlos Sanchezc0f63792016-08-15 10:30:16 +0200178 local plugin version
Sýlvan Heuserb20f3882016-06-01 15:47:38 +0200179
Carlos Sanchezc0f63792016-08-15 10:30:16 +0200180 mkdir -p "$REF_DIR" || exit 1
Nicolas De Loofa7a34c32016-05-30 09:10:58 +0200181
Carlos Sanchezc0f63792016-08-15 10:30:16 +0200182 # Create lockfile manually before first run to make sure any explicit version set is used.
183 echo "Creating initial locks..."
184 for plugin in "$@"; do
185 mkdir "$(getLockFile "${plugin%%:*}")"
186 done
apotterebbd13d02016-06-23 12:24:15 -0400187
Carlos Sanchez2fb06842016-10-06 14:13:05 -0700188 echo "Analyzing war..."
Carlos Sanchezc0f63792016-08-15 10:30:16 +0200189 bundledPlugins="$(bundledPlugins)"
Carlos Sancheze1b99f42016-07-06 14:22:39 +0200190
Carlos Sanchez2fb06842016-10-06 14:13:05 -0700191 echo "Downloading plugins..."
Carlos Sanchezc0f63792016-08-15 10:30:16 +0200192 for plugin in "$@"; do
193 version=""
apotterebbd13d02016-06-23 12:24:15 -0400194
Carlos Sanchezc0f63792016-08-15 10:30:16 +0200195 if [[ $plugin =~ .*:.* ]]; then
196 version=$(versionFromPlugin "${plugin}")
197 plugin="${plugin%%:*}"
198 fi
apotterebbd13d02016-06-23 12:24:15 -0400199
Carlos Sanchezc0f63792016-08-15 10:30:16 +0200200 download "$plugin" "$version" "true" &
201 done
202 wait
apotterebbd13d02016-06-23 12:24:15 -0400203
Carlos Sanchezb5ae0c52016-08-15 11:38:24 +0200204 echo
205 echo "WAR bundled plugins:"
206 echo "${bundledPlugins}"
207 echo
208 echo "Installed plugins:"
209 installedPlugins
210
Carlos Sanchezc0f63792016-08-15 10:30:16 +0200211 if [[ -f $FAILED ]]; then
Carlos Sanchez2fb06842016-10-06 14:13:05 -0700212 echo "Some plugins failed to download!" "$(<"$FAILED")" >&2
Carlos Sanchezc0f63792016-08-15 10:30:16 +0200213 exit 1
214 fi
apotterebbd13d02016-06-23 12:24:15 -0400215
Carlos Sanchez2fb06842016-10-06 14:13:05 -0700216 echo "Cleaning up locks"
Carlos Sanchezc0f63792016-08-15 10:30:16 +0200217 rm -r "$REF_DIR"/*.lock
apotterebbd13d02016-06-23 12:24:15 -0400218}
219
Brian Antonelli6706b262016-06-24 06:31:54 -0400220main "$@"