Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 58 additions & 8 deletions .github/workflows/PublishModuleToPowerShellGallery.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -54,21 +54,24 @@ jobs:
shell: bash
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
VERSION: ${{ steps.version.outputs.version }}
run: |
if gh release view "v${{ steps.version.outputs.version }}" > /dev/null 2>&1; then
if gh release view "v$VERSION" > /dev/null 2>&1; then
echo "exists=true" >> $GITHUB_OUTPUT
echo "GitHub release v${{ steps.version.outputs.version }} already exists"
echo "GitHub release v$VERSION already exists"
else
echo "exists=false" >> $GITHUB_OUTPUT
echo "GitHub release v${{ steps.version.outputs.version }} does not exist"
echo "GitHub release v$VERSION does not exist"
fi

- name: Check if PSGallery Version Exists
id: check_psgallery
if: steps.check_release.outputs.exists == 'false'
shell: pwsh
env:
VERSION: ${{ steps.version.outputs.version }}
run: |
$version = "${{ steps.version.outputs.version }}"
$version = $env:VERSION
$published = Find-Module -Name {{ModuleName}} -RequiredVersion $version -Repository PSGallery -ErrorAction SilentlyContinue
if ($published) {
Write-Host "PSGallery version $version already exists"
Expand All @@ -85,13 +88,60 @@ jobs:

- name: Create GitHub Release
if: steps.check_release.outputs.exists == 'false'
shell: bash
shell: pwsh
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
REPOSITORY: ${{ github.repository }}
VERSION: ${{ steps.version.outputs.version }}
run: |
gh release create "v${{ steps.version.outputs.version }}" \
--title "v${{ steps.version.outputs.version }}" \
--generate-notes
$version = $env:VERSION

# Build release notes from this version's CHANGELOG.md section so the release
# body carries only the curated, user-facing entries (not the full PR list that
# --generate-notes produces, which is dominated by bot/CI/chore PRs).
# Read defensively: a missing/unreadable CHANGELOG.md must fall back to
# --generate-notes (below), never fail the publish.
$changelogLines = $null
if (Test-Path -LiteralPath './CHANGELOG.md') {
try {
$changelogLines = Get-Content -LiteralPath './CHANGELOG.md' -ErrorAction Stop
}
catch {
Write-Host "::warning::Could not read CHANGELOG.md ($($_.Exception.Message)); falling back to auto-generated notes."
}
}
$captured = [System.Collections.Generic.List[string]]::new()
if ($changelogLines) {
$headerPattern = '^##\s+\[' + [regex]::Escape($version) + '\]'
$capturing = $false
foreach ($line in $changelogLines) {
if (-not $capturing) {
if ($line -match $headerPattern) { $capturing = $true }
continue
}
if ($line -match '^##\s+\[') { break } # next version header ends the section
$captured.Add($line)
}
}
$body = ($captured -join "`n").Trim()

if ([string]::IsNullOrWhiteSpace($body)) {
Write-Host "::warning::No CHANGELOG.md section found for $version; falling back to auto-generated notes."
gh release create "v$version" --title "v$version" --generate-notes
}
else {
# Append a compare link against the most recent existing tag. The v$version
# tag does not exist yet (this step creates it), so the latest tag is the
# previous release.
$previousTag = git tag --list 'v*' --sort=-version:refname |
Where-Object { $_ -ne "v$version" } |
Select-Object -First 1
if ($previousTag) {
$body += "`n`n**Full Changelog**: https://github.com/$env:REPOSITORY/compare/$previousTag...v$version"
}
Set-Content -LiteralPath './release-notes.md' -Value $body -Encoding utf8
gh release create "v$version" --title "v$version" --notes-file './release-notes.md'
}

- name: Publish to PSGallery
if: steps.check_release.outputs.exists == 'false' && steps.check_psgallery.outputs.exists == 'false'
Expand Down
5 changes: 5 additions & 0 deletions build.depend.psd1
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,9 @@
'PSScriptAnalyzer' = @{
Version = '1.25.0'
}
# Parses CHANGELOG.md (Keep a Changelog format) so the Publish task can populate the
# built manifest's PSData.ReleaseNotes from the matching version's entry.
Comment thread
tablackburn marked this conversation as resolved.
'ChangelogManagement' = @{
Version = '3.1.0'
}
}
45 changes: 45 additions & 0 deletions build.psake.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -45,5 +45,50 @@ Task -Name 'Init_Integration' -Description 'Load integration test environment va
}
}

# Populate the built manifest's ReleaseNotes from the matching CHANGELOG.md entry so the
# PowerShell Gallery release-notes panel shows the curated, user-facing notes (the same
# content used for the GitHub release) instead of just a link. Depends on Build so the
# staged manifest in ModuleOutDir exists; runs before Publish (see $PSBPublishDependency
# below). Non-fatal if the changelog can't be read or has no entry for the version being
# published, so a release is never blocked.
Task -Name 'UpdateReleaseNotes' -Depends 'Build' -Description 'Set built manifest ReleaseNotes from the matching CHANGELOG.md entry' {
$changelogPath = Join-Path -Path $PSScriptRoot -ChildPath 'CHANGELOG.md'
if (-not (Test-Path -Path $changelogPath)) {
Write-Warning 'CHANGELOG.md not found; leaving ReleaseNotes unchanged.'
return
}

$moduleVersion = $PSBPreference.General.ModuleVersion
try {
Import-Module -Name 'ChangelogManagement' -ErrorAction Stop
$changelogData = Get-ChangelogData -Path $changelogPath -ErrorAction Stop
}
catch {
Write-Warning "Could not read CHANGELOG.md ($($_.Exception.Message)); leaving ReleaseNotes unchanged."
return
}

$releaseEntry = $changelogData.Released |
Where-Object { [string]$_.Version -eq [string]$moduleVersion } |
Select-Object -First 1
if (-not $releaseEntry) {
Write-Warning "No CHANGELOG.md entry found for version $moduleVersion; leaving ReleaseNotes unchanged."
return
}

$releaseNotes = $releaseEntry.RawData.Trim()
Comment thread
tablackburn marked this conversation as resolved.
if ([string]::IsNullOrWhiteSpace($releaseNotes)) {
Write-Warning "CHANGELOG.md entry for version $moduleVersion is empty; leaving ReleaseNotes unchanged."
return
}
$builtManifest = Join-Path -Path $PSBPreference.Build.ModuleOutDir -ChildPath "$($PSBPreference.General.ModuleName).psd1"
Update-ModuleManifest -Path $builtManifest -ReleaseNotes $releaseNotes -ErrorAction Stop
Write-Host " Set ReleaseNotes on built manifest from CHANGELOG [$($releaseEntry.Version)] ($($releaseNotes.Length) chars)" -ForegroundColor Gray
}

# Inject ReleaseNotes into the built manifest before publishing (PowerShellBuild's Publish
# defaults to depending only on 'Test').
$PSBPublishDependency = @('Test', 'UpdateReleaseNotes')

# Note: -Depends replaces PowerShellBuild's default dependencies, so we must include Pester and Analyze explicitly
Task -Name 'Test' -FromModule 'PowerShellBuild' -MinimumVersion '0.7.3' -Depends 'Init_Integration', 'Pester', 'Analyze'
Loading