Why can upgrading Jenkins plugins be risky, and what does the LTS release line have to do with it?
answer
- two release lines, independent schedules
- manifest declares a minimum core
- one copy of each plugin, shared
- the cascade reaches the JVM
- rehearse on a staging JENKINS_HOME copy
basics
~20 sPlugins and Jenkins core release on separate schedules, and each plugin declares a minimum core version. Upgrading one plugin can pull its dependencies, the core, and even the JVM forward — so upgrades are coupled, never isolated.
solid answer
~50 sJenkins core ships weekly releases plus an LTS line, which adopts one weekly as a baseline roughly every twelve weeks and then receives backported fixes as patch releases such as 2.479.1, 2.479.2. Plugins ship on their own schedules with no coordinated train, and each declares a minimum core in its `Jenkins-Version` manifest attribute. When a maintainer raises that baseline, the newest version of a plugin you depend on suddenly demands a newer core — and a core upgrade may in turn demand a newer Java. Upgrades also spread sideways: exactly one copy of each plugin is loaded, so upgrading one plugin bumps a shared dependency for everything else. Plugin version numbers often carry no semantic meaning, so you cannot infer risk from the number. Practically: track LTS, upgrade in batches on a staging controller, and keep the plugin count small.
code
bash · 2 lines# Which installed plugins have an update waiting? A trailing "(x.y)" marks one.
java -jar jenkins-cli.jar -s "$JENKINS_URL" -auth @token.txt list-plugins | grep '('go deeper
Know that Jenkins has weekly and LTS releases, that production should run LTS, and that plugin updates are not automatically safe just because the Updates tab offers them.
Explain the coupling concretely: the minimum-core manifest attribute, one shared copy of each dependency plugin, and the cascade from plugin to core to Java version.
Show a rehearsal and recovery plan — staging controller from a JENKINS_HOME copy, batched upgrades, and the offline .bak restore when the controller will not start.
Own the cadence question: how far behind the current LTS the organisation is willing to sit, who pays for the upgrade window, and how plugin count feeds directly into that cost.
## Two release lines that do not move together Jenkins core ships two ways. **Weekly** releases (2.x) come out most weeks and carry new features immediately. The **LTS** line picks one weekly as a baseline about every twelve weeks and then publishes patch releases against it — versions of the form 2.479.1, 2.479.2, where 2.479 is the chosen weekly and the last digit is the patch level. LTS carries backported fixes only, so it is the line almost every production controller should sit on. Plugins have no such train. Each plugin is released by its own maintainer whenever they like, with no coordination across the ecosystem and no guarantee that two plugins you use were ever tested together at the versions you are running. ## What actually couples plugins to core Every plugin release declares `Jenkins-Version` in its manifest: the oldest core it will run on. Maintainers periodically raise that baseline, and the project's guidance encourages targeting a reasonably recent LTS. The moment a maintainer bumps it past your core, the Plugin Manager stops offering you that plugin's newest version — it shows a compatibility warning instead. You are pinned to an older release, and if a security advisory lands on that older release, the only fix is to move core first. Core upgrades then have their own prerequisites. The project has moved its minimum Java baseline forward more than once (from 8, to 11, to 17, with newer LTS support added since), so a chain that started as "upgrade one plugin" can end as "upgrade the JVM and the base image". That cascade is the honest answer to why teams postpone Jenkins upgrades until they are painful. ## Why one plugin upgrade moves plugins you did not touch A controller loads **exactly one** copy of each plugin. There is no per-consumer version resolution as in a language package manager: if plugin A requires Credentials at version X or newer, upgrading A upgrades Credentials for every other plugin in the JVM at the same time. A dependency graph across sixty or a hundred plugins therefore behaves like a single lockstep application — one upgrade ripples, and the blast radius is the whole controller rather than one job. ## Version numbers tell you almost nothing Many plugins publish versions derived from the build rather than from semantic versioning — a large number followed by a commit-derived suffix. Others use plain sequential numbers. Either way you cannot read "patch" or "breaking" out of the number the way you can with a strict semver library. The changelog on the plugin's page is the only real signal, which is why blanket "update all" clicks are how controllers break. ## The failure mode, and why it stings Upgrades run live against a stateful controller. A bad plugin version can fail to load, and jobs whose configuration references its classes can fail to deserialize; in the worst case the controller does not come back up at all. Recovery is then **offline**, because the UI you would fix it in is the thing that is down: ```bash # On the controller host, with Jenkins stopped cd "$JENKINS_HOME/plugins" mv bad-plugin.jpi.bak bad-plugin.jpi # restore the pre-upgrade file rm -rf bad-plugin # drop the exploded directory ``` Jenkins keeps the previous file as `<shortname>.jpi.bak` on upgrade, which is also what the Installed tab's "Downgrade" button uses when the UI is still reachable. ## What good practice looks like - **Sit on LTS** and upgrade core on its cadence rather than drifting years behind. Distance from the current baseline is what makes an upgrade a project instead of a maintenance task. - **Batch plugin upgrades on a staging controller** restored from a copy of `JENKINS_HOME`, then promote the same set. Testing against real job configs is the only test that means anything, because the risk lives in your job definitions as much as in the plugins. - **Read security advisories** and prioritise by exposure rather than by what the Updates tab lists first. - **Keep the plugin list small.** Every extra plugin is another maintainer who gets a vote on when you may upgrade core. - **Pin versions declaratively** so an upgrade arrives as a reviewable diff and a rollback is redeploying the previous build, instead of a click nobody recorded. ## The interview point The candidate who says "upgrade regularly, it is fine" has not run an old controller. The one who says "never upgrade" has not read an advisory. The good answer describes the coupling — plugin to plugin, plugin to core, core to JVM — and then describes a cadence and a rehearsal step that make the coupling survivable.
- A plugin update you need requires a newer Jenkins core than you run. What are your options?Three, in order of preference: upgrade core to the LTS line that satisfies the baseline, which usually means also checking the Java requirement; stay on the older plugin version and mitigate around it if the driver was a bug rather than an advisory; or drop the plugin and do the work another way. Standing still indefinitely is not an option once advisories accumulate.
- A plugin upgrade leaves Jenkins unable to start. How do you roll it back?Offline, on the controller's filesystem, since the UI is unavailable. Stop Jenkins, go to `$JENKINS_HOME/plugins`, restore the `<shortname>.jpi.bak` file the upgrade left behind or delete the `.jpi` plus its exploded directory, then start again. If the plugin was a dependency of others, expect those to disable themselves until it is back.
- Why is "select all updates and install" a bad habit on a production controller?Because plugin versions carry little semantic meaning, so the list mixes trivial fixes with breaking changes, and each entry drags transitive dependencies forward for every other plugin. You end up with an untested combination that you cannot easily bisect when a job breaks. Batching deliberately, on a staging copy first, keeps failures attributable.
It is like upgrading system packages with no lockfile and exactly one copy of every shared library: a single install pulls the whole dependency graph forward, and the machine either boots afterwards or it does not.
saying these in an interview costs you the question
- Thinks plugins are versioned together with core
- Assumes each plugin loads its own dependency versions
- Reads plugin version numbers as semver
- Believes an LTS controller can never break on plugin updates
- Plans rollback through a UI that a failed upgrade took down