diff --git a/config/golden-image-container-integration.yaml b/config/golden-image-container-integration.yaml index 855ce991..74c5e17b 100644 --- a/config/golden-image-container-integration.yaml +++ b/config/golden-image-container-integration.yaml @@ -2,7 +2,7 @@ schema_version: 1 image: type: container - alias: nddev-u24-amd64-ctr-docker-runner-2.336.0-r20260801-b16 + alias: nddev-u24-amd64-ctr-docker-runner-2.336.0-r20260801-b17 current_alias: nddev-ubuntu-24.04-amd64-container-docker-current previous_alias: nddev-ubuntu-24.04-amd64-container-docker-previous source_alias: nddev-source-ubuntu-24.04-amd64-container-r20260801 @@ -49,20 +49,20 @@ go_cache_seed: toolchains: - name: bun - version: 1.3.14 + version: 1.4.0 archive: bun-linux-x64.zip - download_url: https://github.com/oven-sh/bun/releases/download/bun-v1.3.14/bun-linux-x64.zip - archive_sha256: 951ee2aee855f08595aeec6225226a298d3fea83a3dcd6465c09cbccdf7e848f + download_url: https://github.com/oven-sh/bun/releases/download/bun-v1.4.0/bun-linux-x64.zip + archive_sha256: 2d03fb5fb83ac8b567aca0a281b2ce1a1a19d488f56c2968d88c3f25e92fe452 - name: codeql version: 2.26.4 archive: codeql-bundle-linux64.tar.gz download_url: https://github.com/github/codeql-action/releases/download/codeql-bundle-v2.26.4/codeql-bundle-linux64.tar.gz archive_sha256: 48e1ab8b874d57bd6fd7c90fefee75addc5a45e9bd063982df9beb45a62dd5d3 - name: go - version: 1.26.6 - archive: go1.26.6.linux-amd64.tar.gz - download_url: https://go.dev/dl/go1.26.6.linux-amd64.tar.gz - archive_sha256: 708effb774be8237570d0add163225abbdfaf4fca28b2611df167beba4feef89 + version: 1.26.7 + archive: go1.26.7.linux-amd64.tar.gz + download_url: https://go.dev/dl/go1.26.7.linux-amd64.tar.gz + archive_sha256: ffb5f8de10c62550dfddab66b36b57030721e0a44a3218e9e1181d7b59f121ca - name: gh version: 2.97.0 archive: gh_2.97.0_linux_amd64.tar.gz @@ -83,11 +83,21 @@ toolchains: archive: node-v25.9.0-linux-x64.tar.xz download_url: https://nodejs.org/dist/v25.9.0/node-v25.9.0-linux-x64.tar.xz archive_sha256: 1d8db7d6e291d167e8c467ae4094be175e1a0b3969c7ae1f8955b9f7824f7b2e + - name: node26 + version: 26.8.1 + archive: node-v26.8.1-linux-x64.tar.xz + download_url: https://nodejs.org/dist/v26.8.1/node-v26.8.1-linux-x64.tar.xz + archive_sha256: 3e301118d7df53d563b7e96c1617545f26e2f76f9724be668d6cab65c15dda5d - name: pnpm version: 11.22.0 archive: pnpm-11.22.0.tgz download_url: https://registry.npmjs.org/pnpm/-/pnpm-11.22.0.tgz archive_sha256: 57a97e6f23a3faffc03153a4ef8c770a0552612b8640aebe39bfdd5754d0ebdc + - name: python314 + version: 3.14.7 + archive: python-3.14.7-linux-24.04-x64.tar.gz + download_url: https://github.com/actions/python-versions/releases/download/3.14.7-31064857500/python-3.14.7-linux-24.04-x64.tar.gz + archive_sha256: 76d5ddab6d2dd89a39c06220f6efeda486a48ed481eae97bfc596c74ac3623db - name: rustup version: 1.29.0 archive: rustup-init diff --git a/config/golden-image-container.yaml b/config/golden-image-container.yaml index 04d27bdd..e2db9a8c 100644 --- a/config/golden-image-container.yaml +++ b/config/golden-image-container.yaml @@ -2,7 +2,7 @@ schema_version: 1 image: type: container - alias: nddev-ubuntu-24.04-amd64-container-runner-2.336.0-r20260801-b22 + alias: nddev-ubuntu-24.04-amd64-container-runner-2.336.0-r20260801-b23 current_alias: nddev-ubuntu-24.04-amd64-container-current previous_alias: nddev-ubuntu-24.04-amd64-container-previous source_alias: nddev-source-ubuntu-24.04-amd64-container-r20260801 @@ -49,20 +49,20 @@ go_cache_seed: toolchains: - name: bun - version: 1.3.14 + version: 1.4.0 archive: bun-linux-x64.zip - download_url: https://github.com/oven-sh/bun/releases/download/bun-v1.3.14/bun-linux-x64.zip - archive_sha256: 951ee2aee855f08595aeec6225226a298d3fea83a3dcd6465c09cbccdf7e848f + download_url: https://github.com/oven-sh/bun/releases/download/bun-v1.4.0/bun-linux-x64.zip + archive_sha256: 2d03fb5fb83ac8b567aca0a281b2ce1a1a19d488f56c2968d88c3f25e92fe452 - name: codeql version: 2.26.4 archive: codeql-bundle-linux64.tar.gz download_url: https://github.com/github/codeql-action/releases/download/codeql-bundle-v2.26.4/codeql-bundle-linux64.tar.gz archive_sha256: 48e1ab8b874d57bd6fd7c90fefee75addc5a45e9bd063982df9beb45a62dd5d3 - name: go - version: 1.26.6 - archive: go1.26.6.linux-amd64.tar.gz - download_url: https://go.dev/dl/go1.26.6.linux-amd64.tar.gz - archive_sha256: 708effb774be8237570d0add163225abbdfaf4fca28b2611df167beba4feef89 + version: 1.26.7 + archive: go1.26.7.linux-amd64.tar.gz + download_url: https://go.dev/dl/go1.26.7.linux-amd64.tar.gz + archive_sha256: ffb5f8de10c62550dfddab66b36b57030721e0a44a3218e9e1181d7b59f121ca - name: flutter version: 3.44.9 archive: flutter_linux_3.44.9-stable.tar.xz @@ -88,11 +88,21 @@ toolchains: archive: node-v25.9.0-linux-x64.tar.xz download_url: https://nodejs.org/dist/v25.9.0/node-v25.9.0-linux-x64.tar.xz archive_sha256: 1d8db7d6e291d167e8c467ae4094be175e1a0b3969c7ae1f8955b9f7824f7b2e + - name: node26 + version: 26.8.1 + archive: node-v26.8.1-linux-x64.tar.xz + download_url: https://nodejs.org/dist/v26.8.1/node-v26.8.1-linux-x64.tar.xz + archive_sha256: 3e301118d7df53d563b7e96c1617545f26e2f76f9724be668d6cab65c15dda5d - name: pnpm version: 11.22.0 archive: pnpm-11.22.0.tgz download_url: https://registry.npmjs.org/pnpm/-/pnpm-11.22.0.tgz archive_sha256: 57a97e6f23a3faffc03153a4ef8c770a0552612b8640aebe39bfdd5754d0ebdc + - name: python314 + version: 3.14.7 + archive: python-3.14.7-linux-24.04-x64.tar.gz + download_url: https://github.com/actions/python-versions/releases/download/3.14.7-31064857500/python-3.14.7-linux-24.04-x64.tar.gz + archive_sha256: 76d5ddab6d2dd89a39c06220f6efeda486a48ed481eae97bfc596c74ac3623db - name: rustup version: 1.29.0 archive: rustup-init diff --git a/config/golden-image-integration.yaml b/config/golden-image-integration.yaml index 44e9fa65..434a7b94 100644 --- a/config/golden-image-integration.yaml +++ b/config/golden-image-integration.yaml @@ -1,7 +1,7 @@ schema_version: 1 image: - alias: nddev-ubuntu-24.04-amd64-docker-runner-2.336.0-r20260801-b17 + alias: nddev-ubuntu-24.04-amd64-docker-runner-2.336.0-r20260801-b18 current_alias: nddev-ubuntu-24.04-amd64-docker-current previous_alias: nddev-ubuntu-24.04-amd64-docker-previous source_alias: nddev-source-ubuntu-24.04-amd64-r20260801 @@ -48,20 +48,20 @@ go_cache_seed: toolchains: - name: bun - version: 1.3.14 + version: 1.4.0 archive: bun-linux-x64.zip - download_url: https://github.com/oven-sh/bun/releases/download/bun-v1.3.14/bun-linux-x64.zip - archive_sha256: 951ee2aee855f08595aeec6225226a298d3fea83a3dcd6465c09cbccdf7e848f + download_url: https://github.com/oven-sh/bun/releases/download/bun-v1.4.0/bun-linux-x64.zip + archive_sha256: 2d03fb5fb83ac8b567aca0a281b2ce1a1a19d488f56c2968d88c3f25e92fe452 - name: codeql version: 2.26.4 archive: codeql-bundle-linux64.tar.gz download_url: https://github.com/github/codeql-action/releases/download/codeql-bundle-v2.26.4/codeql-bundle-linux64.tar.gz archive_sha256: 48e1ab8b874d57bd6fd7c90fefee75addc5a45e9bd063982df9beb45a62dd5d3 - name: go - version: 1.26.6 - archive: go1.26.6.linux-amd64.tar.gz - download_url: https://go.dev/dl/go1.26.6.linux-amd64.tar.gz - archive_sha256: 708effb774be8237570d0add163225abbdfaf4fca28b2611df167beba4feef89 + version: 1.26.7 + archive: go1.26.7.linux-amd64.tar.gz + download_url: https://go.dev/dl/go1.26.7.linux-amd64.tar.gz + archive_sha256: ffb5f8de10c62550dfddab66b36b57030721e0a44a3218e9e1181d7b59f121ca - name: gh version: 2.97.0 archive: gh_2.97.0_linux_amd64.tar.gz @@ -82,11 +82,21 @@ toolchains: archive: node-v25.9.0-linux-x64.tar.xz download_url: https://nodejs.org/dist/v25.9.0/node-v25.9.0-linux-x64.tar.xz archive_sha256: 1d8db7d6e291d167e8c467ae4094be175e1a0b3969c7ae1f8955b9f7824f7b2e + - name: node26 + version: 26.8.1 + archive: node-v26.8.1-linux-x64.tar.xz + download_url: https://nodejs.org/dist/v26.8.1/node-v26.8.1-linux-x64.tar.xz + archive_sha256: 3e301118d7df53d563b7e96c1617545f26e2f76f9724be668d6cab65c15dda5d - name: pnpm version: 11.22.0 archive: pnpm-11.22.0.tgz download_url: https://registry.npmjs.org/pnpm/-/pnpm-11.22.0.tgz archive_sha256: 57a97e6f23a3faffc03153a4ef8c770a0552612b8640aebe39bfdd5754d0ebdc + - name: python314 + version: 3.14.7 + archive: python-3.14.7-linux-24.04-x64.tar.gz + download_url: https://github.com/actions/python-versions/releases/download/3.14.7-31064857500/python-3.14.7-linux-24.04-x64.tar.gz + archive_sha256: 76d5ddab6d2dd89a39c06220f6efeda486a48ed481eae97bfc596c74ac3623db - name: rustup version: 1.29.0 archive: rustup-init diff --git a/config/golden-image.yaml b/config/golden-image.yaml index 58ef81d6..281fe2d7 100644 --- a/config/golden-image.yaml +++ b/config/golden-image.yaml @@ -1,7 +1,7 @@ schema_version: 1 image: - alias: nddev-ubuntu-24.04-amd64-runner-2.336.0-r20260801-b18 + alias: nddev-ubuntu-24.04-amd64-runner-2.336.0-r20260801-b19 current_alias: nddev-ubuntu-24.04-amd64-current previous_alias: nddev-ubuntu-24.04-amd64-previous source_alias: nddev-source-ubuntu-24.04-amd64-r20260801 @@ -48,20 +48,20 @@ go_cache_seed: toolchains: - name: bun - version: 1.3.14 + version: 1.4.0 archive: bun-linux-x64.zip - download_url: https://github.com/oven-sh/bun/releases/download/bun-v1.3.14/bun-linux-x64.zip - archive_sha256: 951ee2aee855f08595aeec6225226a298d3fea83a3dcd6465c09cbccdf7e848f + download_url: https://github.com/oven-sh/bun/releases/download/bun-v1.4.0/bun-linux-x64.zip + archive_sha256: 2d03fb5fb83ac8b567aca0a281b2ce1a1a19d488f56c2968d88c3f25e92fe452 - name: codeql version: 2.26.4 archive: codeql-bundle-linux64.tar.gz download_url: https://github.com/github/codeql-action/releases/download/codeql-bundle-v2.26.4/codeql-bundle-linux64.tar.gz archive_sha256: 48e1ab8b874d57bd6fd7c90fefee75addc5a45e9bd063982df9beb45a62dd5d3 - name: go - version: 1.26.6 - archive: go1.26.6.linux-amd64.tar.gz - download_url: https://go.dev/dl/go1.26.6.linux-amd64.tar.gz - archive_sha256: 708effb774be8237570d0add163225abbdfaf4fca28b2611df167beba4feef89 + version: 1.26.7 + archive: go1.26.7.linux-amd64.tar.gz + download_url: https://go.dev/dl/go1.26.7.linux-amd64.tar.gz + archive_sha256: ffb5f8de10c62550dfddab66b36b57030721e0a44a3218e9e1181d7b59f121ca - name: gh version: 2.97.0 archive: gh_2.97.0_linux_amd64.tar.gz @@ -82,11 +82,21 @@ toolchains: archive: node-v25.9.0-linux-x64.tar.xz download_url: https://nodejs.org/dist/v25.9.0/node-v25.9.0-linux-x64.tar.xz archive_sha256: 1d8db7d6e291d167e8c467ae4094be175e1a0b3969c7ae1f8955b9f7824f7b2e + - name: node26 + version: 26.8.1 + archive: node-v26.8.1-linux-x64.tar.xz + download_url: https://nodejs.org/dist/v26.8.1/node-v26.8.1-linux-x64.tar.xz + archive_sha256: 3e301118d7df53d563b7e96c1617545f26e2f76f9724be668d6cab65c15dda5d - name: pnpm version: 11.22.0 archive: pnpm-11.22.0.tgz download_url: https://registry.npmjs.org/pnpm/-/pnpm-11.22.0.tgz archive_sha256: 57a97e6f23a3faffc03153a4ef8c770a0552612b8640aebe39bfdd5754d0ebdc + - name: python314 + version: 3.14.7 + archive: python-3.14.7-linux-24.04-x64.tar.gz + download_url: https://github.com/actions/python-versions/releases/download/3.14.7-31064857500/python-3.14.7-linux-24.04-x64.tar.gz + archive_sha256: 76d5ddab6d2dd89a39c06220f6efeda486a48ed481eae97bfc596c74ac3623db - name: rustup version: 1.29.0 archive: rustup-init diff --git a/internal/imagebuild/assets/provision.sh b/internal/imagebuild/assets/provision.sh index 27298aca..0f9e2611 100644 --- a/internal/imagebuild/assets/provision.sh +++ b/internal/imagebuild/assets/provision.sh @@ -288,8 +288,8 @@ jq -e 'type == "array"' <<<"${toolchain_manifest}" >/dev/null mapfile -t toolchain_names < <(jq -r '.[].name' <<<"${toolchain_manifest}") toolchain_set="$(printf '%s\n' "${toolchain_names[@]}" | LC_ALL=C sort | paste -sd, -)" if [[ "${toolchain_set}" != bun,codeql,gh,go,rustup,uv \ - && "${toolchain_set}" != bun,codeql,gh,go,node22,node24,node25,pnpm,rustup,uv,yarn \ - && "${toolchain_set}" != bun,codeql,flutter,gh,go,node22,node24,node25,pnpm,rustup,uv,yarn ]]; then + && "${toolchain_set}" != bun,codeql,gh,go,node22,node24,node25,node26,pnpm,python314,rustup,uv,yarn \ + && "${toolchain_set}" != bun,codeql,flutter,gh,go,node22,node24,node25,node26,pnpm,python314,rustup,uv,yarn ]]; then echo "toolchain manifest does not pin the exact baked set" >&2 exit 1 fi @@ -383,7 +383,7 @@ for toolchain_name in "${toolchain_names[@]}"; do ln -sfn "${runner_tool_cache}/go/${toolchain_version}/x64/bin/gofmt" /usr/local/bin/gofmt [[ "$(go version)" == "go version go${toolchain_version} linux/amd64" ]] ;; - node22|node24|node25) + node22|node24|node25|node26) tar --extract --xz --file "${toolchain_archive}" \ --directory "${toolchain_scratch}" --no-same-owner --no-same-permissions node_root="${runner_tool_cache}/node/${toolchain_version}" @@ -402,6 +402,41 @@ for toolchain_name in "${toolchain_names[@]}"; do corepack --version >/dev/null fi ;; + python314) + # The official actions/python-versions archive is linked for + # /opt/hostedtoolcache. Install it there and expose that exact tree through + # this runner's tool cache so actions/setup-python resolves it locally. + python_hosted_root="/opt/hostedtoolcache/Python/${toolchain_version}/x64" + python_runner_root="${runner_tool_cache}/Python/${toolchain_version}" + install -d -o runner -g runner -m 0755 \ + /opt/hostedtoolcache/Python "${python_hosted_root}" \ + "${runner_tool_cache}/Python" + tar --extract --gzip --file "${toolchain_archive}" \ + --directory "${python_hosted_root}" --no-same-owner --no-same-permissions + rm -f -- "${python_hosted_root}/setup.sh" + chown -R runner:runner "/opt/hostedtoolcache/Python/${toolchain_version}" + runuser -u runner -- env HOME=/home/runner \ + "${python_hosted_root}/bin/python3.14" -m ensurepip --upgrade >/dev/null + ln -sfn "${python_hosted_root}/bin/python3.14" "${python_hosted_root}/python" + install -o runner -g runner -m 0644 /dev/null \ + "/opt/hostedtoolcache/Python/${toolchain_version}/x64.complete" + ln -sfn "/opt/hostedtoolcache/Python/${toolchain_version}" "${python_runner_root}" + chown -h runner:runner "${python_runner_root}" + for executable in python python3 pip pip3; do + target="${python_hosted_root}/bin/${executable}" + if [[ ! -e "${target}" ]]; then + case "${executable}" in + python) target="${python_hosted_root}/bin/python3.14" ;; + python3) target="${python_hosted_root}/bin/python3.14" ;; + pip) target="${python_hosted_root}/bin/pip3.14" ;; + pip3) target="${python_hosted_root}/bin/pip3.14" ;; + esac + fi + ln -sfn "${target}" "/usr/local/bin/${executable}" + done + [[ "$(python --version)" == "Python ${toolchain_version}" ]] + python -m pip --version >/dev/null + ;; pnpm) package_root="/usr/local/libexec/gha-toolchains/pnpm-${toolchain_version}" install -d -o root -g root -m 0755 "${package_root}" diff --git a/internal/imagebuild/assets/smoke-integration.sh b/internal/imagebuild/assets/smoke-integration.sh index 4ea83bac..f54570da 100644 --- a/internal/imagebuild/assets/smoke-integration.sh +++ b/internal/imagebuild/assets/smoke-integration.sh @@ -106,7 +106,7 @@ runner_tool_cache="$(jq -er .runner_tool_cache /etc/nddev/image-build.json)" [[ "${runner_tool_cache}" == /home/runner/actions-runner/_work/_tool ]] smoke_toolchains="$(printf '%s' "${GHA_TOOLCHAINS_B64}" | base64 --decode)" mapfile -t smoke_toolchain_names < <(jq -r '.[].name' <<<"${smoke_toolchains}") -[[ "$(printf '%s\n' "${smoke_toolchain_names[@]}" | LC_ALL=C sort | paste -sd, -)" == bun,codeql,gh,go,node22,node24,node25,pnpm,rustup,uv,yarn ]] +[[ "$(printf '%s\n' "${smoke_toolchain_names[@]}" | LC_ALL=C sort | paste -sd, -)" == bun,codeql,gh,go,node22,node24,node25,node26,pnpm,python314,rustup,uv,yarn ]] for smoke_toolchain in "${smoke_toolchain_names[@]}"; do entry="$(jq -ce --arg name "${smoke_toolchain}" '.[] | select(.name == $name)' <<<"${smoke_toolchains}")" expected_version="$(jq -er .version <<<"${entry}")" @@ -139,7 +139,7 @@ for smoke_toolchain in "${smoke_toolchain_names[@]}"; do [[ "$("${go_root}/bin/go" version)" == "go version go${expected_version} linux/amd64" ]] [[ "$(go version)" == "go version go${expected_version} linux/amd64" ]] ;; - node22|node24|node25) + node22|node24|node25|node26) node_root="${runner_tool_cache}/node/${expected_version}" test -f "${node_root}/x64.complete" test -x "${node_root}/x64/bin/node" @@ -151,6 +151,17 @@ for smoke_toolchain in "${smoke_toolchain_names[@]}"; do corepack --version >/dev/null fi ;; + python314) + python_hosted_root="/opt/hostedtoolcache/Python/${expected_version}/x64" + python_runner_root="${runner_tool_cache}/Python/${expected_version}" + test -f "/opt/hostedtoolcache/Python/${expected_version}/x64.complete" + test -x "${python_hosted_root}/bin/python3.14" + test -L "${python_runner_root}" + [[ "$(readlink -f -- "${python_runner_root}")" == "/opt/hostedtoolcache/Python/${expected_version}" ]] + [[ "$(runuser -u runner -- env HOME=/home/runner "${python_hosted_root}/bin/python3.14" --version)" == "Python ${expected_version}" ]] + runuser -u runner -- env HOME=/home/runner "${python_hosted_root}/bin/python3.14" -m pip --version >/dev/null + [[ "$(python --version)" == "Python ${expected_version}" ]] + ;; pnpm) [[ "$(pnpm --version)" == "${expected_version}" ]] ;; rustup) # Verified exactly as a job sees it: through the runner user, whose diff --git a/internal/imagebuild/assets/smoke.sh b/internal/imagebuild/assets/smoke.sh index 81f70dda..30deaa5a 100644 --- a/internal/imagebuild/assets/smoke.sh +++ b/internal/imagebuild/assets/smoke.sh @@ -94,8 +94,8 @@ smoke_toolchains="$(printf '%s' "${GHA_TOOLCHAINS_B64}" | base64 --decode)" mapfile -t smoke_toolchain_names < <(jq -r '.[].name' <<<"${smoke_toolchains}") smoke_toolchain_set="$(printf '%s\n' "${smoke_toolchain_names[@]}" | LC_ALL=C sort | paste -sd, -)" [[ "${smoke_toolchain_set}" == bun,codeql,gh,go,rustup,uv \ - || "${smoke_toolchain_set}" == bun,codeql,gh,go,node22,node24,node25,pnpm,rustup,uv,yarn \ - || "${smoke_toolchain_set}" == bun,codeql,flutter,gh,go,node22,node24,node25,pnpm,rustup,uv,yarn ]] + || "${smoke_toolchain_set}" == bun,codeql,gh,go,node22,node24,node25,node26,pnpm,python314,rustup,uv,yarn \ + || "${smoke_toolchain_set}" == bun,codeql,flutter,gh,go,node22,node24,node25,node26,pnpm,python314,rustup,uv,yarn ]] for smoke_toolchain in "${smoke_toolchain_names[@]}"; do entry="$(jq -ce --arg name "${smoke_toolchain}" '.[] | select(.name == $name)' <<<"${smoke_toolchains}")" expected_version="$(jq -er .version <<<"${entry}")" @@ -137,7 +137,7 @@ for smoke_toolchain in "${smoke_toolchain_names[@]}"; do [[ "$("${go_root}/bin/go" version)" == "go version go${expected_version} linux/amd64" ]] [[ "$(go version)" == "go version go${expected_version} linux/amd64" ]] ;; - node22|node24|node25) + node22|node24|node25|node26) node_root="${runner_tool_cache}/node/${expected_version}" test -f "${node_root}/x64.complete" test -x "${node_root}/x64/bin/node" @@ -149,6 +149,17 @@ for smoke_toolchain in "${smoke_toolchain_names[@]}"; do corepack --version >/dev/null fi ;; + python314) + python_hosted_root="/opt/hostedtoolcache/Python/${expected_version}/x64" + python_runner_root="${runner_tool_cache}/Python/${expected_version}" + test -f "/opt/hostedtoolcache/Python/${expected_version}/x64.complete" + test -x "${python_hosted_root}/bin/python3.14" + test -L "${python_runner_root}" + [[ "$(readlink -f -- "${python_runner_root}")" == "/opt/hostedtoolcache/Python/${expected_version}" ]] + [[ "$(runuser -u runner -- env HOME=/home/runner "${python_hosted_root}/bin/python3.14" --version)" == "Python ${expected_version}" ]] + runuser -u runner -- env HOME=/home/runner "${python_hosted_root}/bin/python3.14" -m pip --version >/dev/null + [[ "$(python --version)" == "Python ${expected_version}" ]] + ;; pnpm) [[ "$(pnpm --version)" == "${expected_version}" ]] ;; rustup) # Verified exactly as a job sees it: through the runner user, whose diff --git a/internal/imagebuild/orchestrator_test.go b/internal/imagebuild/orchestrator_test.go index 06fbfdc2..b987a40a 100644 --- a/internal/imagebuild/orchestrator_test.go +++ b/internal/imagebuild/orchestrator_test.go @@ -165,7 +165,7 @@ func TestRecipeFingerprintIsDeterministic(t *testing.T) { // coupling is the point: the alias is part of the recipe, so a manifest // whose contents changed under an unchanged alias would otherwise ask the // builder to produce different bytes for a name that is already promoted. - if first != "sha256:e8397808b79585a0d46dabf914549eaba101687602eba859ad4d0599ddbb67ef" { + if first != "sha256:6595cdc1795927be79055c6bc5d7a834cd1bb63c1eaa13233b51973067515e22" { t.Fatalf("deployed standard recipe fingerprint drifted: %q", first) } smoke, err := SmokeFingerprint(plan) @@ -351,6 +351,7 @@ func TestEmbeddedScriptsPreserveSecurityBoundary(t *testing.T) { } for _, compatibilityInvariant := range []string{ "python3 -m pip --version", "/usr/local/bin/python", "/usr/local/bin/pip", + "python314", "/opt/hostedtoolcache/Python", "-m ensurepip --upgrade", "/usr/local/bin/go", "/usr/local/bin/gofmt", "pnpm.cjs", "pnpx.cjs", "yarn.js", `chmod 0755 "${package_root}/bin/pnpm.cjs" "${package_root}/bin/pnpx.cjs"`, `chmod 0755 "${package_root}/bin/yarn.js"`, "pnpm --version", "yarn --version", @@ -369,7 +370,7 @@ func TestEmbeddedScriptsPreserveSecurityBoundary(t *testing.T) { } for _, name := range []string{"assets/smoke.sh", "assets/smoke-integration.sh"} { content, _ := scripts.ReadFile(name) - for _, compatibilityInvariant := range []string{"python3 -m pip --version", "pip --version", "pnpm --version", "yarn --version", "go version"} { + for _, compatibilityInvariant := range []string{"python3 -m pip --version", "pip --version", "python314", "/opt/hostedtoolcache/Python", "pnpm --version", "yarn --version", "go version"} { if !strings.Contains(string(content), compatibilityInvariant) { t.Fatalf("%s misses compatibility runtime invariant %s", name, compatibilityInvariant) } diff --git a/internal/imagemanifest/manifest_test.go b/internal/imagemanifest/manifest_test.go index 4cf72acd..d838f09f 100644 --- a/internal/imagemanifest/manifest_test.go +++ b/internal/imagemanifest/manifest_test.go @@ -42,7 +42,7 @@ func TestRepositoryManifestIsValidAndPinned(t *testing.T) { if !strings.HasPrefix(fingerprint, "sha256:") || len(fingerprint) != len("sha256:")+64 { t.Fatalf("unexpected fingerprint %q", fingerprint) } - if fingerprint != "sha256:fe9f3da1c5e7b997008fe2b8ea04e1d4e1cfdb60f30db69cabdb4d69e06fb4b8" { + if fingerprint != "sha256:3ab8bc1630fe32db7b8e5943045e238c60b1f5ef129e4ac60aa69e9ae11c2f6c" { t.Fatalf("standard manifest fingerprint drifted: %q", fingerprint) } } @@ -70,17 +70,19 @@ func TestContainerManifestPinsCanonicalSignedRootfs(t *testing.T) { func assertBakedToolchains(t *testing.T, manifest Manifest) { t.Helper() wanted := map[string]struct{ version, archiveSHA256 string }{ - "bun": {"1.3.14", "951ee2aee855f08595aeec6225226a298d3fea83a3dcd6465c09cbccdf7e848f"}, - "codeql": {"2.26.4", "48e1ab8b874d57bd6fd7c90fefee75addc5a45e9bd063982df9beb45a62dd5d3"}, - "gh": {"2.97.0", "a2c9b8497e1f85b1ad0dfcb78b5a622e098801b8e461e459e88e1ee12f018112"}, - "go": {"1.26.6", "708effb774be8237570d0add163225abbdfaf4fca28b2611df167beba4feef89"}, - "node22": {"22.23.2", "d60acfe00a2932254bb0ad20e01b0d74397a0875595de719654b214f4b03f307"}, - "node24": {"24.19.0", "14b342e71204f811bde6153be8e04b62aef63c236fef92b55f9c83154b409647"}, - "node25": {"25.9.0", "1d8db7d6e291d167e8c467ae4094be175e1a0b3969c7ae1f8955b9f7824f7b2e"}, - "pnpm": {"11.22.0", "57a97e6f23a3faffc03153a4ef8c770a0552612b8640aebe39bfdd5754d0ebdc"}, - "rustup": {"1.29.0", "4acc9acc76d5079515b46346a485974457b5a79893cfb01112423c89aeb5aa10"}, - "uv": {"0.11.30", "04bc7d180d6138bf6dc08387acf507a823f397a98fea55da36b0ccc7fbce3b68"}, - "yarn": {"4.18.0", "606e7e2dfc8bcc24e1b3a70a1043288a271ad2cc71cf42248fadc25f5938a497"}, + "bun": {"1.4.0", "2d03fb5fb83ac8b567aca0a281b2ce1a1a19d488f56c2968d88c3f25e92fe452"}, + "codeql": {"2.26.4", "48e1ab8b874d57bd6fd7c90fefee75addc5a45e9bd063982df9beb45a62dd5d3"}, + "gh": {"2.97.0", "a2c9b8497e1f85b1ad0dfcb78b5a622e098801b8e461e459e88e1ee12f018112"}, + "go": {"1.26.7", "ffb5f8de10c62550dfddab66b36b57030721e0a44a3218e9e1181d7b59f121ca"}, + "node22": {"22.23.2", "d60acfe00a2932254bb0ad20e01b0d74397a0875595de719654b214f4b03f307"}, + "node24": {"24.19.0", "14b342e71204f811bde6153be8e04b62aef63c236fef92b55f9c83154b409647"}, + "node25": {"25.9.0", "1d8db7d6e291d167e8c467ae4094be175e1a0b3969c7ae1f8955b9f7824f7b2e"}, + "node26": {"26.8.1", "3e301118d7df53d563b7e96c1617545f26e2f76f9724be668d6cab65c15dda5d"}, + "pnpm": {"11.22.0", "57a97e6f23a3faffc03153a4ef8c770a0552612b8640aebe39bfdd5754d0ebdc"}, + "python314": {"3.14.7", "76d5ddab6d2dd89a39c06220f6efeda486a48ed481eae97bfc596c74ac3623db"}, + "rustup": {"1.29.0", "4acc9acc76d5079515b46346a485974457b5a79893cfb01112423c89aeb5aa10"}, + "uv": {"0.11.30", "04bc7d180d6138bf6dc08387acf507a823f397a98fea55da36b0ccc7fbce3b68"}, + "yarn": {"4.18.0", "606e7e2dfc8bcc24e1b3a70a1043288a271ad2cc71cf42248fadc25f5938a497"}, } if len(manifest.Toolchains) != len(wanted) { t.Fatalf("toolchains = %d, want %d", len(manifest.Toolchains), len(wanted)) diff --git a/internal/imagemanifest/types.go b/internal/imagemanifest/types.go index e5615e4b..c6fd6a58 100644 --- a/internal/imagemanifest/types.go +++ b/internal/imagemanifest/types.go @@ -122,7 +122,7 @@ func BakedToolchains() []string { // was unreachable in the shipped image. The default channel serves jobs // that call cargo directly, and actions-rust-lang/setup-rust-toolchain // resolves rust-toolchain.toml channels through rustup either way. - return []string{"bun", "codeql", "gh", "go", "node22", "node24", "node25", "pnpm", "rustup", "uv", "yarn"} + return []string{"bun", "codeql", "gh", "go", "node22", "node24", "node25", "node26", "pnpm", "python314", "rustup", "uv", "yarn"} } // OptionalToolchains may be pinned by an image that needs them and omitted by diff --git a/internal/imagemanifest/validate.go b/internal/imagemanifest/validate.go index 5cab291e..6fa5137e 100644 --- a/internal/imagemanifest/validate.go +++ b/internal/imagemanifest/validate.go @@ -89,6 +89,20 @@ var toolchainAssets = map[string]struct { return "/dist/v" + version + "/node-v" + version + "-linux-x64.tar.xz" }, }, + "node26": { + Host: "nodejs.org", + Archive: func(version string) string { return "node-v" + version + "-linux-x64.tar.xz" }, + Path: func(version string) string { + return "/dist/v" + version + "/node-v" + version + "-linux-x64.tar.xz" + }, + }, + "python314": { + Host: "github.com", + Archive: func(version string) string { return "python-" + version + "-linux-24.04-x64.tar.gz" }, + Path: func(version string) string { + return "/actions/python-versions/releases/download/3.14.7-31064857500/python-" + version + "-linux-24.04-x64.tar.gz" + }, + }, "pnpm": { Host: "registry.npmjs.org", Archive: func(version string) string { return "pnpm-" + version + ".tgz" }, diff --git a/internal/imageplan/plan_test.go b/internal/imageplan/plan_test.go index 968b081e..878ce9a0 100644 --- a/internal/imageplan/plan_test.go +++ b/internal/imageplan/plan_test.go @@ -82,7 +82,7 @@ func TestBuildProducesDeterministicBoundedPlan(t *testing.T) { } // The baked set plus the optional Flutter SDK this manifest pins, still // sorted: the plan's ordering is what makes the recipe fingerprint stable. - if !slices.Equal(names, []string{"bun", "codeql", "flutter", "gh", "go", "node22", "node24", "node25", "pnpm", "rustup", "uv", "yarn"}) { + if !slices.Equal(names, []string{"bun", "codeql", "flutter", "gh", "go", "node22", "node24", "node25", "node26", "pnpm", "python314", "rustup", "uv", "yarn"}) { t.Fatalf("plan toolchains are not the canonical sorted set: %v", names) } if first.CompilerCache.Name != "sccache" || first.CompilerCache.Version != "v0.17.0" || diff --git a/scripts/install-benchmark-toolchain.sh b/scripts/install-benchmark-toolchain.sh index b3e6aac5..826637eb 100755 --- a/scripts/install-benchmark-toolchain.sh +++ b/scripts/install-benchmark-toolchain.sh @@ -109,18 +109,18 @@ case "${toolchain}" in [[ "$(uv --version)" == "uv 0.11.30"* ]] ;; bun) - if [[ "$(bun --version 2>/dev/null || true)" == "1.3.14" ]]; then + if [[ "$(bun --version 2>/dev/null || true)" == "1.4.0" ]]; then exit 0 fi archive="${scratch}/bun.zip" download_verified \ - "https://github.com/oven-sh/bun/releases/download/bun-v1.3.14/bun-linux-x64.zip" \ - "951ee2aee855f08595aeec6225226a298d3fea83a3dcd6465c09cbccdf7e848f" \ + "https://github.com/oven-sh/bun/releases/download/bun-v1.4.0/bun-linux-x64.zip" \ + "2d03fb5fb83ac8b567aca0a281b2ce1a1a19d488f56c2968d88c3f25e92fe452" \ "${archive}" unzip -q "${archive}" -d "${scratch}" install -m 0755 "${scratch}/bun-linux-x64/bun" "${binary_root}/bun" printf '%s\n' "${binary_root}" >>"${GITHUB_PATH}" export PATH="${binary_root}:${PATH}" - [[ "$(bun --version)" == "1.3.14" ]] + [[ "$(bun --version)" == "1.4.0" ]] ;; esac