Skip to content

Commit 013cb4f

Browse files
jpnurmiclaude
andauthored
feat: support GIT_TAG with CMake variable (#149)
* feat: support GIT_TAG with CMake variable When GIT_TAG uses a variable like ${FOO_REF}, resolve it to the corresponding set() definition and update that line instead of the FetchContent_Declare block. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * docs: add changelog entry for CMake variable GIT_TAG support Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 5b609b7 commit 013cb4f

File tree

3 files changed

+202
-4
lines changed

3 files changed

+202
-4
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# Changelog
22

3+
## Unreleased
4+
5+
### Features
6+
7+
- Updater - Support CMake `GIT_TAG` with variable references like `${FOO_REF}`, resolving and updating the corresponding `set()` definition ([#149](https://github.com/getsentry/github-workflows/pull/149))
8+
39
## 3.2.1
410

511
### Fixes

updater/scripts/cmake-functions.ps1

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,18 @@ function Parse-CMakeFetchContent {
4444
throw "Could not parse GIT_REPOSITORY or GIT_TAG from FetchContent_Declare block"
4545
}
4646

47-
return @{ GitRepository = $repo; GitTag = $tag; DepName = $depName }
47+
# Resolve CMake variable references like ${FOO_REF}
48+
$gitTagVariable = $null
49+
if ($tag -match '^\$\{(\w+)\}$') {
50+
$gitTagVariable = $Matches[1]
51+
$setMatch = [regex]::Match($content, "(?m)^\s*set\s*\(\s*$gitTagVariable\s+`"?([^`"\s)]+)")
52+
if (-not $setMatch.Success) {
53+
throw "CMake variable '$gitTagVariable' referenced by GIT_TAG not found in $filePath"
54+
}
55+
$tag = $setMatch.Groups[1].Value
56+
}
57+
58+
return @{ GitRepository = $repo; GitTag = $tag; DepName = $depName; GitTagVariable = $gitTagVariable }
4859
}
4960

5061
function Find-TagForHash {
@@ -167,10 +178,20 @@ function Update-CMakeFile {
167178
$replacement = $newValue
168179
}
169180

170-
# Update GIT_TAG value, replacing entire line content after GIT_TAG
181+
# Update the value, replacing entire line content after the value
171182
# This removes potentially outdated version-specific comments
172-
$pattern = "(FetchContent_Declare\s*\(\s*$depName\s+[^)]*GIT_TAG\s+)[^\r\n]+(\r?\n[^)]*\))"
173-
$newContent = [regex]::Replace($content, $pattern, "`${1}$replacement`${2}", 'Singleline')
183+
$gitTagVariable = $fetchContent.GitTagVariable
184+
if ($gitTagVariable) {
185+
# Update the set() line that defines the variable
186+
$pattern = "(?m)(^\s*set\s*\(\s*$gitTagVariable\s+`"?)([^`"\s)]+)(`"?[^)]*\))[^\r\n]*"
187+
$valueOnly = if ($wasHash) { $newHash } else { $newValue }
188+
$trailingComment = if ($wasHash) { " # $newValue" } else { "" }
189+
$newContent = [regex]::Replace($content, $pattern, "`${1}$valueOnly`${3}$trailingComment")
190+
} else {
191+
# Update GIT_TAG value in FetchContent_Declare block
192+
$pattern = "(FetchContent_Declare\s*\(\s*$depName\s+[^)]*GIT_TAG\s+)[^\r\n]+(\r?\n[^)]*\))"
193+
$newContent = [regex]::Replace($content, $pattern, "`${1}$replacement`${2}", 'Singleline')
194+
}
174195

175196
if ($newContent -eq $content) {
176197
throw "Failed to update GIT_TAG in $filePath - pattern may not have matched"

updater/tests/update-dependency-cmake.Tests.ps1

Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,92 @@ FetchContent_MakeAvailable(sentry-native googletest)
147147
}
148148
}
149149

150+
Context 'Variable reference GIT_TAG' {
151+
BeforeAll {
152+
$script:tempDir = "$TestDrive/cmake-tests"
153+
New-Item $tempDir -ItemType Directory -Force | Out-Null
154+
155+
$script:varRefFile = "$tempDir/varref.cmake"
156+
@'
157+
include(FetchContent)
158+
159+
set(SENTRY_NATIVE_REF "v0.9.1" CACHE STRING "The sentry-native ref")
160+
161+
FetchContent_Declare(
162+
sentry-native
163+
GIT_REPOSITORY https://github.com/getsentry/sentry-native
164+
GIT_TAG ${SENTRY_NATIVE_REF}
165+
GIT_SHALLOW FALSE
166+
)
167+
168+
FetchContent_MakeAvailable(sentry-native)
169+
'@ | Out-File $varRefFile
170+
171+
$script:varRefHashFile = "$tempDir/varref-hash.cmake"
172+
@'
173+
include(FetchContent)
174+
175+
set(SENTRY_NATIVE_REF a64d5bd8ee130f2cda196b6fa7d9b65bfa6d32e2) # 0.9.1
176+
177+
FetchContent_Declare(
178+
sentry-native
179+
GIT_REPOSITORY https://github.com/getsentry/sentry-native
180+
GIT_TAG ${SENTRY_NATIVE_REF}
181+
)
182+
183+
FetchContent_MakeAvailable(sentry-native)
184+
'@ | Out-File $varRefHashFile
185+
186+
$script:varRefDirectFile = "$tempDir/varref-direct.cmake"
187+
@'
188+
include(FetchContent)
189+
190+
FetchContent_Declare(
191+
sentry-native
192+
GIT_REPOSITORY https://github.com/getsentry/sentry-native
193+
GIT_TAG v0.9.1
194+
)
195+
'@ | Out-File $varRefDirectFile
196+
197+
$script:varRefMissingFile = "$tempDir/varref-missing.cmake"
198+
@'
199+
include(FetchContent)
200+
201+
FetchContent_Declare(
202+
sentry-native
203+
GIT_REPOSITORY https://github.com/getsentry/sentry-native
204+
GIT_TAG ${UNDEFINED_VAR}
205+
)
206+
'@ | Out-File $varRefMissingFile
207+
}
208+
209+
It 'resolves quoted variable to actual value' {
210+
$result = Parse-CMakeFetchContent $varRefFile 'sentry-native'
211+
212+
$result.GitRepository | Should -Be 'https://github.com/getsentry/sentry-native'
213+
$result.GitTag | Should -Be 'v0.9.1'
214+
$result.GitTagVariable | Should -Be 'SENTRY_NATIVE_REF'
215+
$result.DepName | Should -Be 'sentry-native'
216+
}
217+
218+
It 'resolves unquoted variable with hash value' {
219+
$result = Parse-CMakeFetchContent $varRefHashFile 'sentry-native'
220+
221+
$result.GitTag | Should -Be 'a64d5bd8ee130f2cda196b6fa7d9b65bfa6d32e2'
222+
$result.GitTagVariable | Should -Be 'SENTRY_NATIVE_REF'
223+
}
224+
225+
It 'throws when variable definition is missing' {
226+
{ Parse-CMakeFetchContent $varRefMissingFile 'sentry-native' } | Should -Throw "*CMake variable 'UNDEFINED_VAR' referenced by GIT_TAG not found*"
227+
}
228+
229+
It 'returns null GitTagVariable for direct values' {
230+
$result = Parse-CMakeFetchContent $varRefDirectFile 'sentry-native'
231+
232+
$result.GitTagVariable | Should -BeNullOrEmpty
233+
}
234+
}
235+
150236
Context 'Malformed files' {
151237
BeforeAll {
152238
$script:tempDir = "$TestDrive/cmake-tests"
@@ -342,6 +428,91 @@ FetchContent_MakeAvailable(sentry-native)
342428
}
343429
}
344430

431+
Context 'Variable reference tag updates' {
432+
BeforeAll {
433+
$script:tempDir = "$TestDrive/cmake-update-tests"
434+
New-Item $tempDir -ItemType Directory -Force | Out-Null
435+
436+
$script:varRefTagTemplate = @'
437+
include(FetchContent)
438+
439+
set(SENTRY_NATIVE_REF "v0.9.1" CACHE STRING "The sentry-native ref")
440+
441+
FetchContent_Declare(
442+
sentry-native
443+
GIT_REPOSITORY https://github.com/getsentry/sentry-native
444+
GIT_TAG ${SENTRY_NATIVE_REF}
445+
GIT_SHALLOW FALSE
446+
)
447+
448+
FetchContent_MakeAvailable(sentry-native)
449+
'@
450+
}
451+
452+
BeforeEach {
453+
$script:varRefTagTestFile = "$tempDir/varref-tag-test.cmake"
454+
}
455+
456+
It 'updates set() value and leaves GIT_TAG variable reference untouched' {
457+
$varRefTagTemplate | Out-File $varRefTagTestFile
458+
459+
Update-CMakeFile $varRefTagTestFile 'sentry-native' 'v0.9.2'
460+
461+
$content = Get-Content $varRefTagTestFile -Raw
462+
$content | Should -Match 'set\(SENTRY_NATIVE_REF "v0.9.2"'
463+
$content | Should -Match 'GIT_TAG \$\{SENTRY_NATIVE_REF\}'
464+
$content | Should -Not -Match 'v0.9.1'
465+
}
466+
467+
It 'preserves file structure' {
468+
$varRefTagTemplate | Out-File $varRefTagTestFile
469+
470+
Update-CMakeFile $varRefTagTestFile 'sentry-native' 'v0.9.2'
471+
472+
$content = Get-Content $varRefTagTestFile -Raw
473+
$content | Should -Match 'include\(FetchContent\)'
474+
$content | Should -Match 'FetchContent_MakeAvailable'
475+
$content | Should -Match 'GIT_SHALLOW FALSE'
476+
}
477+
}
478+
479+
Context 'Variable reference hash updates' {
480+
BeforeAll {
481+
$script:tempDir = "$TestDrive/cmake-update-tests"
482+
New-Item $tempDir -ItemType Directory -Force | Out-Null
483+
484+
$script:varRefHashTemplate = @'
485+
include(FetchContent)
486+
487+
set(SENTRY_NATIVE_REF a64d5bd8ee130f2cda196b6fa7d9b65bfa6d32e2) # 0.9.1
488+
489+
FetchContent_Declare(
490+
sentry-native
491+
GIT_REPOSITORY https://github.com/getsentry/sentry-native
492+
GIT_TAG ${SENTRY_NATIVE_REF}
493+
)
494+
495+
FetchContent_MakeAvailable(sentry-native)
496+
'@
497+
}
498+
499+
BeforeEach {
500+
$script:varRefHashTestFile = "$tempDir/varref-hash-test.cmake"
501+
}
502+
503+
It 'updates set() value with new hash and comment' {
504+
$varRefHashTemplate | Out-File $varRefHashTestFile
505+
506+
Update-CMakeFile $varRefHashTestFile 'sentry-native' '0.11.0'
507+
508+
$content = Get-Content $varRefHashTestFile -Raw
509+
$content | Should -Match 'set\(SENTRY_NATIVE_REF 3bd091313ae97be90be62696a2babe591a988eb8\) # 0.11.0'
510+
$content | Should -Match 'GIT_TAG \$\{SENTRY_NATIVE_REF\}'
511+
$content | Should -Not -Match 'a64d5bd8ee130f2cda196b6fa7d9b65bfa6d32e2'
512+
$content | Should -Not -Match '# 0.9.1'
513+
}
514+
}
515+
345516
# Note: Hash update tests require network access for git ls-remote
346517
# and are better suited for integration tests
347518
}

0 commit comments

Comments
 (0)