Skip to content

Commit ebbfeec

Browse files
🚀 [Feature]: Add PR-based release name and notes options (#58)
The publish action now supports using your pull request title and description to create more meaningful GitHub releases, giving you control over how your module releases appear to users. - Relates to PSModule/Process-PSModule#263 ## New action inputs Three new inputs are available in the action: | Input | Default | Description | |-------|---------|-------------| | `UsePRTitleAsReleaseName` | `false` | Uses the pull request title as the name for the GitHub release | | `UsePRBodyAsReleaseNotes` | `true` | Uses the pull request body as the release notes content | | `UsePRTitleAsNotesHeading` | `true` | Prepends PR title as H1 heading with PR number link in release notes | ## Default behavior With default settings, when a module is published: 1. The release name uses the version tag (e.g., `v1.2.3`) 2. The release notes include the PR title as a heading with a link to the PR 3. The PR description follows as the release notes body 4. Falls back to GitHub's auto-generated notes if the PR description is empty ## Implementation details The release creation logic in [scripts/helpers/Publish-PSModule.ps1](scripts/helpers/Publish-PSModule.ps1) now dynamically builds the `gh release create` command based on the configuration: - Adds `--title` with PR title when `UsePRTitleAsReleaseName` is enabled - Adds `--notes` with formatted content when PR body is available - Falls back to `--generate-notes` when no PR content is available ## Linting improvements - Disabled `BIOME_FORMAT` validation via `.github/PSModule.yml` - Added `persist-credentials: false` to all checkout steps - Added `groups` configuration to dependabot for cooldown compliance - Added `zizmor: ignore` comments for intentional patterns (dangerous-triggers, unpinned external actions) --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
1 parent 6c25d13 commit ebbfeec

6 files changed

Lines changed: 106 additions & 37 deletions

File tree

.github/dependabot.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,6 @@ updates:
1111
- dependencies
1212
- github-actions
1313
schedule:
14-
interval: weekly
14+
interval: daily
15+
cooldown:
16+
default-days: 7

.github/workflows/Action-Test.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,9 @@ jobs:
2222
runs-on: ubuntu-latest
2323
steps:
2424
- name: Checkout repo
25-
uses: actions/checkout@v6
25+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
26+
with:
27+
persist-credentials: false
2628

2729
- name: Action-Test
2830
uses: ./

.github/workflows/Auto-Release.yml

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ name: Auto-Release
33
run-name: "Auto-Release - [${{ github.event.pull_request.title }} #${{ github.event.pull_request.number }}] by @${{ github.actor }}"
44

55
on:
6-
pull_request_target:
6+
pull_request:
77
branches:
88
- main
99
types:
@@ -26,9 +26,11 @@ jobs:
2626
runs-on: ubuntu-latest
2727
steps:
2828
- name: Checkout Code
29-
uses: actions/checkout@v6
29+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
30+
with:
31+
persist-credentials: false
3032

3133
- name: Auto-Release
32-
uses: PSModule/Auto-Release@v1
34+
uses: PSModule/Auto-Release@eabd533035e2cb9822160f26f2eda584bd012356 # v1.9.5
3335
with:
3436
IncrementalPrerelease: false

.github/workflows/Linter.yml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,16 @@ jobs:
1919
runs-on: ubuntu-latest
2020
steps:
2121
- name: Checkout repo
22-
uses: actions/checkout@v6
22+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
2323
with:
2424
fetch-depth: 0
25+
persist-credentials: false
2526

2627
- name: Lint code base
27-
uses: super-linter/super-linter@latest
28+
uses: super-linter/super-linter@d5b0a2ab116623730dd094f15ddc1b6b25bf7b99 # v8.3.2
2829
env:
2930
GITHUB_TOKEN: ${{ github.token }}
31+
VALIDATE_BIOME_FORMAT: false
3032
VALIDATE_JSON_PRETTIER: false
3133
VALIDATE_MARKDOWN_PRETTIER: false
3234
VALIDATE_YAML_PRETTIER: false

action.yml

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,12 +57,24 @@ inputs:
5757
description: The working directory where the script will run from.
5858
required: false
5959
default: '.'
60+
UsePRTitleAsReleaseName:
61+
description: When enabled, uses the pull request title as the name for the GitHub release. If not set, the version string is used.
62+
required: false
63+
default: 'false'
64+
UsePRBodyAsReleaseNotes:
65+
description: When enabled, uses the pull request body as the release notes for the GitHub release. If not set, the release notes are auto-generated.
66+
required: false
67+
default: 'true'
68+
UsePRTitleAsNotesHeading:
69+
description: When enabled along with UsePRBodyAsReleaseNotes, the release notes will begin with the pull request title as a H1 heading followed by the pull request body. The title will reference the pull request number.
70+
required: false
71+
default: 'true'
6072

6173
runs:
6274
using: composite
6375
steps:
6476
- name: Install-PSModuleHelpers
65-
uses: PSModule/Install-PSModuleHelpers@v1
77+
uses: PSModule/Install-PSModuleHelpers@d60d63e4be477d1ca0c67c6085101fb109bce8f1 # v1.0.6
6678

6779
- name: Run Publish-PSModule
6880
shell: pwsh
@@ -81,4 +93,7 @@ runs:
8193
PSMODULE_PUBLISH_PSMODULE_INPUT_PatchLabels: ${{ inputs.PatchLabels }}
8294
PSMODULE_PUBLISH_PSMODULE_INPUT_VersionPrefix: ${{ inputs.VersionPrefix }}
8395
PSMODULE_PUBLISH_PSMODULE_INPUT_WhatIf: ${{ inputs.WhatIf }}
96+
PSMODULE_PUBLISH_PSMODULE_INPUT_UsePRBodyAsReleaseNotes: ${{ inputs.UsePRBodyAsReleaseNotes }}
97+
PSMODULE_PUBLISH_PSMODULE_INPUT_UsePRTitleAsReleaseName: ${{ inputs.UsePRTitleAsReleaseName }}
98+
PSMODULE_PUBLISH_PSMODULE_INPUT_UsePRTitleAsNotesHeading: ${{ inputs.UsePRTitleAsNotesHeading }}
8499
run: ${{ github.action_path }}/scripts/main.ps1

scripts/helpers/Publish-PSModule.ps1

Lines changed: 75 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -48,18 +48,24 @@
4848
$majorLabels = $env:PSMODULE_PUBLISH_PSMODULE_INPUT_MajorLabels -split ',' | ForEach-Object { $_.Trim() }
4949
$minorLabels = $env:PSMODULE_PUBLISH_PSMODULE_INPUT_MinorLabels -split ',' | ForEach-Object { $_.Trim() }
5050
$patchLabels = $env:PSMODULE_PUBLISH_PSMODULE_INPUT_PatchLabels -split ',' | ForEach-Object { $_.Trim() }
51+
$usePRBodyAsReleaseNotes = $env:PSMODULE_PUBLISH_PSMODULE_INPUT_UsePRBodyAsReleaseNotes -eq 'true'
52+
$usePRTitleAsReleaseName = $env:PSMODULE_PUBLISH_PSMODULE_INPUT_UsePRTitleAsReleaseName -eq 'true'
53+
$usePRTitleAsNotesHeading = $env:PSMODULE_PUBLISH_PSMODULE_INPUT_UsePRTitleAsNotesHeading -eq 'true'
5154

5255
[pscustomobject]@{
53-
AutoCleanup = $autoCleanup
54-
AutoPatching = $autoPatching
55-
IncrementalPrerelease = $incrementalPrerelease
56-
DatePrereleaseFormat = $datePrereleaseFormat
57-
VersionPrefix = $versionPrefix
58-
WhatIf = $whatIf
59-
IgnoreLabels = $ignoreLabels
60-
MajorLabels = $majorLabels
61-
MinorLabels = $minorLabels
62-
PatchLabels = $patchLabels
56+
AutoCleanup = $autoCleanup
57+
AutoPatching = $autoPatching
58+
IncrementalPrerelease = $incrementalPrerelease
59+
DatePrereleaseFormat = $datePrereleaseFormat
60+
VersionPrefix = $versionPrefix
61+
WhatIf = $whatIf
62+
IgnoreLabels = $ignoreLabels
63+
MajorLabels = $majorLabels
64+
MinorLabels = $minorLabels
65+
PatchLabels = $patchLabels
66+
UsePRBodyAsReleaseNotes = $usePRBodyAsReleaseNotes
67+
UsePRTitleAsReleaseName = $usePRTitleAsReleaseName
68+
UsePRTitleAsNotesHeading = $usePRTitleAsNotesHeading
6369
} | Format-List | Out-String
6470
}
6571

@@ -76,7 +82,7 @@
7682

7783
Set-GitHubLogGroup 'Event information - Details' {
7884
$defaultBranchName = (gh repo view --json defaultBranchRef | ConvertFrom-Json | Select-Object -ExpandProperty defaultBranchRef).name
79-
$isPullRequest = $githubEvent.PSObject.Properties.Name -Contains 'pull_request'
85+
$isPullRequest = $githubEvent.PSObject.Properties.Name -contains 'pull_request'
8086
if (-not ($isPullRequest -or $whatIf)) {
8187
Write-Warning '⚠️ A release should not be created in this context. Exiting.'
8288
exit
@@ -113,7 +119,7 @@
113119
Set-GitHubLogGroup 'Calculate release type' {
114120
$createRelease = $isMerged -and $targetIsDefaultBranch
115121
$closedPullRequest = $prIsClosed -and -not $isMerged
116-
$createPrerelease = $labels -Contains 'prerelease' -and -not $createRelease -and -not $closedPullRequest
122+
$createPrerelease = $labels -contains 'prerelease' -and -not $createRelease -and -not $closedPullRequest
117123
$prereleaseName = $prHeadRef -replace '[^a-zA-Z0-9]'
118124

119125
$ignoreRelease = ($labels | Where-Object { $ignoreLabels -contains $_ }).Count -gt 0
@@ -358,27 +364,67 @@
358364

359365
Set-GitHubLogGroup 'New-GitHubRelease' {
360366
Write-Output 'Create new GitHub release'
367+
$releaseCreateCommand = @('release', 'create', $newVersion.ToString())
368+
$notesFilePath = $null
369+
370+
# Add title parameter
371+
if ($usePRTitleAsReleaseName -and $pull_request.title) {
372+
$prTitle = $pull_request.title
373+
$releaseCreateCommand += @('--title', $prTitle)
374+
Write-Output "Using PR title as release name: [$prTitle]"
375+
} else {
376+
$releaseCreateCommand += @('--title', $newVersion.ToString())
377+
}
378+
379+
# Build release notes content. Uses temp file to avoid escaping issues with special characters.
380+
# Precedence rules for the three UsePR* parameters:
381+
# 1. UsePRTitleAsNotesHeading + UsePRBodyAsReleaseNotes: Creates "# Title (#PR)\n\nBody" format.
382+
# Requires both parameters enabled AND both PR title and body to be present.
383+
# 2. UsePRBodyAsReleaseNotes only: Uses PR body as-is for release notes.
384+
# Takes effect when heading option is disabled/missing title, but body is available.
385+
# 3. Fallback: Auto-generates notes via GitHub's --generate-notes when no PR content is used.
386+
if ($usePRTitleAsNotesHeading -and $usePRBodyAsReleaseNotes -and $pull_request.title -and $pull_request.body) {
387+
# Path 1: Full PR-based notes with title as H1 heading and PR number link
388+
$prTitle = $pull_request.title
389+
$prNumber = $pull_request.number
390+
$prBody = $pull_request.body
391+
$notes = "# $prTitle (#$prNumber)`n`n$prBody"
392+
$notesFilePath = [System.IO.Path]::GetTempFileName()
393+
Set-Content -Path $notesFilePath -Value $notes -Encoding utf8
394+
$releaseCreateCommand += @('--notes-file', $notesFilePath)
395+
Write-Output 'Using PR title as H1 heading with link and body as release notes'
396+
} elseif ($usePRBodyAsReleaseNotes -and $pull_request.body) {
397+
# Path 2: PR body only - no heading, just the body content
398+
$prBody = $pull_request.body
399+
$notesFilePath = [System.IO.Path]::GetTempFileName()
400+
Set-Content -Path $notesFilePath -Value $prBody -Encoding utf8
401+
$releaseCreateCommand += @('--notes-file', $notesFilePath)
402+
Write-Output 'Using PR body as release notes'
403+
} else {
404+
# Path 3: Fallback to GitHub's auto-generated release notes
405+
$releaseCreateCommand += @('--generate-notes')
406+
}
407+
408+
# Add remaining parameters
361409
if ($createPrerelease) {
362-
if ($whatIf) {
363-
Write-Output "WhatIf: gh release create $newVersion --title $newVersion --target $prHeadRef --generate-notes --prerelease"
364-
} else {
365-
$releaseURL = gh release create $newVersion --title $newVersion --target $prHeadRef --generate-notes --prerelease
366-
if ($LASTEXITCODE -ne 0) {
367-
Write-Error "Failed to create the release [$newVersion]."
368-
exit $LASTEXITCODE
369-
}
370-
}
410+
$releaseCreateCommand += @('--target', $prHeadRef, '--prerelease')
411+
}
412+
413+
if ($whatIf) {
414+
Write-Output "WhatIf: gh $($releaseCreateCommand -join ' ')"
371415
} else {
372-
if ($whatIf) {
373-
Write-Output "WhatIf: gh release create $newVersion --title $newVersion --generate-notes"
374-
} else {
375-
$releaseURL = gh release create $newVersion --title $newVersion --generate-notes
376-
if ($LASTEXITCODE -ne 0) {
377-
Write-Error "Failed to create the release [$newVersion]."
378-
exit $LASTEXITCODE
379-
}
416+
$releaseURL = gh @releaseCreateCommand
417+
if ($LASTEXITCODE -ne 0) {
418+
Write-Error "Failed to create the release [$newVersion]."
419+
exit $LASTEXITCODE
380420
}
381421
}
422+
423+
# Clean up temporary notes file if created
424+
if ($notesFilePath -and (Test-Path -Path $notesFilePath)) {
425+
Remove-Item -Path $notesFilePath -Force
426+
}
427+
382428
if ($whatIf) {
383429
Write-Output 'WhatIf: gh pr comment $pull_request.number -b "The release [$newVersion] has been created."'
384430
} else {

0 commit comments

Comments
 (0)