From d2e7b0f0490a76b50900d61aaf5309e2829c14b5 Mon Sep 17 00:00:00 2001 From: Eduardo Dantas Date: Fri, 14 Aug 2026 17:57:51 -0300 Subject: [PATCH] ci(vcpkg): keep baseline updates synchronized and auto-mergeable (#1803) ci(vcpkg): keep baseline updates synchronized and auto-mergeable Improve the vcpkg baseline updater so automated dependency PRs stay synchronized with main and can be queued for native GitHub auto-merge. Main changes: - Fetch full repository history before updating the baseline branch. - Synchronize the updater branch with the latest origin/main before applying baseline changes. - Rebase existing updater branches onto main. - Create missing updater branches directly from origin/main. - Use force-with-lease when refreshing bot-managed branches. - Restrict existing PR lookup to open baseline PRs targeting main. - Queue both existing and newly created baseline PRs for native GitHub squash auto-merge. - Set a consistent squash commit subject and body for automated baseline merges. - Validate PR numbers before attempting to enable auto-merge. - Warn and leave the PR open when auto-merge cannot be queued. - Continue triggering CI when the requested baseline is already present. - Update CI path filters so changes to update_vcpkg_baseline.yml trigger Windows, macOS, Android, Docker, and browser validation. Safety: - The updater does not approve reviews. - The updater does not bypass branch protection. - Auto-merge remains subject to required reviews and status checks. - Branch rewrites use force-with-lease instead of an unconditional force push. Validation: - actionlint passed. - YAML parsing passed. - Extracted updater shell script passed bash -n. - git diff --check passed. This makes automated vcpkg baseline maintenance more reliable by preventing stale update branches and allowing GitHub to complete the merge once all repository requirements are satisfied. --- .github/workflows/ci.yml | 5 ++ .github/workflows/update_vcpkg_baseline.yml | 66 +++++++++++++++++---- 2 files changed, 59 insertions(+), 12 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3ddc1df80..29794105b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -112,6 +112,7 @@ jobs: - ".github/workflows/reusable-build-windows.yml" - ".github/workflows/reusable-checks.yml" - ".github/workflows/reusable-tests-lua.yml" + - ".github/workflows/update_vcpkg_baseline.yml" macos: - "src/**" - "cmake/**" @@ -122,6 +123,7 @@ jobs: - "CMakePresets.json" - ".github/workflows/ci.yml" - ".github/workflows/reusable-build-macos.yml" + - ".github/workflows/update_vcpkg_baseline.yml" android: - "src/**" - "android/**" @@ -134,6 +136,7 @@ jobs: - "setup_android_deps.sh" - ".github/workflows/ci.yml" - ".github/workflows/reusable-build-android-apk.yml" + - ".github/workflows/update_vcpkg_baseline.yml" docker: - "Dockerfile" - ".dockerignore" @@ -147,6 +150,7 @@ jobs: - ".yamllint.yaml" - ".github/workflows/ci.yml" - ".github/workflows/reusable-build-docker.yml" + - ".github/workflows/update_vcpkg_baseline.yml" browser: - "Dockerfile.browser" - "Dockerfile.browser.sh" @@ -160,6 +164,7 @@ jobs: - ".yamllint.yaml" - ".github/workflows/ci.yml" - ".github/workflows/reusable-build-browser.yml" + - ".github/workflows/update_vcpkg_baseline.yml" checks: name: Fast Checks diff --git a/.github/workflows/update_vcpkg_baseline.yml b/.github/workflows/update_vcpkg_baseline.yml index 402615c94..329903291 100644 --- a/.github/workflows/update_vcpkg_baseline.yml +++ b/.github/workflows/update_vcpkg_baseline.yml @@ -25,6 +25,7 @@ jobs: - name: Checkout repository uses: actions/checkout@v6 with: + fetch-depth: 0 ref: main - name: Get latest vcpkg release @@ -75,20 +76,59 @@ jobs: gh workflow run ci.yml --ref "${branch_name}" } + queue_auto_merge() { + local pr_number="$1" + local merge_subject="chore(vcpkg): update baseline to ${RELEASE_TAG}" + local merge_body="vcpkg baseline: ${NEW_BASELINE}" + + if [[ ! "${pr_number}" =~ ^[0-9]+$ ]]; then + echo "::error::Invalid baseline pull request number: ${pr_number}" + return 1 + fi + + if gh pr merge "${pr_number}" --auto --squash \ + --subject "${merge_subject}" \ + --body "${merge_body}"; then + echo "Queued native GitHub auto-merge for PR #${pr_number}" + else + echo "::warning::Could not queue auto-merge for PR #${pr_number}. Repository auto-merge may be disabled or branch protection may require a review." + fi + } + + sync_update_branch() { + git fetch --prune origin main + + if git ls-remote --exit-code --heads origin "${branch_name}" >/dev/null 2>&1; then + git fetch origin "+refs/heads/${branch_name}:refs/remotes/origin/${branch_name}" + git checkout -B "${branch_name}" "origin/${branch_name}" + git rebase origin/main + git push --force-with-lease origin "${branch_name}" + else + git checkout -B "${branch_name}" origin/main + fi + } + git config user.name "github-actions[bot]" git config user.email "github-actions[bot]@users.noreply.github.com" - existing_pr="$(gh pr list --state open --json number,headRefName | jq -r '.[] | select(.headRefName == "'"${branch_name}"'") | .number')" + existing_pr="$(gh api \ + --method GET \ + "repos/${GITHUB_REPOSITORY}/pulls" \ + -f state=open \ + -f base=main \ + -f head="${GITHUB_REPOSITORY_OWNER}:${branch_name}" \ + -f per_page=1 \ + --jq '.[0].number // empty')" if [[ -n "${existing_pr}" ]]; then echo "Found existing baseline PR #${existing_pr}, updating it" - git fetch origin "${branch_name}" - git checkout "${branch_name}" + sync_update_branch current_in_branch="$(jq -r '."builtin-baseline"' vcpkg.json)" if [[ "${current_in_branch}" == "${NEW_BASELINE}" ]]; then echo "PR #${existing_pr} already has baseline ${NEW_BASELINE}" trigger_ci + queue_auto_merge "${existing_pr}" exit 0 fi @@ -100,7 +140,7 @@ jobs: else git add vcpkg.json git commit -m "chore: update vcpkg baseline to ${RELEASE_TAG}" - git push origin "${branch_name}" + git push --force-with-lease origin "${branch_name}" fi gh pr edit "${existing_pr}" --title "chore: Update vcpkg baseline to ${RELEASE_TAG}" @@ -110,15 +150,11 @@ jobs: gh pr comment "${existing_pr}" --body "${comment_body}" trigger_ci + queue_auto_merge "${existing_pr}" else echo "No existing baseline PR found, creating new one" - if git ls-remote --heads origin "${branch_name}" | grep -q "${branch_name}"; then - git fetch origin "${branch_name}" - git checkout "${branch_name}" - else - git checkout -b "${branch_name}" - fi + sync_update_branch jq --arg baseline "${NEW_BASELINE}" '."builtin-baseline" = $baseline' vcpkg.json > vcpkg.json.tmp mv vcpkg.json.tmp vcpkg.json @@ -134,11 +170,17 @@ jobs: printf -v pr_body '## vcpkg Baseline Update\n\nThis PR updates the vcpkg baseline to the latest release.\n\n**Release:** `%s`\n**Previous:** `%s`\n**New:** `%s`\n\n**Release notes:** https://github.com/microsoft/vcpkg/releases/tag/%s\n\n---\nThis PR is automatically updated when new vcpkg releases are published.' \ "${RELEASE_TAG}" "${PREVIOUS}" "${NEW_BASELINE}" "${RELEASE_TAG}" - gh pr create \ + pr_url="$(gh pr create \ --title "chore: Update vcpkg baseline to ${RELEASE_TAG}" \ --body "${pr_body}" \ --base main \ - --head "${branch_name}" + --head "${branch_name}")" trigger_ci + new_pr="${pr_url##*/}" + if [[ "${new_pr}" =~ ^[0-9]+$ ]]; then + queue_auto_merge "${new_pr}" + else + echo "::warning::Created a baseline PR, but could not parse its number for auto-merge." + fi fi