From de67ef56b09423a0fe29d9e50e526a16df852a6f Mon Sep 17 00:00:00 2001 From: Gordon Beeming Date: Mon, 29 Jun 2026 17:36:51 +1000 Subject: [PATCH 1/3] fix(docker): resolve toolchain versions at build time instead of pinning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Build java job 404'd because the Eclipse JDT language server was pinned to a milestone URL, and Eclipse deletes old milestones. The same pinned-version pattern applied to Go, Maven, Gradle, and PlantUML — they don't 404 but go stale and need manual bumps. Mirror the .NET snippets (which resolve latest-in-channel at build time): each tool now resolves its current version during docker build, with an optional ARG to pin. Generated Dockerfiles no longer carry version numbers, so the version rot can't recur. - JDTLS: download the stable snapshots/jdt-language-server-latest.tar.gz symlink - Go: resolve from go.dev/VERSION - Gradle: resolve from services.gradle.org/versions/current - PlantUML: GitHub latest-release unversioned asset - Maven: latest stable 3.9.x from the dlcdn listing (maven-metadata is a Maven 4 RC, which we don't want) Each resolve step guards against an empty result so the build fails loudly rather than producing a broken image. Co-authored-by: Claude Co-authored-by: GitButler --- docker/generated/Dockerfile.golang | 9 ++++--- docker/generated/Dockerfile.java | 40 +++++++++++++++++++---------- docker/snippets/golang.Dockerfile | 9 ++++--- docker/snippets/java.Dockerfile | 31 ++++++++++++++-------- docker/snippets/lsp-java.Dockerfile | 9 ++++--- 5 files changed, 64 insertions(+), 34 deletions(-) diff --git a/docker/generated/Dockerfile.golang b/docker/generated/Dockerfile.golang index 81c885f..bf567d9 100644 --- a/docker/generated/Dockerfile.golang +++ b/docker/generated/Dockerfile.golang @@ -76,12 +76,15 @@ RUN ARCH=$(dpkg --print-architecture) \ # --- snippet: golang --- # Install Go # Using official Go installation method -ENV GOLANG_VERSION=1.26.3 ENV GOPATH=/usr/local/go-workspace ENV PATH="/usr/local/go/bin:${GOPATH}/bin:${PATH}" -# Install Go from official tarball -RUN curl -fsSL "https://go.dev/dl/go${GOLANG_VERSION}.linux-$(dpkg --print-architecture).tar.gz" -o go.tar.gz \ +# Resolve the latest stable Go at image-build time (go.dev/VERSION returns the +# current release, e.g. "go1.26.4"). Set GOLANG_VERSION (same "goX.Y.Z" form) to pin. +ARG GOLANG_VERSION +RUN ver="${GOLANG_VERSION:-$(curl -fsSL 'https://go.dev/VERSION?m=text' | head -1)}" \ + && test -n "$ver" \ + && curl -fsSL "https://go.dev/dl/${ver}.linux-$(dpkg --print-architecture).tar.gz" -o go.tar.gz \ && tar -C /usr/local -xzf go.tar.gz \ && rm go.tar.gz diff --git a/docker/generated/Dockerfile.java b/docker/generated/Dockerfile.java index 5a39ca2..6d5bdab 100644 --- a/docker/generated/Dockerfile.java +++ b/docker/generated/Dockerfile.java @@ -89,23 +89,32 @@ ENV JAVA_HOME=/usr/lib/jvm/temurin-25-jdk ENV PATH="${JAVA_HOME}/bin:${PATH}" -# Install Maven -ARG MAVEN_VERSION=3.9.9 -RUN curl -fsSL "https://archive.apache.org/dist/maven/maven-3/${MAVEN_VERSION}/binaries/apache-maven-${MAVEN_VERSION}-bin.tar.gz" -o maven.tar.gz \ +# Install Maven. Resolve the latest stable 3.9.x at build time from the Apache +# mirror listing (the maven-metadata tag points at Maven 4 RCs, which +# we don't want). Set MAVEN_VERSION to pin a specific 3.x release. +ARG MAVEN_VERSION +RUN ver="${MAVEN_VERSION:-$(curl -fsSL https://dlcdn.apache.org/maven/maven-3/ | grep -oE '3\.[0-9]+\.[0-9]+/' | tr -d / | sort -uV | tail -1)}" \ + && test -n "$ver" \ + && curl -fsSL "https://dlcdn.apache.org/maven/maven-3/${ver}/binaries/apache-maven-${ver}-bin.tar.gz" -o maven.tar.gz \ && tar -C /usr/local -xzf maven.tar.gz \ - && ln -s /usr/local/apache-maven-${MAVEN_VERSION}/bin/mvn /usr/local/bin/mvn \ + && ln -s "/usr/local/apache-maven-${ver}/bin/mvn" /usr/local/bin/mvn \ && rm maven.tar.gz -# Install Gradle -ARG GRADLE_VERSION=8.12 -RUN curl -fsSL "https://services.gradle.org/distributions/gradle-${GRADLE_VERSION}-bin.zip" -o gradle.zip \ +# Install Gradle. Resolve the current release at build time from the Gradle +# version API. Set GRADLE_VERSION to pin a specific release. +ARG GRADLE_VERSION +RUN ver="${GRADLE_VERSION}" \ + && if [ -z "$ver" ]; then ver="$(curl -fsSL https://services.gradle.org/versions/current | grep -oP '"version"\s*:\s*"\K[^"]+')"; fi \ + && test -n "$ver" \ + && curl -fsSL "https://services.gradle.org/distributions/gradle-${ver}-bin.zip" -o gradle.zip \ && unzip -d /usr/local gradle.zip \ - && ln -s /usr/local/gradle-${GRADLE_VERSION}/bin/gradle /usr/local/bin/gradle \ + && ln -s "/usr/local/gradle-${ver}/bin/gradle" /usr/local/bin/gradle \ && rm gradle.zip -# Install PlantUML -ARG PLANTUML_VERSION=1.2025.2 -RUN curl -fsSL "https://github.com/plantuml/plantuml/releases/download/v${PLANTUML_VERSION}/plantuml-${PLANTUML_VERSION}.jar" -o /usr/local/lib/plantuml.jar \ +# Install PlantUML. The GitHub "latest release" exposes a stable unversioned +# asset URL, and the jar lands at a version-free path. Set PLANTUML_URL to pin. +ARG PLANTUML_URL=https://github.com/plantuml/plantuml/releases/latest/download/plantuml.jar +RUN curl -fsSL "${PLANTUML_URL}" -o /usr/local/lib/plantuml.jar \ && echo '#!/bin/sh\nexec java -jar /usr/local/lib/plantuml.jar "$@"' > /usr/local/bin/plantuml \ && chmod +x /usr/local/bin/plantuml @@ -133,10 +142,13 @@ # --- snippet: lsp-java --- # Install Eclipse JDT Language Server for Java code intelligence -ARG JDTLS_VERSION=1.43.0 -ARG JDTLS_TIMESTAMP=202412191447 +# Resolve the latest build at image-build time. Eclipse only retains the most +# recent milestone, so any pinned milestone URL eventually 404s; the snapshots +# `-latest.tar.gz` symlink always points at the current build. Set JDTLS_URL to +# a specific versioned tarball to pin. +ARG JDTLS_URL=https://download.eclipse.org/jdtls/snapshots/jdt-language-server-latest.tar.gz RUN mkdir -p /usr/local/share/jdtls \ - && curl -fsSL "https://download.eclipse.org/jdtls/milestones/${JDTLS_VERSION}/jdt-language-server-${JDTLS_VERSION}-${JDTLS_TIMESTAMP}.tar.gz" -o jdtls.tar.gz \ + && curl -fsSL "${JDTLS_URL}" -o jdtls.tar.gz \ && tar -C /usr/local/share/jdtls -xzf jdtls.tar.gz \ && rm jdtls.tar.gz diff --git a/docker/snippets/golang.Dockerfile b/docker/snippets/golang.Dockerfile index 0442150..b4b15b1 100644 --- a/docker/snippets/golang.Dockerfile +++ b/docker/snippets/golang.Dockerfile @@ -1,11 +1,14 @@ # Install Go # Using official Go installation method -ENV GOLANG_VERSION=1.26.3 ENV GOPATH=/usr/local/go-workspace ENV PATH="/usr/local/go/bin:${GOPATH}/bin:${PATH}" -# Install Go from official tarball -RUN curl -fsSL "https://go.dev/dl/go${GOLANG_VERSION}.linux-$(dpkg --print-architecture).tar.gz" -o go.tar.gz \ +# Resolve the latest stable Go at image-build time (go.dev/VERSION returns the +# current release, e.g. "go1.26.4"). Set GOLANG_VERSION (same "goX.Y.Z" form) to pin. +ARG GOLANG_VERSION +RUN ver="${GOLANG_VERSION:-$(curl -fsSL 'https://go.dev/VERSION?m=text' | head -1)}" \ + && test -n "$ver" \ + && curl -fsSL "https://go.dev/dl/${ver}.linux-$(dpkg --print-architecture).tar.gz" -o go.tar.gz \ && tar -C /usr/local -xzf go.tar.gz \ && rm go.tar.gz diff --git a/docker/snippets/java.Dockerfile b/docker/snippets/java.Dockerfile index ae8e0da..896e727 100644 --- a/docker/snippets/java.Dockerfile +++ b/docker/snippets/java.Dockerfile @@ -13,23 +13,32 @@ RUN ln -s /usr/lib/jvm/temurin-25-jdk-$(dpkg --print-architecture) /usr/lib/jvm/ ENV JAVA_HOME=/usr/lib/jvm/temurin-25-jdk ENV PATH="${JAVA_HOME}/bin:${PATH}" -# Install Maven -ARG MAVEN_VERSION=3.9.9 -RUN curl -fsSL "https://archive.apache.org/dist/maven/maven-3/${MAVEN_VERSION}/binaries/apache-maven-${MAVEN_VERSION}-bin.tar.gz" -o maven.tar.gz \ +# Install Maven. Resolve the latest stable 3.9.x at build time from the Apache +# mirror listing (the maven-metadata tag points at Maven 4 RCs, which +# we don't want). Set MAVEN_VERSION to pin a specific 3.x release. +ARG MAVEN_VERSION +RUN ver="${MAVEN_VERSION:-$(curl -fsSL https://dlcdn.apache.org/maven/maven-3/ | grep -oE '3\.[0-9]+\.[0-9]+/' | tr -d / | sort -uV | tail -1)}" \ + && test -n "$ver" \ + && curl -fsSL "https://dlcdn.apache.org/maven/maven-3/${ver}/binaries/apache-maven-${ver}-bin.tar.gz" -o maven.tar.gz \ && tar -C /usr/local -xzf maven.tar.gz \ - && ln -s /usr/local/apache-maven-${MAVEN_VERSION}/bin/mvn /usr/local/bin/mvn \ + && ln -s "/usr/local/apache-maven-${ver}/bin/mvn" /usr/local/bin/mvn \ && rm maven.tar.gz -# Install Gradle -ARG GRADLE_VERSION=8.12 -RUN curl -fsSL "https://services.gradle.org/distributions/gradle-${GRADLE_VERSION}-bin.zip" -o gradle.zip \ +# Install Gradle. Resolve the current release at build time from the Gradle +# version API. Set GRADLE_VERSION to pin a specific release. +ARG GRADLE_VERSION +RUN ver="${GRADLE_VERSION}" \ + && if [ -z "$ver" ]; then ver="$(curl -fsSL https://services.gradle.org/versions/current | grep -oP '"version"\s*:\s*"\K[^"]+')"; fi \ + && test -n "$ver" \ + && curl -fsSL "https://services.gradle.org/distributions/gradle-${ver}-bin.zip" -o gradle.zip \ && unzip -d /usr/local gradle.zip \ - && ln -s /usr/local/gradle-${GRADLE_VERSION}/bin/gradle /usr/local/bin/gradle \ + && ln -s "/usr/local/gradle-${ver}/bin/gradle" /usr/local/bin/gradle \ && rm gradle.zip -# Install PlantUML -ARG PLANTUML_VERSION=1.2025.2 -RUN curl -fsSL "https://github.com/plantuml/plantuml/releases/download/v${PLANTUML_VERSION}/plantuml-${PLANTUML_VERSION}.jar" -o /usr/local/lib/plantuml.jar \ +# Install PlantUML. The GitHub "latest release" exposes a stable unversioned +# asset URL, and the jar lands at a version-free path. Set PLANTUML_URL to pin. +ARG PLANTUML_URL=https://github.com/plantuml/plantuml/releases/latest/download/plantuml.jar +RUN curl -fsSL "${PLANTUML_URL}" -o /usr/local/lib/plantuml.jar \ && echo '#!/bin/sh\nexec java -jar /usr/local/lib/plantuml.jar "$@"' > /usr/local/bin/plantuml \ && chmod +x /usr/local/bin/plantuml diff --git a/docker/snippets/lsp-java.Dockerfile b/docker/snippets/lsp-java.Dockerfile index 8b1f08a..386e671 100644 --- a/docker/snippets/lsp-java.Dockerfile +++ b/docker/snippets/lsp-java.Dockerfile @@ -1,8 +1,11 @@ # Install Eclipse JDT Language Server for Java code intelligence -ARG JDTLS_VERSION=1.43.0 -ARG JDTLS_TIMESTAMP=202412191447 +# Resolve the latest build at image-build time. Eclipse only retains the most +# recent milestone, so any pinned milestone URL eventually 404s; the snapshots +# `-latest.tar.gz` symlink always points at the current build. Set JDTLS_URL to +# a specific versioned tarball to pin. +ARG JDTLS_URL=https://download.eclipse.org/jdtls/snapshots/jdt-language-server-latest.tar.gz RUN mkdir -p /usr/local/share/jdtls \ - && curl -fsSL "https://download.eclipse.org/jdtls/milestones/${JDTLS_VERSION}/jdt-language-server-${JDTLS_VERSION}-${JDTLS_TIMESTAMP}.tar.gz" -o jdtls.tar.gz \ + && curl -fsSL "${JDTLS_URL}" -o jdtls.tar.gz \ && tar -C /usr/local/share/jdtls -xzf jdtls.tar.gz \ && rm jdtls.tar.gz From e54790344f7ce72df8ab019950f267002714d6a9 Mon Sep 17 00:00:00 2001 From: Gordon Beeming Date: Mon, 29 Jun 2026 17:49:05 +1000 Subject: [PATCH 2/3] fix(docker): address review feedback on version resolution - Maven: download from archive.apache.org (keeps all releases) while still resolving the latest from the dlcdn listing, so a pinned older MAVEN_VERSION doesn't 404 on dlcdn (which prunes old versions). - Go: strip a leading 'go' from the resolved/pinned version and re-prepend it, so GOLANG_VERSION accepts either '1.26.3' or 'go1.26.3'. - Gradle: use ${GRADLE_VERSION:-...} parameter expansion for consistency with the Go and Maven snippets. Co-authored-by: Claude Co-authored-by: GitButler --- docker/generated/Dockerfile.golang | 6 ++++-- docker/generated/Dockerfile.java | 13 +++++++------ docker/snippets/golang.Dockerfile | 6 ++++-- docker/snippets/java.Dockerfile | 13 +++++++------ 4 files changed, 22 insertions(+), 16 deletions(-) diff --git a/docker/generated/Dockerfile.golang b/docker/generated/Dockerfile.golang index bf567d9..4949beb 100644 --- a/docker/generated/Dockerfile.golang +++ b/docker/generated/Dockerfile.golang @@ -80,11 +80,13 @@ ENV GOPATH=/usr/local/go-workspace ENV PATH="/usr/local/go/bin:${GOPATH}/bin:${PATH}" # Resolve the latest stable Go at image-build time (go.dev/VERSION returns the -# current release, e.g. "go1.26.4"). Set GOLANG_VERSION (same "goX.Y.Z" form) to pin. +# current release, e.g. "go1.26.4"). Strip any leading "go" and re-prepend it so +# GOLANG_VERSION can be pinned as either "1.26.3" or "go1.26.3". ARG GOLANG_VERSION RUN ver="${GOLANG_VERSION:-$(curl -fsSL 'https://go.dev/VERSION?m=text' | head -1)}" \ && test -n "$ver" \ - && curl -fsSL "https://go.dev/dl/${ver}.linux-$(dpkg --print-architecture).tar.gz" -o go.tar.gz \ + && ver="${ver#go}" \ + && curl -fsSL "https://go.dev/dl/go${ver}.linux-$(dpkg --print-architecture).tar.gz" -o go.tar.gz \ && tar -C /usr/local -xzf go.tar.gz \ && rm go.tar.gz diff --git a/docker/generated/Dockerfile.java b/docker/generated/Dockerfile.java index 6d5bdab..449304f 100644 --- a/docker/generated/Dockerfile.java +++ b/docker/generated/Dockerfile.java @@ -89,13 +89,15 @@ ENV JAVA_HOME=/usr/lib/jvm/temurin-25-jdk ENV PATH="${JAVA_HOME}/bin:${PATH}" -# Install Maven. Resolve the latest stable 3.9.x at build time from the Apache -# mirror listing (the maven-metadata tag points at Maven 4 RCs, which -# we don't want). Set MAVEN_VERSION to pin a specific 3.x release. +# Install Maven. Resolve the latest stable 3.9.x from the dlcdn mirror listing +# (the maven-metadata tag points at Maven 4 RCs, which we don't want), +# but download from archive.apache.org, which keeps every historical release — +# dlcdn prunes old versions, so a pinned older MAVEN_VERSION would 404 there. +# Set MAVEN_VERSION to pin a specific 3.x release. ARG MAVEN_VERSION RUN ver="${MAVEN_VERSION:-$(curl -fsSL https://dlcdn.apache.org/maven/maven-3/ | grep -oE '3\.[0-9]+\.[0-9]+/' | tr -d / | sort -uV | tail -1)}" \ && test -n "$ver" \ - && curl -fsSL "https://dlcdn.apache.org/maven/maven-3/${ver}/binaries/apache-maven-${ver}-bin.tar.gz" -o maven.tar.gz \ + && curl -fsSL "https://archive.apache.org/dist/maven/maven-3/${ver}/binaries/apache-maven-${ver}-bin.tar.gz" -o maven.tar.gz \ && tar -C /usr/local -xzf maven.tar.gz \ && ln -s "/usr/local/apache-maven-${ver}/bin/mvn" /usr/local/bin/mvn \ && rm maven.tar.gz @@ -103,8 +105,7 @@ # Install Gradle. Resolve the current release at build time from the Gradle # version API. Set GRADLE_VERSION to pin a specific release. ARG GRADLE_VERSION -RUN ver="${GRADLE_VERSION}" \ - && if [ -z "$ver" ]; then ver="$(curl -fsSL https://services.gradle.org/versions/current | grep -oP '"version"\s*:\s*"\K[^"]+')"; fi \ +RUN ver="${GRADLE_VERSION:-$(curl -fsSL https://services.gradle.org/versions/current | grep -oP '"version"\s*:\s*"\K[^"]+')}" \ && test -n "$ver" \ && curl -fsSL "https://services.gradle.org/distributions/gradle-${ver}-bin.zip" -o gradle.zip \ && unzip -d /usr/local gradle.zip \ diff --git a/docker/snippets/golang.Dockerfile b/docker/snippets/golang.Dockerfile index b4b15b1..ceb49a8 100644 --- a/docker/snippets/golang.Dockerfile +++ b/docker/snippets/golang.Dockerfile @@ -4,11 +4,13 @@ ENV GOPATH=/usr/local/go-workspace ENV PATH="/usr/local/go/bin:${GOPATH}/bin:${PATH}" # Resolve the latest stable Go at image-build time (go.dev/VERSION returns the -# current release, e.g. "go1.26.4"). Set GOLANG_VERSION (same "goX.Y.Z" form) to pin. +# current release, e.g. "go1.26.4"). Strip any leading "go" and re-prepend it so +# GOLANG_VERSION can be pinned as either "1.26.3" or "go1.26.3". ARG GOLANG_VERSION RUN ver="${GOLANG_VERSION:-$(curl -fsSL 'https://go.dev/VERSION?m=text' | head -1)}" \ && test -n "$ver" \ - && curl -fsSL "https://go.dev/dl/${ver}.linux-$(dpkg --print-architecture).tar.gz" -o go.tar.gz \ + && ver="${ver#go}" \ + && curl -fsSL "https://go.dev/dl/go${ver}.linux-$(dpkg --print-architecture).tar.gz" -o go.tar.gz \ && tar -C /usr/local -xzf go.tar.gz \ && rm go.tar.gz diff --git a/docker/snippets/java.Dockerfile b/docker/snippets/java.Dockerfile index 896e727..159b72c 100644 --- a/docker/snippets/java.Dockerfile +++ b/docker/snippets/java.Dockerfile @@ -13,13 +13,15 @@ RUN ln -s /usr/lib/jvm/temurin-25-jdk-$(dpkg --print-architecture) /usr/lib/jvm/ ENV JAVA_HOME=/usr/lib/jvm/temurin-25-jdk ENV PATH="${JAVA_HOME}/bin:${PATH}" -# Install Maven. Resolve the latest stable 3.9.x at build time from the Apache -# mirror listing (the maven-metadata tag points at Maven 4 RCs, which -# we don't want). Set MAVEN_VERSION to pin a specific 3.x release. +# Install Maven. Resolve the latest stable 3.9.x from the dlcdn mirror listing +# (the maven-metadata tag points at Maven 4 RCs, which we don't want), +# but download from archive.apache.org, which keeps every historical release — +# dlcdn prunes old versions, so a pinned older MAVEN_VERSION would 404 there. +# Set MAVEN_VERSION to pin a specific 3.x release. ARG MAVEN_VERSION RUN ver="${MAVEN_VERSION:-$(curl -fsSL https://dlcdn.apache.org/maven/maven-3/ | grep -oE '3\.[0-9]+\.[0-9]+/' | tr -d / | sort -uV | tail -1)}" \ && test -n "$ver" \ - && curl -fsSL "https://dlcdn.apache.org/maven/maven-3/${ver}/binaries/apache-maven-${ver}-bin.tar.gz" -o maven.tar.gz \ + && curl -fsSL "https://archive.apache.org/dist/maven/maven-3/${ver}/binaries/apache-maven-${ver}-bin.tar.gz" -o maven.tar.gz \ && tar -C /usr/local -xzf maven.tar.gz \ && ln -s "/usr/local/apache-maven-${ver}/bin/mvn" /usr/local/bin/mvn \ && rm maven.tar.gz @@ -27,8 +29,7 @@ RUN ver="${MAVEN_VERSION:-$(curl -fsSL https://dlcdn.apache.org/maven/maven-3/ | # Install Gradle. Resolve the current release at build time from the Gradle # version API. Set GRADLE_VERSION to pin a specific release. ARG GRADLE_VERSION -RUN ver="${GRADLE_VERSION}" \ - && if [ -z "$ver" ]; then ver="$(curl -fsSL https://services.gradle.org/versions/current | grep -oP '"version"\s*:\s*"\K[^"]+')"; fi \ +RUN ver="${GRADLE_VERSION:-$(curl -fsSL https://services.gradle.org/versions/current | grep -oP '"version"\s*:\s*"\K[^"]+')}" \ && test -n "$ver" \ && curl -fsSL "https://services.gradle.org/distributions/gradle-${ver}-bin.zip" -o gradle.zip \ && unzip -d /usr/local gradle.zip \ From dbdb3a300872eb0e87d610e51e0edbb78efb082a Mon Sep 17 00:00:00 2001 From: Gordon Beeming Date: Mon, 29 Jun 2026 18:25:37 +1000 Subject: [PATCH 3/3] ci(publish): resolve toolchains in prepare-versions and pass as build-args MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Resolving the version inside the image RUN doesn't survive the registry layer cache: the instruction text is static, so BuildKit reuses the cached layer and never re-runs the curl — images would freeze at whatever version was first cached (caught in review by chatgpt-codex-connector). Resolve go/maven/gradle/jdtls/plantuml in the prepare-versions job (same place the dotnet SDK versions are resolved) and pass them as build-args on the golang and java image matrix entries. The resolved value is now part of the layer cache key, so a new version busts the cache and rebuilds — exactly how the dotnet images already stay current. The in-Dockerfile resolution stays as the fallback for local dev-build.sh, which passes no build-args. Also convert the matrix build_args to multi-line YAML block scalars for readability (the Prepare build args step's echo -e handles them unchanged). Co-authored-by: Claude Co-authored-by: GitButler --- .github/workflows/publish.yml | 86 ++++++++++++++++++++++++++++++----- 1 file changed, 75 insertions(+), 11 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index c689801..5571320 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -398,6 +398,11 @@ jobs: dotnet_8_version: ${{ steps.versions.outputs.dotnet_8_version }} dotnet_9_version: ${{ steps.versions.outputs.dotnet_9_version }} dotnet_10_version: ${{ steps.versions.outputs.dotnet_10_version }} + golang_version: ${{ steps.versions.outputs.golang_version }} + maven_version: ${{ steps.versions.outputs.maven_version }} + gradle_version: ${{ steps.versions.outputs.gradle_version }} + jdtls_url: ${{ steps.versions.outputs.jdtls_url }} + plantuml_url: ${{ steps.versions.outputs.plantuml_url }} steps: - name: Set lowercase repository name id: repo @@ -424,6 +429,26 @@ jobs: CSHARP_LS_VERSION=$(curl -s https://api.nuget.org/v3-flatcontainer/csharp-ls/index.json | jq -r '.versions[-1]') echo "csharp_ls_version=$CSHARP_LS_VERSION" >> $GITHUB_OUTPUT + # Toolchains pinned per-build so the resolved version is the layer cache + # key: passing it as a build-arg busts the image cache when it changes. + # The snippets resolve these themselves when the arg is empty (local dev + # builds), but CI must resolve here or the registry layer cache freezes + # the version. Go strips the "go" prefix; the snippet re-adds it. + GOLANG_VERSION=$(curl -fsSL 'https://go.dev/VERSION?m=text' | head -1) + echo "golang_version=${GOLANG_VERSION#go}" >> $GITHUB_OUTPUT + + MAVEN_VERSION=$(curl -fsSL https://dlcdn.apache.org/maven/maven-3/ | grep -oE '3\.[0-9]+\.[0-9]+/' | tr -d / | sort -uV | tail -1) + echo "maven_version=$MAVEN_VERSION" >> $GITHUB_OUTPUT + + GRADLE_VERSION=$(curl -fsSL https://services.gradle.org/versions/current | jq -r '.version') + echo "gradle_version=$GRADLE_VERSION" >> $GITHUB_OUTPUT + + JDTLS_FILE=$(curl -fsSL https://download.eclipse.org/jdtls/snapshots/latest.txt) + echo "jdtls_url=https://download.eclipse.org/jdtls/snapshots/${JDTLS_FILE}" >> $GITHUB_OUTPUT + + PLANTUML_TAG=$(curl -fsSL https://api.github.com/repos/plantuml/plantuml/releases/latest | jq -r '.tag_name') + echo "plantuml_url=https://github.com/plantuml/plantuml/releases/download/${PLANTUML_TAG}/plantuml-${PLANTUML_TAG#v}.jar" >> $GITHUB_OUTPUT + # Build all container images in parallel (each builds independently from node:20-slim) build-images: name: Build ${{ matrix.image }} @@ -438,37 +463,71 @@ jobs: tags_extra: | ghcr.io/${{ needs.prepare-versions.outputs.repo_name }}:latest ghcr.io/${{ needs.prepare-versions.outputs.repo_name }}:copilot-latest - build_args: "COPILOT_VERSION=$COPILOT_VERSION" + build_args: | + COPILOT_VERSION=$COPILOT_VERSION - image: rust dockerfile: ./docker/generated/Dockerfile.rust - build_args: "COPILOT_VERSION=$COPILOT_VERSION" + build_args: | + COPILOT_VERSION=$COPILOT_VERSION - image: golang dockerfile: ./docker/generated/Dockerfile.golang - build_args: "COPILOT_VERSION=$COPILOT_VERSION" + build_args: | + COPILOT_VERSION=$COPILOT_VERSION + GOLANG_VERSION=$GOLANG_VERSION - image: playwright dockerfile: ./docker/generated/Dockerfile.playwright - build_args: "COPILOT_VERSION=$COPILOT_VERSION\nPLAYWRIGHT_VERSION=$PLAYWRIGHT_VERSION" + build_args: | + COPILOT_VERSION=$COPILOT_VERSION + PLAYWRIGHT_VERSION=$PLAYWRIGHT_VERSION - image: dotnet-8 dockerfile: ./docker/generated/Dockerfile.dotnet-8 - build_args: "COPILOT_VERSION=$COPILOT_VERSION\nDOTNET_SDK_8_VERSION=$DOTNET_8_VERSION" + build_args: | + COPILOT_VERSION=$COPILOT_VERSION + DOTNET_SDK_8_VERSION=$DOTNET_8_VERSION - image: dotnet-9 dockerfile: ./docker/generated/Dockerfile.dotnet-9 - build_args: "COPILOT_VERSION=$COPILOT_VERSION\nDOTNET_SDK_9_VERSION=$DOTNET_9_VERSION" + build_args: | + COPILOT_VERSION=$COPILOT_VERSION + DOTNET_SDK_9_VERSION=$DOTNET_9_VERSION - image: dotnet-10 dockerfile: ./docker/generated/Dockerfile.dotnet-10 - build_args: "COPILOT_VERSION=$COPILOT_VERSION\nDOTNET_SDK_10_VERSION=$DOTNET_10_VERSION\nCSHARP_LS_VERSION=$CSHARP_LS_VERSION" + build_args: | + COPILOT_VERSION=$COPILOT_VERSION + DOTNET_SDK_10_VERSION=$DOTNET_10_VERSION + CSHARP_LS_VERSION=$CSHARP_LS_VERSION - image: dotnet dockerfile: ./docker/generated/Dockerfile.dotnet - build_args: "COPILOT_VERSION=$COPILOT_VERSION\nDOTNET_SDK_8_VERSION=$DOTNET_8_VERSION\nDOTNET_SDK_9_VERSION=$DOTNET_9_VERSION\nDOTNET_SDK_10_VERSION=$DOTNET_10_VERSION\nCSHARP_LS_VERSION=$CSHARP_LS_VERSION" + build_args: | + COPILOT_VERSION=$COPILOT_VERSION + DOTNET_SDK_8_VERSION=$DOTNET_8_VERSION + DOTNET_SDK_9_VERSION=$DOTNET_9_VERSION + DOTNET_SDK_10_VERSION=$DOTNET_10_VERSION + CSHARP_LS_VERSION=$CSHARP_LS_VERSION - image: dotnet-playwright dockerfile: ./docker/generated/Dockerfile.dotnet-playwright - build_args: "COPILOT_VERSION=$COPILOT_VERSION\nDOTNET_SDK_8_VERSION=$DOTNET_8_VERSION\nDOTNET_SDK_9_VERSION=$DOTNET_9_VERSION\nDOTNET_SDK_10_VERSION=$DOTNET_10_VERSION\nPLAYWRIGHT_VERSION=$PLAYWRIGHT_VERSION\nCSHARP_LS_VERSION=$CSHARP_LS_VERSION" + build_args: | + COPILOT_VERSION=$COPILOT_VERSION + DOTNET_SDK_8_VERSION=$DOTNET_8_VERSION + DOTNET_SDK_9_VERSION=$DOTNET_9_VERSION + DOTNET_SDK_10_VERSION=$DOTNET_10_VERSION + PLAYWRIGHT_VERSION=$PLAYWRIGHT_VERSION + CSHARP_LS_VERSION=$CSHARP_LS_VERSION - image: dotnet-rust dockerfile: ./docker/generated/Dockerfile.dotnet-rust - build_args: "COPILOT_VERSION=$COPILOT_VERSION\nDOTNET_SDK_8_VERSION=$DOTNET_8_VERSION\nDOTNET_SDK_9_VERSION=$DOTNET_9_VERSION\nDOTNET_SDK_10_VERSION=$DOTNET_10_VERSION\nCSHARP_LS_VERSION=$CSHARP_LS_VERSION" + build_args: | + COPILOT_VERSION=$COPILOT_VERSION + DOTNET_SDK_8_VERSION=$DOTNET_8_VERSION + DOTNET_SDK_9_VERSION=$DOTNET_9_VERSION + DOTNET_SDK_10_VERSION=$DOTNET_10_VERSION + CSHARP_LS_VERSION=$CSHARP_LS_VERSION - image: java dockerfile: ./docker/generated/Dockerfile.java - build_args: "COPILOT_VERSION=$COPILOT_VERSION" + build_args: | + COPILOT_VERSION=$COPILOT_VERSION + MAVEN_VERSION=$MAVEN_VERSION + GRADLE_VERSION=$GRADLE_VERSION + JDTLS_URL=$JDTLS_URL + PLANTUML_URL=$PLANTUML_URL steps: - name: Checkout repository uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 @@ -496,6 +555,11 @@ jobs: ARGS="${ARGS//\$DOTNET_9_VERSION/${{ needs.prepare-versions.outputs.dotnet_9_version }}}" ARGS="${ARGS//\$DOTNET_10_VERSION/${{ needs.prepare-versions.outputs.dotnet_10_version }}}" ARGS="${ARGS//\$CSHARP_LS_VERSION/${{ needs.prepare-versions.outputs.csharp_ls_version }}}" + ARGS="${ARGS//\$GOLANG_VERSION/${{ needs.prepare-versions.outputs.golang_version }}}" + ARGS="${ARGS//\$MAVEN_VERSION/${{ needs.prepare-versions.outputs.maven_version }}}" + ARGS="${ARGS//\$GRADLE_VERSION/${{ needs.prepare-versions.outputs.gradle_version }}}" + ARGS="${ARGS//\$JDTLS_URL/${{ needs.prepare-versions.outputs.jdtls_url }}}" + ARGS="${ARGS//\$PLANTUML_URL/${{ needs.prepare-versions.outputs.plantuml_url }}}" echo "build_args<> $GITHUB_OUTPUT echo -e "$ARGS" >> $GITHUB_OUTPUT echo "EOF" >> $GITHUB_OUTPUT