From 4693e7f1187040a7a24113b28087f5fb4e751b46 Mon Sep 17 00:00:00 2001 From: Muhammad Falak R Wani Date: Thu, 27 Aug 2026 13:34:53 +0530 Subject: [PATCH 01/12] chore: bump toolkit to go 1.25 to fix CVEs Co-authored-by: Daniel McIlvaney --- .github/workflows/go-test-coverage.yml | 2 +- .../docs/building/prerequisites-mariner.md | 10 ++++++---- toolkit/docs/building/prerequisites-ubuntu.md | 13 ++++++------ toolkit/docs/building/prerequisites-ubuntu.sh | 10 +++++----- .../manifests/package/pkggen_core_aarch64.txt | 4 ++-- .../manifests/package/pkggen_core_x86_64.txt | 4 ++-- .../manifests/package/update_manifests.sh | 4 ++-- toolkit/tools/go.mod | 12 +++++------ toolkit/tools/go.sum | 20 +++++++++---------- 9 files changed, 41 insertions(+), 38 deletions(-) diff --git a/.github/workflows/go-test-coverage.yml b/.github/workflows/go-test-coverage.yml index 8ed9c0314cd..18103dac43e 100644 --- a/.github/workflows/go-test-coverage.yml +++ b/.github/workflows/go-test-coverage.yml @@ -10,7 +10,7 @@ on: branches: [main, dev, 1.0*, 2.0*, 3.0*, fasttrack/*] env: - EXPECTED_GO_VERSION: "1.24" + EXPECTED_GO_VERSION: "1.25" permissions: contents: read diff --git a/toolkit/docs/building/prerequisites-mariner.md b/toolkit/docs/building/prerequisites-mariner.md index 66ef1f83c2c..a55ee8948ca 100644 --- a/toolkit/docs/building/prerequisites-mariner.md +++ b/toolkit/docs/building/prerequisites-mariner.md @@ -7,10 +7,10 @@ This page outlines the requirements for building with the Azure Linux toolkit on ### Golang Package Requirements -Different versions of Azure Linux have been validated with the following Golang packages: +The Azure Linux toolkit requires Go 1.25 or newer: -- **Azure Linux 2.0 (CBL-Mariner)**: Validated with `msft-golang-1.24.1` -- **Azure Linux 3.0**: Validated with `golang-1.24.3` +- **Azure Linux 2.0 (CBL-Mariner)**: Not supported because its `msft-golang-1.24.1` package is below the minimum version +- **Azure Linux 3.0**: Supported by the current `golang` package ## Installation Methods @@ -40,6 +40,7 @@ sudo make -C toolkit install-prereqs-and-configure ``` **Recommendation**: + - Use `install-prereqs` on your local development machine - Use `install-prereqs-and-configure` in CI/CD pipelines or when you need a complete environment setup @@ -47,7 +48,8 @@ sudo make -C toolkit install-prereqs-and-configure If you prefer running the script directly, use the appropriate options for your OS version: -#### For Azure Linux 3.0: +#### For Azure Linux 3.0 + ```bash # Install prerequisites with standard golang sudo ./toolkit/docs/building/prerequisites-mariner.sh diff --git a/toolkit/docs/building/prerequisites-ubuntu.md b/toolkit/docs/building/prerequisites-ubuntu.md index 5feaeb5537e..6d12e57e0d2 100644 --- a/toolkit/docs/building/prerequisites-ubuntu.md +++ b/toolkit/docs/building/prerequisites-ubuntu.md @@ -7,9 +7,9 @@ This page outlines the requirements for building with the Azure Linux toolkit on ### Golang Package Requirements -The Azure Linux toolkit on Ubuntu has been validated with the following: +The Azure Linux toolkit requires Go 1.25 or newer. Ubuntu 26.04 provides the required package: -- **Ubuntu 22.04**: Validated with `golang-1.24.13` (available as `golang-1.24-go` package) +- **Ubuntu 26.04**: `golang-1.25-go` (currently Go 1.25.7) ## Installation Methods @@ -23,8 +23,8 @@ The make targets automatically install the appropriate packages: sudo make -C toolkit install-prereqs # Manually create Go symlinks for proper PATH integration -sudo ln -sf /usr/lib/go-1.24/bin/go /usr/bin/go -sudo ln -sf /usr/lib/go-1.24/bin/gofmt /usr/bin/gofmt +sudo ln -sf /usr/lib/go-1.25/bin/go /usr/bin/go +sudo ln -sf /usr/lib/go-1.25/bin/gofmt /usr/bin/gofmt # Manually configure Docker if needed curl -fsSL https://get.docker.com -o get-docker.sh @@ -43,6 +43,7 @@ sudo make -C toolkit install-prereqs-and-configure ``` **Recommendation**: + - Use `install-prereqs` on your local development machine - Use `install-prereqs-and-configure` in CI/CD pipelines or when you need a complete environment setup @@ -55,8 +56,8 @@ If you prefer running the script directly, you have several options: sudo ./toolkit/docs/building/prerequisites-ubuntu.sh # Manually create Go symlinks for proper PATH integration -sudo ln -sf /usr/lib/go-1.24/bin/go /usr/bin/go -sudo ln -sf /usr/lib/go-1.24/bin/gofmt /usr/bin/gofmt +sudo ln -sf /usr/lib/go-1.25/bin/go /usr/bin/go +sudo ln -sf /usr/lib/go-1.25/bin/gofmt /usr/bin/gofmt # Manually configure Docker if needed curl -fsSL https://get.docker.com -o get-docker.sh diff --git a/toolkit/docs/building/prerequisites-ubuntu.sh b/toolkit/docs/building/prerequisites-ubuntu.sh index a2c5f6c4146..00717bfa598 100755 --- a/toolkit/docs/building/prerequisites-ubuntu.sh +++ b/toolkit/docs/building/prerequisites-ubuntu.sh @@ -46,7 +46,7 @@ while [ $# -gt 0 ]; do done # Install prerequisites if not disabled -# golang version pinned for stability to avoid breaking changes. As of 11-Jun-2025 we are using golang-1.23.1 on Ubuntu 22.04 since it is the most recent release available. +# golang version pinned for stability to avoid breaking changes. As of 11-Aug-2026 we are using golang-1.25.7 on Ubuntu 26.04 since it is the most recent release available. # When making a breaking change to the toolkit which requires a newer golang version, update this version if needed. # If no newer version is available, suggest moving to a newer Ubuntu LTS version if [ "$INSTALL_PREREQS" = true ]; then @@ -59,7 +59,7 @@ if [ "$INSTALL_PREREQS" = true ]; then gawk \ genisoimage \ git \ - golang-1.24-go \ + golang-1.25-go \ jq \ make \ openssl \ @@ -76,11 +76,11 @@ else echo "Skipping installation of prerequisite packages..." fi -# Fix go 1.24 links if requested +# Fix go 1.25 links if requested if [ "$FIX_GO_LINKS" = true ]; then echo "Creating Go symlinks..." - ln -vsf /usr/lib/go-1.24/bin/go /usr/bin/go - ln -vsf /usr/lib/go-1.24/bin/gofmt /usr/bin/gofmt + ln -vsf /usr/lib/go-1.25/bin/go /usr/bin/go + ln -vsf /usr/lib/go-1.25/bin/gofmt /usr/bin/gofmt fi # Install and configure Docker if requested diff --git a/toolkit/resources/manifests/package/pkggen_core_aarch64.txt b/toolkit/resources/manifests/package/pkggen_core_aarch64.txt index dfcfd46d1d2..5c9e2e2ffa2 100644 --- a/toolkit/resources/manifests/package/pkggen_core_aarch64.txt +++ b/toolkit/resources/manifests/package/pkggen_core_aarch64.txt @@ -236,6 +236,8 @@ azurelinux-repos-3.0-5.azl3.noarch.rpm libffi-3.4.4-1.azl3.aarch64.rpm libffi-devel-3.4.4-1.azl3.aarch64.rpm libtasn1-4.19.0-3.azl3.aarch64.rpm +chkconfig-1.25-1.azl3.aarch64.rpm +chkconfig-lang-1.25-1.azl3.aarch64.rpm p11-kit-0.26.5-1.azl3.aarch64.rpm p11-kit-trust-0.26.5-1.azl3.aarch64.rpm ca-certificates-shared-3.0.0-16.azl3.noarch.rpm @@ -254,8 +256,6 @@ libselinux-3.6-4.azl3.aarch64.rpm slang-2.3.3-1.azl3.aarch64.rpm newt-0.52.23-1.azl3.aarch64.rpm newt-lang-0.52.23-1.azl3.aarch64.rpm -chkconfig-1.25-1.azl3.aarch64.rpm -chkconfig-lang-1.25-1.azl3.aarch64.rpm msopenjdk-17-17.0.12-1.aarch64.rpm pyproject-rpm-macros-1.12.0-2.azl3.noarch.rpm pyproject-srpm-macros-1.12.0-2.azl3.noarch.rpm diff --git a/toolkit/resources/manifests/package/pkggen_core_x86_64.txt b/toolkit/resources/manifests/package/pkggen_core_x86_64.txt index 1548f5c34b3..627b6c19a16 100644 --- a/toolkit/resources/manifests/package/pkggen_core_x86_64.txt +++ b/toolkit/resources/manifests/package/pkggen_core_x86_64.txt @@ -236,6 +236,8 @@ azurelinux-repos-3.0-5.azl3.noarch.rpm libffi-3.4.4-1.azl3.x86_64.rpm libffi-devel-3.4.4-1.azl3.x86_64.rpm libtasn1-4.19.0-3.azl3.x86_64.rpm +chkconfig-1.25-1.azl3.x86_64.rpm +chkconfig-lang-1.25-1.azl3.x86_64.rpm p11-kit-0.26.5-1.azl3.x86_64.rpm p11-kit-trust-0.26.5-1.azl3.x86_64.rpm ca-certificates-shared-3.0.0-16.azl3.noarch.rpm @@ -254,8 +256,6 @@ libselinux-3.6-4.azl3.x86_64.rpm slang-2.3.3-1.azl3.x86_64.rpm newt-0.52.23-1.azl3.x86_64.rpm newt-lang-0.52.23-1.azl3.x86_64.rpm -chkconfig-1.25-1.azl3.x86_64.rpm -chkconfig-lang-1.25-1.azl3.x86_64.rpm msopenjdk-17-17.0.12-1.x86_64.rpm pyproject-rpm-macros-1.12.0-2.azl3.noarch.rpm pyproject-srpm-macros-1.12.0-2.azl3.noarch.rpm diff --git a/toolkit/resources/manifests/package/update_manifests.sh b/toolkit/resources/manifests/package/update_manifests.sh index 0bb7bf1918e..fd6b109bc22 100755 --- a/toolkit/resources/manifests/package/update_manifests.sh +++ b/toolkit/resources/manifests/package/update_manifests.sh @@ -289,6 +289,8 @@ generate_pkggen_core () { grep "^azurelinux-repos" $TmpPkgGen grep "^libffi-" $TmpPkgGen grep "^libtasn1-" $TmpPkgGen + grep "^chkconfig-[0-9]" $TmpPkgGen + grep "^chkconfig-lang-[0-9]" $TmpPkgGen grep "^p11-kit-" $TmpPkgGen grep "^ca-certificates-shared-" $TmpPkgGen grep "^ca-certificates-tools-" $TmpPkgGen @@ -302,8 +304,6 @@ generate_pkggen_core () { grep "^slang-[0-9]" $TmpPkgGen grep "^newt-[0-9]" $TmpPkgGen grep "^newt-lang-[0-9]" $TmpPkgGen - grep "^chkconfig-[0-9]" $TmpPkgGen - grep "^chkconfig-lang-[0-9]" $TmpPkgGen grep "^msopenjdk-" $TmpPkgGen grep "^pyproject-" $TmpPkgGen grep "^audit-" $TmpPkgGen diff --git a/toolkit/tools/go.mod b/toolkit/tools/go.mod index 57992854773..3c4841e6e36 100644 --- a/toolkit/tools/go.mod +++ b/toolkit/tools/go.mod @@ -1,6 +1,6 @@ module github.com/microsoft/azurelinux/toolkit/tools -go 1.24.0 +go 1.25.0 require ( github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.6.0 @@ -21,7 +21,7 @@ require ( github.com/sirupsen/logrus v1.9.3 github.com/stretchr/testify v1.9.0 github.com/ulikunitz/xz v0.5.15 - golang.org/x/sys v0.38.0 + golang.org/x/sys v0.46.0 gonum.org/v1/gonum v0.16.0 gopkg.in/alecthomas/kingpin.v2 v2.2.6 gopkg.in/ini.v1 v1.67.0 @@ -48,8 +48,8 @@ require ( github.com/pmezard/go-difflib v1.0.0 // indirect github.com/rivo/uniseg v0.1.0 // indirect github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect - golang.org/x/crypto v0.45.0 // indirect - golang.org/x/net v0.47.0 // indirect - golang.org/x/sync v0.18.0 // indirect - golang.org/x/text v0.31.0 // indirect + golang.org/x/crypto v0.53.0 // indirect + golang.org/x/net v0.56.0 // indirect + golang.org/x/sync v0.21.0 // indirect + golang.org/x/text v0.39.0 // indirect ) diff --git a/toolkit/tools/go.sum b/toolkit/tools/go.sum index b04e731d682..01289257e58 100644 --- a/toolkit/tools/go.sum +++ b/toolkit/tools/go.sum @@ -102,12 +102,12 @@ github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRT github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= -golang.org/x/crypto v0.45.0 h1:jMBrvKuj23MTlT0bQEOBcAE0mjg8mK9RXFhRH6nyF3Q= -golang.org/x/crypto v0.45.0/go.mod h1:XTGrrkGJve7CYK7J8PEww4aY7gM3qMCElcJQ8n8JdX4= -golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY= -golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU= -golang.org/x/sync v0.18.0 h1:kr88TuHDroi+UVf+0hZnirlk8o8T+4MrK6mr60WkH/I= -golang.org/x/sync v0.18.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= +golang.org/x/crypto v0.53.0 h1:QZ4Muo8THX6CizN2vPPd5fBGHyogrdK9fG4wLPFUsto= +golang.org/x/crypto v0.53.0/go.mod h1:DNLU434OwVakk9PzuwV8w62mAJpRJL3vsgcfp4Qnsio= +golang.org/x/net v0.56.0 h1:Rw8j/hFzGvJUZwNBXnAtf5sVDVt+65SK2C7IxCxZt5o= +golang.org/x/net v0.56.0/go.mod h1:D3Ku6r+V6JROoZK144D2XfMHFcMq/0zSfLelVTCFKec= +golang.org/x/sync v0.21.0 h1:HLII4xRRTtCRkxYp4HNFF0Js/Og6q2i++KXbg0gHCwM= +golang.org/x/sync v0.21.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= golang.org/x/sys v0.0.0-20190626150813-e07cf5db2756/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191018095205-727590c5006e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -115,12 +115,12 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc= -golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/sys v0.46.0 h1:noSf2Fq6F8DBgS+LysIkx7rIExoNHJsxOAtPp4rthXw= +golang.org/x/sys v0.46.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= -golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM= -golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM= +golang.org/x/text v0.39.0 h1:UbZz4pLOvn600D6Oh6GGEI6VAmndrEBLv8/6BEXzyus= +golang.org/x/text v0.39.0/go.mod h1:3UwRclnC2g0TU9x8PZiyfOajCd1zaUNHF9cvqcQZ+ZM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= From 4978fe368c7bd11dfc371d9ff6d965efd6a5268a Mon Sep 17 00:00:00 2001 From: Muhammad Falak R Wani Date: Thu, 27 Aug 2026 13:26:27 +0530 Subject: [PATCH 02/12] chore: install upstream go 1.25 on Ubuntu releases without a distro package Ubuntu 26.04 packages Go 1.25 as golang-1.25-go, but 22.04 and 24.04 do not package it at all, so installing prerequisites there leaves the toolkit without a usable Go. The apt package also is not on PATH, which is why --fix-go-links exists. Drop golang-1.25-go from the apt list and instead check the Go on PATH, falling back to the pinned upstream tarball from go.dev when it is missing or older than 1.25. The download is verified against a hardcoded SHA256 before anything is unpacked, so a corrupted or tampered archive can neither be installed nor replace an existing toolchain. Unsupported architectures fail with an actionable message rather than a 404. This gives every supported release the same Go install path and puts go and gofmt on PATH without a separate step. Signed-off-by: Muhammad Falak R Wani --- toolkit/docs/building/prerequisites-ubuntu.md | 34 ++++++------ toolkit/docs/building/prerequisites-ubuntu.sh | 54 ++++++++++++++++--- 2 files changed, 65 insertions(+), 23 deletions(-) diff --git a/toolkit/docs/building/prerequisites-ubuntu.md b/toolkit/docs/building/prerequisites-ubuntu.md index 6d12e57e0d2..1dba50673a9 100644 --- a/toolkit/docs/building/prerequisites-ubuntu.md +++ b/toolkit/docs/building/prerequisites-ubuntu.md @@ -7,9 +7,20 @@ This page outlines the requirements for building with the Azure Linux toolkit on ### Golang Package Requirements -The Azure Linux toolkit requires Go 1.25 or newer. Ubuntu 26.04 provides the required package: +The Azure Linux toolkit requires Go 1.25 or newer. -- **Ubuntu 26.04**: `golang-1.25-go` (currently Go 1.25.7) +Ubuntu 26.04 packages Go 1.25 as `golang-1.25-go`, but the older releases still in common use +(22.04, 24.04) do not package it at all. The prerequisites script therefore checks the Go already on +your `PATH` and, unless it is 1.25 or newer, downloads the pinned upstream toolchain from +[go.dev/dl](https://go.dev/dl), verifies its SHA256 checksum, unpacks it into `/usr/local/go` and +symlinks `go` and `gofmt` into `/usr/bin`. `amd64` and `arm64` are supported; on any other +architecture the script stops and asks you to install Go yourself. + +The pinned version and its checksums are the `GO_VERSION`/`GO_SHA256_*` variables at the top of +`prerequisites-ubuntu.sh` and must be updated together. + +To use a Go you have installed yourself instead, make sure it is on `PATH` and reports 1.25 or +newer; the script will detect it and skip the download. ## Installation Methods @@ -22,18 +33,14 @@ The make targets automatically install the appropriate packages: # Installs prerequisites but doesn't modify system configuration sudo make -C toolkit install-prereqs -# Manually create Go symlinks for proper PATH integration -sudo ln -sf /usr/lib/go-1.25/bin/go /usr/bin/go -sudo ln -sf /usr/lib/go-1.25/bin/gofmt /usr/bin/gofmt - # Manually configure Docker if needed curl -fsSL https://get.docker.com -o get-docker.sh sudo sh get-docker.sh sudo usermod -aG docker $USER # Note: You will need to log out and log back in for user changes to take effect -# the above 2 steps can alternatively be done using the following command if preferred: -# sudo ./toolkit/docs/building/prerequisites-ubuntu.sh --no-install-prereqs --fix-go-links --configure-docker +# the above step can alternatively be done using the following command if preferred: +# sudo ./toolkit/docs/building/prerequisites-ubuntu.sh --no-install-prereqs --configure-docker ---------------------- @@ -55,25 +62,22 @@ If you prefer running the script directly, you have several options: # Basic installation with Go sudo ./toolkit/docs/building/prerequisites-ubuntu.sh -# Manually create Go symlinks for proper PATH integration -sudo ln -sf /usr/lib/go-1.25/bin/go /usr/bin/go -sudo ln -sf /usr/lib/go-1.25/bin/gofmt /usr/bin/gofmt - # Manually configure Docker if needed curl -fsSL https://get.docker.com -o get-docker.sh sudo sh get-docker.sh sudo usermod -aG docker $USER # Note: You will need to log out and log back in for user changes to take effect -# the above 2 steps can alternatively be done using the following command if preferred: -# sudo ./toolkit/docs/building/prerequisites-ubuntu.sh --no-install-prereqs --fix-go-links --configure-docker +# the above step can alternatively be done using the following command if preferred: +# sudo ./toolkit/docs/building/prerequisites-ubuntu.sh --no-install-prereqs --configure-docker ``` ## Script Options The `prerequisites-ubuntu.sh` script supports the following options: -- `--fix-go-links`: Creates symbolic links for Go binaries to make them available in your PATH +- `--fix-go-links`: Re-creates the `/usr/bin` symlinks for the Go binaries in `/usr/local/go`. The + prerequisites installation already does this, so it is only needed to repair the links. - `--configure-docker`: Installs Docker and adds your user to the docker group - `--no-install-prereqs`: Skips installation of prerequisite packages - `--help`: Displays usage information diff --git a/toolkit/docs/building/prerequisites-ubuntu.sh b/toolkit/docs/building/prerequisites-ubuntu.sh index 00717bfa598..25eb7bc30d2 100755 --- a/toolkit/docs/building/prerequisites-ubuntu.sh +++ b/toolkit/docs/building/prerequisites-ubuntu.sh @@ -2,7 +2,15 @@ # Copyright (c) Microsoft Corporation. # Licensed under the MIT License. -set -e +set -eo pipefail + +# Ubuntu 26.04 packages Go 1.25, but the older releases still used by developers and CI (22.04, +# 24.04) do not package it at all. Rather than special-casing releases, install the upstream +# toolchain whenever the Go already on PATH is missing or older than 1.25. +# Checksums are from https://go.dev/dl and must be updated together with GO_VERSION. +GO_VERSION=1.25.14 +GO_SHA256_AMD64=a21ae5633a269bcd7e90cf767e48225633795e99d831742cbf3397064fee7712 +GO_SHA256_ARM64=9bf234ea70ffec9347fdf6b22ce4add51717d3386a38a441e8c8743fceb5eaee # Define usage function usage() { @@ -46,9 +54,6 @@ while [ $# -gt 0 ]; do done # Install prerequisites if not disabled -# golang version pinned for stability to avoid breaking changes. As of 11-Aug-2026 we are using golang-1.25.7 on Ubuntu 26.04 since it is the most recent release available. -# When making a breaking change to the toolkit which requires a newer golang version, update this version if needed. -# If no newer version is available, suggest moving to a newer Ubuntu LTS version if [ "$INSTALL_PREREQS" = true ]; then echo "Installing required packages..." apt update @@ -59,7 +64,6 @@ if [ "$INSTALL_PREREQS" = true ]; then gawk \ genisoimage \ git \ - golang-1.25-go \ jq \ make \ openssl \ @@ -72,15 +76,49 @@ if [ "$INSTALL_PREREQS" = true ]; then wget \ xfsprogs \ zstd + + # Ubuntu 26.04 ships golang-1.25-go, but 22.04 and 24.04 do not package Go 1.25 at all, and the + # apt package is not on PATH anyway. Install the upstream toolchain unless PATH already has + # Go 1.25 or newer. + if go version 2>/dev/null | grep -qE 'go1\.(2[5-9]|[3-9][0-9])'; then + echo "Found $(go version), skipping Go installation..." + else + go_arch="$(dpkg --print-architecture)" + case "$go_arch" in + amd64) go_sha256="$GO_SHA256_AMD64" ;; + arm64) go_sha256="$GO_SHA256_ARM64" ;; + *) + echo "ERROR: no upstream Go build is pinned for architecture '$go_arch'." >&2 + echo "Install Go $GO_VERSION or newer manually, then re-run with --no-install-prereqs." >&2 + exit 1 + ;; + esac + + echo "Installing Go $GO_VERSION ($go_arch) from https://go.dev/dl..." + go_tmp_dir="$(mktemp -d)" + trap 'rm -rf "$go_tmp_dir"' EXIT + curl -fsSL -o "$go_tmp_dir/go.tar.gz" \ + "https://go.dev/dl/go${GO_VERSION}.linux-${go_arch}.tar.gz" + echo "$go_sha256 $go_tmp_dir/go.tar.gz" | sha256sum -c - + + rm -rf /usr/local/go + tar -C /usr/local -xzf "$go_tmp_dir/go.tar.gz" + ln -vsf /usr/local/go/bin/go /usr/bin/go + ln -vsf /usr/local/go/bin/gofmt /usr/bin/gofmt + fi else echo "Skipping installation of prerequisite packages..." fi # Fix go 1.25 links if requested if [ "$FIX_GO_LINKS" = true ]; then - echo "Creating Go symlinks..." - ln -vsf /usr/lib/go-1.25/bin/go /usr/bin/go - ln -vsf /usr/lib/go-1.25/bin/gofmt /usr/bin/gofmt + if [ -x /usr/local/go/bin/go ]; then + echo "Creating Go symlinks..." + ln -vsf /usr/local/go/bin/go /usr/bin/go + ln -vsf /usr/local/go/bin/gofmt /usr/bin/gofmt + else + echo "No Go installation in /usr/local/go, skipping Go symlinks..." + fi fi # Install and configure Docker if requested From e591701fd2eb549e749ddfa803353d6b47a3d5ca Mon Sep 17 00:00:00 2001 From: Muhammad Falak R Wani Date: Thu, 27 Aug 2026 16:31:49 +0530 Subject: [PATCH 03/12] fix: prefer the distro golang package on Ubuntu releases that have it The previous commit unconditionally downloaded Go from go.dev whenever PATH had no Go 1.25+. That regressed Ubuntu 26.04, where golang-1.25-go exists: hosts that can reach an apt mirror but not the public internet went from working to failing. Try apt first and fall back to go.dev only when the package is genuinely unavailable. Success is decided by the filesystem (/usr/lib/go-1.25/bin/go) rather than by parsing apt output, whose "Candidate:" label is translated and would misfire under a non-English locale. Since Go can now land in either root, go_root() resolves it once and both the install path and --fix-go-links share that result. --- toolkit/docs/building/prerequisites-ubuntu.md | 22 +++-- toolkit/docs/building/prerequisites-ubuntu.sh | 84 +++++++++++-------- 2 files changed, 66 insertions(+), 40 deletions(-) diff --git a/toolkit/docs/building/prerequisites-ubuntu.md b/toolkit/docs/building/prerequisites-ubuntu.md index 1dba50673a9..d89266ee0eb 100644 --- a/toolkit/docs/building/prerequisites-ubuntu.md +++ b/toolkit/docs/building/prerequisites-ubuntu.md @@ -10,11 +10,18 @@ This page outlines the requirements for building with the Azure Linux toolkit on The Azure Linux toolkit requires Go 1.25 or newer. Ubuntu 26.04 packages Go 1.25 as `golang-1.25-go`, but the older releases still in common use -(22.04, 24.04) do not package it at all. The prerequisites script therefore checks the Go already on -your `PATH` and, unless it is 1.25 or newer, downloads the pinned upstream toolchain from -[go.dev/dl](https://go.dev/dl), verifies its SHA256 checksum, unpacks it into `/usr/local/go` and -symlinks `go` and `gofmt` into `/usr/bin`. `amd64` and `arm64` are supported; on any other -architecture the script stops and asks you to install Go yourself. +(22.04, 24.04) do not package it at all. Unless your `PATH` already has Go 1.25 or newer, the +prerequisites script picks a source at runtime: + +1. **The distro package**, when apt has a `golang-1.25-go` candidate (Ubuntu 26.04 and newer). Go is + installed into `/usr/lib/go-1.25`. This keeps working on hosts that can reach an apt mirror but + have no access to the public internet. +2. **The upstream toolchain**, when apt has no candidate. The pinned tarball is downloaded from + [go.dev/dl](https://go.dev/dl), verified against a SHA256 checksum, and unpacked into + `/usr/local/go`. `amd64` and `arm64` are supported; on any other architecture the script stops and + asks you to install Go yourself. + +Either way `go` and `gofmt` are symlinked into `/usr/bin`, so no separate step is needed. The pinned version and its checksums are the `GO_VERSION`/`GO_SHA256_*` variables at the top of `prerequisites-ubuntu.sh` and must be updated together. @@ -76,8 +83,9 @@ sudo usermod -aG docker $USER The `prerequisites-ubuntu.sh` script supports the following options: -- `--fix-go-links`: Re-creates the `/usr/bin` symlinks for the Go binaries in `/usr/local/go`. The - prerequisites installation already does this, so it is only needed to repair the links. +- `--fix-go-links`: Re-creates the `/usr/bin` symlinks for the Go binaries, pointing them at + whichever Go root is installed (`/usr/lib/go-1.25` or `/usr/local/go`). The prerequisites + installation already does this, so it is only needed to repair the links. - `--configure-docker`: Installs Docker and adds your user to the docker group - `--no-install-prereqs`: Skips installation of prerequisite packages - `--help`: Displays usage information diff --git a/toolkit/docs/building/prerequisites-ubuntu.sh b/toolkit/docs/building/prerequisites-ubuntu.sh index 25eb7bc30d2..ff0a2aa8092 100755 --- a/toolkit/docs/building/prerequisites-ubuntu.sh +++ b/toolkit/docs/building/prerequisites-ubuntu.sh @@ -4,14 +4,26 @@ set -eo pipefail -# Ubuntu 26.04 packages Go 1.25, but the older releases still used by developers and CI (22.04, -# 24.04) do not package it at all. Rather than special-casing releases, install the upstream -# toolchain whenever the Go already on PATH is missing or older than 1.25. +# Go is installed separately from the other packages because its source depends on the release. +# Ubuntu 26.04 packages Go 1.25 as golang-1.25-go; 22.04 and 24.04 do not package it at all, so +# those fall back to the upstream toolchain. The distro package is preferred so that hosts which +# can reach an apt mirror but not go.dev keep working without external egress. # Checksums are from https://go.dev/dl and must be updated together with GO_VERSION. +GO_APT_PACKAGE=golang-1.25-go +GO_APT_ROOT=/usr/lib/go-1.25 GO_VERSION=1.25.14 GO_SHA256_AMD64=a21ae5633a269bcd7e90cf767e48225633795e99d831742cbf3397064fee7712 GO_SHA256_ARM64=9bf234ea70ffec9347fdf6b22ce4add51717d3386a38a441e8c8743fceb5eaee +# Echoes the root of an installed Go toolchain, preferring the distro package over the upstream +# tarball. Returns non-zero when neither is present. +go_root() { + for root in "$GO_APT_ROOT" /usr/local/go; do + [ -x "$root/bin/go" ] && { echo "$root"; return 0; } + done + return 1 +} + # Define usage function usage() { echo "Usage: $0 [OPTIONS]" @@ -77,34 +89,40 @@ if [ "$INSTALL_PREREQS" = true ]; then xfsprogs \ zstd - # Ubuntu 26.04 ships golang-1.25-go, but 22.04 and 24.04 do not package Go 1.25 at all, and the - # apt package is not on PATH anyway. Install the upstream toolchain unless PATH already has - # Go 1.25 or newer. + # Install Go from the distro when it is packaged, otherwise from the pinned upstream tarball. if go version 2>/dev/null | grep -qE 'go1\.(2[5-9]|[3-9][0-9])'; then echo "Found $(go version), skipping Go installation..." else - go_arch="$(dpkg --print-architecture)" - case "$go_arch" in - amd64) go_sha256="$GO_SHA256_AMD64" ;; - arm64) go_sha256="$GO_SHA256_ARM64" ;; - *) - echo "ERROR: no upstream Go build is pinned for architecture '$go_arch'." >&2 - echo "Install Go $GO_VERSION or newer manually, then re-run with --no-install-prereqs." >&2 - exit 1 - ;; - esac - - echo "Installing Go $GO_VERSION ($go_arch) from https://go.dev/dl..." - go_tmp_dir="$(mktemp -d)" - trap 'rm -rf "$go_tmp_dir"' EXIT - curl -fsSL -o "$go_tmp_dir/go.tar.gz" \ - "https://go.dev/dl/go${GO_VERSION}.linux-${go_arch}.tar.gz" - echo "$go_sha256 $go_tmp_dir/go.tar.gz" | sha256sum -c - - - rm -rf /usr/local/go - tar -C /usr/local -xzf "$go_tmp_dir/go.tar.gz" - ln -vsf /usr/local/go/bin/go /usr/bin/go - ln -vsf /usr/local/go/bin/gofmt /usr/bin/gofmt + echo "Checking apt for '$GO_APT_PACKAGE' (not packaged before Ubuntu 26.04)..." + if apt install -y "$GO_APT_PACKAGE" && [ -x "$GO_APT_ROOT/bin/go" ]; then + echo "Installed $GO_APT_PACKAGE from apt." + else + echo "'$GO_APT_PACKAGE' is unavailable on this release, using the upstream toolchain..." + go_arch="$(dpkg --print-architecture)" + case "$go_arch" in + amd64) go_sha256="$GO_SHA256_AMD64" ;; + arm64) go_sha256="$GO_SHA256_ARM64" ;; + *) + echo "ERROR: no upstream Go build is pinned for architecture '$go_arch'." >&2 + echo "Install Go $GO_VERSION or newer manually, then re-run with --no-install-prereqs." >&2 + exit 1 + ;; + esac + + echo "Installing Go $GO_VERSION ($go_arch) from https://go.dev/dl..." + go_tmp_dir="$(mktemp -d)" + trap 'rm -rf "$go_tmp_dir"' EXIT + curl -fsSL -o "$go_tmp_dir/go.tar.gz" \ + "https://go.dev/dl/go${GO_VERSION}.linux-${go_arch}.tar.gz" + echo "$go_sha256 $go_tmp_dir/go.tar.gz" | sha256sum -c - + + rm -rf /usr/local/go + tar -C /usr/local -xzf "$go_tmp_dir/go.tar.gz" + fi + + go_installed_root="$(go_root)" + ln -vsf "$go_installed_root/bin/go" /usr/bin/go + ln -vsf "$go_installed_root/bin/gofmt" /usr/bin/gofmt fi else echo "Skipping installation of prerequisite packages..." @@ -112,12 +130,12 @@ fi # Fix go 1.25 links if requested if [ "$FIX_GO_LINKS" = true ]; then - if [ -x /usr/local/go/bin/go ]; then - echo "Creating Go symlinks..." - ln -vsf /usr/local/go/bin/go /usr/bin/go - ln -vsf /usr/local/go/bin/gofmt /usr/bin/gofmt + if go_link_root="$(go_root)"; then + echo "Creating Go symlinks from $go_link_root..." + ln -vsf "$go_link_root/bin/go" /usr/bin/go + ln -vsf "$go_link_root/bin/gofmt" /usr/bin/gofmt else - echo "No Go installation in /usr/local/go, skipping Go symlinks..." + echo "No Go installation in $GO_APT_ROOT or /usr/local/go, skipping Go symlinks..." fi fi From ccc21b5af4df2f5a03112ce4d78b3fd0d6555ee0 Mon Sep 17 00:00:00 2001 From: Muhammad Falak R Wani Date: Thu, 27 Aug 2026 16:36:18 +0530 Subject: [PATCH 04/12] fix: do not overwrite an existing Go toolchain in /usr/local/go The install gate only looked at the go on PATH. A user who had unpacked Go into /usr/local/go without linking it into /usr/bin -- or whose links had been removed -- would silently have that toolchain deleted and, if it was newer than the pinned version, downgraded to 1.25.14. Look for an installed toolchain in either root before installing anything and reuse it when it is 1.25 or newer, so the run only re-creates the symlinks. When /usr/local/go really is too old to keep, say so before removing it instead of doing it silently. --- toolkit/docs/building/prerequisites-ubuntu.md | 3 + toolkit/docs/building/prerequisites-ubuntu.sh | 64 +++++++++++-------- 2 files changed, 42 insertions(+), 25 deletions(-) diff --git a/toolkit/docs/building/prerequisites-ubuntu.md b/toolkit/docs/building/prerequisites-ubuntu.md index d89266ee0eb..84a8dbab80a 100644 --- a/toolkit/docs/building/prerequisites-ubuntu.md +++ b/toolkit/docs/building/prerequisites-ubuntu.md @@ -23,6 +23,9 @@ prerequisites script picks a source at runtime: Either way `go` and `gofmt` are symlinked into `/usr/bin`, so no separate step is needed. +A Go toolchain that is already installed in either location and reports 1.25 or newer is reused +as-is — the script only ever replaces a `/usr/local/go` that is too old, and says so before it does. + The pinned version and its checksums are the `GO_VERSION`/`GO_SHA256_*` variables at the top of `prerequisites-ubuntu.sh` and must be updated together. diff --git a/toolkit/docs/building/prerequisites-ubuntu.sh b/toolkit/docs/building/prerequisites-ubuntu.sh index ff0a2aa8092..44a486a9455 100755 --- a/toolkit/docs/building/prerequisites-ubuntu.sh +++ b/toolkit/docs/building/prerequisites-ubuntu.sh @@ -24,6 +24,11 @@ go_root() { return 1 } +# Returns zero when the given go binary is 1.25 or newer, e.g. go1.25.14, go1.26.0, go1.31rc1. +go_is_supported() { + "$1" version 2>/dev/null | grep -qE 'go1\.(2[5-9]|[3-9][0-9])' +} + # Define usage function usage() { echo "Usage: $0 [OPTIONS]" @@ -90,34 +95,43 @@ if [ "$INSTALL_PREREQS" = true ]; then zstd # Install Go from the distro when it is packaged, otherwise from the pinned upstream tarball. - if go version 2>/dev/null | grep -qE 'go1\.(2[5-9]|[3-9][0-9])'; then + if go_is_supported go; then echo "Found $(go version), skipping Go installation..." else - echo "Checking apt for '$GO_APT_PACKAGE' (not packaged before Ubuntu 26.04)..." - if apt install -y "$GO_APT_PACKAGE" && [ -x "$GO_APT_ROOT/bin/go" ]; then - echo "Installed $GO_APT_PACKAGE from apt." + if go_existing_root="$(go_root)" && go_is_supported "$go_existing_root/bin/go"; then + # Installed, just not on PATH. Relinking below is enough, and reinstalling would + # overwrite a toolchain that may well be newer than the one pinned here. + echo "Found $("$go_existing_root/bin/go" version) in $go_existing_root, reusing it..." else - echo "'$GO_APT_PACKAGE' is unavailable on this release, using the upstream toolchain..." - go_arch="$(dpkg --print-architecture)" - case "$go_arch" in - amd64) go_sha256="$GO_SHA256_AMD64" ;; - arm64) go_sha256="$GO_SHA256_ARM64" ;; - *) - echo "ERROR: no upstream Go build is pinned for architecture '$go_arch'." >&2 - echo "Install Go $GO_VERSION or newer manually, then re-run with --no-install-prereqs." >&2 - exit 1 - ;; - esac - - echo "Installing Go $GO_VERSION ($go_arch) from https://go.dev/dl..." - go_tmp_dir="$(mktemp -d)" - trap 'rm -rf "$go_tmp_dir"' EXIT - curl -fsSL -o "$go_tmp_dir/go.tar.gz" \ - "https://go.dev/dl/go${GO_VERSION}.linux-${go_arch}.tar.gz" - echo "$go_sha256 $go_tmp_dir/go.tar.gz" | sha256sum -c - - - rm -rf /usr/local/go - tar -C /usr/local -xzf "$go_tmp_dir/go.tar.gz" + echo "Checking apt for '$GO_APT_PACKAGE' (not packaged before Ubuntu 26.04)..." + if apt install -y "$GO_APT_PACKAGE" && [ -x "$GO_APT_ROOT/bin/go" ]; then + echo "Installed $GO_APT_PACKAGE from apt." + else + echo "'$GO_APT_PACKAGE' is unavailable on this release, using the upstream toolchain..." + go_arch="$(dpkg --print-architecture)" + case "$go_arch" in + amd64) go_sha256="$GO_SHA256_AMD64" ;; + arm64) go_sha256="$GO_SHA256_ARM64" ;; + *) + echo "ERROR: no upstream Go build is pinned for architecture '$go_arch'." >&2 + echo "Install Go $GO_VERSION or newer manually, then re-run with --no-install-prereqs." >&2 + exit 1 + ;; + esac + + echo "Installing Go $GO_VERSION ($go_arch) from https://go.dev/dl..." + go_tmp_dir="$(mktemp -d)" + trap 'rm -rf "$go_tmp_dir"' EXIT + curl -fsSL -o "$go_tmp_dir/go.tar.gz" \ + "https://go.dev/dl/go${GO_VERSION}.linux-${go_arch}.tar.gz" + echo "$go_sha256 $go_tmp_dir/go.tar.gz" | sha256sum -c - + + if [ -e /usr/local/go ]; then + echo "WARNING: replacing the Go installation in /usr/local/go, it is older than $GO_VERSION." >&2 + fi + rm -rf /usr/local/go + tar -C /usr/local -xzf "$go_tmp_dir/go.tar.gz" + fi fi go_installed_root="$(go_root)" From 2406138b463312375b990446164a2a63f1f7223c Mon Sep 17 00:00:00 2001 From: Muhammad Falak R Wani Date: Thu, 27 Aug 2026 16:42:22 +0530 Subject: [PATCH 05/12] fix: warn when another go on PATH shadows the installed toolchain The script links /usr/bin/go, but that is not necessarily the go that runs: Ubuntu's default PATH and sudo's secure_path both list /usr/local/bin ahead of /usr/bin, so a go left there keeps winning. The failure that follows is remote from its cause -- tools.mk checks go_min_version much later, from a different script, and reports only that the version is too old. Name the shadowing binary and what it reports while we are still in the script that can explain it. Compare with -ef rather than by string so that reaching the same file through the /bin -> usr/bin symlink is not mistaken for a shadow. --- toolkit/docs/building/prerequisites-ubuntu.md | 5 ++++ toolkit/docs/building/prerequisites-ubuntu.sh | 23 +++++++++++++++---- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/toolkit/docs/building/prerequisites-ubuntu.md b/toolkit/docs/building/prerequisites-ubuntu.md index 84a8dbab80a..a2b3147795d 100644 --- a/toolkit/docs/building/prerequisites-ubuntu.md +++ b/toolkit/docs/building/prerequisites-ubuntu.md @@ -26,6 +26,11 @@ Either way `go` and `gofmt` are symlinked into `/usr/bin`, so no separate step i A Go toolchain that is already installed in either location and reports 1.25 or newer is reused as-is — the script only ever replaces a `/usr/local/go` that is too old, and says so before it does. +If some other `go` sits earlier on `PATH` than `/usr/bin` — `/usr/local/bin/go` is the usual +culprit, since both Ubuntu's default `PATH` and `sudo`'s `secure_path` list `/usr/local/bin` first — +the script names it and warns that it will be used instead. Remove it, or the build will later fail +its Go version check. + The pinned version and its checksums are the `GO_VERSION`/`GO_SHA256_*` variables at the top of `prerequisites-ubuntu.sh` and must be updated together. diff --git a/toolkit/docs/building/prerequisites-ubuntu.sh b/toolkit/docs/building/prerequisites-ubuntu.sh index 44a486a9455..454750ec0ab 100755 --- a/toolkit/docs/building/prerequisites-ubuntu.sh +++ b/toolkit/docs/building/prerequisites-ubuntu.sh @@ -29,6 +29,23 @@ go_is_supported() { "$1" version 2>/dev/null | grep -qE 'go1\.(2[5-9]|[3-9][0-9])' } +# Points /usr/bin/go and /usr/bin/gofmt at the given Go root, then checks the links actually win. +link_go() { + ln -vsf "$1/bin/go" /usr/bin/go + ln -vsf "$1/bin/gofmt" /usr/bin/gofmt + + # Ubuntu's default PATH, and sudo's secure_path, list /usr/local/bin ahead of /usr/bin, so a + # stray go left there keeps winning. Without this warning the toolkit's own version gate fails + # much later, from a different script, with nothing pointing back to the real cause. + hash -r + go_on_path="$(command -v go 2>/dev/null || true)" + if [ -n "$go_on_path" ] && ! [ "$go_on_path" -ef /usr/bin/go ]; then + echo "WARNING: '$go_on_path' precedes /usr/bin/go on PATH and will be used instead:" >&2 + echo "WARNING: $("$go_on_path" version 2>&1 | head -n 1)" >&2 + echo "WARNING: remove it if the build later reports an unsupported Go version." >&2 + fi +} + # Define usage function usage() { echo "Usage: $0 [OPTIONS]" @@ -135,8 +152,7 @@ if [ "$INSTALL_PREREQS" = true ]; then fi go_installed_root="$(go_root)" - ln -vsf "$go_installed_root/bin/go" /usr/bin/go - ln -vsf "$go_installed_root/bin/gofmt" /usr/bin/gofmt + link_go "$go_installed_root" fi else echo "Skipping installation of prerequisite packages..." @@ -146,8 +162,7 @@ fi if [ "$FIX_GO_LINKS" = true ]; then if go_link_root="$(go_root)"; then echo "Creating Go symlinks from $go_link_root..." - ln -vsf "$go_link_root/bin/go" /usr/bin/go - ln -vsf "$go_link_root/bin/gofmt" /usr/bin/gofmt + link_go "$go_link_root" else echo "No Go installation in $GO_APT_ROOT or /usr/local/go, skipping Go symlinks..." fi From 3c0455a8d3b2efeec6943d9f8f2dada4da39f965 Mon Sep 17 00:00:00 2001 From: Muhammad Falak R Wani Date: Thu, 27 Aug 2026 16:42:58 +0530 Subject: [PATCH 06/12] docs: drop the stale msft-golang note from the Azure Linux prerequisites The document already says Azure Linux 2.0 is unsupported, then a few lines later tells the reader what install-prereqs does on Azure Linux 2.0. Neither half of that note is true any more. toolkit.mk refuses outright when ID=mariner, and prerequisites-mariner.sh installs plain 'golang' with no msft-golang handling of any kind. Remove it, and say plainly why 2.0 is out. --- toolkit/docs/building/prerequisites-mariner.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/toolkit/docs/building/prerequisites-mariner.md b/toolkit/docs/building/prerequisites-mariner.md index a55ee8948ca..4c6ac4e5415 100644 --- a/toolkit/docs/building/prerequisites-mariner.md +++ b/toolkit/docs/building/prerequisites-mariner.md @@ -9,7 +9,8 @@ This page outlines the requirements for building with the Azure Linux toolkit on The Azure Linux toolkit requires Go 1.25 or newer: -- **Azure Linux 2.0 (CBL-Mariner)**: Not supported because its `msft-golang-1.24.1` package is below the minimum version +- **Azure Linux 2.0 (CBL-Mariner)**: Not supported. `install-prereqs` refuses outright because 2.0 + is end-of-life; its newest Go package, `msft-golang-1.24.1`, is below the minimum in any case. - **Azure Linux 3.0**: Supported by the current `golang` package ## Installation Methods @@ -21,7 +22,6 @@ The make targets automatically detect your OS version and install the appropriat ```bash # For interactive development environments (local machines) # Installs prerequisites but doesn't modify system configuration -# Note: On Azure Linux 2.0, this will remove golang if installed in favor of msft-golang due to the golang version requirement sudo make -C toolkit install-prereqs # Manually configure Docker if needed From c47ff8fd73e9612e2a7990ce569e22fff6435a7b Mon Sep 17 00:00:00 2001 From: Muhammad Falak R Wani Date: Thu, 27 Aug 2026 16:44:45 +0530 Subject: [PATCH 07/12] docs: record how and when to advance the pinned Go version Go supports only its two most recent majors, so a hardcoded GO_VERSION starts aging the day it lands. Nothing said so, and nothing said that the minimum version is also spelled out in go.mod, the coverage workflow and two prerequisite documents -- so the obvious next bump is a one-line edit that leaves four other places behind. Write the cadence and the full list of coupled locations down next to the pin, and point the script's header comment at it. --- toolkit/docs/building/prerequisites-ubuntu.md | 23 +++++++++++++++++++ toolkit/docs/building/prerequisites-ubuntu.sh | 4 ++++ 2 files changed, 27 insertions(+) diff --git a/toolkit/docs/building/prerequisites-ubuntu.md b/toolkit/docs/building/prerequisites-ubuntu.md index a2b3147795d..8cba48d97da 100644 --- a/toolkit/docs/building/prerequisites-ubuntu.md +++ b/toolkit/docs/building/prerequisites-ubuntu.md @@ -37,6 +37,29 @@ The pinned version and its checksums are the `GO_VERSION`/`GO_SHA256_*` variable To use a Go you have installed yourself instead, make sure it is on `PATH` and reports 1.25 or newer; the script will detect it and skip the download. +#### Updating the pinned Go version + +Go supports only the two most recent major releases: when 1.N ships, 1.(N-2) stops receiving +security fixes. This pin therefore moves on Go's release cadence rather than Azure Linux's, and +CVE fixes are a routine reason to move it. lists the supported releases. + +Bumping the *patch* release (1.25.x → 1.25.y) means editing `prerequisites-ubuntu.sh` alone: + +1. Set `GO_VERSION`. +2. Set `GO_SHA256_AMD64` and `GO_SHA256_ARM64` from in the same change — the + checksums are version-specific, and a stale one aborts the install. + +Bumping the *major* release (1.25 → 1.26) additionally requires, all in one change: + +| Location | What to change | +| --- | --- | +| `prerequisites-ubuntu.sh` | `GO_APT_PACKAGE`, `GO_APT_ROOT`, and the version regex in `go_is_supported` | +| `toolkit/tools/go.mod` | the `go` directive, which `toolkit/scripts/tools.mk` turns into the build-time minimum | +| `.github/workflows/go-test-coverage.yml` | `EXPECTED_GO_VERSION`, which both selects the CI toolchain and asserts the `go.mod` directive matches | +| `prerequisites-ubuntu.md`, `prerequisites-mariner.md` | the stated minimum version | + +Leaving any of them behind either fails CI or, worse, installs a toolchain the build then rejects. + ## Installation Methods ### Method 1: Using Make Targets (Recommended) diff --git a/toolkit/docs/building/prerequisites-ubuntu.sh b/toolkit/docs/building/prerequisites-ubuntu.sh index 454750ec0ab..5fbb67bdfe0 100755 --- a/toolkit/docs/building/prerequisites-ubuntu.sh +++ b/toolkit/docs/building/prerequisites-ubuntu.sh @@ -8,6 +8,10 @@ set -eo pipefail # Ubuntu 26.04 packages Go 1.25 as golang-1.25-go; 22.04 and 24.04 do not package it at all, so # those fall back to the upstream toolchain. The distro package is preferred so that hosts which # can reach an apt mirror but not go.dev keep working without external egress. +# +# Go supports only the two most recent major releases, so this pin has to keep moving. See +# "Updating the pinned Go version" in prerequisites-ubuntu.md before changing any of it: the +# minimum version is spelled out in four other places that must move at the same time. # Checksums are from https://go.dev/dl and must be updated together with GO_VERSION. GO_APT_PACKAGE=golang-1.25-go GO_APT_ROOT=/usr/lib/go-1.25 From 3927cf3c95ab352790d3342b2b7420407f878ac1 Mon Sep 17 00:00:00 2001 From: Muhammad Falak R Wani Date: Thu, 27 Aug 2026 16:48:53 +0530 Subject: [PATCH 08/12] fix: explain a checksum mismatch instead of printing sha256sum's FAILED GO_VERSION and the two GO_SHA256_* constants have to move together, and the most likely way to get this wrong is to bump one and forget the others. All that told you was: /tmp/tmp.XXXX/go.tar.gz: FAILED sha256sum: WARNING: 1 computed checksum did NOT match which does not say which release was expected, which constant is stale, where to find the right value, or whether anything was left half-installed. It reads like a compromised download even when it is a one-line editing mistake -- and the reverse mistake, reading a real tampering incident as a stale constant, is worse. Print the release, both sums, the exact constant for the architecture in hand, and the fact that nothing was installed. --- toolkit/docs/building/prerequisites-ubuntu.md | 3 ++- toolkit/docs/building/prerequisites-ubuntu.sh | 16 +++++++++++++--- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/toolkit/docs/building/prerequisites-ubuntu.md b/toolkit/docs/building/prerequisites-ubuntu.md index 8cba48d97da..1cc59024f37 100644 --- a/toolkit/docs/building/prerequisites-ubuntu.md +++ b/toolkit/docs/building/prerequisites-ubuntu.md @@ -47,7 +47,8 @@ Bumping the *patch* release (1.25.x → 1.25.y) means editing `prerequisites-ubu 1. Set `GO_VERSION`. 2. Set `GO_SHA256_AMD64` and `GO_SHA256_ARM64` from in the same change — the - checksums are version-specific, and a stale one aborts the install. + checksums are version-specific, and a stale one aborts the install with a message naming the + constant that needs refreshing. Bumping the *major* release (1.25 → 1.26) additionally requires, all in one change: diff --git a/toolkit/docs/building/prerequisites-ubuntu.sh b/toolkit/docs/building/prerequisites-ubuntu.sh index 5fbb67bdfe0..63ced44b880 100755 --- a/toolkit/docs/building/prerequisites-ubuntu.sh +++ b/toolkit/docs/building/prerequisites-ubuntu.sh @@ -131,8 +131,8 @@ if [ "$INSTALL_PREREQS" = true ]; then echo "'$GO_APT_PACKAGE' is unavailable on this release, using the upstream toolchain..." go_arch="$(dpkg --print-architecture)" case "$go_arch" in - amd64) go_sha256="$GO_SHA256_AMD64" ;; - arm64) go_sha256="$GO_SHA256_ARM64" ;; + amd64) go_sha256="$GO_SHA256_AMD64"; go_sha256_var=GO_SHA256_AMD64 ;; + arm64) go_sha256="$GO_SHA256_ARM64"; go_sha256_var=GO_SHA256_ARM64 ;; *) echo "ERROR: no upstream Go build is pinned for architecture '$go_arch'." >&2 echo "Install Go $GO_VERSION or newer manually, then re-run with --no-install-prereqs." >&2 @@ -145,7 +145,17 @@ if [ "$INSTALL_PREREQS" = true ]; then trap 'rm -rf "$go_tmp_dir"' EXIT curl -fsSL -o "$go_tmp_dir/go.tar.gz" \ "https://go.dev/dl/go${GO_VERSION}.linux-${go_arch}.tar.gz" - echo "$go_sha256 $go_tmp_dir/go.tar.gz" | sha256sum -c - + if echo "$go_sha256 $go_tmp_dir/go.tar.gz" | sha256sum --status -c -; then + echo "Checksum OK." + else + echo "ERROR: go${GO_VERSION}.linux-${go_arch}.tar.gz does not match its pinned checksum." >&2 + echo " expected: $go_sha256" >&2 + echo " actual: $(sha256sum < "$go_tmp_dir/go.tar.gz" | cut -d ' ' -f 1)" >&2 + echo "Either the download was corrupted or tampered with, or GO_VERSION was changed in" >&2 + echo "$0 without refreshing $go_sha256_var. The expected value for a given release is" >&2 + echo "published at https://go.dev/dl. Nothing has been installed." >&2 + exit 1 + fi if [ -e /usr/local/go ]; then echo "WARNING: replacing the Go installation in /usr/local/go, it is older than $GO_VERSION." >&2 From 4e955f6c0e0c7056e9760663eda3045a62baa58f Mon Sep 17 00:00:00 2001 From: Muhammad Falak R Wani Date: Fri, 28 Aug 2026 05:15:36 +0530 Subject: [PATCH 09/12] fix: do not accept a prerelease of the minimum Go series go_is_supported matched go1.25 anywhere in 'go version', so go1.25rc1 satisfied it. That prerelease predates go1.25.0, which is what go.mod asks for, so the script would decide the host was already fine, skip the install, and leave the build to reject the toolchain later. Require the stable form for the minimum series and keep accepting prereleases of later ones, which really are newer. Reported by Copilot in review. --- toolkit/docs/building/prerequisites-ubuntu.sh | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/toolkit/docs/building/prerequisites-ubuntu.sh b/toolkit/docs/building/prerequisites-ubuntu.sh index 63ced44b880..6d775b6646f 100755 --- a/toolkit/docs/building/prerequisites-ubuntu.sh +++ b/toolkit/docs/building/prerequisites-ubuntu.sh @@ -28,9 +28,11 @@ go_root() { return 1 } -# Returns zero when the given go binary is 1.25 or newer, e.g. go1.25.14, go1.26.0, go1.31rc1. +# Returns zero when the given go binary meets the toolkit's minimum. A prerelease of the minimum +# series must not qualify: go1.25rc1 predates go1.25.0, so the toolkit would reject it. Prereleases +# of later series (go1.26rc1) are new enough and stay accepted. go_is_supported() { - "$1" version 2>/dev/null | grep -qE 'go1\.(2[5-9]|[3-9][0-9])' + "$1" version 2>/dev/null | grep -qE 'go1\.(25\.[0-9]|2[6-9]|[3-9][0-9])' } # Points /usr/bin/go and /usr/bin/gofmt at the given Go root, then checks the links actually win. From b6a452900b14897bf23916ab3666517919c072f9 Mon Sep 17 00:00:00 2001 From: Muhammad Falak R Wani Date: Fri, 28 Aug 2026 05:15:50 +0530 Subject: [PATCH 10/12] docs: correct the release terminology and the shadowed-Go advice Review feedback on three separate points: Going from 1.25 to 1.26 was called a major bump. The major version is the leading 1; these are minor releases. Reworded, and "two most recent major releases" became "release series" so the page does not use the same word for two different things a few lines apart. The shadowed-Go note told the reader to remove the offending binary or the build would fail. That is only true when the shadowing copy is too old -- a newer one works fine -- so it now says what the script itself says: remove it if the build reports an unsupported version. The --fix-go-links description hardcoded /usr/lib/go-1.25, which is one more place to remember on the next bump. Also drop the Azure Linux 2.0 bullet: 2.0 is unsupported, so describing what install-prereqs does there is noise. --- toolkit/docs/building/prerequisites-mariner.md | 2 -- toolkit/docs/building/prerequisites-ubuntu.md | 12 ++++++------ toolkit/docs/building/prerequisites-ubuntu.sh | 2 +- 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/toolkit/docs/building/prerequisites-mariner.md b/toolkit/docs/building/prerequisites-mariner.md index 4c6ac4e5415..cf99998a69b 100644 --- a/toolkit/docs/building/prerequisites-mariner.md +++ b/toolkit/docs/building/prerequisites-mariner.md @@ -9,8 +9,6 @@ This page outlines the requirements for building with the Azure Linux toolkit on The Azure Linux toolkit requires Go 1.25 or newer: -- **Azure Linux 2.0 (CBL-Mariner)**: Not supported. `install-prereqs` refuses outright because 2.0 - is end-of-life; its newest Go package, `msft-golang-1.24.1`, is below the minimum in any case. - **Azure Linux 3.0**: Supported by the current `golang` package ## Installation Methods diff --git a/toolkit/docs/building/prerequisites-ubuntu.md b/toolkit/docs/building/prerequisites-ubuntu.md index 1cc59024f37..3935697ca65 100644 --- a/toolkit/docs/building/prerequisites-ubuntu.md +++ b/toolkit/docs/building/prerequisites-ubuntu.md @@ -28,8 +28,8 @@ as-is — the script only ever replaces a `/usr/local/go` that is too old, and s If some other `go` sits earlier on `PATH` than `/usr/bin` — `/usr/local/bin/go` is the usual culprit, since both Ubuntu's default `PATH` and `sudo`'s `secure_path` list `/usr/local/bin` first — -the script names it and warns that it will be used instead. Remove it, or the build will later fail -its Go version check. +the script names it and warns that it will be used instead. That is only a problem if the shadowing +copy is too old — remove it if the build later reports an unsupported Go version. The pinned version and its checksums are the `GO_VERSION`/`GO_SHA256_*` variables at the top of `prerequisites-ubuntu.sh` and must be updated together. @@ -39,7 +39,7 @@ newer; the script will detect it and skip the download. #### Updating the pinned Go version -Go supports only the two most recent major releases: when 1.N ships, 1.(N-2) stops receiving +Go supports only the two most recent release series: when 1.N ships, 1.(N-2) stops receiving security fixes. This pin therefore moves on Go's release cadence rather than Azure Linux's, and CVE fixes are a routine reason to move it. lists the supported releases. @@ -50,7 +50,7 @@ Bumping the *patch* release (1.25.x → 1.25.y) means editing `prerequisites-ubu checksums are version-specific, and a stale one aborts the install with a message naming the constant that needs refreshing. -Bumping the *major* release (1.25 → 1.26) additionally requires, all in one change: +Bumping the *minor* release (1.25 → 1.26) additionally requires, all in one change: | Location | What to change | | --- | --- | @@ -116,8 +116,8 @@ sudo usermod -aG docker $USER The `prerequisites-ubuntu.sh` script supports the following options: - `--fix-go-links`: Re-creates the `/usr/bin` symlinks for the Go binaries, pointing them at - whichever Go root is installed (`/usr/lib/go-1.25` or `/usr/local/go`). The prerequisites - installation already does this, so it is only needed to repair the links. + whichever Go root is installed (`/usr/lib/go-1.` or `/usr/local/go`). The + prerequisites installation already does this, so it is only needed to repair the links. - `--configure-docker`: Installs Docker and adds your user to the docker group - `--no-install-prereqs`: Skips installation of prerequisite packages - `--help`: Displays usage information diff --git a/toolkit/docs/building/prerequisites-ubuntu.sh b/toolkit/docs/building/prerequisites-ubuntu.sh index 6d775b6646f..4cb858928d6 100755 --- a/toolkit/docs/building/prerequisites-ubuntu.sh +++ b/toolkit/docs/building/prerequisites-ubuntu.sh @@ -9,7 +9,7 @@ set -eo pipefail # those fall back to the upstream toolchain. The distro package is preferred so that hosts which # can reach an apt mirror but not go.dev keep working without external egress. # -# Go supports only the two most recent major releases, so this pin has to keep moving. See +# Go supports only the two most recent release series, so this pin has to keep moving. See # "Updating the pinned Go version" in prerequisites-ubuntu.md before changing any of it: the # minimum version is spelled out in four other places that must move at the same time. # Checksums are from https://go.dev/dl and must be updated together with GO_VERSION. From b037c5eecb73626d5c0033dfaa588dbe8a186c13 Mon Sep 17 00:00:00 2001 From: Muhammad Falak R Wani Date: Fri, 28 Aug 2026 05:16:41 +0530 Subject: [PATCH 11/12] refactor: let the Go helpers resolve the toolchain themselves Review feedback: go_is_supported took a go binary to test, link_go took a root to link, and every caller had to work out what to pass. The result was a nested ladder in the middle of the install block and two separate link call sites, one of which ran even when the caller had not asked for links and both of which ran when it had -- so a plain install-prereqs relinked twice. go_is_supported now answers the question the caller actually has, "is a usable Go already here", checking PATH and both roots itself. link_go resolves the root, prints where it is linking from, and reports the skip when there is nothing to link, so its two callers collapse into one. The version test that both need moved into go_version_ok. The tarball install, which was most of the nesting, is now install_go. go_root prefers a root that meets the minimum over one that does not, so a stale /usr/lib/go-1.25 no longer gets linked over a good /usr/local/go; it still falls back to whatever is installed so that --fix-go-links can repair links to an old toolchain. Linking now happens whenever prerequisites were installed, not only under --fix-go-links. Neither root is on PATH -- that is why the flag exists -- so skipping it would leave install-prereqs reporting success with an unusable toolchain. --- toolkit/docs/building/prerequisites-ubuntu.md | 2 +- toolkit/docs/building/prerequisites-ubuntu.sh | 156 ++++++++++-------- 2 files changed, 89 insertions(+), 69 deletions(-) diff --git a/toolkit/docs/building/prerequisites-ubuntu.md b/toolkit/docs/building/prerequisites-ubuntu.md index 3935697ca65..5c09d572fe5 100644 --- a/toolkit/docs/building/prerequisites-ubuntu.md +++ b/toolkit/docs/building/prerequisites-ubuntu.md @@ -54,7 +54,7 @@ Bumping the *minor* release (1.25 → 1.26) additionally requires, all in one ch | Location | What to change | | --- | --- | -| `prerequisites-ubuntu.sh` | `GO_APT_PACKAGE`, `GO_APT_ROOT`, and the version regex in `go_is_supported` | +| `prerequisites-ubuntu.sh` | `GO_APT_PACKAGE`, `GO_APT_ROOT`, and the version regex in `go_version_ok` | | `toolkit/tools/go.mod` | the `go` directive, which `toolkit/scripts/tools.mk` turns into the build-time minimum | | `.github/workflows/go-test-coverage.yml` | `EXPECTED_GO_VERSION`, which both selects the CI toolchain and asserts the `go.mod` directive matches | | `prerequisites-ubuntu.md`, `prerequisites-mariner.md` | the stated minimum version | diff --git a/toolkit/docs/building/prerequisites-ubuntu.sh b/toolkit/docs/building/prerequisites-ubuntu.sh index 4cb858928d6..ff4b8ab577f 100755 --- a/toolkit/docs/building/prerequisites-ubuntu.sh +++ b/toolkit/docs/building/prerequisites-ubuntu.sh @@ -19,26 +19,94 @@ GO_VERSION=1.25.14 GO_SHA256_AMD64=a21ae5633a269bcd7e90cf767e48225633795e99d831742cbf3397064fee7712 GO_SHA256_ARM64=9bf234ea70ffec9347fdf6b22ce4add51717d3386a38a441e8c8743fceb5eaee +# Returns zero when the given go binary meets the toolkit's minimum. Prereleases of the minimum +# series must not qualify -- go1.25rc1 predates go1.25.0 and the toolkit would reject it -- while +# prereleases of later series (go1.26rc1) are new enough. +go_version_ok() { + "$1" version 2>/dev/null | grep -qE 'go1\.(25\.[0-9]|2[6-9]|[3-9][0-9])' +} + # Echoes the root of an installed Go toolchain, preferring the distro package over the upstream -# tarball. Returns non-zero when neither is present. +# tarball, and a toolchain that meets the minimum over one that does not -- so a stale apt root +# does not get linked over a good upstream one. Returns non-zero when neither root has a Go. go_root() { + go_root_fallback="" for root in "$GO_APT_ROOT" /usr/local/go; do - [ -x "$root/bin/go" ] && { echo "$root"; return 0; } + if [ -x "$root/bin/go" ]; then + go_version_ok "$root/bin/go" && { echo "$root"; return 0; } + [ -z "$go_root_fallback" ] && go_root_fallback="$root" + fi done + + [ -n "$go_root_fallback" ] && { echo "$go_root_fallback"; return 0; } return 1 } -# Returns zero when the given go binary meets the toolkit's minimum. A prerelease of the minimum -# series must not qualify: go1.25rc1 predates go1.25.0, so the toolkit would reject it. Prereleases -# of later series (go1.26rc1) are new enough and stay accepted. +# Returns zero when a Go new enough for the toolkit is already available, whether it is first on +# PATH or sitting unlinked in one of the roots this script manages. go_is_supported() { - "$1" version 2>/dev/null | grep -qE 'go1\.(25\.[0-9]|2[6-9]|[3-9][0-9])' + go_version_ok go && return 0 + + go_installed_root="$(go_root)" || return 1 + go_version_ok "$go_installed_root/bin/go" } -# Points /usr/bin/go and /usr/bin/gofmt at the given Go root, then checks the links actually win. +# Installs Go from the distro when it is packaged, otherwise from the pinned upstream tarball. +install_go() { + echo "Checking apt for '$GO_APT_PACKAGE' (not packaged before Ubuntu 26.04)..." + if apt install -y "$GO_APT_PACKAGE" && [ -x "$GO_APT_ROOT/bin/go" ]; then + echo "Installed $GO_APT_PACKAGE from apt." + return + fi + + echo "'$GO_APT_PACKAGE' is unavailable on this release, using the upstream toolchain..." + go_arch="$(dpkg --print-architecture)" + case "$go_arch" in + amd64) go_sha256="$GO_SHA256_AMD64"; go_sha256_var=GO_SHA256_AMD64 ;; + arm64) go_sha256="$GO_SHA256_ARM64"; go_sha256_var=GO_SHA256_ARM64 ;; + *) + echo "ERROR: no upstream Go build is pinned for architecture '$go_arch'." >&2 + echo "Install Go $GO_VERSION or newer manually, then re-run with --no-install-prereqs." >&2 + exit 1 + ;; + esac + + echo "Installing Go $GO_VERSION ($go_arch) from https://go.dev/dl..." + # Deliberately not 'local': the EXIT trap below runs after this function has returned, when a + # function-scoped variable would already be out of scope and the temp dir would leak. + go_tmp_dir="$(mktemp -d)" + trap 'rm -rf "$go_tmp_dir"' EXIT + curl -fsSL -o "$go_tmp_dir/go.tar.gz" \ + "https://go.dev/dl/go${GO_VERSION}.linux-${go_arch}.tar.gz" + if echo "$go_sha256 $go_tmp_dir/go.tar.gz" | sha256sum --status -c -; then + echo "Checksum OK." + else + echo "ERROR: go${GO_VERSION}.linux-${go_arch}.tar.gz does not match its pinned checksum." >&2 + echo " expected: $go_sha256" >&2 + echo " actual: $(sha256sum < "$go_tmp_dir/go.tar.gz" | cut -d ' ' -f 1)" >&2 + echo "Either the download was corrupted or tampered with, or GO_VERSION was changed in" >&2 + echo "$0 without refreshing $go_sha256_var. The expected value for a given release is" >&2 + echo "published at https://go.dev/dl. Nothing has been installed." >&2 + exit 1 + fi + + if [ -e /usr/local/go ]; then + echo "WARNING: replacing the Go installation in /usr/local/go, it is older than $GO_VERSION." >&2 + fi + rm -rf /usr/local/go + tar -C /usr/local -xzf "$go_tmp_dir/go.tar.gz" +} + +# Points /usr/bin/go and /usr/bin/gofmt at the installed Go root, then checks the links actually win. link_go() { - ln -vsf "$1/bin/go" /usr/bin/go - ln -vsf "$1/bin/gofmt" /usr/bin/gofmt + if ! go_link_root="$(go_root)"; then + echo "No Go installation in $GO_APT_ROOT or /usr/local/go, skipping Go symlinks..." + return + fi + + echo "Creating Go symlinks from $go_link_root..." + ln -vsf "$go_link_root/bin/go" /usr/bin/go + ln -vsf "$go_link_root/bin/gofmt" /usr/bin/gofmt # Ubuntu's default PATH, and sudo's secure_path, list /usr/local/bin ahead of /usr/bin, so a # stray go left there keeps winning. Without this warning the toolkit's own version gate fails @@ -117,71 +185,23 @@ if [ "$INSTALL_PREREQS" = true ]; then xfsprogs \ zstd - # Install Go from the distro when it is packaged, otherwise from the pinned upstream tarball. - if go_is_supported go; then - echo "Found $(go version), skipping Go installation..." + # Install Go separately from the packages above: which source it comes from depends on the + # Ubuntu release, and a toolchain that is already good enough is reused rather than replaced. + if go_is_supported; then + echo "Found a Go toolchain that meets the minimum, skipping Go installation..." else - if go_existing_root="$(go_root)" && go_is_supported "$go_existing_root/bin/go"; then - # Installed, just not on PATH. Relinking below is enough, and reinstalling would - # overwrite a toolchain that may well be newer than the one pinned here. - echo "Found $("$go_existing_root/bin/go" version) in $go_existing_root, reusing it..." - else - echo "Checking apt for '$GO_APT_PACKAGE' (not packaged before Ubuntu 26.04)..." - if apt install -y "$GO_APT_PACKAGE" && [ -x "$GO_APT_ROOT/bin/go" ]; then - echo "Installed $GO_APT_PACKAGE from apt." - else - echo "'$GO_APT_PACKAGE' is unavailable on this release, using the upstream toolchain..." - go_arch="$(dpkg --print-architecture)" - case "$go_arch" in - amd64) go_sha256="$GO_SHA256_AMD64"; go_sha256_var=GO_SHA256_AMD64 ;; - arm64) go_sha256="$GO_SHA256_ARM64"; go_sha256_var=GO_SHA256_ARM64 ;; - *) - echo "ERROR: no upstream Go build is pinned for architecture '$go_arch'." >&2 - echo "Install Go $GO_VERSION or newer manually, then re-run with --no-install-prereqs." >&2 - exit 1 - ;; - esac - - echo "Installing Go $GO_VERSION ($go_arch) from https://go.dev/dl..." - go_tmp_dir="$(mktemp -d)" - trap 'rm -rf "$go_tmp_dir"' EXIT - curl -fsSL -o "$go_tmp_dir/go.tar.gz" \ - "https://go.dev/dl/go${GO_VERSION}.linux-${go_arch}.tar.gz" - if echo "$go_sha256 $go_tmp_dir/go.tar.gz" | sha256sum --status -c -; then - echo "Checksum OK." - else - echo "ERROR: go${GO_VERSION}.linux-${go_arch}.tar.gz does not match its pinned checksum." >&2 - echo " expected: $go_sha256" >&2 - echo " actual: $(sha256sum < "$go_tmp_dir/go.tar.gz" | cut -d ' ' -f 1)" >&2 - echo "Either the download was corrupted or tampered with, or GO_VERSION was changed in" >&2 - echo "$0 without refreshing $go_sha256_var. The expected value for a given release is" >&2 - echo "published at https://go.dev/dl. Nothing has been installed." >&2 - exit 1 - fi - - if [ -e /usr/local/go ]; then - echo "WARNING: replacing the Go installation in /usr/local/go, it is older than $GO_VERSION." >&2 - fi - rm -rf /usr/local/go - tar -C /usr/local -xzf "$go_tmp_dir/go.tar.gz" - fi - fi - - go_installed_root="$(go_root)" - link_go "$go_installed_root" + install_go fi else echo "Skipping installation of prerequisite packages..." fi -# Fix go 1.25 links if requested -if [ "$FIX_GO_LINKS" = true ]; then - if go_link_root="$(go_root)"; then - echo "Creating Go symlinks from $go_link_root..." - link_go "$go_link_root" - else - echo "No Go installation in $GO_APT_ROOT or /usr/local/go, skipping Go symlinks..." - fi +# Neither Go root is on PATH -- that is the whole reason --fix-go-links exists -- so installing +# prerequisites has to refresh the links as well, or the toolkit this just prepared still cannot +# find go. --fix-go-links then means "only do the links", to repair them or to pair with +# --no-install-prereqs. +if [ "$INSTALL_PREREQS" = true ] || [ "$FIX_GO_LINKS" = true ]; then + link_go fi # Install and configure Docker if requested From cfcd6dc6b01c5150680902e82f74da2ddfb7d3ba Mon Sep 17 00:00:00 2001 From: Muhammad Falak R Wani Date: Fri, 28 Aug 2026 05:17:02 +0530 Subject: [PATCH 12/12] ci: install the toolkit's prerequisites before building tools The GitHub runners ship Go 1.24, so every workflow that builds the Go tools started failing the moment go.mod asked for 1.25: the toolchain is pinned to local, which turns a too-old Go into a hard error rather than a download. Review feedback was to fix this the same way a developer does, by running install-prereqs, instead of teaching CI a second way to get Go. That also keeps the runners honest about the rest of the prerequisites rather than relying on whatever the image happens to preinstall. install-prereqs is safe to parse on Go 1.24 -- the version check lives behind REBUILD_TOOLS, which defaults to n -- so there is no ordering problem in bootstrapping it. The plain target is used, not install-prereqs-and-configure, which would also install Docker. go-test-coverage.yml keeps setup-go: it exists to check the pinned version, so it should read go.mod rather than trust the same script under test. --- .github/workflows/check-circular-deps.yml | 3 +++ .github/workflows/check-package-builds.yml | 3 +++ .github/workflows/check-package-cgmanifest.yml | 3 +++ .github/workflows/check-source-signatures.yml | 3 +++ .github/workflows/check-srpm-duplicates.yml | 3 +++ 5 files changed, 15 insertions(+) diff --git a/.github/workflows/check-circular-deps.yml b/.github/workflows/check-circular-deps.yml index d92638990de..418d9c9a53d 100644 --- a/.github/workflows/check-circular-deps.yml +++ b/.github/workflows/check-circular-deps.yml @@ -22,6 +22,9 @@ jobs: - name: Workflow trigger checkout uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0 + - name: Install toolkit prerequisites + run: sudo make -C toolkit install-prereqs + - name: Determine DAILY_BUILD_ID value run: | echo "GitHub 'base_ref': ${{ github.base_ref }}" diff --git a/.github/workflows/check-package-builds.yml b/.github/workflows/check-package-builds.yml index 3e075c6d30a..c9601afe4f8 100644 --- a/.github/workflows/check-package-builds.yml +++ b/.github/workflows/check-package-builds.yml @@ -127,6 +127,9 @@ jobs: - name: Checkout a stable version of the specs uses: ./.github/actions/checkout-with-stable-pkgs + - name: Install toolkit prerequisites + run: sudo make -C toolkit install-prereqs + - name: Prepare the build environment if: ${{ matrix.build-prep != '' }} run: | diff --git a/.github/workflows/check-package-cgmanifest.yml b/.github/workflows/check-package-cgmanifest.yml index 53bcb5c23ea..265d5e23be2 100644 --- a/.github/workflows/check-package-cgmanifest.yml +++ b/.github/workflows/check-package-cgmanifest.yml @@ -22,6 +22,9 @@ jobs: - name: Check out code uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0 + - name: Install toolkit prerequisites + run: sudo make -C toolkit install-prereqs + # This PR runner uses an older Ubuntu with rpm version 4.17, which doesn't understand some newer macros like %bcond - name: Define missing rpm macros run: | diff --git a/.github/workflows/check-source-signatures.yml b/.github/workflows/check-source-signatures.yml index 5fa8a06d36b..0762fb01602 100644 --- a/.github/workflows/check-source-signatures.yml +++ b/.github/workflows/check-source-signatures.yml @@ -25,6 +25,9 @@ jobs: - name: Workflow trigger checkout uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0 + - name: Install toolkit prerequisites + run: sudo make -C toolkit install-prereqs + # For consistency, we use the same major/minor version of Python that Azure Linux ships - name: Setup Python 3.12 uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 diff --git a/.github/workflows/check-srpm-duplicates.yml b/.github/workflows/check-srpm-duplicates.yml index b5d6f2496a7..2e2062441b7 100644 --- a/.github/workflows/check-srpm-duplicates.yml +++ b/.github/workflows/check-srpm-duplicates.yml @@ -29,6 +29,9 @@ jobs: - name: Workflow trigger checkout uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0 + - name: Install toolkit prerequisites + run: sudo make -C toolkit install-prereqs + # For consistency, we use the same major/minor version of Python that Azure Linux ships - name: Setup Python 3.12 uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0