Compare commits

..

1 Commits

Author SHA1 Message Date
Paulo Santos 38a1da19ee add image version check script 2025-12-12 16:57:07 +00:00
2 changed files with 330 additions and 31 deletions
+294
View File
@@ -0,0 +1,294 @@
#!/usr/bin/env bash
################################################################################
## File: diff-image-versions.sh
## Desc: Compare software versions between two runner image releases
## Usage: ./diff-image-versions.sh <os-name> <version1> <version2>
##
## Example:
## ./diff-image-versions.sh ubuntu22 20251102.127 20251125.163
## ./diff-image-versions.sh win25 20251102.77 20251125.122
## ./diff-image-versions.sh macos-14 20251102.0024 20251125.0031
################################################################################
set -euo pipefail
usage() {
cat <<EOF
Usage: $(basename "${0}") <os-name> <version1> <version2>
Compare runner image versions and display software changes.
Arguments:
os-name OS identifier (ubuntu22, ubuntu24, win19, win22, win25,
macos-13, macos-14, macos-15, or arm64 variants)
version1 Earlier version (YYYYMMDD.NNN)
version2 Later version (YYYYMMDD.NNN)
Examples:
$(basename "${0}") ubuntu22 20251102.127 20251125.163
$(basename "${0}") win25 20251102.77 20251125.122
EOF
}
get_readme_path() {
local os_name="${1}"
local os_folder=""
local pattern=""
# Determine OS folder and readme filename pattern
case "${os_name}" in
ubuntu*)
os_folder="ubuntu"
local version="${os_name#ubuntu}"
pattern="Ubuntu${version}04-Readme.md"
;;
win*)
os_folder="windows"
local version="${os_name#win}"
pattern="Windows20${version}-Readme.md"
;;
macos*)
os_folder="macos"
pattern="${os_name}-Readme.md"
;;
*)
echo "Error: Unknown OS '${os_name}'" >&2
echo "Valid: ubuntu*, win*, macos-*" >&2
return 1
;;
esac
local readme_path="images/${os_folder}/${pattern}"
# Verify file exists in git repository
if ! git cat-file -e "HEAD:${readme_path}" 2>/dev/null; then
echo "Error: Readme not found: ${readme_path}" >&2
return 1
fi
echo "${readme_path}"
}
validate_version() {
local version="${1}"
if [[ ! "${version}" =~ ^[0-9]{8}\.[0-9]+$ ]]; then
echo "Error: Invalid version '${version}'" >&2
echo "Format: YYYYMMDD.NNN (e.g., 20251102.127)" >&2
return 1
fi
return 0
}
tag_exists() {
local tag="${1}"
if git rev-parse "${tag}" >/dev/null 2>&1; then
return 0
else
echo "Error: Tag '${tag}' not found" >&2
return 1
fi
}
main() {
# Check arguments
if [[ $# -ne 3 ]]; then
usage
return 1
fi
local os_name="${1}"
local version1="${2}"
local version2="${3}"
# Validate inputs
validate_version "${version1}" || return 1
validate_version "${version2}" || return 1
# Get readme path
local readme_path
readme_path="$(get_readme_path "${os_name}")" || return 1
# Construct git tags
local tag1="${os_name}/${version1}"
local tag2="${os_name}/${version2}"
# Verify tags exist
tag_exists "${tag1}" || return 1
tag_exists "${tag2}" || return 1
# Get release dates
local date1
local date2
date1=$(git log -1 --format="%ci" "${tag1}" | cut -d' ' -f1)
date2=$(git log -1 --format="%ci" "${tag2}" | cut -d' ' -f1)
# Calculate days between releases
local days_diff
days_diff=$(( ($(date -d "${date2}" +%s) - $(date -d "${date1}" +%s)) / 86400 ))
# Display header
echo "================================================================================"
echo "Comparing: ${os_name}"
echo " From: ${version1} (${date1})"
echo " To: ${version2} (${date2})"
echo " Span: ${days_diff} days"
echo "================================================================================"
echo ""
# Perform diff with minimal context (only changed lines with colors)
# ANSI codes: ^[[31m (red for -), ^[[32m (green for +), ^[[36m (cyan for @@)
# Filter to show only lines starting with red/green (additions/deletions)
local diff_output
diff_output=$(git diff --color=always --unified=0 "${tag1}:${readme_path}" "${tag2}:${readme_path}" | \
grep -E $'^\x1b\\[(31|32)m' | \
grep -v -E $'^\x1b\\[1m(---|\\+\\+\\+)')
if [[ -n "${diff_output}" ]]; then
# Extract announcements from both versions
local announcements1
local announcements2
announcements1=$(git show "${tag1}:${readme_path}" | sed -n '/| Announcements |/,/^\*\*\*$/p' | grep -E '^\| \[' | sed 's/^| \[/• [/' | sed 's/ |$//' || true)
announcements2=$(git show "${tag2}:${readme_path}" | sed -n '/| Announcements |/,/^\*\*\*$/p' | grep -E '^\| \[' | sed 's/^| \[/• [/' | sed 's/ |$//' || true)
# Show announcement changes
if [[ "${announcements1}" != "${announcements2}" ]]; then
echo "📢 Announcement Changes:"
echo "────────────────────────────────────────────────────────────────────────────────"
if [[ -n "${announcements2}" ]]; then
echo "${announcements2}"
else
echo "(no announcements)"
fi
echo "────────────────────────────────────────────────────────────────────────────────"
echo ""
fi
# Extract cached tools sections
local cached_tools1
local cached_tools2
cached_tools1=$(git show "${tag1}:${readme_path}" | sed -n '/^### Cached Tools$/,/^###[^#]/p' | head -n -1 || true)
cached_tools2=$(git show "${tag2}:${readme_path}" | sed -n '/^### Cached Tools$/,/^###[^#]/p' | head -n -1 || true)
# Show cached tools changes
if [[ "${cached_tools1}" != "${cached_tools2}" ]]; then
local cached_diff
cached_diff=$(git diff --color=always --unified=2 --no-index \
<(echo "${cached_tools1}") <(echo "${cached_tools2}") 2>/dev/null | \
grep -E $'(^\x1b\\[(31|32)m[-+]| #### )' | \
sed -r 's/\x1b\[m$//' || true)
if [[ -n "${cached_diff}" ]]; then
echo "🔧 Cached Tools Changes (setup-* actions):"
echo "────────────────────────────────────────────────────────────────────────────────"
echo "${cached_diff}"
echo "────────────────────────────────────────────────────────────────────────────────"
echo ""
fi
fi
echo "Full Diff:"
echo "────────────────────────────────────────────────────────────────────────────────"
echo "${diff_output}"
echo "────────────────────────────────────────────────────────────────────────────────"
echo ""
# Count changes
local changes
changes=$(echo "${diff_output}" | wc -l)
echo "Changes: ${changes} lines"
# Parse version changes for breaking change analysis
local breaking_changes=()
local removals=()
local additions=()
# Extract clean lines (strip ANSI codes)
while IFS= read -r line; do
if [[ "${line}" =~ ^\-(.+)$ ]]; then
removals+=("${BASH_REMATCH[1]}")
elif [[ "${line}" =~ ^\+(.+)$ ]]; then
additions+=("${BASH_REMATCH[1]}")
fi
done < <(echo "${diff_output}" | sed -r 's/\x1b\[[0-9;]*m//g')
# Detect breaking changes
for removed in "${removals[@]}"; do
local tool_name=""
local old_version=""
local found_match=false
# Try to extract tool name and version (handle various formats)
if [[ "${removed}" =~ ^([^0-9]+[[:space:]]+)([0-9]+\.[0-9]+[^[:space:]]*) ]]; then
tool_name="${BASH_REMATCH[1]}"
old_version="${BASH_REMATCH[2]}"
elif [[ "${removed}" =~ ^([^0-9]+[[:space:]]+v)([0-9]+\.[0-9]+[^[:space:]]*) ]]; then
tool_name="${BASH_REMATCH[1]}"
old_version="${BASH_REMATCH[2]}"
fi
# If we found a semver-style version, look for matching addition
if [[ -n "${tool_name}" && -n "${old_version}" ]]; then
for added in "${additions[@]}"; do
if [[ "${added}" =~ ^${tool_name}([0-9]+\.[0-9]+[^[:space:]]*) ]]; then
local new_version="${BASH_REMATCH[1]}"
found_match=true
# Extract major version for semver comparison
if [[ "${old_version}" =~ ^([0-9]+)\. && "${new_version}" =~ ^([0-9]+)\. ]]; then
local old_major="${BASH_REMATCH[1]}"
local new_major="${BASH_REMATCH[1]}"
[[ "${old_version}" =~ ^([0-9]+)\. ]] && old_major="${BASH_REMATCH[1]}"
[[ "${new_version}" =~ ^([0-9]+)\. ]] && new_major="${BASH_REMATCH[1]}"
if [[ ${new_major} -gt ${old_major} ]]; then
breaking_changes+=("🔴 ${tool_name}${old_version}${new_version} (major version bump)")
fi
fi
break
fi
done
fi
# If no match found and looks like a versioned tool, it's a removal
if [[ ${found_match} == false && -n "${old_version}" ]]; then
breaking_changes+=("${removed} (removed)")
elif [[ ${found_match} == false && "${removed}" =~ [0-9]+\.[0-9]+ ]]; then
breaking_changes+=("${removed} (removed)")
fi
done
# Display breaking changes
if [[ ${#breaking_changes[@]} -gt 0 ]]; then
echo ""
echo "⚠️ Breaking changes detected (${#breaking_changes[@]}):"
echo "--------------------------------------------------------------------------------"
printf '%s\n' "${breaking_changes[@]}"
echo "--------------------------------------------------------------------------------"
fi
else
echo "No changes found."
fi
# Display PR link and commit count
local pr_number
pr_number=$(git log --all --format="%s" --grep="${version2}" | \
grep -oP '\(#\K[0-9]+(?=\))' | head -1)
local commit_count
commit_count=$(git rev-list --count "${tag1}..${tag2}")
echo "Commits: ${commit_count}"
if [[ -n "${pr_number}" ]]; then
echo "PR: https://github.com/actions/runner-images/pull/${pr_number}"
fi
return 0
}
# Execute main function
main "$@"
+36 -31
View File
@@ -1,7 +1,11 @@
| Announcements |
|-|
| [[Ubuntu & Windows] Four tools scheduled for deprecation on November 3, 2025](https://github.com/actions/runner-images/issues/12898) |
***
# Ubuntu 22.04
- OS Version: 22.04.5 LTS
- Kernel Version: 6.8.0-1041-azure
- Image Version: 20251208.177.1
- Image Version: 20251125.163.1
- Systemd version: 249.11-0ubuntu3.17
## Installed Software
@@ -27,7 +31,7 @@
### Package Management
- cpan 1.64
- Helm 3.19.2
- Homebrew 5.0.5
- Homebrew 5.0.3
- Miniconda 25.9.1
- Npm 10.8.2
- NuGet 6.6.1.2
@@ -35,7 +39,7 @@
- Pip3 22.0.2
- Pipx 1.8.0
- RubyGems 3.3.5
- Vcpkg (build from commit 52f93a645e)
- Vcpkg (build from commit 9aee6e968f)
- Yarn 1.22.22
#### Environment variables
@@ -55,7 +59,7 @@ to accomplish this.
### Project Management
- Ant 1.10.12
- Gradle 9.2.1
- Lerna 9.0.3
- Lerna 9.0.1
- Maven 3.9.11
- Sbt 1.11.7
@@ -68,7 +72,7 @@ to accomplish this.
- Bicep 0.39.26
- Buildah 1.23.1
- CMake 3.31.6
- CodeQL Action Bundle 2.23.7
- CodeQL Action Bundle 2.23.6
- Docker Amazon ECR Credential Helper 0.11.0
- Docker Compose v2 2.38.2
- Docker-Buildx 0.30.1
@@ -79,7 +83,7 @@ to accomplish this.
- Git LFS 3.7.1
- Git-ftp 1.6.0
- Haveged 1.9.14
- Heroku 10.16.0
- Heroku 10.15.1
- jq 1.6
- Kind 0.30.0
- Kubectl 1.34.2
@@ -93,32 +97,32 @@ to accomplish this.
- nvm 0.40.3
- OpenSSL 3.0.2-0ubuntu1.20
- Packer 1.14.3
- Parcel 2.16.3
- Parcel 2.16.1
- Podman 3.4.4
- Pulumi 3.210.0
- Pulumi 3.208.0
- R 4.5.2
- Skopeo 1.4.1
- Sphinx Open Source Search Server 2.2.11
- SVN 1.14.1
- Terraform 1.14.1
- Terraform 1.14.0
- yamllint 1.37.1
- yq 4.49.2
- zstd 1.5.7
- Ninja 1.13.2
### CLI Tools
- Alibaba Cloud CLI 3.2.0
- AWS CLI 2.32.12
- Alibaba Cloud CLI 3.1.5
- AWS CLI 2.32.5
- AWS CLI Session Manager Plugin 1.2.764.0
- AWS SAM CLI 1.150.1
- Azure CLI 2.81.0
- AWS SAM CLI 1.148.0
- Azure CLI 2.80.0
- Azure CLI (azure-devops) 1.0.2
- GitHub CLI 2.83.1
- Google Cloud CLI 548.0.0
- Netlify CLI 23.12.3
- OpenShift CLI 4.20.6
- Netlify CLI 23.11.1
- OpenShift CLI 4.20.5
- ORAS CLI 1.3.0
- Vercel CLI 49.1.2
- Vercel CLI 48.10.13
### Java
| Version | Environment Variable |
@@ -132,7 +136,7 @@ to accomplish this.
### PHP Tools
- PHP: 8.1.2
- Composer 2.9.2
- PHPUnit 8.5.50
- PHPUnit 8.5.48
```
Both Xdebug and PCOV extensions are installed, but only Xdebug is enabled.
```
@@ -158,12 +162,12 @@ Both Xdebug and PCOV extensions are installed, but only Xdebug is enabled.
- Rustfmt 1.8.0
### Browsers and Drivers
- Google Chrome 143.0.7499.40
- ChromeDriver 143.0.7499.40
- Chromium 143.0.7499.0
- Microsoft Edge 143.0.3650.66
- Microsoft Edge WebDriver 143.0.3650.66
- Selenium server 4.39.0
- Google Chrome 142.0.7444.175
- ChromeDriver 142.0.7444.175
- Chromium 142.0.7444.0
- Microsoft Edge 142.0.3595.94
- Microsoft Edge WebDriver 142.0.3595.94
- Selenium server 4.38.0
- Mozilla Firefox 145.0.2
- Geckodriver 0.36.0
@@ -208,11 +212,11 @@ Use the following command as a part of your job to start the service: 'sudo syst
#### Go
- 1.22.12
- 1.23.12
- 1.24.11
- 1.25.5
- 1.24.10
- 1.25.4
#### Node.js
- 20.19.6
- 20.19.5
- 22.21.1
- 24.11.1
@@ -221,8 +225,8 @@ Use the following command as a part of your job to start the service: 'sudo syst
- 3.10.19
- 3.11.14
- 3.12.12
- 3.13.11
- 3.14.2
- 3.13.9
- 3.14.0
#### PyPy
- 3.7.13 [PyPy 7.3.9]
@@ -288,9 +292,9 @@ Use the following command as a part of your job to start the service: 'sudo syst
| node:18 | sha256:c6ae79e38498325db67193d391e6ec1d224d96c693a8a4d943498556716d3783 | 2025-03-27 |
| node:18-alpine | sha256:8d6421d663b4c28fd3ebc498332f249011d118945588d0a35cb9bc4b8ca09d9e | 2025-03-27 |
| node:20 | sha256:66d2eb8b463114d1f416d61dbd5fa9cea83e8fc250feb997338467728a06124b | 2025-11-25 |
| node:20-alpine | sha256:643e7036aa985317ebfee460005e322aa550c6b6883000d01daefb58689a58e2 | 2025-12-04 |
| node:20-alpine | sha256:16858294071a56ffd4cce9f17b57136cc39e41507b40e245b4f8e906f7a19463 | 2025-11-25 |
| node:22 | sha256:4ad2c2b350ab49fb637ab40a269ffe207c61818bb7eb3a4ea122001a0c605e1f | 2025-11-18 |
| node:22-alpine | sha256:9632533eda8061fc1e9960cfb3f8762781c07a00ee7317f5dc0e13c05e15166f | 2025-12-04 |
| node:22-alpine | sha256:b2358485e3e33bc3a33114d2b1bdb18cdbe4df01bd2b257198eb51beb1f026c5 | 2025-10-29 |
| ubuntu:20.04 | sha256:8feb4d8ca5354def3d8fce243717141ce31e2c428701f6682bd2fafe15388214 | 2025-04-08 |
| ubuntu:22.04 | sha256:104ae83764a5119017b8e8d6218fa0832b09df65aae7d5a6de29a85d813da2fb | 2025-10-13 |
@@ -301,7 +305,7 @@ Use the following command as a part of your job to start the service: 'sudo syst
| aria2 | 1.36.0-1 |
| autoconf | 2.71-2 |
| automake | 1:1.16.5-1.3 |
| binutils | 2.38-4ubuntu2.11 |
| binutils | 2.38-4ubuntu2.10 |
| bison | 2:3.8.2+dfsg-1build1 |
| brotli | 1.0.9-2build6 |
| bzip2 | 1.0.8-5build1 |
@@ -389,3 +393,4 @@ Use the following command as a part of your job to start the service: 'sudo syst
| xz-utils | 5.2.5-2ubuntu1 |
| zip | 3.0-12build2 |
| zsync | 0.6.2-3ubuntu1 |