From eaa7ed7c18d343dc7db26c9f6ba448b123f2132b Mon Sep 17 00:00:00 2001 From: Ivan Dlugos Date: Wed, 24 Sep 2025 07:47:32 +0200 Subject: [PATCH 01/12] feat: add gh-title-pattern input for release channel filtering MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implements Issue #85 by adding a new `gh-title-pattern` input parameter that allows filtering releases by GitHub release titles using regex patterns. Features: - Filter releases by title patterns (e.g., '\(Stable\)$' for stable releases) - Uses GitHub API to fetch release metadata - Fully backward compatible when parameter is not specified - Comprehensive test coverage with error handling Usage example: ```yaml uses: getsentry/github-workflows/updater@v3 with: path: modules/sentry-cocoa name: Cocoa SDK (Stable) gh-title-pattern: '\(Stable\)$' ``` 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- updater/README.md | 15 +++++ updater/action.yml | 7 ++- updater/scripts/update-dependency.ps1 | 71 +++++++++++++++++++++++ updater/tests/update-dependency.Tests.ps1 | 53 ++++++++++++++++- 4 files changed, 143 insertions(+), 3 deletions(-) diff --git a/updater/README.md b/updater/README.md index ca5db31f..9c517ea6 100644 --- a/updater/README.md +++ b/updater/README.md @@ -32,6 +32,17 @@ jobs: pattern: '^1\.' # Limit to major version '1' api-token: ${{ secrets.CI_DEPLOY_KEY }} + # Update to stable releases only by filtering GitHub release titles + cocoa-stable: + runs-on: ubuntu-latest + steps: + - uses: getsentry/github-workflows/updater@v3 + with: + path: modules/sentry-cocoa + name: Cocoa SDK (Stable) + gh-title-pattern: '\(Stable\)$' # Only releases with "(Stable)" suffix + api-token: ${{ secrets.CI_DEPLOY_KEY }} + # Update a properties file cli: runs-on: ubuntu-latest @@ -91,6 +102,10 @@ jobs: * type: string * required: false * default: '' +* `gh-title-pattern`: RegEx pattern to match against GitHub release titles. Only releases with matching titles will be considered. Useful for filtering to specific release channels (e.g., stable releases). + * type: string + * required: false + * default: '' * `changelog-entry`: Whether to add a changelog entry for the update. * type: boolean * required: false diff --git a/updater/action.yml b/updater/action.yml index a40a9f9f..3abe270e 100644 --- a/updater/action.yml +++ b/updater/action.yml @@ -13,6 +13,10 @@ inputs: description: 'RegEx pattern that will be matched against available versions when picking the latest one.' required: false default: '' + gh-title-pattern: + description: 'RegEx pattern to match against GitHub release titles. Only releases with matching titles will be considered.' + required: false + default: '' changelog-entry: description: 'Whether to add a changelog entry for the update.' required: false @@ -107,7 +111,8 @@ runs: env: DEPENDENCY_PATH: ${{ inputs.path }} DEPENDENCY_PATTERN: ${{ inputs.pattern }} - run: ${{ github.action_path }}/scripts/update-dependency.ps1 -Path $env:DEPENDENCY_PATH -Pattern $env:DEPENDENCY_PATTERN + GH_TITLE_PATTERN: ${{ inputs.gh-title-pattern }} + run: ${{ github.action_path }}/scripts/update-dependency.ps1 -Path $env:DEPENDENCY_PATH -Pattern $env:DEPENDENCY_PATTERN -GhTitlePattern $env:GH_TITLE_PATTERN - name: Get the base repo info if: steps.target.outputs.latestTag != steps.target.outputs.originalTag diff --git a/updater/scripts/update-dependency.ps1 b/updater/scripts/update-dependency.ps1 index 89c9fc18..1d6be3aa 100644 --- a/updater/scripts/update-dependency.ps1 +++ b/updater/scripts/update-dependency.ps1 @@ -12,6 +12,8 @@ param( [Parameter(Mandatory = $true)][string] $Path, # RegEx pattern that will be matched against available versions when picking the latest one [string] $Pattern = '', + # RegEx pattern to match against GitHub release titles. Only releases with matching titles will be considered + [string] $GhTitlePattern = '', # Specific version - if passed, no discovery is performed and the version is set directly [string] $Tag = '' ) @@ -188,6 +190,75 @@ if ("$Tag" -eq '') $url = $url -replace '\.git$', '' + # Filter by GitHub release titles if pattern is provided + if ("$GhTitlePattern" -ne '') + { + Write-Host "Filtering tags by GitHub release title pattern '$GhTitlePattern'" + + # Check if URL is a GitHub URL first + if ($url -notmatch 'github\.com') + { + throw "Could not parse GitHub owner/repo from URL: $url" + } + + # Parse GitHub repo owner/name from URL + if ($url -match 'github\.com[:/]([^/]+)/([^/]+?)(?:\.git)?$') + { + $owner = $Matches[1] + $repo = $Matches[2] + + try + { + # Fetch all releases from GitHub API + $releases = gh api "repos/$owner/$repo/releases" --paginate --jq '.[] | {tag_name: .tag_name, name: .name}' | ConvertFrom-Json + + # Handle case where releases might be null or single object + if ($null -eq $releases) + { + $releases = @() + } + elseif ($releases -isnot [array]) + { + $releases = @($releases) + } + + # Create a hashtable of tag->title mappings for releases that match the pattern + $validTags = @{} + foreach ($release in $releases) + { + if ($release.name -match $GhTitlePattern) + { + $validTags[$release.tag_name] = $true + } + } + + # Filter tags to only include those with matching release titles + $originalTagCount = $tags.Length + $tags = @($tags | Where-Object { $validTags.ContainsKey($_) }) + Write-Host "GitHub release title filtering: $originalTagCount -> $($tags.Count) tags" + + if ($tags.Count -le 0) + { + throw "Found no tags with GitHub releases matching title pattern '$GhTitlePattern'" + } + } + catch + { + # If it's our specific "no matching tags" error, re-throw it + if ($_.Exception.Message -like "*Found no tags with GitHub releases matching title pattern*") + { + throw + } + # Otherwise, wrap it as a GitHub API error + throw "Failed to fetch GitHub releases for $owner/$repo`: $($_.Exception.Message)" + } + } + else + { + throw "Could not parse GitHub owner/repo from URL: $url" + } + } + if ("$Pattern" -eq '') { # Use a default pattern that excludes pre-releases diff --git a/updater/tests/update-dependency.Tests.ps1 b/updater/tests/update-dependency.Tests.ps1 index 1437fbae..90c4c630 100644 --- a/updater/tests/update-dependency.Tests.ps1 +++ b/updater/tests/update-dependency.Tests.ps1 @@ -1,7 +1,11 @@ BeforeAll { - function UpdateDependency([Parameter(Mandatory = $true)][string] $path, [string] $pattern = $null) + function UpdateDependency([Parameter(Mandatory = $true)][string] $path, [string] $pattern = $null, [string] $ghTitlePattern = $null) { - $result = & "$PSScriptRoot/../scripts/update-dependency.ps1" -Path $path -Pattern $pattern + $params = @{ Path = $path } + if ($pattern) { $params.Pattern = $pattern } + if ($ghTitlePattern) { $params.GhTitlePattern = $ghTitlePattern } + + $result = & "$PSScriptRoot/../scripts/update-dependency.ps1" @params if (-not $?) { throw $result @@ -426,4 +430,49 @@ FetchContent_Declare( { UpdateDependency "$testFile#nonexistent" } | Should -Throw "*FetchContent_Declare for 'nonexistent' not found*" } } + + Context 'gh-title-pattern' { + It 'filters by GitHub release title pattern' { + $testFile = "$testDir/test.properties" + # Use sentry-cocoa repo which has releases with "(Stable)" suffix + $repo = 'https://github.com/getsentry/sentry-cocoa' + @("repo=$repo", 'version=0') | Out-File $testFile + + # Test filtering for releases with "(Stable)" suffix + UpdateDependency $testFile '' '\(Stable\)$' + + $content = Get-Content $testFile + $version = ($content | Where-Object { $_ -match '^version\s*=\s*(.+)$' }) -replace '^version\s*=\s*', '' + + # Verify that a version was selected (should be a stable release) + $version | Should -Not -Be '0' + $version | Should -Match '^\d+\.\d+\.\d+$' + } + + It 'throws error when no releases match title pattern' { + $testFile = "$testDir/test.properties" + # Use a smaller repo that's less likely to timeout + $repo = 'https://github.com/getsentry/github-workflows' + @("repo=$repo", 'version=0') | Out-File $testFile + + # Use a pattern that should match no releases + { UpdateDependency $testFile '' 'NonExistentPattern' } | Should -Throw '*Found no tags with GitHub releases matching title pattern*' + } + + It 'works without title pattern (backward compatibility)' { + $testFile = "$testDir/test.properties" + $repo = 'https://github.com/getsentry/sentry-cocoa' + @("repo=$repo", 'version=0') | Out-File $testFile + + # Test without title pattern should work as before + UpdateDependency $testFile '^8\.' + + $content = Get-Content $testFile + $version = ($content | Where-Object { $_ -match '^version\s*=\s*(.+)$' }) -replace '^version\s*=\s*', '' + + # Should get a version starting with 8 + $version | Should -Match '^8\.' + } + + } } From 1510bc292648598648ba07263f784d7fd027d835 Mon Sep 17 00:00:00 2001 From: Ivan Dlugos Date: Wed, 24 Sep 2025 07:52:12 +0200 Subject: [PATCH 02/12] fix: remove --paginate flag from GitHub API call MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The --paginate flag returns separate pages, not combined results. Using the default API call (first 30 releases) is sufficient for most repositories when filtering by release title patterns. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- updater/scripts/update-dependency.ps1 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/updater/scripts/update-dependency.ps1 b/updater/scripts/update-dependency.ps1 index 1d6be3aa..08ace9a9 100644 --- a/updater/scripts/update-dependency.ps1 +++ b/updater/scripts/update-dependency.ps1 @@ -209,8 +209,8 @@ if ("$Tag" -eq '') try { - # Fetch all releases from GitHub API - $releases = gh api "repos/$owner/$repo/releases" --paginate --jq '.[] | {tag_name: .tag_name, name: .name}' | ConvertFrom-Json + # Fetch releases from GitHub API (first 30 releases should be sufficient for most cases) + $releases = gh api "repos/$owner/$repo/releases" --jq '.[] | {tag_name: .tag_name, name: .name}' | ConvertFrom-Json # Handle case where releases might be null or single object if ($null -eq $releases) From 4a2197bddbbca693857b76b5aded285e326019ba Mon Sep 17 00:00:00 2001 From: Ivan Dlugos Date: Wed, 24 Sep 2025 07:54:43 +0200 Subject: [PATCH 03/12] refactor: clean up GitHub release filtering code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Simplify the implementation with: - Consolidated URL validation with single regex match - Cleaner variable assignment using tuple unpacking - Simplified array handling by wrapping API result in @() - Removed unnecessary null/single object checks - More concise comments and clearer logic flow 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- updater/scripts/update-dependency.ps1 | 71 ++++++++++----------------- 1 file changed, 25 insertions(+), 46 deletions(-) diff --git a/updater/scripts/update-dependency.ps1 b/updater/scripts/update-dependency.ps1 index 08ace9a9..dcae0cf0 100644 --- a/updater/scripts/update-dependency.ps1 +++ b/updater/scripts/update-dependency.ps1 @@ -195,67 +195,46 @@ if ("$Tag" -eq '') { Write-Host "Filtering tags by GitHub release title pattern '$GhTitlePattern'" - # Check if URL is a GitHub URL first - if ($url -notmatch 'github\.com') + # Parse GitHub repo owner/name from URL + if ($url -notmatch 'github\.com[:/]([^/]+)/([^/]+?)(?:\.git)?$') { throw "Could not parse GitHub owner/repo from URL: $url" } - # Parse GitHub repo owner/name from URL - if ($url -match 'github\.com[:/]([^/]+)/([^/]+?)(?:\.git)?$') + $owner, $repo = $Matches[1], $Matches[2] + + try { - $owner = $Matches[1] - $repo = $Matches[2] + # Fetch releases from GitHub API + $releases = @(gh api "repos/$owner/$repo/releases" --jq '.[] | {tag_name: .tag_name, name: .name}' | ConvertFrom-Json) - try + # Find tags that have matching release titles + $validTags = @{} + foreach ($release in $releases) { - # Fetch releases from GitHub API (first 30 releases should be sufficient for most cases) - $releases = gh api "repos/$owner/$repo/releases" --jq '.[] | {tag_name: .tag_name, name: .name}' | ConvertFrom-Json - - # Handle case where releases might be null or single object - if ($null -eq $releases) + if ($release.name -match $GhTitlePattern) { - $releases = @() - } - elseif ($releases -isnot [array]) - { - $releases = @($releases) - } - - # Create a hashtable of tag->title mappings for releases that match the pattern - $validTags = @{} - foreach ($release in $releases) - { - if ($release.name -match $GhTitlePattern) - { - $validTags[$release.tag_name] = $true - } + $validTags[$release.tag_name] = $true } + } - # Filter tags to only include those with matching release titles - $originalTagCount = $tags.Length - $tags = @($tags | Where-Object { $validTags.ContainsKey($_) }) - Write-Host "GitHub release title filtering: $originalTagCount -> $($tags.Count) tags" + # Filter tags to only include those with matching release titles + $originalTagCount = $tags.Length + $tags = @($tags | Where-Object { $validTags.ContainsKey($_) }) + Write-Host "GitHub release title filtering: $originalTagCount -> $($tags.Count) tags" - if ($tags.Count -le 0) - { - throw "Found no tags with GitHub releases matching title pattern '$GhTitlePattern'" - } - } - catch + if ($tags.Count -eq 0) { - # If it's our specific "no matching tags" error, re-throw it - if ($_.Exception.Message -like "*Found no tags with GitHub releases matching title pattern*") - { - throw - } - # Otherwise, wrap it as a GitHub API error - throw "Failed to fetch GitHub releases for $owner/$repo`: $($_.Exception.Message)" + throw "Found no tags with GitHub releases matching title pattern '$GhTitlePattern'" } } - else + catch { - throw "Could not parse GitHub owner/repo from URL: $url" + if ($_.Exception.Message -like "*Found no tags with GitHub releases matching title pattern*") + { + throw + } + throw "Failed to fetch GitHub releases for $owner/$repo`: $($_.Exception.Message)" } } From ec043ac004a1a91d4e10d3ffc2254a3a3a4fa286 Mon Sep 17 00:00:00 2001 From: Ivan Dlugos Date: Wed, 24 Sep 2025 08:10:27 +0200 Subject: [PATCH 04/12] refactor: streamline conditional checks and improve code readability in update-dependency.ps1 --- updater/scripts/update-dependency.ps1 | 159 ++++++++------------------ 1 file changed, 49 insertions(+), 110 deletions(-) diff --git a/updater/scripts/update-dependency.ps1 b/updater/scripts/update-dependency.ps1 index dcae0cf0..8e641979 100644 --- a/updater/scripts/update-dependency.ps1 +++ b/updater/scripts/update-dependency.ps1 @@ -39,31 +39,24 @@ if ($Path -match '^(.+\.cmake)(#(.+))?$') { $isCMakeFile = $false } -if (-not (Test-Path $Path )) -{ +if (-not (Test-Path $Path )) { throw "Dependency $Path doesn't exit"; } # If it's a directory, we consider it a submodule dependendency. Otherwise, it must a properties-style file or a script. $isSubmodule = (Test-Path $Path -PathType Container) -function SetOutput([string] $name, $value) -{ - if (Test-Path env:GITHUB_OUTPUT) - { +function SetOutput([string] $name, $value) { + if (Test-Path env:GITHUB_OUTPUT) { "$name=$value" | Tee-Object $env:GITHUB_OUTPUT -Append - } - else - { + } else { "$name=$value" } } -if (-not $isSubmodule) -{ +if (-not $isSubmodule) { $isScript = $Path -match '\.(ps1|sh)$' - function DependencyConfig ([Parameter(Mandatory = $true)][string] $action, [string] $value = $null) - { + function DependencyConfig ([Parameter(Mandatory = $true)][string] $action, [string] $value = $null) { if ($isCMakeFile) { # CMake file handling switch ($action) { @@ -84,64 +77,48 @@ if (-not $isSubmodule) 'set-version' { Update-CMakeFile $Path $cmakeDep $value } - Default { + default { throw "Unknown action $action" } } - } - elseif ($isScript) - { - if (Get-Command 'chmod' -ErrorAction SilentlyContinue) - { + } elseif ($isScript) { + if (Get-Command 'chmod' -ErrorAction SilentlyContinue) { chmod +x $Path - if ($LastExitCode -ne 0) - { + if ($LastExitCode -ne 0) { throw 'chmod failed'; } } - try - { + try { $result = & $Path $action $value $failed = -not $? - } - catch - { + } catch { $result = $_ $failed = $true } - if ($failed) - { + if ($failed) { throw "Script execution failed: $Path $action $value | output: $result" } return $result - } - else - { - switch ($action) - { - 'get-version' - { + } else { + switch ($action) { + 'get-version' { return (Get-Content $Path -Raw | ConvertFrom-StringData).version } - 'get-repo' - { + 'get-repo' { return (Get-Content $Path -Raw | ConvertFrom-StringData).repo } - 'set-version' - { + 'set-version' { $content = Get-Content $Path $content = $content -replace '^(?version *= *).*$', "`${prop}$value" $content | Out-File $Path $readVersion = (Get-Content $Path -Raw | ConvertFrom-StringData).version - if ("$readVersion" -ne "$value") - { + if ("$readVersion" -ne "$value") { throw "Update failed - read-after-write yielded '$readVersion' instead of expected '$value'" } } - Default - { + default { throw "Unknown action $action" } } @@ -152,27 +129,20 @@ if (-not $isSubmodule) . "$PSScriptRoot/cmake-functions.ps1" } -if ("$Tag" -eq '') -{ - if ($isSubmodule) - { +if ("$Tag" -eq '') { + if ($isSubmodule) { git submodule update --init --no-fetch --single-branch $Path Push-Location $Path - try - { + try { $originalTag = $(git describe --tags) git fetch --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 - } - finally - { + } finally { Pop-Location } - } - else - { + } else { $originalTag = DependencyConfig 'get-version' $url = DependencyConfig 'get-repo' @@ -181,8 +151,7 @@ if ("$Tag" -eq '') $tags = $tags | ForEach-Object { ($_ -split '\s+')[1] -replace '^refs/tags/', '' } $headRef = ($(git ls-remote $url HEAD) -split '\s+')[0] - if ("$headRef" -eq '') - { + if ("$headRef" -eq '') { throw "Couldn't determine repository head (no ref returned by ls-remote HEAD" } $mainBranch = (git ls-remote --heads $url | Where-Object { $_.StartsWith($headRef) }) -replace '.*\srefs/heads/', '' @@ -191,55 +160,34 @@ if ("$Tag" -eq '') $url = $url -replace '\.git$', '' # Filter by GitHub release titles if pattern is provided - if ("$GhTitlePattern" -ne '') - { + if ("$GhTitlePattern" -ne '') { Write-Host "Filtering tags by GitHub release title pattern '$GhTitlePattern'" # Parse GitHub repo owner/name from URL - if ($url -notmatch 'github\.com[:/]([^/]+)/([^/]+?)(?:\.git)?$') - { + if ($url -notmatch 'github\.com[:/]([^/]+)/([^/]+?)(?:\.git)?$') { throw "Could not parse GitHub owner/repo from URL: $url" } $owner, $repo = $Matches[1], $Matches[2] - try - { - # Fetch releases from GitHub API - $releases = @(gh api "repos/$owner/$repo/releases" --jq '.[] | {tag_name: .tag_name, name: .name}' | ConvertFrom-Json) - - # Find tags that have matching release titles - $validTags = @{} - foreach ($release in $releases) - { - if ($release.name -match $GhTitlePattern) - { - $validTags[$release.tag_name] = $true - } - } - - # Filter tags to only include those with matching release titles - $originalTagCount = $tags.Length - $tags = @($tags | Where-Object { $validTags.ContainsKey($_) }) - Write-Host "GitHub release title filtering: $originalTagCount -> $($tags.Count) tags" + # Fetch releases from GitHub API + $releases = @(gh api "repos/$owner/$repo/releases" --jq '.[] | {tag_name: .tag_name, name: .name}' | ConvertFrom-Json) - if ($tags.Count -eq 0) - { - throw "Found no tags with GitHub releases matching title pattern '$GhTitlePattern'" + # Find tags that have matching release titles + $validTags = @{} + foreach ($release in $releases) { + if ($release.name -match $GhTitlePattern) { + $validTags[$release.tag_name] = $true } } - catch - { - if ($_.Exception.Message -like "*Found no tags with GitHub releases matching title pattern*") - { - throw - } - throw "Failed to fetch GitHub releases for $owner/$repo`: $($_.Exception.Message)" - } + + # Filter tags to only include those with matching release titles + $originalTagCount = $tags.Length + $tags = @($tags | Where-Object { $validTags.ContainsKey($_) }) + Write-Host "GitHub release title filtering: $originalTagCount -> $($tags.Count) tags" } - if ("$Pattern" -eq '') - { + if ("$Pattern" -eq '') { # Use a default pattern that excludes pre-releases $Pattern = '^v?([0-9.]+)$' } @@ -247,8 +195,7 @@ if ("$Tag" -eq '') Write-Host "Filtering tags with pattern '$Pattern'" $tags = $tags -match $Pattern - if ($tags.Length -le 0) - { + if ($tags.Length -le 0) { throw "Found no tags matching pattern '$Pattern'" } @@ -257,14 +204,11 @@ if ("$Tag" -eq '') Write-Host "Sorted tags: $tags" $latestTag = $tags[-1] - if (("$originalTag" -ne '') -and ("$latestTag" -ne '') -and ("$latestTag" -ne "$originalTag")) - { - do - { + if (("$originalTag" -ne '') -and ("$latestTag" -ne '') -and ("$latestTag" -ne "$originalTag")) { + do { # It's possible that the dependency was updated to a pre-release version manually in which case we don't want to # roll back, even though it's not the latest version matching the configured pattern. - if ((GetComparableVersion $originalTag) -ge (GetComparableVersion $latestTag)) - { + if ((GetComparableVersion $originalTag) -ge (GetComparableVersion $latestTag)) { Write-Host "SemVer represented by the original tag '$originalTag' is newer than the latest tag '$latestTag'. Skipping update." $latestTag = $originalTag break @@ -274,8 +218,7 @@ if ("$Tag" -eq '') $refs = $(git ls-remote --tags $url) $refOriginal = (($refs -match "refs/tags/$originalTag" ) -split '[ \t]') | Select-Object -First 1 $refLatest = (($refs -match "refs/tags/$latestTag" ) -split '[ \t]') | Select-Object -First 1 - if ($refOriginal -eq $refLatest) - { + if ($refOriginal -eq $refLatest) { Write-Host "Latest tag '$latestTag' points to the same commit as the original tag '$originalTag'. Skipping update." $latestTag = $originalTag break @@ -291,23 +234,19 @@ if ("$Tag" -eq '') SetOutput 'url' $url SetOutput 'mainBranch' $mainBranch - if ("$originalTag" -eq "$latestTag") - { + if ("$originalTag" -eq "$latestTag") { return } $Tag = $latestTag } -if ($isSubmodule) -{ +if ($isSubmodule) { Write-Host "Updating submodule $Path to $Tag" Push-Location $Path git checkout $Tag Pop-Location -} -else -{ +} else { Write-Host "Updating 'version' in $Path to $Tag" DependencyConfig 'set-version' $tag } From 4d09c548341e208bc2558280edcc7c966dc05687 Mon Sep 17 00:00:00 2001 From: Ivan Dlugos Date: Wed, 24 Sep 2025 08:11:42 +0200 Subject: [PATCH 05/12] refactor: remove unnecessary comment in update-dependency.Tests.ps1 --- updater/tests/update-dependency.Tests.ps1 | 2 -- 1 file changed, 2 deletions(-) diff --git a/updater/tests/update-dependency.Tests.ps1 b/updater/tests/update-dependency.Tests.ps1 index 90c4c630..923486ae 100644 --- a/updater/tests/update-dependency.Tests.ps1 +++ b/updater/tests/update-dependency.Tests.ps1 @@ -451,7 +451,6 @@ FetchContent_Declare( It 'throws error when no releases match title pattern' { $testFile = "$testDir/test.properties" - # Use a smaller repo that's less likely to timeout $repo = 'https://github.com/getsentry/github-workflows' @("repo=$repo", 'version=0') | Out-File $testFile @@ -473,6 +472,5 @@ FetchContent_Declare( # Should get a version starting with 8 $version | Should -Match '^8\.' } - } } From 139d57a06031c6bb735465e729f6c6addd6f6abc Mon Sep 17 00:00:00 2001 From: Ivan Dlugos Date: Wed, 24 Sep 2025 08:17:32 +0200 Subject: [PATCH 06/12] test: add deterministic test case for specific version matching MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add test that matches exact release version (2.11.1) by title pattern - This provides a deterministic test case that verifies exact behavior - Fix error handling to ensure proper error message when no releases match - All 4 gh-title-pattern tests now pass 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- updater/scripts/update-dependency.ps1 | 4 ++++ updater/tests/update-dependency.Tests.ps1 | 15 +++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/updater/scripts/update-dependency.ps1 b/updater/scripts/update-dependency.ps1 index 8e641979..05640537 100644 --- a/updater/scripts/update-dependency.ps1 +++ b/updater/scripts/update-dependency.ps1 @@ -185,6 +185,10 @@ if ("$Tag" -eq '') { $originalTagCount = $tags.Length $tags = @($tags | Where-Object { $validTags.ContainsKey($_) }) Write-Host "GitHub release title filtering: $originalTagCount -> $($tags.Count) tags" + + if ($tags.Count -eq 0) { + throw "Found no tags with GitHub releases matching title pattern '$GhTitlePattern'" + } } if ("$Pattern" -eq '') { diff --git a/updater/tests/update-dependency.Tests.ps1 b/updater/tests/update-dependency.Tests.ps1 index 923486ae..6b77a426 100644 --- a/updater/tests/update-dependency.Tests.ps1 +++ b/updater/tests/update-dependency.Tests.ps1 @@ -458,6 +458,21 @@ FetchContent_Declare( { UpdateDependency $testFile '' 'NonExistentPattern' } | Should -Throw '*Found no tags with GitHub releases matching title pattern*' } + It 'matches specific release version by exact title pattern' { + $testFile = "$testDir/test.properties" + $repo = 'https://github.com/getsentry/github-workflows' + @("repo=$repo", 'version=0') | Out-File $testFile + + # Target a specific known release by exact title match + UpdateDependency $testFile '' '^2\.11\.1$' + + $content = Get-Content $testFile + $version = ($content | Where-Object { $_ -match '^version\s*=\s*(.+)$' }) -replace '^version\s*=\s*', '' + + # Should get exactly version 2.11.1 (with or without 'v' prefix) + $version | Should -Match '^v?2\.11\.1$' + } + It 'works without title pattern (backward compatibility)' { $testFile = "$testDir/test.properties" $repo = 'https://github.com/getsentry/sentry-cocoa' From e45f92939449175f3fb9ed53bd969b446a4df562 Mon Sep 17 00:00:00 2001 From: Ivan Dlugos Date: Wed, 24 Sep 2025 08:20:40 +0200 Subject: [PATCH 07/12] docs: add changelog entry for GitHub release title pattern filtering MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Documents the new gh-title-pattern feature that allows users to filter releases by their GitHub release titles using regex patterns. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 15b130e3..08bba3d0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -44,6 +44,7 @@ To update your existing Danger workflows: ### Features +- Updater now supports filtering releases by GitHub release title patterns ([#117](https://github.com/getsentry/github-workflows/pull/117)) - Updater now supports dependencies without changelog files by falling back to git commit messages ([#116](https://github.com/getsentry/github-workflows/pull/116)) - Danger - Improve conventional commit scope handling, and non-conventional PR title support ([#105](https://github.com/getsentry/github-workflows/pull/105)) - Add Proguard artifact endpoint for Android builds in sentry-server ([#100](https://github.com/getsentry/github-workflows/pull/100)) From e7c37fe6bd00f87fb926c4b6f3d97f13f35d6986 Mon Sep 17 00:00:00 2001 From: Ivan Dlugos Date: Wed, 24 Sep 2025 08:41:08 +0200 Subject: [PATCH 08/12] fix: set GH_TOKEN env var for GitHub CLI in CI MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ensures that gh api commands work properly in CI environments by setting the GH_TOKEN environment variable to the provided api-token input. This fixes the issue where GitHub release title filtering would fail silently in CI due to lack of authentication. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- updater/action.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/updater/action.yml b/updater/action.yml index 3abe270e..bfc30234 100644 --- a/updater/action.yml +++ b/updater/action.yml @@ -112,6 +112,7 @@ runs: DEPENDENCY_PATH: ${{ inputs.path }} DEPENDENCY_PATTERN: ${{ inputs.pattern }} GH_TITLE_PATTERN: ${{ inputs.gh-title-pattern }} + GH_TOKEN: ${{ inputs.api-token }} run: ${{ github.action_path }}/scripts/update-dependency.ps1 -Path $env:DEPENDENCY_PATH -Pattern $env:DEPENDENCY_PATTERN -GhTitlePattern $env:GH_TITLE_PATTERN - name: Get the base repo info From 85607c6847fc67f3867c1ee005476f87f0b7d3c9 Mon Sep 17 00:00:00 2001 From: Ivan Dlugos Date: Wed, 24 Sep 2025 08:46:29 +0200 Subject: [PATCH 09/12] fix: pass GH_TOKEN environment variable to scripts for authentication --- updater/action.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/updater/action.yml b/updater/action.yml index bfc30234..b3f21ad5 100644 --- a/updater/action.yml +++ b/updater/action.yml @@ -170,6 +170,8 @@ runs: - name: Get target changelog if: ${{ ( steps.target.outputs.latestTag != steps.target.outputs.originalTag ) && ( steps.root.outputs.changed == 'false') }} shell: pwsh + env: + GH_TOKEN: ${{ inputs.api-token }} run: | $changelog = ${{ github.action_path }}/scripts/get-changelog.ps1 ` -RepoUrl '${{ steps.target.outputs.url }}' ` @@ -229,6 +231,7 @@ runs: shell: pwsh env: DEPENDENCY_PATH: ${{ inputs.path }} + GH_TOKEN: ${{ inputs.api-token }} run: ${{ github.action_path }}/scripts/update-dependency.ps1 -Path $env:DEPENDENCY_PATH -Tag '${{ steps.target.outputs.latestTag }}' - name: Update Changelog @@ -237,6 +240,7 @@ runs: env: DEPENDENCY_NAME: ${{ inputs.name }} CHANGELOG_SECTION: ${{ inputs.changelog-section }} + GH_TOKEN: ${{ inputs.api-token }} run: | ${{ github.action_path }}/scripts/update-changelog.ps1 ` -Name $env:DEPENDENCY_NAME ` From cb12e1ea2de16b1385e7b5ed4905fe1efc5548e3 Mon Sep 17 00:00:00 2001 From: Ivan Dlugos Date: Wed, 24 Sep 2025 08:49:43 +0200 Subject: [PATCH 10/12] docs: clarify changelog entry for GitHub release title pattern filtering --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 08bba3d0..01f9f752 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -44,7 +44,7 @@ To update your existing Danger workflows: ### Features -- Updater now supports filtering releases by GitHub release title patterns ([#117](https://github.com/getsentry/github-workflows/pull/117)) +- Updater now supports filtering releases by GitHub release title patterns, e.g. to support release channels ([#117](https://github.com/getsentry/github-workflows/pull/117)) - Updater now supports dependencies without changelog files by falling back to git commit messages ([#116](https://github.com/getsentry/github-workflows/pull/116)) - Danger - Improve conventional commit scope handling, and non-conventional PR title support ([#105](https://github.com/getsentry/github-workflows/pull/105)) - Add Proguard artifact endpoint for Android builds in sentry-server ([#100](https://github.com/getsentry/github-workflows/pull/100)) From 1a4e26b2a284077605c2231e5979baf357d6dbe4 Mon Sep 17 00:00:00 2001 From: Ivan Dlugos Date: Wed, 24 Sep 2025 09:06:04 +0200 Subject: [PATCH 11/12] fix: set GH_TOKEN environment variable for Invoke-Pester step in CI --- .github/workflows/script-tests.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/script-tests.yml b/.github/workflows/script-tests.yml index 1c32d38d..2b79699f 100644 --- a/.github/workflows/script-tests.yml +++ b/.github/workflows/script-tests.yml @@ -25,6 +25,8 @@ jobs: - run: Invoke-Pester working-directory: updater shell: pwsh + env: + GH_TOKEN: ${{ github.token }} danger: name: Danger JS Tests From 3275e8c44670d4f4db5cb9de7816c473cab62f7d Mon Sep 17 00:00:00 2001 From: Ivan Dlugos Date: Wed, 24 Sep 2025 09:39:56 +0200 Subject: [PATCH 12/12] fix: enhance error handling for GitHub releases fetching in update-dependency script --- updater/scripts/update-dependency.ps1 | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/updater/scripts/update-dependency.ps1 b/updater/scripts/update-dependency.ps1 index 05640537..c8258581 100644 --- a/updater/scripts/update-dependency.ps1 +++ b/updater/scripts/update-dependency.ps1 @@ -18,6 +18,7 @@ param( [string] $Tag = '' ) +$ErrorActionPreference = 'Stop' Set-StrictMode -Version latest . "$PSScriptRoot/common.ps1" @@ -171,7 +172,10 @@ if ("$Tag" -eq '') { $owner, $repo = $Matches[1], $Matches[2] # Fetch releases from GitHub API - $releases = @(gh api "repos/$owner/$repo/releases" --jq '.[] | {tag_name: .tag_name, name: .name}' | ConvertFrom-Json) + $releases = @(gh api "repos/$owner/$repo/releases" --paginate --jq '.[] | {tag_name: .tag_name, name: .name}' | ConvertFrom-Json) + if ($LASTEXITCODE -ne 0) { + throw "Failed to fetch GitHub releases from $owner/$repo (exit code: $LASTEXITCODE)" + } # Find tags that have matching release titles $validTags = @{}