From ae90058897bbd8d5cda8000ec9109ea0eabdaa37 Mon Sep 17 00:00:00 2001 From: Gordon Beeming Date: Wed, 25 Mar 2026 09:07:17 +1000 Subject: [PATCH] Pin csharp-ls to exact version Always use an exact version for csharp-ls instead of "latest" to ensure reproducible builds and align with the requirement that tools be pinned to a specific release (like dotnet copilot cli). Add csharp_l s_version to the workflow outputs, capture the latest NuGet version in prepare-versions, propagate the value into the image build arguments, and replace the Dockerfile ARG default from "latest" to a fixed 0.22.0 to guarantee deterministic installations. fix: Pin csharp-ls to exact NuGet version in Docker builds The `dotnet tool install --version latest` is invalid because NuGet doesn't accept "latest" as a version range. Resolve the actual latest version from the NuGet API in the prepare-versions CI job and pass it as a build arg, matching the pattern used for copilot, playwright, and dotnet SDK versions. Co-authored-by: Claude Opus 4.6 (1M context) Co-authored-by: GitButler --- .github/workflows/publish.yml | 13 +++++++++---- docker/generated/Dockerfile.dotnet | 2 +- docker/generated/Dockerfile.dotnet-10 | 2 +- docker/generated/Dockerfile.dotnet-playwright | 2 +- docker/generated/Dockerfile.dotnet-rust | 2 +- docker/snippets/lsp-csharp.Dockerfile | 2 +- 6 files changed, 14 insertions(+), 9 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index f9152bf..c133852 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -343,6 +343,7 @@ jobs: repo_name: ${{ steps.repo.outputs.name }} copilot_version: ${{ steps.versions.outputs.copilot_version }} playwright_version: ${{ steps.versions.outputs.playwright_version }} + csharp_ls_version: ${{ steps.versions.outputs.csharp_ls_version }} 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 }} @@ -369,6 +370,9 @@ jobs: DOTNET_10_VERSION=$(curl -s https://dotnetcli.blob.core.windows.net/dotnet/release-metadata/10.0/releases.json | jq -r '."latest-sdk"') echo "dotnet_10_version=$DOTNET_10_VERSION" >> $GITHUB_OUTPUT + 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 + # Build all container images in parallel (each builds independently from node:20-slim) build-images: name: Build ${{ matrix.image }} @@ -401,16 +405,16 @@ jobs: build_args: "COPILOT_VERSION=$COPILOT_VERSION\nDOTNET_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" + build_args: "COPILOT_VERSION=$COPILOT_VERSION\nDOTNET_SDK_10_VERSION=$DOTNET_10_VERSION\nCSHARP_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" + 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" - 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" + 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" - 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" + 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" steps: - name: Checkout repository uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 @@ -437,6 +441,7 @@ jobs: ARGS="${ARGS//\$DOTNET_8_VERSION/${{ needs.prepare-versions.outputs.dotnet_8_version }}}" 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 }}}" echo "build_args<> $GITHUB_OUTPUT echo -e "$ARGS" >> $GITHUB_OUTPUT echo "EOF" >> $GITHUB_OUTPUT diff --git a/docker/generated/Dockerfile.dotnet b/docker/generated/Dockerfile.dotnet index f3b803e..f5cd994 100644 --- a/docker/generated/Dockerfile.dotnet +++ b/docker/generated/Dockerfile.dotnet @@ -109,7 +109,7 @@ RUN mkdir -p /etc/copilot/lsp-config.d && \ # --- snippet: lsp-csharp --- # Install C# Language Server for code intelligence # Install directly to a shared location so appuser can access it -ARG CSHARP_LS_VERSION=latest +ARG CSHARP_LS_VERSION=0.22.0 RUN dotnet tool install csharp-ls --tool-path /usr/local/bin --version ${CSHARP_LS_VERSION} # Write LSP config fragment for C# diff --git a/docker/generated/Dockerfile.dotnet-10 b/docker/generated/Dockerfile.dotnet-10 index 470dc39..1535622 100644 --- a/docker/generated/Dockerfile.dotnet-10 +++ b/docker/generated/Dockerfile.dotnet-10 @@ -83,7 +83,7 @@ RUN mkdir -p /etc/copilot/lsp-config.d && \ # --- snippet: lsp-csharp --- # Install C# Language Server for code intelligence # Install directly to a shared location so appuser can access it -ARG CSHARP_LS_VERSION=latest +ARG CSHARP_LS_VERSION=0.22.0 RUN dotnet tool install csharp-ls --tool-path /usr/local/bin --version ${CSHARP_LS_VERSION} # Write LSP config fragment for C# diff --git a/docker/generated/Dockerfile.dotnet-playwright b/docker/generated/Dockerfile.dotnet-playwright index 087c97a..cc3f394 100644 --- a/docker/generated/Dockerfile.dotnet-playwright +++ b/docker/generated/Dockerfile.dotnet-playwright @@ -150,7 +150,7 @@ RUN mkdir -p /etc/copilot/lsp-config.d && \ # --- snippet: lsp-csharp --- # Install C# Language Server for code intelligence # Install directly to a shared location so appuser can access it -ARG CSHARP_LS_VERSION=latest +ARG CSHARP_LS_VERSION=0.22.0 RUN dotnet tool install csharp-ls --tool-path /usr/local/bin --version ${CSHARP_LS_VERSION} # Write LSP config fragment for C# diff --git a/docker/generated/Dockerfile.dotnet-rust b/docker/generated/Dockerfile.dotnet-rust index c831d3c..79869ee 100644 --- a/docker/generated/Dockerfile.dotnet-rust +++ b/docker/generated/Dockerfile.dotnet-rust @@ -130,7 +130,7 @@ RUN mkdir -p /etc/copilot/lsp-config.d && \ # --- snippet: lsp-csharp --- # Install C# Language Server for code intelligence # Install directly to a shared location so appuser can access it -ARG CSHARP_LS_VERSION=latest +ARG CSHARP_LS_VERSION=0.22.0 RUN dotnet tool install csharp-ls --tool-path /usr/local/bin --version ${CSHARP_LS_VERSION} # Write LSP config fragment for C# diff --git a/docker/snippets/lsp-csharp.Dockerfile b/docker/snippets/lsp-csharp.Dockerfile index 98c8d84..31c141b 100644 --- a/docker/snippets/lsp-csharp.Dockerfile +++ b/docker/snippets/lsp-csharp.Dockerfile @@ -1,6 +1,6 @@ # Install C# Language Server for code intelligence # Install directly to a shared location so appuser can access it -ARG CSHARP_LS_VERSION=latest +ARG CSHARP_LS_VERSION=0.22.0 RUN dotnet tool install csharp-ls --tool-path /usr/local/bin --version ${CSHARP_LS_VERSION} # Write LSP config fragment for C#