Skip to content

Commit 3076fd6

Browse files
authored
publish module to powershell gallery (wip) (#34)
* Add publish to powershellgallery workflow #9 * Added dry-run capability to manual publish
1 parent 4ec2890 commit 3076fd6

2 files changed

Lines changed: 458 additions & 0 deletions

File tree

Lines changed: 238 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,238 @@
1+
name: Manual Publish to PowerShell Gallery
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
mode:
7+
description: 'Select mode'
8+
required: true
9+
type: choice
10+
options:
11+
- 'DRY_RUN'
12+
- 'PUBLISH'
13+
default: 'DRY_RUN'
14+
confirm_publish:
15+
description: 'If PUBLISH mode: Type "CONFIRM" to proceed'
16+
required: false
17+
type: string
18+
19+
jobs:
20+
publish:
21+
runs-on: windows-latest
22+
if: github.event.inputs.mode == 'DRY_RUN' || (github.event.inputs.mode == 'PUBLISH' && github.event.inputs.confirm_publish == 'CONFIRM')
23+
24+
steps:
25+
- name: Checkout code
26+
uses: actions/checkout@v4
27+
28+
- name: Install PowerShell Module Dependencies
29+
shell: pwsh
30+
run: |
31+
Set-PSRepository PSGallery -InstallationPolicy Trusted
32+
Install-Module -Name PowerShell-Yaml -Force -SkipPublisherCheck
33+
34+
- name: Get Module Version
35+
id: version
36+
shell: pwsh
37+
run: |
38+
$manifestPath = "src/PSBlogger.psd1"
39+
$manifest = Import-PowerShellDataFile -Path $manifestPath
40+
$version = $manifest.ModuleVersion
41+
Write-Host "Module version: $version"
42+
echo "version=$version" >> $env:GITHUB_OUTPUT
43+
44+
- name: Validate Module Manifest
45+
shell: pwsh
46+
run: |
47+
# Test module manifest
48+
$manifestPath = "./src/PSBlogger.psd1"
49+
Write-Host "Testing module manifest at: $manifestPath"
50+
51+
# Test manifest syntax
52+
$manifest = Test-ModuleManifest -Path $manifestPath -Verbose
53+
Write-Host "Module manifest is valid"
54+
Write-Host "Module Name: $($manifest.Name)"
55+
Write-Host "Module Version: $($manifest.Version)"
56+
Write-Host "Module Author: $($manifest.Author)"
57+
Write-Host "Module Description: $($manifest.Description)"
58+
59+
# Check required fields for PowerShell Gallery
60+
if (-not $manifest.Description) {
61+
throw "Module description is required for PowerShell Gallery"
62+
}
63+
if (-not $manifest.Author) {
64+
throw "Module author is required for PowerShell Gallery"
65+
}
66+
67+
# Test that the module can be imported successfully
68+
Import-Module $manifestPath -Force
69+
$loadedModule = Get-Module PSBlogger
70+
Write-Host "Successfully imported module. Exported commands:"
71+
$loadedModule.ExportedCommands.Keys | Sort-Object | ForEach-Object { Write-Host " - $_" }
72+
73+
- name: Run Tests
74+
shell: pwsh
75+
run: |
76+
# Install Pester for testing
77+
Install-Module -Name Pester -Force -SkipPublisherCheck
78+
79+
# Install pandoc for tests
80+
choco install pandoc -y
81+
82+
# Change to src directory and run tests
83+
Set-Location "./src"
84+
85+
# Configure Pester
86+
$PesterConfig = @{
87+
Run = @{
88+
Path = './tests'
89+
}
90+
Output = @{
91+
Verbosity = 'Normal'
92+
}
93+
Should = @{
94+
ErrorAction = 'Stop'
95+
}
96+
}
97+
98+
# Run tests and fail if any tests fail
99+
$testResults = Invoke-Pester -Configuration $PesterConfig
100+
if ($testResults.FailedCount -gt 0) {
101+
throw "Tests failed. Cannot publish to PowerShell Gallery."
102+
}
103+
104+
- name: Publish to PowerShell Gallery
105+
shell: pwsh
106+
env:
107+
NUGET_API_KEY: ${{ secrets.POWERSHELLGALLERY_API }}
108+
run: |
109+
$isDryRun = "${{ github.event.inputs.mode }}" -eq "DRY_RUN"
110+
111+
if ($isDryRun) {
112+
Write-Host "🧪 DRY RUN MODE - No actual publishing will occur"
113+
} else {
114+
# Validate that we have the API key
115+
if (-not $env:NUGET_API_KEY) {
116+
throw "POWERSHELLGALLERY_API secret is not set"
117+
}
118+
}
119+
120+
Write-Host "Publishing PSBlogger version ${{ steps.version.outputs.version }} to PowerShell Gallery..."
121+
122+
# Check if this version already exists
123+
try {
124+
$existingModule = Find-Module -Name PSBlogger -RequiredVersion ${{ steps.version.outputs.version }} -ErrorAction SilentlyContinue
125+
if ($existingModule) {
126+
if ($isDryRun) {
127+
Write-Host "⚠️ DRY RUN: Version ${{ steps.version.outputs.version }} already exists on PowerShell Gallery"
128+
} else {
129+
throw "Version ${{ steps.version.outputs.version }} already exists on PowerShell Gallery"
130+
}
131+
}
132+
} catch {
133+
if ($_.Exception.Message -notlike "*Version*already exists*") {
134+
Write-Host "Could not check existing versions (this is normal for new modules): $($_.Exception.Message)"
135+
} else {
136+
throw
137+
}
138+
}
139+
140+
# Publish the module
141+
try {
142+
if ($isDryRun) {
143+
Publish-Module -Path "./src" -WhatIf -Verbose
144+
Write-Host "🧪 DRY RUN: Would publish to PowerShell Gallery (no actual publishing)"
145+
} else {
146+
Publish-Module -Path "./src" -NuGetApiKey $env:NUGET_API_KEY -Verbose -Force
147+
Write-Host "✅ Successfully published to PowerShell Gallery"
148+
}
149+
} catch {
150+
Write-Error "❌ Failed to publish to PowerShell Gallery: $_"
151+
throw
152+
}
153+
154+
- name: Create Git Tag and Release
155+
shell: pwsh
156+
run: |
157+
$isDryRun = "${{ github.event.inputs.mode }}" -eq "DRY_RUN"
158+
159+
if ($isDryRun) {
160+
Write-Host "🧪 DRY RUN: Would create tag v${{ steps.version.outputs.version }} and GitHub release"
161+
return
162+
}
163+
164+
# Configure git
165+
git config user.name "github-actions"
166+
git config user.email "github-actions@github.com"
167+
168+
# Check if tag already exists
169+
$tagExists = git tag -l "v${{ steps.version.outputs.version }}"
170+
if ($tagExists) {
171+
Write-Host "Tag v${{ steps.version.outputs.version }} already exists"
172+
} else {
173+
# Create and push tag
174+
git tag -a "v${{ steps.version.outputs.version }}" -m "Release version ${{ steps.version.outputs.version }}"
175+
git push origin "v${{ steps.version.outputs.version }}"
176+
Write-Host "Created and pushed tag v${{ steps.version.outputs.version }}"
177+
}
178+
179+
- name: Get Commit Messages for Release Notes
180+
id: release-notes
181+
shell: pwsh
182+
run: |
183+
# Get the previous tag
184+
$previousTag = git describe --tags --abbrev=0 "v${{ steps.version.outputs.version }}~1" 2>$null
185+
if ($LASTEXITCODE -ne 0) {
186+
# If no previous tag, get last 10 commits
187+
$commits = git log --oneline --pretty=format:"- %s (%h)" -n 10
188+
} else {
189+
# Get commits since the previous tag
190+
$commits = git log --oneline --pretty=format:"- %s (%h)" "$previousTag..v${{ steps.version.outputs.version }}"
191+
}
192+
193+
$releaseNotes = @"
194+
## Changes in version ${{ steps.version.outputs.version }}
195+
196+
$($commits -join "`n")
197+
198+
## Installation
199+
``````powershell
200+
Install-Module -Name PSBlogger -RequiredVersion ${{ steps.version.outputs.version }}
201+
``````
202+
"@
203+
204+
# Escape for GitHub Actions
205+
$releaseNotes = $releaseNotes -replace "`r`n", "`n" -replace "`n", "%0A"
206+
echo "release-notes=$releaseNotes" >> $env:GITHUB_OUTPUT
207+
208+
- name: Create GitHub Release
209+
if: github.event.inputs.mode == 'PUBLISH'
210+
uses: actions/create-release@v1
211+
env:
212+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
213+
with:
214+
tag_name: v${{ steps.version.outputs.version }}
215+
release_name: Release v${{ steps.version.outputs.version }}
216+
body: ${{ steps.release-notes.outputs.release-notes }}
217+
draft: false
218+
prerelease: false
219+
220+
- name: Notify Success
221+
if: success()
222+
shell: pwsh
223+
run: |
224+
$isDryRun = "${{ github.event.inputs.mode }}" -eq "DRY_RUN"
225+
226+
if ($isDryRun) {
227+
Write-Host "🧪 DRY RUN COMPLETED SUCCESSFULLY!"
228+
Write-Host "✅ Module manifest validation passed"
229+
Write-Host "✅ All tests passed"
230+
Write-Host "✅ Module can be imported successfully"
231+
Write-Host ""
232+
Write-Host "Ready to publish PSBlogger v${{ steps.version.outputs.version }} to PowerShell Gallery"
233+
Write-Host "To actually publish, run this workflow again with PUBLISH mode and type CONFIRM"
234+
} else {
235+
Write-Host "🎉 Successfully published PSBlogger v${{ steps.version.outputs.version }} to PowerShell Gallery!"
236+
Write-Host "📦 Module is now available at: https://www.powershellgallery.com/packages/PSBlogger/${{ steps.version.outputs.version }}"
237+
Write-Host "🏷️ Created release: https://github.com/${{ github.repository }}/releases/tag/v${{ steps.version.outputs.version }}"
238+
}

0 commit comments

Comments
 (0)