From baa2f627e9a0c27eb9c9c3c2edde07915c0b60d2 Mon Sep 17 00:00:00 2001 From: Serhii Snitsaruk Date: Mon, 9 Nov 2026 12:37:32 +0100 Subject: [PATCH 1/3] fix(updater): Fetch missing submodule release commits --- CHANGELOG.md | 2 + updater/scripts/update-dependency.ps1 | 10 +++- updater/tests/submodule-checkout.Tests.ps1 | 57 ++++++++++++++++++++++ 3 files changed, 67 insertions(+), 2 deletions(-) create mode 100644 updater/tests/submodule-checkout.Tests.ps1 diff --git a/CHANGELOG.md b/CHANGELOG.md index 8f9391a..95b9f1c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,8 @@ ### Fixes +- Updater - Fetch pinned submodule commits outside the default branch and stop on initialization or tag-fetch failures ([#185](https://github.com/getsentry/github-workflows/issues/185)). + - Validate PR - Skip PRs opened by bots of GitHub Apps owned by Sentry (the `getsentry` organization or the `sentry` enterprise), such as `sentry-junior[bot]`. App bot users are never repo collaborators, so the write-access check couldn't recognize them. ([#179](https://github.com/getsentry/github-workflows/pull/179)) - Updater - Support prefixed release tags, such as `cli@1.2.3`, via a `version` named group in `pattern`. ([#184](https://github.com/getsentry/github-workflows/pull/184)) diff --git a/updater/scripts/update-dependency.ps1 b/updater/scripts/update-dependency.ps1 index 1ffb948..f5cef79 100644 --- a/updater/scripts/update-dependency.ps1 +++ b/updater/scripts/update-dependency.ps1 @@ -140,11 +140,17 @@ if ("$Tag" -eq '') { $OriginalTag | Should -Be '' if ($isSubmodule) { - git submodule update --init --no-fetch --single-branch $Path + git submodule update --init --single-branch $Path + if ($LASTEXITCODE -ne 0) { + throw "Failed to initialize submodule '$Path' (exit code: $LASTEXITCODE)" + } Push-Location $Path try { - $originalTag = $(git describe --tags) git fetch --tags + if ($LASTEXITCODE -ne 0) { + throw "Failed to fetch tags for submodule '$Path' (exit code: $LASTEXITCODE)" + } + $originalTag = $(git describe --tags) [string[]]$tags = $(git tag --list) $url = $(git remote get-url origin) $mainBranch = $(git remote show origin | Select-String 'HEAD branch: (.*)').Matches[0].Groups[1].Value diff --git a/updater/tests/submodule-checkout.Tests.ps1 b/updater/tests/submodule-checkout.Tests.ps1 new file mode 100644 index 0000000..2fc2f20 --- /dev/null +++ b/updater/tests/submodule-checkout.Tests.ps1 @@ -0,0 +1,57 @@ +BeforeAll { + $script:updater = "$PSScriptRoot/../scripts/update-dependency.ps1" + $script:previousProtocols = $env:GIT_ALLOW_PROTOCOL + $env:GIT_ALLOW_PROTOCOL = 'file' +} + +AfterAll { $env:GIT_ALLOW_PROTOCOL = $script:previousProtocols } + +Describe 'Submodule initialization' { + BeforeEach { + $script:caseDir = Join-Path $TestDrive ([guid]::NewGuid()) + $script:remote = "$caseDir/remote" + git init --quiet --initial-branch=main $remote + git -C $remote config user.name 'Updater tests' + git -C $remote config user.email 'updater@example.invalid' + git -C $remote -c commit.gpgsign=false commit --quiet --allow-empty -m base + git -C $remote tag 1.0.0 + git -C $remote checkout --quiet -b release + git -C $remote -c commit.gpgsign=false commit --quiet --allow-empty -m release + git -C $remote tag 1.1.0 + $script:pin = git -C $remote rev-parse HEAD + git -C $remote checkout --quiet main + git -C $remote -c commit.gpgsign=false commit --quiet --allow-empty -m development + git init --quiet "$caseDir/caller" + Push-Location "$caseDir/caller" + $remoteUrl = ([uri]::new((Resolve-Path $remote).ProviderPath)).AbsoluteUri + git config -f .gitmodules submodule.dependency.path dependency + git config -f .gitmodules submodule.dependency.url $remoteUrl + git add .gitmodules + git update-index --add --cacheinfo "160000,$pin,dependency" + New-Item dependency -ItemType Directory | Out-Null + if ($LASTEXITCODE -ne 0) { throw 'Could not create Git fixture' } + } + + AfterEach { Pop-Location } + + It 'recognizes an already pinned release outside the default branch' { + $output = & $updater -Path dependency + $output | Should -Contain 'originalTag=1.1.0' + $output | Should -Contain 'latestTag=1.1.0' + git -C dependency rev-parse HEAD | Should -Be $pin + git diff --exit-code -- dependency + $LASTEXITCODE | Should -Be 0 + } + + It 'stops when the pinned commit cannot be checked out' { + git update-index --cacheinfo '160000,1111111111111111111111111111111111111111,dependency' + { & $updater -Path dependency } | Should -Throw '*Failed to initialize submodule*' + } + + It 'stops when fetching tags fails' { + git submodule update --init --single-branch dependency + $LASTEXITCODE | Should -Be 0 + git -C dependency remote set-url origin "$caseDir/missing" + { & $updater -Path dependency } | Should -Throw '*Failed to fetch tags*' + } +} From cd58a562118ea6fae9bff4d53402a967cc9587b7 Mon Sep 17 00:00:00 2001 From: Ivan Dlugos Date: Tue, 10 Nov 2026 20:25:43 +0100 Subject: [PATCH 2/3] docs(changelog): Link the updater submodule fix to its PR Co-Authored-By: Claude Opus 5.5 --- CHANGELOG.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 95b9f1c..64c2b39 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,8 +8,7 @@ ### Fixes -- Updater - Fetch pinned submodule commits outside the default branch and stop on initialization or tag-fetch failures ([#185](https://github.com/getsentry/github-workflows/issues/185)). - +- Updater - Fetch pinned submodule commits outside the default branch and stop on initialization or tag-fetch failures. ([#186](https://github.com/getsentry/github-workflows/pull/186)) - Validate PR - Skip PRs opened by bots of GitHub Apps owned by Sentry (the `getsentry` organization or the `sentry` enterprise), such as `sentry-junior[bot]`. App bot users are never repo collaborators, so the write-access check couldn't recognize them. ([#179](https://github.com/getsentry/github-workflows/pull/179)) - Updater - Support prefixed release tags, such as `cli@1.2.3`, via a `version` named group in `pattern`. ([#184](https://github.com/getsentry/github-workflows/pull/184)) From ea84c7a05fe06cdbbf0f6d7093daa69af1e5b4f1 Mon Sep 17 00:00:00 2001 From: Ivan Dlugos Date: Tue, 10 Nov 2026 20:34:07 +0100 Subject: [PATCH 3/3] test(updater): Fail submodule fixture setup on the first Git error Fixture Git failures were unchecked, and popping the location after a failed setup hid the real error. Co-Authored-By: Claude Opus 5.5 --- updater/tests/submodule-checkout.Tests.ps1 | 43 +++++++++++++--------- 1 file changed, 25 insertions(+), 18 deletions(-) diff --git a/updater/tests/submodule-checkout.Tests.ps1 b/updater/tests/submodule-checkout.Tests.ps1 index 2fc2f20..ad694a9 100644 --- a/updater/tests/submodule-checkout.Tests.ps1 +++ b/updater/tests/submodule-checkout.Tests.ps1 @@ -2,37 +2,44 @@ BeforeAll { $script:updater = "$PSScriptRoot/../scripts/update-dependency.ps1" $script:previousProtocols = $env:GIT_ALLOW_PROTOCOL $env:GIT_ALLOW_PROTOCOL = 'file' + + function script:Invoke-FixtureGit { + git @args + if ($LASTEXITCODE -ne 0) { throw "Could not create Git fixture: 'git $args' exited with $LASTEXITCODE" } + } } AfterAll { $env:GIT_ALLOW_PROTOCOL = $script:previousProtocols } Describe 'Submodule initialization' { BeforeEach { + $script:pushedLocation = $false $script:caseDir = Join-Path $TestDrive ([guid]::NewGuid()) $script:remote = "$caseDir/remote" - git init --quiet --initial-branch=main $remote - git -C $remote config user.name 'Updater tests' - git -C $remote config user.email 'updater@example.invalid' - git -C $remote -c commit.gpgsign=false commit --quiet --allow-empty -m base - git -C $remote tag 1.0.0 - git -C $remote checkout --quiet -b release - git -C $remote -c commit.gpgsign=false commit --quiet --allow-empty -m release - git -C $remote tag 1.1.0 - $script:pin = git -C $remote rev-parse HEAD - git -C $remote checkout --quiet main - git -C $remote -c commit.gpgsign=false commit --quiet --allow-empty -m development - git init --quiet "$caseDir/caller" + Invoke-FixtureGit init --quiet --initial-branch=main $remote + Invoke-FixtureGit -C $remote config user.name 'Updater tests' + Invoke-FixtureGit -C $remote config user.email 'updater@example.invalid' + Invoke-FixtureGit -C $remote -c commit.gpgsign=false commit --quiet --allow-empty -m base + Invoke-FixtureGit -C $remote tag 1.0.0 + Invoke-FixtureGit -C $remote checkout --quiet -b release + Invoke-FixtureGit -C $remote -c commit.gpgsign=false commit --quiet --allow-empty -m release + Invoke-FixtureGit -C $remote tag 1.1.0 + $script:pin = Invoke-FixtureGit -C $remote rev-parse HEAD + Invoke-FixtureGit -C $remote checkout --quiet main + Invoke-FixtureGit -C $remote -c commit.gpgsign=false commit --quiet --allow-empty -m development + Invoke-FixtureGit init --quiet "$caseDir/caller" Push-Location "$caseDir/caller" + $script:pushedLocation = $true $remoteUrl = ([uri]::new((Resolve-Path $remote).ProviderPath)).AbsoluteUri - git config -f .gitmodules submodule.dependency.path dependency - git config -f .gitmodules submodule.dependency.url $remoteUrl - git add .gitmodules - git update-index --add --cacheinfo "160000,$pin,dependency" + Invoke-FixtureGit config -f .gitmodules submodule.dependency.path dependency + Invoke-FixtureGit config -f .gitmodules submodule.dependency.url $remoteUrl + Invoke-FixtureGit add .gitmodules + Invoke-FixtureGit update-index --add --cacheinfo "160000,$pin,dependency" New-Item dependency -ItemType Directory | Out-Null - if ($LASTEXITCODE -ne 0) { throw 'Could not create Git fixture' } } - AfterEach { Pop-Location } + # Popping without a matching push would hide the setup failure behind a stack error. + AfterEach { if ($script:pushedLocation) { Pop-Location } } It 'recognizes an already pinned release outside the default branch' { $output = & $updater -Path dependency