Upgrade ARG default values used in Docker FROM instructions - #1213
Draft
timtebeek wants to merge 4 commits into
Draft
Upgrade ARG default values used in Docker FROM instructions#1213timtebeek wants to merge 4 commits into
ARG default values used in Docker FROM instructions#1213timtebeek wants to merge 4 commits into
Conversation
Follow up to #1212, which left any `FROM` built from a variable untouched. When the variable is a global `ARG` with a literal default, that default can be upgraded instead, so `ARG java_version=17` used as `FROM eclipse-temurin:${java_version}` becomes `ARG java_version=25`.
Three follow ups from review:
- A `FROM` whose image we do not upgrade now vetoes the arguments feeding it,
so `ARG VERSION=11` used by both `eclipse-temurin:${VERSION}` and
`node:${VERSION}` is left alone rather than turning the latter into `node:25`.
- Drop the digest pin when an argument holding a whole `name:tag` reference is
upgraded, as the stale digest would keep resolving to the old image.
- Upgrade quoted default values, keeping their quotes. The parser hands an
`ARG` value to us as a single literal with the quotes still in its text and
no quote style, so `ARG JAVA_VERSION="11"` never matched a version before.
Rewriting a `FROM` as it was visited, and only withholding the matching `ARG` bump after the traversal, left half applied edits behind: a dropped digest pin or a rename to `eclipse-temurin` next to an argument still holding the old version. The whole file is now planned up front, and replayed until the set of withheld arguments stops growing, as withholding one argument can rule out the images that depend on it. Only the surviving plan is applied. Every give up path now withholds the arguments that `FROM` reads.
timtebeek
marked this pull request as draft
August 20, 2026 15:20
timtebeek
commented
Aug 20, 2026
Comment on lines
+326
to
+328
| private static class QuotedText { | ||
| String quote; | ||
| String text; |
Member
Author
There was a problem hiding this comment.
Not yet happy with this handling, as I believe it's inconsistent with other usages. Investigating upstream first.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
FROMimages built from variables #1212.What's changed
FROMimages built from variables #1212 madeUpgradeDockerImageVersionskip anyFROMwhose image name or tag contains a$, since the value can not be determined statically. That is the right call for a bareARG IMAGE_TAG, but a great many Dockerfiles pin the Java version in a globalARGwith a default value:Here the value is statically known, and the version can be bumped by rewriting the
ARGdefault rather than theFROM.The visitor now collects the literal defaults of the global
ARGs (those before the firstFROM, which are the only ones aFROMcan reference) and resolves variable image references against them. When the resolved reference is an upgradable Java image, it writes the upgrade back to whichever of the two carries the value:ARG java_version=17FROM eclipse-temurin:${java_version}ARG java_version=25FROM eclipse-temurin:${java_version}ARG JAVA_VERSION=11FROM eclipse-temurin:${JAVA_VERSION}-jreARG JAVA_VERSION=25FROM eclipse-temurin:${JAVA_VERSION}-jreARG IMAGE_TAG=11-jre-alpineFROM eclipse-temurin:${IMAGE_TAG}ARG IMAGE_TAG=25-jre-alpineFROM eclipse-temurin:${IMAGE_TAG}ARG BASE_IMAGE=openjdk:11-jreFROM ${BASE_IMAGE}ARG BASE_IMAGE=eclipse-temurin:25-jreFROM ${BASE_IMAGE}ARG BASE_IMAGE=openjdkFROM ${BASE_IMAGE}:11-jreARG BASE_IMAGE=eclipse-temurinFROM ${BASE_IMAGE}:25-jreNote the last two: an
openjdkbase has no tag beyond 17, so the deprecated image name has to move toeclipse-temurinalong with the tag, whether that name sits in theFROMor in theARG.Everything that can not be resolved is still left untouched: an
ARGwithout a default, anARGwhose default is itself built from another variable, a variable that only contributes part of the image name (FROM ${REGISTRY}/eclipse-temurin:11-jre), a variable that does not supply the leading version (FROM eclipse-temurin:11${SUFFIX}), and anyARGdeclared after the firstFROM.ARGs that are not used in aFROMat all are never rewritten. As before, a digest pin is dropped when the tag is upgraded.The fully literal
FROMpath is unchanged.Tests
Added parameterized cases for each row of the table above, plus multi-stage
ARGreuse, digest pin removal through anARG, and a set of negative cases covering the unresolvable and unrelated shapes. The existing tests are unchanged and still pass.