Update Jenkins core and plugins: 2022Q1 edition
- Last time: #17799 (closed)
- Current installed version: 2.289.2
- Latest version available in the upstream repo: 2.332.1
Update steps
Preparation:
-
Create a list of plugins actively/directly used by Tails (see: #17799 (comment 173701)). -
Go through the changelog, paying attention to changes on how agents connect to controller, config changes that may need update, important changes in plugins, etc. -
Check whether we can turn on "Agent to master security subsystem"
Deployment:
-
Take note of currently running builds before starting the upgrades -
Deploy Jenkins upgrade -
Deploy plugins upgrades -
Restart all agents. -
Manually run the Update jobs script (may be needed so XML is valid with current Jenkins): sudo -u jenkins /usr/local/sbin/deploy_jenkins_jobs update
Wrap up:
-
Go through warnings in Jenkins interface. -
Manually remove removed plugins or fix Puppet code to do this automatically. -
Restart builds that were interrupted by Jenkins restart -
Schedule next update → #17894 (closed) -
Document use of port 42585: #17800 (closed) -
Document the list of actively used plugins as well as the Groovy and Python scripts -
Change master
→built-in
in our Jenkins jobs config and apply migration manually by clicking on the "Apply Migration" button in the yellow notification on the top of the "Manage Jenkins" page.
Relevant bits from CHANGELOGs (2.289 → 2.338)
- 2.307: replaced "master" with "controller" :-)
- 2.326: The agent-to-controller security subsystem is now always enabled. The admin-customizable allowlists for callables and file paths have been removed. The ability to access some files on the controller from agents has been removed. Some plugins are incompatible with this change and may need to be updated. (pull 5885, issue 67173, the issue tracker)
Plugins
Plugins included with Jenkins (in bold are the ones our tests directly rely on):
- antisamy-markup-formatter
- bouncycastle-api
- command-launcher
- display-url-api
- external-monitor-job
- jaxb
- jdk-tool
- junit
- ldap
- mailer
- matrix-auth
- matrix-project
- pam-auth
- scm-api
- script-security
- sshd
- structs
- trilead-api
- windows-slaves
- workflow-api
- workflow-step-api
Other installed plugins (in bold are the ones our tests directly rely on):
- apache-httpcomponents-client-4-api
- bootstrap4-api
- bootstrap5-api
- build-symlink
- build-timeout
- caffeine-api
- checks-api
- cloudbees-folder
- cluster-stats
- conditional-buildstep
- copyartifact
- credentials
- credentials-binding
- cucumber-reports
- cucumber-testresult-plugin → now unused since we use cucumber-reports?
- downstream-ext
- durable-task
- echarts-api
- email-ext
- envinject
- envinject-api
- font-awesome-api
- git
- git-client
- global-build-stats
- jackson2-api
- javadoc
- jquery3-api
- jsch
- mapdb-api
- maven-plugin
- parameterized-trigger
- plain-credentials
- plugin-util-api
- popper2-api
- popper-api
- postbuildscript
- PrioritySorter
- resource-disposer
- run-condition
- scm-sync-configuration
- scoring-load-balancer
- simple-theme-plugin
- snakeyaml-api
- ssh-credentials
- subversion
- timestamper
- token-macro
- workflow-durable-task-step
- workflow-scm-step
- workflow-support
- ws-cleanup
Plugin Updates
The following Groovy script provides a list of upgradable plugins, their latest versions and the URL from where to download them:
initialList = [
'build-symlink',
'build-timeout',
'cluster-stats',
'conditional-buildstep',
'copyartifact',
'cucumber-reports',
'email-ext',
'envinject',
'git',
'git-client',
'global-build-stats',
'junit',
'matrix-project',
'parameterized-trigger',
'postbuildscript',
'PrioritySorter',
'scm-api',
'timestamper',
'ws-cleanup',
]
plugins = [:]
def getLatestInfo(shortName) {
if (plugins.containsKey(shortName))
return
def plugin = Jenkins.instance.updateCenter.getPlugin(shortName)
def version = plugin.version
def deps = plugin.dependencies
def depList = []
def depShortName = ''
deps.each { dep ->
// Some dependencies are returned as hudson.PluginWrapper$Dependency
// while others are java.util.HashMap$Node (no idea why!).
if (dep.getClass() == hudson.PluginWrapper$Dependency) {
depShortName = dep.shortName
} else if (dep.getClass() == java.util.HashMap$Node) {
depShortName = dep.getKey()
}
getLatestInfo(depShortName)
depList.add(depShortName)
}
plugins.put(shortName, [
'version': version,
'dependencies': depList.toSet().sort()
])
}
initialList.each { shortName ->
getLatestInfo(shortName)
}
for (key in plugins.keySet().sort{ it.toLowerCase() }) {
println "${key} ${plugins[key]['version']} ${plugins[key]['dependencies']}"
}
This is the output of the above script:
antisamy-markup-formatter 2.7 [javax-activation-api, javax-mail-api, sshd]
apache-httpcomponents-client-4-api 4.5.13-1.0 [command-launcher, javax-activation-api, javax-mail-api, jaxb, jdk-tool, sshd, trilead-api]
bootstrap4-api 4.6.0-3 [font-awesome-api, javax-activation-api, javax-mail-api, jquery3-api, popper-api, sshd]
bootstrap5-api 5.1.3-6 [font-awesome-api, javax-activation-api, javax-mail-api, popper2-api]
bouncycastle-api 2.25 [javax-activation-api, javax-mail-api, sshd]
build-timeout 1.20 [javax-activation-api, javax-mail-api, sshd, token-macro]
caffeine-api 2.9.2-29.v717aac953ff3 [javax-activation-api, javax-mail-api, sshd]
checks-api 1.7.2 [display-url-api, javax-activation-api, javax-mail-api, plugin-util-api, sshd, workflow-step-api, workflow-support]
cloudbees-folder 6.714.v79e858ef76a_2 [javax-activation-api, javax-mail-api, sshd]
cluster-stats 0.4.6 [bouncycastle-api, command-launcher, javax-activation-api, javax-mail-api, jaxb, jdk-tool, junit, matrix-project, sshd, trilead-api]
command-launcher 1.6 [javax-activation-api, javax-mail-api, script-security, sshd]
conditional-buildstep 1.4.2 [javax-activation-api, javax-mail-api, run-condition, token-macro]
copyartifact 1.46.3 [apache-httpcomponents-client-4-api, javax-activation-api, javax-mail-api, matrix-project, sshd, structs, trilead-api]
credentials 1074.v60e6c29b_b_44b_ [javax-activation-api, javax-mail-api, structs]
credentials-binding 1.27.1 [credentials, javax-activation-api, javax-mail-api, plain-credentials, ssh-credentials, sshd, structs, workflow-step-api]
cucumber-reports 5.7.0 [javax-activation-api, javax-mail-api, sshd, structs, token-macro]
display-url-api 2.3.6 []
echarts-api 5.3.0-2 [bootstrap5-api, font-awesome-api, jackson2-api, javax-activation-api, javax-mail-api, jquery3-api, plugin-util-api]
email-ext 2.87 [credentials, jackson2-api, javax-activation-api, javax-mail-api, junit, mailer, matrix-project, script-security, sshd, structs, token-macro]
envinject 2.839.v52c702c10635 [envinject-api, javax-activation-api, javax-mail-api, matrix-project, script-security]
envinject-api 1.180.v98d833b_27470 [javax-activation-api, javax-mail-api]
font-awesome-api 6.0.0-1 [javax-activation-api, javax-mail-api, plugin-util-api]
git 4.10.3 [credentials, credentials-binding, git-client, javax-activation-api, javax-mail-api, mailer, scm-api, script-security, ssh-credentials, structs, workflow-scm-step, workflow-step-api]
git-client 3.11.0 [apache-httpcomponents-client-4-api, credentials, javax-activation-api, javax-mail-api, jsch, script-security, ssh-credentials, structs, trilead-api]
global-build-stats 1.5 [bouncycastle-api, cloudbees-folder, command-launcher, javax-activation-api, javax-mail-api, jaxb, jdk-tool, sshd, trilead-api]
jackson2-api 2.13.2-260.v43d711474c77 [javax-activation-api, javax-mail-api, snakeyaml-api, sshd]
javax-activation-api 1.2.0-2 []
javax-mail-api 1.6.2-5 [javax-activation-api]
jaxb 2.3.0.1 [javax-activation-api, javax-mail-api, sshd, trilead-api]
jdk-tool 1.5 [javax-activation-api, javax-mail-api, sshd, trilead-api]
jquery3-api 3.6.0-2 [javax-activation-api, javax-mail-api, sshd]
jsch 0.1.55.2 [javax-activation-api, javax-mail-api, ssh-credentials, sshd, trilead-api]
junit 1.56 [bootstrap4-api, checks-api, display-url-api, echarts-api, jackson2-api, javax-activation-api, javax-mail-api, plugin-util-api, script-security, workflow-api, workflow-step-api]
mailer 408.vd726a_1130320 [display-url-api, javax-activation-api, javax-mail-api]
matrix-project 758.v7a_ea_491852f3 [javax-activation-api, javax-mail-api, junit, script-security]
parameterized-trigger 2.44 [javax-activation-api, javax-mail-api, matrix-project, script-security, sshd]
plain-credentials 1.8 [credentials, javax-activation-api, javax-mail-api, sshd]
plugin-util-api 2.15.0 [javax-activation-api, javax-mail-api]
popper-api 1.16.1-2 [javax-activation-api, javax-mail-api, sshd]
popper2-api 2.11.4-1 [javax-activation-api, javax-mail-api]
postbuildscript 3.1.0-375.v3db_cd92485e1 [javax-activation-api, javax-mail-api, matrix-project]
PrioritySorter 4.1.0 [javax-activation-api, javax-mail-api, sshd]
resource-disposer 0.17 [javax-activation-api, javax-mail-api, sshd]
run-condition 1.5 [javax-activation-api, javax-mail-api, sshd, token-macro]
scm-api 595.vd5a_df5eb_0e39 [javax-activation-api, javax-mail-api, structs]
script-security 1145.vb_cf6cf6ed960 [caffeine-api]
snakeyaml-api 1.29.1 [javax-activation-api, javax-mail-api, sshd]
ssh-credentials 1.19 [credentials, javax-activation-api, javax-mail-api, trilead-api]
sshd 3.1.0 [javax-activation-api, javax-mail-api]
structs 308.v852b473a2b8c [javax-activation-api, javax-mail-api, sshd]
timestamper 1.17 [antisamy-markup-formatter, javax-activation-api, javax-mail-api, sshd, workflow-api, workflow-step-api]
token-macro 280.v97a_82642793c [javax-activation-api, javax-mail-api, structs]
trilead-api 1.0.13 [javax-activation-api, javax-mail-api, sshd]
workflow-api 1143.v2d42f1e9dea_5 [javax-activation-api, javax-mail-api, scm-api, sshd, workflow-step-api]
workflow-scm-step 2.13 [javax-activation-api, javax-mail-api, sshd, workflow-step-api]
workflow-step-api 622.vb_8e7c15b_c95a_ [javax-activation-api, javax-mail-api, sshd, structs]
workflow-support 815.vd60466279fc8 [caffeine-api, javax-activation-api, javax-mail-api, scm-api, script-security, workflow-api, workflow-step-api]
ws-cleanup 0.40 [javax-activation-api, javax-mail-api, matrix-project, resource-disposer, sshd, structs]
And here's some Python3 code to parse the output of the above script and generate Puppet code:
#!/usr/bin/python3
import argparse
import fileinput
import re
import requests
from bs4 import BeautifulSoup
BASE_URL = 'https://updates.jenkins.io/download/plugins'
def fetch_hash(plugin):
url = BASE_URL + '/' + plugin
page = requests.get(url)
soup = BeautifulSoup(page.text, 'html.parser')
h = next(filter(lambda e: 'SHA-256' in e.text, soup.findAll('div', {'class':'checksums'}))).findChildren('code')[0].text
return h
def parse_plugins(path):
with open(path) as f:
lines = f.readlines()
plugins = {}
for l in lines:
plugin, version, rawdeps = l.split(' ', maxsplit=2)
plugins[plugin] = version
rawdeplist = rawdeps.strip('[]\n').split(' ')
deps = []
for rawdep in rawdeplist:
depname = rawdep.rstrip(',')
if (depname):
deps.append(depname)
plugins[plugin] = {'version': version, 'deps': deps}
return plugins
def print_puppet_code(plugins):
for plugin, data in plugins.items():
h = fetch_hash(plugin)
print(' jenkins::plugin { \'' + plugin + '\':')
print(' version => \'' + data['version'] + '\',')
print(' digest_string => \'' + h + '\',')
print(' digest_type => \'sha256\',')
if data['deps']:
print(' require => Jenkins::Plugin[')
for dep in data['deps']:
print(' \'' + dep + '\',')
print(' ],')
print(' }')
print('')
def main(path):
plugins = parse_plugins(path)
print_puppet_code(plugins)
if __name__ == '__main__':
p = argparse.ArgumentParser()
p.add_argument('file', help='The input file, as generated by the Groovy script')
args = p.parse_args()
main(args.file)
Edited by Zen Fu