From 139f37d99a698720279544f88d46927844cc0039 Mon Sep 17 00:00:00 2001 From: Parth Aggarwal Date: Thu, 19 Feb 2026 15:21:46 -0800 Subject: [PATCH 1/6] Fix propagation to use consistent commits throughout run Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- update_deps/helper_scripts/git_operations.ps1 | 118 +++++++++++++++++- update_deps/propagate_updates.ps1 | 10 ++ 2 files changed, 126 insertions(+), 2 deletions(-) diff --git a/update_deps/helper_scripts/git_operations.ps1 b/update_deps/helper_scripts/git_operations.ps1 index a9ad0e5..52d840e 100644 --- a/update_deps/helper_scripts/git_operations.ps1 +++ b/update_deps/helper_scripts/git_operations.ps1 @@ -23,6 +23,120 @@ function create-ignore-pattern # Initialize the ignore pattern when script is sourced create-ignore-pattern +# Snapshot the current master HEAD commit for all repos in the work directory. +# Called once before propagation starts so that every repo is updated to the +# same set of commits throughout the entire run. +function snapshot-repo-commits +{ + param( + [string[]] $repo_order + ) + $commits = @{} + foreach ($repo_name in $repo_order) + { + if (Test-Path $repo_name) + { + Push-Location $repo_name + $sha = (git rev-parse master 2>$null) + if ($LASTEXITCODE -eq 0 -and $sha) + { + $commits[$repo_name] = $sha.Trim() + Write-Host " $repo_name : $($commits[$repo_name].Substring(0, 8))" + } + else + { + Write-Host " Warning: Could not get master commit for $repo_name" -ForegroundColor Yellow + } + Pop-Location + } + else + { + # repo not cloned yet, skip + } + } + return $commits +} + +# Update each submodule to its fixed commit, or latest master if no fixed commit is available +function update-submodules-to-fixed-commits +{ + # Parse ignore pattern into a list for matching + $ignore_paths = @() + if ($global:ignore_pattern) + { + $ignore_paths = $global:ignore_pattern -split '\|' + } + + # Get submodule paths from .gitmodules + if (-not (Test-Path ".gitmodules")) + { + return + } + $submodule_lines = git config --file .gitmodules --get-regexp '\.path$' + if (-not $submodule_lines) + { + return + } + + foreach ($line in $submodule_lines) + { + $sub_path = ($line -split "\s+", 2)[1] + + # Check if this submodule should be ignored + if ($sub_path -in $ignore_paths) + { + continue + } + + # Derive repo name from submodule path (e.g., "deps/c-util" -> "c-util") + $sub_repo_name = Split-Path $sub_path -Leaf + + Push-Location $sub_path + if ($global:fixed_commits -and $global:fixed_commits.ContainsKey($sub_repo_name)) + { + $target_sha = $global:fixed_commits[$sub_repo_name] + Write-Host " Checking out $sub_path at fixed commit $($target_sha.Substring(0, 8))" + git fetch origin + git checkout $target_sha + } + else + { + Write-Host " Updating $sub_path to latest master (no fixed commit)" + git checkout master + git pull + } + Pop-Location + } +} + +# After a repo's PR is merged, fetch the new master HEAD and update fixed_commits +# so that downstream repos use the commit created by this propagation. +function update-fixed-commit +{ + param( + [string] $repo_name + ) + + if (-not $global:fixed_commits) + { + return + } + + Push-Location $repo_name + git fetch origin master 2>$null + $new_sha = (git rev-parse origin/master 2>$null) + if ($LASTEXITCODE -eq 0 -and $new_sha) + { + $global:fixed_commits[$repo_name] = $new_sha.Trim() + Write-Host " Updated fixed commit for $repo_name to $($new_sha.Trim().Substring(0, 8))" + } + else + { + Write-Host " Warning: Could not fetch new master commit for $repo_name" -ForegroundColor Yellow + } + Pop-Location +} + function refresh-submodules { $submodules = git submodule | Out-String @@ -64,8 +178,8 @@ function update-local-repo # no deps folder } git submodule update --init - # update all submodules except the ones mentioned in ignores.json - git submodule foreach "case `$name in $ignore_pattern ) ;; *) git checkout master && git pull;; esac" + # update all submodules to their fixed commits (or latest master as fallback) + update-submodules-to-fixed-commits # create new branch git checkout -B $new_branch_name # add updates and push to remote diff --git a/update_deps/propagate_updates.ps1 b/update_deps/propagate_updates.ps1 index 8047348..b6bed2b 100644 --- a/update_deps/propagate_updates.ps1 +++ b/update_deps/propagate_updates.ps1 @@ -113,11 +113,13 @@ function update-repo { $pr_url = update-repo-github $repo_name $new_branch_name set-repo-status -repo_name $repo_name -status $script:STATUS_UPDATED -pr_url $pr_url + update-fixed-commit $repo_name } elseif ($repo_type -eq "azure") { $pr_url = update-repo-azure $repo_name $new_branch_name set-repo-status -repo_name $repo_name -status $script:STATUS_UPDATED -pr_url $pr_url + update-fixed-commit $repo_name } else { @@ -231,6 +233,14 @@ function propagate-updates # Initialize status tracking initialize-repo-status -repos $repo_order + # Snapshot master HEAD commits for all repos before starting updates. + # This ensures we propagate the same commit for each dependency throughout + # the entire run, even if a repo's master branch is updated externally. + Write-Host "`nSnapshotting master commits for all repos..." + Set-Location $global:work_dir + $global:fixed_commits = snapshot-repo-commits -repo_order $repo_order + Write-Host "Fixed commits captured for $($global:fixed_commits.Count) repos`n" + Write-Host "Updating repositories in the following order: " for($i = 0; $i -lt $repo_order.Length; $i++) { From db6b3ef482b7686ff9113e796ff671b9aa4ed226 Mon Sep 17 00:00:00 2001 From: Parth Aggarwal Date: Thu, 19 Feb 2026 15:29:42 -0800 Subject: [PATCH 2/6] Replace early return/continue with if-else patterns Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- update_deps/helper_scripts/git_operations.ps1 | 99 ++++++++++--------- 1 file changed, 54 insertions(+), 45 deletions(-) diff --git a/update_deps/helper_scripts/git_operations.ps1 b/update_deps/helper_scripts/git_operations.ps1 index 52d840e..d65101a 100644 --- a/update_deps/helper_scripts/git_operations.ps1 +++ b/update_deps/helper_scripts/git_operations.ps1 @@ -68,44 +68,51 @@ function update-submodules-to-fixed-commits } # Get submodule paths from .gitmodules - if (-not (Test-Path ".gitmodules")) + if (Test-Path ".gitmodules") { - return - } - $submodule_lines = git config --file .gitmodules --get-regexp '\.path$' - if (-not $submodule_lines) - { - return - } - - foreach ($line in $submodule_lines) - { - $sub_path = ($line -split "\s+", 2)[1] - - # Check if this submodule should be ignored - if ($sub_path -in $ignore_paths) - { - continue - } - - # Derive repo name from submodule path (e.g., "deps/c-util" -> "c-util") - $sub_repo_name = Split-Path $sub_path -Leaf - - Push-Location $sub_path - if ($global:fixed_commits -and $global:fixed_commits.ContainsKey($sub_repo_name)) + $submodule_lines = git config --file .gitmodules --get-regexp '\.path$' + if ($submodule_lines) { - $target_sha = $global:fixed_commits[$sub_repo_name] - Write-Host " Checking out $sub_path at fixed commit $($target_sha.Substring(0, 8))" - git fetch origin - git checkout $target_sha + foreach ($line in $submodule_lines) + { + $sub_path = ($line -split "\s+", 2)[1] + + # Check if this submodule should be ignored + if ($sub_path -in $ignore_paths) + { + # ignored submodule, skip + } + else + { + # Derive repo name from submodule path (e.g., "deps/c-util" -> "c-util") + $sub_repo_name = Split-Path $sub_path -Leaf + + Push-Location $sub_path + if ($global:fixed_commits -and $global:fixed_commits.ContainsKey($sub_repo_name)) + { + $target_sha = $global:fixed_commits[$sub_repo_name] + Write-Host " Checking out $sub_path at fixed commit $($target_sha.Substring(0, 8))" + git fetch origin + git checkout $target_sha + } + else + { + Write-Host " Updating $sub_path to latest master (no fixed commit)" + git checkout master + git pull + } + Pop-Location + } + } } else { - Write-Host " Updating $sub_path to latest master (no fixed commit)" - git checkout master - git pull + # no submodules found } - Pop-Location + } + else + { + # no .gitmodules file } } @@ -117,24 +124,26 @@ function update-fixed-commit [string] $repo_name ) - if (-not $global:fixed_commits) + if ($global:fixed_commits) { - return - } - - Push-Location $repo_name - git fetch origin master 2>$null - $new_sha = (git rev-parse origin/master 2>$null) - if ($LASTEXITCODE -eq 0 -and $new_sha) - { - $global:fixed_commits[$repo_name] = $new_sha.Trim() - Write-Host " Updated fixed commit for $repo_name to $($new_sha.Trim().Substring(0, 8))" + Push-Location $repo_name + git fetch origin master 2>$null + $new_sha = (git rev-parse origin/master 2>$null) + if ($LASTEXITCODE -eq 0 -and $new_sha) + { + $global:fixed_commits[$repo_name] = $new_sha.Trim() + Write-Host " Updated fixed commit for $repo_name to $($new_sha.Trim().Substring(0, 8))" + } + else + { + Write-Host " Warning: Could not fetch new master commit for $repo_name" -ForegroundColor Yellow + } + Pop-Location } else { - Write-Host " Warning: Could not fetch new master commit for $repo_name" -ForegroundColor Yellow + # no fixed commits table, nothing to update } - Pop-Location } function refresh-submodules From ac5076a3185ade79cf0d61f176692ab28d4feb7d Mon Sep 17 00:00:00 2001 From: Parth Aggarwal Date: Thu, 19 Feb 2026 16:26:14 -0800 Subject: [PATCH 3/6] Warn about newer un-propagated commits during and after run Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- update_deps/helper_scripts/git_operations.ps1 | 47 +++++++++++++++++++ update_deps/propagate_updates.ps1 | 4 ++ 2 files changed, 51 insertions(+) diff --git a/update_deps/helper_scripts/git_operations.ps1 b/update_deps/helper_scripts/git_operations.ps1 index d65101a..1a78b95 100644 --- a/update_deps/helper_scripts/git_operations.ps1 +++ b/update_deps/helper_scripts/git_operations.ps1 @@ -94,6 +94,25 @@ function update-submodules-to-fixed-commits Write-Host " Checking out $sub_path at fixed commit $($target_sha.Substring(0, 8))" git fetch origin git checkout $target_sha + + # Warn if remote master has moved ahead of the fixed commit + $remote_sha = (git rev-parse origin/master 2>$null) + if ($LASTEXITCODE -eq 0 -and $remote_sha -and $remote_sha.Trim() -ne $target_sha) + { + Write-Host " WARNING: $sub_repo_name has newer commits on master ($($remote_sha.Trim().Substring(0, 8))) that will NOT be propagated" -ForegroundColor Yellow + if (-not $global:skipped_newer_commits) + { + $global:skipped_newer_commits = @{} + } + $global:skipped_newer_commits[$sub_repo_name] = @{ + FixedCommit = $target_sha + RemoteCommit = $remote_sha.Trim() + } + } + else + { + # remote master matches fixed commit + } } else { @@ -146,6 +165,34 @@ function update-fixed-commit } } +# Show a summary of repos that had newer commits on master that were not propagated +function show-skipped-commits-summary +{ + if ($global:skipped_newer_commits -and $global:skipped_newer_commits.Count -gt 0) + { + Write-Host "" + Write-Host "========================================" -ForegroundColor Yellow + Write-Host " NEWER COMMITS NOT PROPAGATED" -ForegroundColor Yellow + Write-Host "========================================" -ForegroundColor Yellow + Write-Host "The following repos had newer commits on master" -ForegroundColor Yellow + Write-Host "that were not included in this propagation run:" -ForegroundColor Yellow + Write-Host "" + foreach ($repo in $global:skipped_newer_commits.Keys) + { + $info = $global:skipped_newer_commits[$repo] + Write-Host " $repo" -ForegroundColor Yellow -NoNewline + Write-Host " used: $($info.FixedCommit.Substring(0, 8)) remote: $($info.RemoteCommit.Substring(0, 8))" + } + Write-Host "" + Write-Host "Consider running propagation again to pick up these changes." -ForegroundColor Yellow + Write-Host "========================================" -ForegroundColor Yellow + } + else + { + # all repos were up to date + } +} + function refresh-submodules { $submodules = git submodule | Out-String diff --git a/update_deps/propagate_updates.ps1 b/update_deps/propagate_updates.ps1 index b6bed2b..5d1885b 100644 --- a/update_deps/propagate_updates.ps1 +++ b/update_deps/propagate_updates.ps1 @@ -254,6 +254,10 @@ function propagate-updates # Show final status and check if all succeeded $success = show-propagation-status -Final + + # Warn about any repos with newer commits that were not propagated + show-skipped-commits-summary + if ($success) { play-success-animation From 68bf73db748af4bd6ee72ef2e539607e76b09502 Mon Sep 17 00:00:00 2001 From: Parth Aggarwal Date: Fri, 20 Feb 2026 18:53:09 -0800 Subject: [PATCH 4/6] Only treat required GitHub checks as blocking for PR success Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- update_deps/helper_scripts/pr_watch_utils.ps1 | 24 +++++++++++-- .../helper_scripts/watch_github_pr.ps1 | 35 +++++++++++++++++++ 2 files changed, 57 insertions(+), 2 deletions(-) diff --git a/update_deps/helper_scripts/pr_watch_utils.ps1 b/update_deps/helper_scripts/pr_watch_utils.ps1 index c2b61ea..cfa3807 100644 --- a/update_deps/helper_scripts/pr_watch_utils.ps1 +++ b/update_deps/helper_scripts/pr_watch_utils.ps1 @@ -339,7 +339,17 @@ function global:show-pr-check-table # Display each check foreach($check in $checks) { - $check_name = truncate-string -text $check.Name -max_width $name_width + $check_name = $check.Name + # Mark optional (non-blocking) checks + if($check.IsBlocking -eq $false) + { + $check_name = $check_name + " (optional)" + } + else + { + # required or unknown blocking status + } + $check_name = truncate-string -text $check_name -max_width $name_width $elapsed = format-elapsed-time -start_time $check.StartTime -finish_time $check.FinishTime $url = truncate-string -text $check.Url -max_width $url_width @@ -347,6 +357,16 @@ function global:show-pr-check-table $symbol = $display.Symbol $color = $display.Color + # Use dimmer color for optional failed checks + if($check.IsBlocking -eq $false -and $check.Status -eq [PrCheckStatus]::Failed) + { + $color = "DarkYellow" + } + else + { + # use default color + } + $line = "{0} {1,-$name_width} {2,-$elapsed_width} {3}" -f $symbol, $check_name, $elapsed, $url Write-Host $line -ForegroundColor $color } @@ -391,7 +411,7 @@ function global:get-check-status-counts # Test if checks are complete # # For Azure DevOps: checks have IsBlocking property, only blocking checks matter -# For GitHub: all checks matter (IsBlocking = $null means treat as blocking) +# For GitHub: uses --required flag to identify required checks (IsBlocking = $false for optional) # function global:Test-ChecksComplete { diff --git a/update_deps/helper_scripts/watch_github_pr.ps1 b/update_deps/helper_scripts/watch_github_pr.ps1 index b4caa1a..c913de7 100644 --- a/update_deps/helper_scripts/watch_github_pr.ps1 +++ b/update_deps/helper_scripts/watch_github_pr.ps1 @@ -176,18 +176,53 @@ function watch-github-pr-checks } else { + # Get list of required check names + $required_names = @{} + $required_output = gh pr checks --required --json name 2>&1 + if($LASTEXITCODE -eq 0 -and $required_output) + { + $required_checks = $required_output | ConvertFrom-Json + if($required_checks) + { + foreach($rc in $required_checks) + { + $required_names[$rc.name] = $true + } + } + else + { + # no required checks parsed + } + } + else + { + # couldn't get required checks, treat all as blocking + } + # Build normalized check items $normalized_checks = @() foreach($check in $checks) { $normalized_status = convert-github-bucket-to-normalized -bucket $check.bucket + # If we got required check info, use it; otherwise leave IsBlocking as $null (all blocking) + $is_blocking = $null + if($required_names.Count -gt 0) + { + $is_blocking = $required_names.ContainsKey($check.name) + } + else + { + # no required info available, default to blocking + } + $normalized_checks += [PSCustomObject]@{ Name = $check.name Status = $normalized_status StartTime = $check.startedAt FinishTime = $check.completedAt Url = $check.link + IsBlocking = $is_blocking } } From 7eb7a28bbf87d1f2eee21a0b9939157ecd852113 Mon Sep 17 00:00:00 2001 From: Parth Aggarwal Date: Fri, 20 Feb 2026 19:07:34 -0800 Subject: [PATCH 5/6] Align snapshot table columns by padding repo names Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- update_deps/helper_scripts/git_operations.ps1 | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/update_deps/helper_scripts/git_operations.ps1 b/update_deps/helper_scripts/git_operations.ps1 index 1a78b95..eb939a0 100644 --- a/update_deps/helper_scripts/git_operations.ps1 +++ b/update_deps/helper_scripts/git_operations.ps1 @@ -32,6 +32,8 @@ function snapshot-repo-commits [string[]] $repo_order ) $commits = @{} + # Calculate max repo name length for aligned output + $max_name_len = ($repo_order | ForEach-Object { $_.Length } | Measure-Object -Maximum).Maximum foreach ($repo_name in $repo_order) { if (Test-Path $repo_name) @@ -41,7 +43,7 @@ function snapshot-repo-commits if ($LASTEXITCODE -eq 0 -and $sha) { $commits[$repo_name] = $sha.Trim() - Write-Host " $repo_name : $($commits[$repo_name].Substring(0, 8))" + Write-Host (" {0,-$max_name_len} : {1}" -f $repo_name, $commits[$repo_name].Substring(0, 8)) } else { From f1ac080c1c7df71d04cc151d8244311f45236f5f Mon Sep 17 00:00:00 2001 From: Parth Aggarwal Date: Fri, 20 Feb 2026 19:16:55 -0800 Subject: [PATCH 6/6] Treat child jobs of required checks as blocking Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../helper_scripts/watch_github_pr.ps1 | 24 ++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/update_deps/helper_scripts/watch_github_pr.ps1 b/update_deps/helper_scripts/watch_github_pr.ps1 index c913de7..928bf62 100644 --- a/update_deps/helper_scripts/watch_github_pr.ps1 +++ b/update_deps/helper_scripts/watch_github_pr.ps1 @@ -209,7 +209,29 @@ function watch-github-pr-checks $is_blocking = $null if($required_names.Count -gt 0) { - $is_blocking = $required_names.ContainsKey($check.name) + # Check exact match first, then check if this is a child job + # of a required pipeline (e.g., "Gate (Build x64)" is a child of "Gate") + if($required_names.ContainsKey($check.name)) + { + $is_blocking = $true + } + else + { + $is_child = $false + foreach($req_name in $required_names.Keys) + { + if($check.name.StartsWith("$req_name ")) + { + $is_child = $true + break + } + else + { + # not a child of this required check + } + } + $is_blocking = $is_child + } } else {