diff --git a/README.md b/README.md index b149c54..16655b6 100644 --- a/README.md +++ b/README.md @@ -46,11 +46,20 @@ jobs: name: Gradle Plugin secrets: api-token: ${{ secrets.CI_DEPLOY_KEY }} + + # Update a CMake file with FetchContent_Declare + cmake-dep: + uses: getsentry/github-workflows/.github/workflows/updater.yml@v2 + with: + path: cmake/dependencies.cmake + name: CMake Dependency + secrets: + api-token: ${{ secrets.CI_DEPLOY_KEY }} ``` ### Inputs -* `path`: Dependency path in the source repository, this can be either a submodule, a .properties file or a shell script. +* `path`: Dependency path in the source repository, this can be either a submodule, a .properties file, a CMake file, or a shell script. * type: string * required: true * `name`: Name used in the PR title and the changelog entry. diff --git a/updater/scripts/update-dependency.ps1 b/updater/scripts/update-dependency.ps1 index c9af07b..44769e1 100644 --- a/updater/scripts/update-dependency.ps1 +++ b/updater/scripts/update-dependency.ps1 @@ -2,6 +2,7 @@ param( # Path to the dependency, which can be either of the following: # - a submodule # - a [.properties](https://en.wikipedia.org/wiki/.properties) file with `version` (e.g. 1.0.0) and `repo` (e.g. https://github.com/getsentry/dependency) + # - a CMake file (.cmake, CMakeLists.txt) or any file containing FetchContent_Declare with `GIT_REPOSITORY` and `GIT_TAG` # - a script (.sh, .ps1) that takes the executes a given action based on a given argument: # * `get-version` - return the currently specified dependency version # * `get-repo` - return the repository url (e.g. https://github.com/getsentry/dependency) @@ -39,6 +40,7 @@ function SetOutput([string] $name, $value) if (-not $isSubmodule) { $isScript = $Path -match '\.(ps1|sh)$' + $isCMake = $Path -match '\.(cmake|txt)$' -or ((Test-Path $Path -PathType Leaf) -and $Path -notmatch '\.(ps1|sh)$' -and ((Get-Content $Path -Raw -ErrorAction SilentlyContinue) -match 'FetchContent_Declare')) function DependencyConfig ([Parameter(Mandatory = $true)][string] $action, [string] $value = $null) { if ($isScript) @@ -67,6 +69,72 @@ if (-not $isSubmodule) } return $result } + elseif ($isCMake) + { + switch ($action) + { + 'get-version' + { + $content = Get-Content $Path -Raw + if ($content -match '(?m)^\s*GIT_TAG\s+(?:"([^"]+)"|([^\s#]+))') + { + if ($Matches[1]) { + return $Matches[1] + } else { + return $Matches[2] + } + } + throw "Could not find GIT_TAG in CMake file $Path" + } + 'get-repo' + { + $content = Get-Content $Path -Raw + if ($content -match '(?m)^\s*GIT_REPOSITORY\s+([^\s]+)') + { + return $Matches[1] + } + throw "Could not find GIT_REPOSITORY in CMake file $Path" + } + 'set-version' + { + $content = Get-Content $Path + $updated = $false + for ($i = 0; $i -lt $content.Length; $i++) + { + if ($content[$i] -match '^(\s*GIT_TAG\s+)(")([^"]+)(".*)$') + { + # Quoted version - preserve quotes + $content[$i] = $Matches[1] + $Matches[2] + $value + $Matches[4] + $updated = $true + break + } + elseif ($content[$i] -match '^(\s*GIT_TAG\s+)([^\s#]+)(.*)$') + { + # Unquoted version + $content[$i] = $Matches[1] + $value + $Matches[3] + $updated = $true + break + } + } + if (-not $updated) + { + throw "Could not find GIT_TAG line to update in CMake file $Path" + } + $content | Out-File $Path + + # Verify the update worked + $readVersion = DependencyConfig 'get-version' + if ("$readVersion" -ne "$value") + { + throw "Update failed - read-after-write yielded '$readVersion' instead of expected '$value'" + } + } + Default + { + throw "Unknown action $action" + } + } + } else { switch ($action) diff --git a/updater/tests/update-dependency.Tests.ps1 b/updater/tests/update-dependency.Tests.ps1 index 3d1c9fe..030862f 100644 --- a/updater/tests/update-dependency.Tests.ps1 +++ b/updater/tests/update-dependency.Tests.ps1 @@ -247,4 +247,118 @@ switch ($action) } } } + + Context 'cmake-file' { + It 'works with FetchContent_Declare' { + $testFile = "$testDir/test.cmake" + @( + 'FetchContent_Declare(', + ' sentry-native', + " GIT_REPOSITORY $repoUrl", + ' GIT_TAG none # 0.9.1', + ' GIT_SHALLOW FALSE', + ' GIT_SUBMODULES "external/breakpad"', + ')' + ) | Out-File $testFile + UpdateDependency $testFile + $content = Get-Content $testFile + $content[3] | Should -Match "GIT_TAG $currentVersion" + $content[3] | Should -Match '# 0.9.1' # Comment should be preserved + } + + It 'works with CMakeLists.txt' { + $testFile = "$testDir/CMakeLists.txt" + @( + 'cmake_minimum_required(VERSION 3.10)', + 'FetchContent_Declare(', + ' some-dependency', + " GIT_REPOSITORY $repoUrl", + ' GIT_TAG v0.0.1', + ')' + ) | Out-File $testFile + UpdateDependency $testFile + $content = Get-Content $testFile + $content[4] | Should -Match "GIT_TAG $currentVersion" + } + + It 'handles indented GIT_TAG' { + $testFile = "$testDir/test.cmake" + @( + 'FetchContent_Declare(dependency', + " GIT_REPOSITORY $repoUrl", + ' GIT_TAG old_version', + ')' + ) | Out-File $testFile + UpdateDependency $testFile + $content = Get-Content $testFile + $content[2] | Should -Match "^\s+GIT_TAG $currentVersion" + } + + It 'version pattern match' { + $testFile = "$testDir/test.cmake" + $repo = 'https://github.com/getsentry/sentry-cli' + @( + 'FetchContent_Declare(', + ' sentry-cli', + " GIT_REPOSITORY $repo", + ' GIT_TAG 0.1.0', + ')' + ) | Out-File $testFile + UpdateDependency $testFile '^0\.' + $content = Get-Content $testFile + $content[3] | Should -Match 'GIT_TAG 0.28.0' + } + + It 'fails when GIT_TAG is missing' { + $testFile = "$testDir/test.cmake" + @( + 'FetchContent_Declare(', + ' dependency', + " GIT_REPOSITORY $repoUrl", + ')' + ) | Out-File $testFile + { UpdateDependency $testFile } | Should -Throw '*Could not find GIT_TAG*' + } + + It 'fails when GIT_REPOSITORY is missing' { + $testFile = "$testDir/test.cmake" + @( + 'FetchContent_Declare(', + ' dependency', + ' GIT_TAG v1.0.0', + ')' + ) | Out-File $testFile + { UpdateDependency $testFile } | Should -Throw '*Could not find GIT_REPOSITORY*' + } + + It 'detects FetchContent_Declare in any file' { + $testFile = "$testDir/dependency.txt" + @( + 'Some text before', + 'FetchContent_Declare(', + ' dependency', + " GIT_REPOSITORY $repoUrl", + ' GIT_TAG v0.0.1', + ')', + 'Some text after' + ) | Out-File $testFile + UpdateDependency $testFile + $content = Get-Content $testFile + $content[4] | Should -Match "GIT_TAG $currentVersion" + } + + It 'handles quoted GIT_TAG values' { + $testFile = "$testDir/test.cmake" + @( + 'FetchContent_Declare(', + ' dependency', + " GIT_REPOSITORY $repoUrl", + ' GIT_TAG "v0.0.1"', + ')' + ) | Out-File $testFile + UpdateDependency $testFile + $content = Get-Content $testFile + $content[3] | Should -Match "GIT_TAG `"$currentVersion`"" + } + } }