Skip to content

Commit 3182dd4

Browse files
vaindclaude
andauthored
feat(updater): Add post-update-script support (#130)
Add support for running custom scripts after dependency updates to enable additional repository modifications before PR creation. Changes: - Add `post-update-script` input parameter to action.yml - Update update-dependency.ps1 to accept PostUpdateScript parameter - Scripts receive original and new version as arguments - Support both bash (.sh) and PowerShell (.ps1) scripts - Add comprehensive unit tests for post-update script functionality - Update README with usage examples for both script types The post-update script is executed after the dependency is updated but before the PR is created, allowing users to make additional changes such as updating lock files, running code generators, or modifying related configuration files. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude <[email protected]>
1 parent 15e4b10 commit 3182dd4

File tree

5 files changed

+221
-4
lines changed

5 files changed

+221
-4
lines changed

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,13 @@
22

33
## Unreleased
44

5+
### Features
6+
7+
- Updater - Add `post-update-script` input parameter to run custom scripts after dependency updates ([#130](https://github.com/getsentry/github-workflows/pull/130))
8+
- Scripts receive original and new version as arguments
9+
- Support both bash (`.sh`) and PowerShell (`.ps1`) scripts
10+
- Enables workflows like updating lock files, running code generators, or modifying configuration files
11+
512
### Fixes
613

714
- Updater - Fix boolean input handling for `changelog-entry` parameter and add input validation ([#127](https://github.com/getsentry/github-workflows/pull/127))

updater/README.md

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,18 @@ jobs:
9595
target-branch: v7
9696
pattern: '^1\.' # Limit to major version '1'
9797
api-token: ${{ secrets.CI_DEPLOY_KEY }}
98+
99+
# Use a post-update script (sh or ps1) to make additional changes after dependency update
100+
# The script receives two arguments: original version and new version
101+
post-update-script:
102+
runs-on: ubuntu-latest
103+
steps:
104+
- uses: getsentry/github-workflows/updater@v3
105+
with:
106+
path: modules/sentry-cocoa
107+
name: Cocoa SDK
108+
post-update-script: scripts/post-update.sh # Receives args: $1=old version, $2=new version
109+
api-token: ${{ secrets.CI_DEPLOY_KEY }}
98110
```
99111
100112
## Inputs
@@ -135,12 +147,45 @@ jobs:
135147
* type: string
136148
* required: false
137149
* default: '' (uses repository default branch)
150+
* `post-update-script`: Optional script to run after successful dependency update. Can be a bash script (`.sh`) or PowerShell script (`.ps1`). The script will be executed in the repository root directory before PR creation. The script receives two arguments:
151+
* `$1` / `$args[0]` - The original version (version before update)
152+
* `$2` / `$args[1]` - The new version (version after update)
153+
* type: string
154+
* required: false
155+
* default: ''
138156
* `api-token`: Token for the repo. Can be passed in using `${{ secrets.GITHUB_TOKEN }}`.
139157
If you provide the usual `${{ github.token }}`, no followup CI will run on the created PR.
140158
If you want CI to run on the PRs created by the Updater, you need to provide custom user-specific auth token.
141159
* type: string
142160
* required: true
143161

162+
### Post-Update Script Example
163+
164+
**Bash script** (`scripts/post-update.sh`):
165+
166+
```bash
167+
#!/usr/bin/env bash
168+
set -euo pipefail
169+
170+
ORIGINAL_VERSION="$1"
171+
NEW_VERSION="$2"
172+
173+
echo "Updated from $ORIGINAL_VERSION to $NEW_VERSION"
174+
# Make additional changes to repository files here
175+
```
176+
177+
**PowerShell script** (`scripts/post-update.ps1`):
178+
179+
```powershell
180+
param(
181+
[Parameter(Mandatory = $true)][string] $OriginalVersion,
182+
[Parameter(Mandatory = $true)][string] $NewVersion
183+
)
184+
185+
Write-Output "Updated from $OriginalVersion to $NewVersion"
186+
# Make additional changes to repository files here
187+
```
188+
144189
## Outputs
145190

146191
* `prUrl`: The created/updated PR's URL.

updater/action.yml

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@ inputs:
3636
api-token:
3737
description: 'Token for the repo. Can be passed in using {{ secrets.GITHUB_TOKEN }}'
3838
required: true
39+
post-update-script:
40+
description: 'Optional script to run after successful dependency update. Can be a bash script (.sh) or PowerShell script (.ps1). The script will be executed in the caller-repo directory before PR creation.'
41+
required: false
42+
default: ''
3943

4044
outputs:
4145
prUrl:
@@ -102,6 +106,17 @@ runs:
102106
}
103107
Write-Output "✓ PR strategy value '${{ inputs.pr-strategy }}' is valid"
104108
109+
- name: Validate post-update-script
110+
if: ${{ inputs.post-update-script != '' }}
111+
shell: pwsh
112+
run: |
113+
# Validate that inputs.post-update-script contains only safe characters
114+
if ('${{ inputs.post-update-script }}' -notmatch '^[a-zA-Z0-9_\./#\s-]+$') {
115+
Write-Output "::error::Invalid post-update-script path: '${{ inputs.post-update-script }}'. Only alphanumeric characters, spaces, and _-./# are allowed."
116+
exit 1
117+
}
118+
Write-Output "✓ Post-update script path '${{ inputs.post-update-script }}' is valid"
119+
105120
# What we need to accomplish:
106121
# * update to the latest tag
107122
# * create a PR
@@ -134,8 +149,9 @@ runs:
134149
DEPENDENCY_PATH: ${{ inputs.path }}
135150
DEPENDENCY_PATTERN: ${{ inputs.pattern }}
136151
GH_TITLE_PATTERN: ${{ inputs.gh-title-pattern }}
152+
POST_UPDATE_SCRIPT: ${{ inputs.post-update-script }}
137153
GH_TOKEN: ${{ inputs.api-token }}
138-
run: ${{ github.action_path }}/scripts/update-dependency.ps1 -Path $env:DEPENDENCY_PATH -Pattern $env:DEPENDENCY_PATTERN -GhTitlePattern $env:GH_TITLE_PATTERN
154+
run: ${{ github.action_path }}/scripts/update-dependency.ps1 -Path $env:DEPENDENCY_PATH -Pattern $env:DEPENDENCY_PATTERN -GhTitlePattern $env:GH_TITLE_PATTERN -PostUpdateScript $env:POST_UPDATE_SCRIPT
139155

140156
- name: Get the base repo info
141157
if: steps.target.outputs.latestTag != steps.target.outputs.originalTag
@@ -270,8 +286,9 @@ runs:
270286
working-directory: caller-repo
271287
env:
272288
DEPENDENCY_PATH: ${{ inputs.path }}
289+
POST_UPDATE_SCRIPT: ${{ inputs.post-update-script }}
273290
GH_TOKEN: ${{ inputs.api-token }}
274-
run: ${{ github.action_path }}/scripts/update-dependency.ps1 -Path $env:DEPENDENCY_PATH -Tag '${{ steps.target.outputs.latestTag }}'
291+
run: ${{ github.action_path }}/scripts/update-dependency.ps1 -Path $env:DEPENDENCY_PATH -Tag '${{ steps.target.outputs.latestTag }}' -PostUpdateScript $env:POST_UPDATE_SCRIPT
275292

276293
- name: Update Changelog
277294
if: ${{ inputs.changelog-entry == 'true' && ( steps.target.outputs.latestTag != steps.target.outputs.originalTag ) && ( steps.root.outputs.changed == 'false') }}

updater/scripts/update-dependency.ps1

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,10 @@ param(
1515
# RegEx pattern to match against GitHub release titles. Only releases with matching titles will be considered
1616
[string] $GhTitlePattern = '',
1717
# Specific version - if passed, no discovery is performed and the version is set directly
18-
[string] $Tag = ''
18+
[string] $Tag = '',
19+
# Optional post-update script to run after successful dependency update
20+
# The script receives the original and new version as arguments
21+
[string] $PostUpdateScript = ''
1922
)
2023

2124
$ErrorActionPreference = 'Stop'
@@ -249,6 +252,9 @@ if ("$Tag" -eq '') {
249252
$Tag = $latestTag
250253
}
251254

255+
$originalTagForPostUpdate = if ($originalTag) { $originalTag } else { '' }
256+
$newTagForPostUpdate = $Tag
257+
252258
if ($isSubmodule) {
253259
Write-Host "Updating submodule $Path to $Tag"
254260
Push-Location $Path
@@ -258,3 +264,25 @@ if ($isSubmodule) {
258264
Write-Host "Updating 'version' in $Path to $Tag"
259265
DependencyConfig 'set-version' $tag
260266
}
267+
268+
# Run post-update script if provided
269+
if ("$PostUpdateScript" -ne '') {
270+
Write-Host "Running post-update script: $PostUpdateScript"
271+
if (-not (Test-Path $PostUpdateScript)) {
272+
throw "Post-update script not found: $PostUpdateScript"
273+
}
274+
275+
if (Get-Command 'chmod' -ErrorAction SilentlyContinue) {
276+
chmod +x $PostUpdateScript
277+
if ($LastExitCode -ne 0) {
278+
throw 'chmod failed';
279+
}
280+
}
281+
282+
& $PostUpdateScript "$originalTag" "$tag"
283+
if ($LastExitCode -ne 0) {
284+
throw "Post-update script failed with exit code $LastExitCode"
285+
}
286+
287+
Write-Host '✓ Post-update script completed successfully'
288+
}

updater/tests/update-dependency.Tests.ps1

Lines changed: 121 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
BeforeAll {
2-
function UpdateDependency([Parameter(Mandatory = $true)][string] $path, [string] $pattern = $null, [string] $ghTitlePattern = $null)
2+
function UpdateDependency([Parameter(Mandatory = $true)][string] $path, [string] $pattern = $null, [string] $ghTitlePattern = $null, [string] $postUpdateScript = $null)
33
{
44
$params = @{ Path = $path }
55
if ($pattern) { $params.Pattern = $pattern }
66
if ($ghTitlePattern) { $params.GhTitlePattern = $ghTitlePattern }
7+
if ($postUpdateScript) { $params.PostUpdateScript = $postUpdateScript }
78

89
$result = & "$PSScriptRoot/../scripts/update-dependency.ps1" @params
910
if (-not $?)
@@ -488,4 +489,123 @@ FetchContent_Declare(
488489
$version | Should -Match '^8\.'
489490
}
490491
}
492+
493+
Context 'post-update-script' {
494+
It 'runs PowerShell post-update script with version arguments' {
495+
$testFile = "$testDir/test.properties"
496+
$repo = 'https://github.com/getsentry/sentry-cli'
497+
@("repo=$repo", 'version=0') | Out-File $testFile
498+
499+
$postUpdateScript = "$testDir/post-update-test.ps1"
500+
$markerFile = "$testDir/post-update-marker.txt"
501+
@'
502+
param([string] $originalVersion, [string] $newVersion)
503+
"$originalVersion|$newVersion" | Out-File
504+
'@ + " '$markerFile'" | Out-File $postUpdateScript
505+
506+
UpdateDependency $testFile '^0\.' -postUpdateScript $postUpdateScript
507+
508+
# Verify post-update script was executed
509+
Test-Path $markerFile | Should -Be $true
510+
$markerContent = Get-Content $markerFile
511+
$markerContent | Should -Match '^0\|0\.28\.0$'
512+
513+
# Clean up
514+
Remove-Item $markerFile -ErrorAction SilentlyContinue
515+
Remove-Item $postUpdateScript -ErrorAction SilentlyContinue
516+
}
517+
518+
It 'runs bash post-update script with version arguments' -Skip:$IsWindows {
519+
$testFile = "$testDir/test.properties"
520+
$repo = 'https://github.com/getsentry/sentry-cli'
521+
@("repo=$repo", 'version=0') | Out-File $testFile
522+
523+
$postUpdateScript = "$testDir/post-update-test.sh"
524+
$markerFile = "$testDir/post-update-marker.txt"
525+
@"
526+
#!/usr/bin/env bash
527+
set -euo pipefail
528+
echo "`$1|`$2" > '$markerFile'
529+
"@ | Out-File $postUpdateScript
530+
531+
UpdateDependency $testFile '^0\.' -postUpdateScript $postUpdateScript
532+
533+
# Verify post-update script was executed
534+
Test-Path $markerFile | Should -Be $true
535+
$markerContent = Get-Content $markerFile
536+
$markerContent | Should -Match '^0\|0\.28\.0$'
537+
538+
# Clean up
539+
Remove-Item $markerFile -ErrorAction SilentlyContinue
540+
Remove-Item $postUpdateScript -ErrorAction SilentlyContinue
541+
}
542+
543+
It 'fails when post-update script does not exist' {
544+
$testFile = "$testDir/test.properties"
545+
$repo = 'https://github.com/getsentry/sentry-cli'
546+
@("repo=$repo", 'version=0') | Out-File $testFile
547+
548+
$postUpdateScript = "$testDir/nonexistent-script.ps1"
549+
550+
{ UpdateDependency $testFile '^0\.' -postUpdateScript $postUpdateScript } | Should -Throw '*Post-update script not found*'
551+
}
552+
553+
It 'fails when PowerShell post-update script exits with error' {
554+
$testFile = "$testDir/test.properties"
555+
$repo = 'https://github.com/getsentry/sentry-cli'
556+
@("repo=$repo", 'version=0') | Out-File $testFile
557+
558+
$postUpdateScript = "$testDir/failing-post-update.ps1"
559+
@'
560+
param([string] $originalVersion, [string] $newVersion)
561+
throw "Post-update script failed intentionally"
562+
'@ | Out-File $postUpdateScript
563+
564+
{ UpdateDependency $testFile '^0\.' -postUpdateScript $postUpdateScript } | Should -Throw '*Post-update script failed*'
565+
566+
# Clean up
567+
Remove-Item $postUpdateScript -ErrorAction SilentlyContinue
568+
}
569+
570+
It 'fails when bash post-update script exits with error' -Skip:$IsWindows {
571+
$testFile = "$testDir/test.properties"
572+
$repo = 'https://github.com/getsentry/sentry-cli'
573+
@("repo=$repo", 'version=0') | Out-File $testFile
574+
575+
$postUpdateScript = "$testDir/failing-post-update.sh"
576+
@'
577+
#!/usr/bin/env bash
578+
exit 1
579+
'@ | Out-File $postUpdateScript
580+
581+
{ UpdateDependency $testFile '^0\.' -postUpdateScript $postUpdateScript } | Should -Throw '*Post-update script failed*'
582+
583+
# Clean up
584+
Remove-Item $postUpdateScript -ErrorAction SilentlyContinue
585+
}
586+
587+
It 'receives empty string for original version when updating from scratch' {
588+
$testFile = "$testDir/test.properties"
589+
$repo = 'https://github.com/getsentry/sentry-cli'
590+
@("repo=$repo", 'version=') | Out-File $testFile
591+
592+
$postUpdateScript = "$testDir/post-update-empty-original.ps1"
593+
$markerFile = "$testDir/post-update-marker-empty.txt"
594+
@'
595+
param([string] $originalVersion, [string] $newVersion)
596+
"original=[$originalVersion]|new=[$newVersion]" | Out-File
597+
'@ + " '$markerFile'" | Out-File $postUpdateScript
598+
599+
UpdateDependency $testFile '^0\.' -postUpdateScript $postUpdateScript
600+
601+
# Verify post-update script received empty original version
602+
Test-Path $markerFile | Should -Be $true
603+
$markerContent = Get-Content $markerFile
604+
$markerContent | Should -Match 'original=\[\]\|new=\[0\.28\.0\]'
605+
606+
# Clean up
607+
Remove-Item $markerFile -ErrorAction SilentlyContinue
608+
Remove-Item $postUpdateScript -ErrorAction SilentlyContinue
609+
}
610+
}
491611
}

0 commit comments

Comments
 (0)