From 679d71a9b5fe0c8e9b91c8beccaeea8d86ea8890 Mon Sep 17 00:00:00 2001 From: deepalak56 Date: Tue, 12 May 2026 00:50:47 -0700 Subject: [PATCH] Fix: Prevent GitHub 'Latest' badge regression on maintenance releases (https://github.com/bazelbuild/bazel/pull/29452) Problem: GitHub automatically marks the most recently created release as "Latest." When a maintenance patch (e.g., 8.7.0) is released after a newer major version (e.g., 9.1.0), the "Latest" badge incorrectly regresses to the older version. Solution: Updated scripts/ci/build.sh to perform a semantic version check using sort -V. If the new release is semantically older than an existing one, the script now explicitly calls the GitHub API to set make_latest: false, ensuring the badge stays on the true highest version. Impact: - Guarantees the "Latest" badge always points to the highest semantic version. - Prevents legacy branch updates from hijacking the project's "Latest" status. - Syncs GitHub UI state with the fix introduced in bazelbuild/continuous-integration#2598. PR #[2598](https://github.com/bazelbuild/continuous-integration/pull/2598) (Continuous-integration): Fixes the Docker Registry (bazel:latest tag). PR #29452 (Bazel): Fixes the GitHub Releases Page (the green "Latest" badge). PR #[2692](https://github.com/bazelbuild/continuous-integration/pull/2602) (Continuous-integration): Buildkite pipeline for Github CLI migration. Closes #29452. PiperOrigin-RevId: 914121481 Change-Id: Ic725b3e49105b3d25c54545740e289a6f13f1aa0 --- scripts/ci/build.sh | 62 +++++++++++++++++++++++++++++++++++++-------- 1 file changed, 51 insertions(+), 11 deletions(-) diff --git a/scripts/ci/build.sh b/scripts/ci/build.sh index 4bcfa560096017..3ece8257960bd0 100755 --- a/scripts/ci/build.sh +++ b/scripts/ci/build.sh @@ -33,10 +33,9 @@ if ! command -v gsutil &>/dev/null; then echo "See https://cloud.google.com/sdk/downloads for instructions." exit 1 fi -if ! command -v github-release &>/dev/null; then - echo "Required tool 'github-release' not found. Download it from here:" - echo "https://github.com/c4milo/github-release/releases" - echo "Just extract the archive and put the binary on your PATH." +if ! command -v gh &>/dev/null; then + echo "Required tool 'gh' (GitHub CLI) not found. Please install it:" + echo "See https://cli.github.com/ for instructions." exit 1 fi if ! command -v debsign &>/dev/null; then @@ -136,8 +135,8 @@ _Security_: All our binaries are signed with our ' } -# Deploy a github release using a third party tool: -# https://github.com/c4milo/github-release +# Deploy a github release using the official GitHub CLI (gh): +# https://cli.github.com/ # This methods expects the following arguments: # $1..$n files generated by package_build (should not contains the README file) # Please set GITHUB_TOKEN to talk to the Github API. @@ -150,13 +149,55 @@ function release_to_github() { local release_branch=$(get_release_branch) if [ -n "${release_name}" ]; then - local github_token="$(gsutil cat gs://bazel-trusted-encrypted-secrets/github-trusted-token.enc | \ + local github_token + github_token="$(gsutil cat gs://bazel-trusted-encrypted-secrets/github-trusted-token.enc | \ gcloud kms decrypt --project bazel-public --location global --keyring buildkite --key github-trusted-token --ciphertext-file - --plaintext-file -)" - if [ -z "${rc}" ]; then - GITHUB_TOKEN="${github_token}" github-release "bazelbuild/bazel" "${release_name}" "" "$(get_release_page)" "${artifact_dir}/*" + + local latest_flag="true" + local prerelease_flag="" + local tag_to_deploy="${release_name}" + + if [ -n "${rc}" ]; then + tag_to_deploy="${full_release_name}" + prerelease_flag="--prerelease" + latest_flag="false" else - GITHUB_TOKEN="${github_token}" github-release -prerelease "bazelbuild/bazel" "${full_release_name}" "${release_branch}" "$(get_release_page)" "${artifact_dir}/*" + echo "+++ Checking if ${release_name} should be marked as Latest" + # Query the current GitHub "latest" release to compare versions. + local current_latest_tag + if current_latest_tag=$(GH_TOKEN="${github_token}" gh release view --repo "bazelbuild/bazel" --json tagName --jq .tagName 2>/dev/null); then + if [[ -n "${current_latest_tag}" ]]; then + local highest + highest=$(printf '%s\n%s' "${current_latest_tag}" "${release_name}" | sort -V | tail -n 1) + if [[ "${release_name}" != "${highest}" ]]; then + echo "+++ Version ${release_name} is older than ${current_latest_tag}. Will NOT mark as latest." + latest_flag="false" + fi + fi + else + echo "+++ Warning: Could not determine current latest release tag. Will NOT mark as latest to be safe." + latest_flag="false" + fi fi + + # Use a subshell so that the EXIT trap for temp file cleanup does not + # affect the outer script's traps. + ( + notes_file="$(mktemp)" + trap 'rm -f "$notes_file"' EXIT + get_release_page > "$notes_file" + + echo "+++ Deploying to GitHub (Tag: ${tag_to_deploy}, Latest: ${latest_flag})" + + GH_TOKEN="${github_token}" gh release create "${tag_to_deploy}" \ + "${artifact_dir}"/* \ + --repo "bazelbuild/bazel" \ + --target "${release_branch}" \ + --title "${tag_to_deploy}" \ + --notes-file "$notes_file" \ + ${prerelease_flag} \ + --latest="${latest_flag}" + ) fi } @@ -457,4 +498,3 @@ function deploy_release() { cp "${artifact_dir}"/* "${gcs_working_dir}" release_to_gcs "${gcs_working_dir}" } -