Skip to content

Commit 8cccec4

Browse files
🌟 [Major]: Standalone Module Builder with isolation (#108)
## Description This PR refactors **Build-PSModule** into a standalone, reusable action focused solely on building and packaging PowerShell modules. It simplifies inputs/outputs, improves script reliability, and removes deprecated logic. This aligns with recent changes in **Process-PSModule** (see [PR #150](PSModule/Process-PSModule#150)) that shift orchestration responsibilities out of Build-PSModule. ## Why Previously, Build-PSModule handled some orchestration logic (e.g., naming, path assumptions), tightly coupling it to specific CI setups. This update makes it a pure builder, allowing workflows like Process-PSModule to fully own orchestration and testing. ## Key Changes - New inputs: - `ArtifactName` (custom name for upload) - `WorkingDirectory` (controls source/build path) - New output: - `moduleOutputFolderPath` (used for artifact upload and downstream steps) - Upload step: Now dynamically uses the output path instead of hardcoded ones. - Improved helper scripts: - Better error handling - Simpler, more robust logic - Removed legacy scripts and inputs ## Impact - Workflows now get a clean contract: provide source path → get built module path. - Build-PSModule no longer makes assumptions about structure or downstream steps. - Enables more modular, flexible workflows (like the new Process-PSModule pipeline). --- Let me know if you'd like an even more minimal or changelog-style version! ## Type of change <!-- Use the check-boxes [x] on the options that are relevant. --> - [ ] 📖 [Docs] - [ ] 🪲 [Fix] - [ ] 🩹 [Patch] - [ ] ⚠️ [Security fix] - [ ] 🚀 [Feature] - [x] 🌟 [Breaking change] ## Checklist <!-- Use the check-boxes [x] on the options that are relevant. --> - [x] I have performed a self-review of my own code - [x] I have commented my code, particularly in hard-to-understand areas
1 parent 7f3f350 commit 8cccec4

File tree

65 files changed

+159
-242
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

65 files changed

+159
-242
lines changed

.github/workflows/Action-Test.yml

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,8 @@ jobs:
3232
uses: ./
3333
with:
3434
Name: PSModuleTest
35-
Path: tests/src
36-
ModulesOutputPath: tests/outputs/modules
35+
ArtifactName: PSModuleTestDefault
36+
WorkingDirectory: tests/srcTestRepo
3737

3838
ActionTestMinimal:
3939
name: Action-Test - [Minimal]
@@ -49,9 +49,8 @@ jobs:
4949
uses: ./
5050
with:
5151
Name: PSModuleTest
52-
Path: tests/srcMinimal
53-
ModulesOutputPath: tests/outputs/modules
54-
ModuleArtifactName: moduleMinimal
52+
ArtifactName: PSModuleTestMinimal
53+
WorkingDirectory: tests/srcMinimalTestRepo
5554

5655
ActionTestWithManifest:
5756
name: Action-Test - [DefaultWithManifest]
@@ -67,6 +66,5 @@ jobs:
6766
uses: ./
6867
with:
6968
Name: PSModuleTest
70-
Path: tests/srcWithManifest
71-
ModulesOutputPath: tests/outputs/modules
72-
ModuleArtifactName: moduleWithManifest
69+
ArtifactName: PSModuleTestWithManifest
70+
WorkingDirectory: tests/srcWithManifestTestRepo

.github/workflows/Auto-Release.yml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,5 @@ jobs:
3030

3131
- name: Auto-Release
3232
uses: PSModule/Auto-Release@v1
33-
env:
34-
GITHUB_TOKEN: ${{ github.token }} # Used for GitHub CLI authentication
3533
with:
3634
IncrementalPrerelease: false

README.md

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -25,16 +25,16 @@ This step lets you add custom build logic to process or modify the module conten
2525

2626
## Usage
2727

28-
| Name | Description | Required | Default |
29-
| ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | ----------------- |
30-
| `Name` | Name of the module to process. | `false` | |
31-
| `Path` | Path to the folder where the modules are located. | `false` | `src` |
32-
| `ModulesOutputPath` | Path to the folder where the built modules are outputted. | `false` | `outputs/modules` |
33-
| `ModuleArtifactName` | Name of the module artifact to upload. | `false` | `module` |
34-
| `Debug` | Enable debug output. | `false` | `'false'` |
35-
| `Verbose` | Enable verbose output. | `false` | `'false'` |
36-
| `Version` | Specifies the version of the GitHub module to be installed. The value must be an exact version. | `false` | |
37-
| `Prerelease` | Allow prerelease versions if available. | `false` | `'false'` |
28+
| Name | Description | Required | Default |
29+
| --------------------| ----------------------------------------------------------------------------------------------- | -------- | ----------------- |
30+
| `Name` | Name of the module to process. | `false` | |
31+
| `Path` | Path to the folder where the modules are located. | `false` | `src` |
32+
| `ModulesOutputPath` | Path to the folder where the built modules are outputted. | `false` | `outputs/modules` |
33+
| `Debug` | Enable debug output. | `false` | `'false'` |
34+
| `Verbose` | Enable verbose output. | `false` | `'false'` |
35+
| `Version` | Specifies the version of the GitHub module to be installed. The value must be an exact version. | `false` | |
36+
| `Prerelease` | Allow prerelease versions if available. | `false` | `'false'` |
37+
| `WorkingDirectory` | The working directory where the script runs. | `false` | `'.'` |
3838

3939
## Root module
4040

action.yml

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,8 @@ inputs:
99
Name:
1010
description: Name of the module to process.
1111
required: false
12-
Path:
13-
description: Path to the folder where the modules are located.
14-
required: false
15-
default: src
16-
ModulesOutputPath:
17-
description: Path to the folder where the built modules are outputted.
18-
required: false
19-
default: outputs/modules
20-
ModuleArtifactName:
21-
description: Name of the module artifact to upload.
12+
ArtifactName:
13+
description: Name of the artifact to upload.
2214
required: false
2315
default: module
2416
Debug:
@@ -36,29 +28,36 @@ inputs:
3628
description: Allow prerelease versions if available.
3729
required: false
3830
default: 'false'
31+
WorkingDirectory:
32+
description: The working directory where the script will run from.
33+
required: false
34+
default: '.'
3935

4036
runs:
4137
using: composite
4238
steps:
39+
- name: Install-PSModuleHelpers
40+
uses: PSModule/Install-PSModuleHelpers@v1
41+
4342
- name: Run Build-PSModule
4443
uses: PSModule/GitHub-Script@v1
44+
id: build
4545
env:
46-
GITHUB_ACTION_INPUT_Name: ${{ inputs.Name }}
47-
GITHUB_ACTION_INPUT_Path: ${{ inputs.Path }}
48-
GITHUB_ACTION_INPUT_ModulesOutputPath: ${{ inputs.ModulesOutputPath }}
46+
PSMODULE_BUILD_PSMODULE_INPUT_Name: ${{ inputs.Name }}
4947
with:
5048
Debug: ${{ inputs.Debug }}
5149
Prerelease: ${{ inputs.Prerelease }}
5250
Verbose: ${{ inputs.Verbose }}
5351
Version: ${{ inputs.Version }}
52+
WorkingDirectory: ${{ inputs.WorkingDirectory }}
5453
Script: |
5554
# Build-PSModule
56-
${{ github.action_path }}\scripts\main.ps1
55+
${{ github.action_path }}/scripts/main.ps1
5756
5857
- name: Upload module artifact
5958
uses: actions/upload-artifact@v4
6059
with:
61-
name: ${{ inputs.ModuleArtifactName }}
62-
path: ${{ inputs.ModulesOutputPath }}
60+
name: ${{ inputs.ArtifactName }}
61+
path: ${{ fromJson(steps.build.outputs.result).moduleOutputFolderPath }}
6362
if-no-files-found: error
6463
retention-days: 1

scripts/helpers/Build-PSModule.ps1

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
.DESCRIPTION
77
Builds a module.
88
#>
9+
[OutputType([void])]
910
[CmdletBinding()]
1011
#Requires -Modules @{ ModuleName = 'GitHub'; ModuleVersion = '0.13.2' }
1112
#Requires -Modules @{ ModuleName = 'Utilities'; ModuleVersion = '0.3.0' }
@@ -28,26 +29,22 @@
2829

2930
# Path to the folder where the built modules are outputted.
3031
[Parameter(Mandatory)]
31-
[string] $ModulesOutputFolderPath
32+
[string] $ModuleOutputFolderPath
3233
)
3334

3435
LogGroup "Building module [$ModuleName]" {
35-
Write-Host "Source path: [$ModuleSourceFolderPath]"
36-
if (-not (Test-Path -Path $ModuleSourceFolderPath)) {
37-
Write-Error "Source folder not found at [$ModuleSourceFolderPath]"
38-
exit 1
39-
}
4036
$moduleSourceFolder = Get-Item -Path $ModuleSourceFolderPath
41-
Write-Host "Module source folder: [$moduleSourceFolder]"
42-
43-
$moduleOutputFolder = New-Item -Path $ModulesOutputFolderPath -Name $ModuleName -ItemType Directory -Force
44-
Write-Host "Module output folder: [$moduleOutputFolder]"
37+
$moduleOutputFolder = New-Item -Path $ModuleOutputFolderPath -Name $ModuleName -ItemType Directory -Force
38+
[pscustomobject]@{
39+
ModuleSourceFolderPath = $moduleSourceFolder
40+
ModuleOutputFolderPath = $moduleOutputFolder
41+
} | Format-List | Out-String
4542
}
4643

4744
Build-PSModuleBase -ModuleName $ModuleName -ModuleSourceFolder $moduleSourceFolder -ModuleOutputFolder $moduleOutputFolder
4845
Build-PSModuleManifest -ModuleName $ModuleName -ModuleOutputFolder $moduleOutputFolder
4946
Build-PSModuleRootModule -ModuleName $ModuleName -ModuleOutputFolder $moduleOutputFolder
50-
Update-PSModuleManifestAliasesToExport -ModuleName $ModuleName -ModuleOutputFolder $moduleOutputFolder
47+
Update-PSModuleManifestAliasesToExport -ModuleName $ModuleName -ModuleSourceFolder $moduleSourceFolder -ModuleOutputFolder $moduleOutputFolder
5148

5249
LogGroup 'Build manifest file - Final Result' {
5350
$outputManifestPath = Join-Path -Path $ModuleOutputFolder -ChildPath "$ModuleName.psd1"

scripts/helpers/Build/Build-PSModuleBase.ps1

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,14 @@
3535
)
3636

3737
LogGroup 'Build base' {
38-
Write-Host "Copying files from [$ModuleSourceFolder] to [$ModuleOutputFolder]"
39-
Copy-Item -Path "$ModuleSourceFolder\*" -Destination $ModuleOutputFolder -Recurse -Force -Verbose -Exclude "$ModuleName.psm1"
40-
New-Item -Path $ModuleOutputFolder -Name "$ModuleName.psm1" -ItemType File -Force -Verbose
38+
$relModuleSourceFolder = $ModuleSourceFolder | Resolve-Path -Relative
39+
$relModuleOutputFolder = $ModuleOutputFolder | Resolve-Path -Relative
40+
Write-Host "Copying files from [$relModuleSourceFolder] to [$relModuleOutputFolder]"
41+
Copy-Item -Path "$ModuleSourceFolder\*" -Destination $ModuleOutputFolder -Recurse -Force -Exclude "$ModuleName.psm1"
42+
$null = New-Item -Path $ModuleOutputFolder -Name "$ModuleName.psm1" -ItemType File -Force
4143
}
4244

4345
LogGroup 'Build base - Result' {
44-
(Get-ChildItem -Path $ModuleOutputFolder -Recurse -Force).FullName | Sort-Object
46+
Get-ChildItem -Path $ModuleOutputFolder -Recurse -Force | Resolve-Path -Relative | Sort-Object
4547
}
4648
}

scripts/helpers/Build/Build-PSModuleManifest.ps1

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,7 @@
363363
$manifestTags = [System.Collections.Generic.List[string]]::new()
364364
$tags = $PSData.Keys -contains 'Tags' ? ($PSData.Tags).Count -gt 0 ? $PSData.Tags : $repoLabels : $repoLabels
365365
$tags | ForEach-Object { $manifestTags.Add($_) }
366+
'Windows', 'Linux', 'MacOS' | ForEach-Object { $manifestTags.Add($_) }
366367
# Add tags for compatability mode. https://docs.microsoft.com/en-us/powershell/scripting/developer/module/how-to-write-a-powershell-module-manifest?view=powershell-7.1#compatibility-tags
367368
if ($manifest.CompatiblePSEditions -contains 'Desktop') {
368369
if ($manifestTags -notcontains 'PSEdition_Desktop') {
@@ -448,7 +449,7 @@
448449
}
449450

450451
LogGroup 'Build manifest file - Format' {
451-
Set-ModuleManifest -Path $outputManifestPath -Verbose
452+
Set-ModuleManifest -Path $outputManifestPath
452453
}
453454

454455
LogGroup 'Build manifest file - Result - After format' {
@@ -460,6 +461,6 @@
460461
}
461462

462463
LogGroup 'Build manifest file - Validate - Test manifest file' {
463-
Test-ModuleManifest -Path $outputManifestPath
464+
Test-ModuleManifest -Path $outputManifestPath | Format-List | Out-String
464465
}
465466
}

scripts/helpers/Build/Build-PSModuleRootModule.ps1

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ foreach ($Type in $ExportableClasses) {
115115
# Remove type accelerators when the module is removed.
116116
$MyInvocation.MyCommand.ScriptBlock.Module.OnRemove = {
117117
foreach ($Type in ($ExportableEnums + $ExportableClasses)) {
118-
$TypeAcceleratorsClass::Remove($Type.FullName)
118+
$null = $TypeAcceleratorsClass::Remove($Type.FullName)
119119
}
120120
}.GetNewClosure()
121121
#endregion Class exporter
@@ -130,10 +130,21 @@ $MyInvocation.MyCommand.ScriptBlock.Module.OnRemove = {
130130
$exports.Add('Function', (Get-PSModuleFunctionsToExport -SourceFolderPath $ModuleOutputFolder))
131131
$exports.Add('Variable', (Get-PSModuleVariablesToExport -SourceFolderPath $ModuleOutputFolder))
132132

133-
Write-Host ($exports | Out-String)
133+
[pscustomobject]$exports | Format-List | Out-String
134134
#endregion - Analyze source files
135135

136136
#region - Module header
137+
Add-Content -Path $rootModuleFile -Force -Value @'
138+
[Diagnostics.CodeAnalysis.SuppressMessageAttribute(
139+
'PSAvoidAssignmentToAutomaticVariable', 'IsWindows',
140+
Justification = 'IsWindows doesnt exist in PS5.1'
141+
)]
142+
[Diagnostics.CodeAnalysis.SuppressMessageAttribute(
143+
'PSUseDeclaredVarsMoreThanAssignments', 'IsWindows',
144+
Justification = 'IsWindows doesnt exist in PS5.1'
145+
)]
146+
'@
147+
137148
$headerFilePath = Join-Path -Path $ModuleOutputFolder -ChildPath 'header.ps1'
138149
if (Test-Path -Path $headerFilePath) {
139150
Get-Content -Path $headerFilePath -Raw | Add-Content -Path $rootModuleFile -Force
@@ -149,10 +160,15 @@ param()
149160
#region - Module post-header
150161
Add-Content -Path $rootModuleFile -Force -Value @'
151162
$baseName = [System.IO.Path]::GetFileNameWithoutExtension($PSCommandPath)
152-
$script:PSModuleInfo = Test-ModuleManifest -Path "$PSScriptRoot\$baseName.psd1"
163+
$script:PSModuleInfo = Import-PowerShellDataFile -Path "$PSScriptRoot\$baseName.psd1"
153164
$script:PSModuleInfo | Format-List | Out-String -Stream | ForEach-Object { Write-Debug $_ }
154165
$scriptName = $script:PSModuleInfo.Name
155166
Write-Debug "[$scriptName] - Importing module"
167+
168+
if ($PSEdition -eq 'Desktop') {
169+
$IsWindows = $true
170+
}
171+
156172
'@
157173
#endregion - Module post-header
158174

@@ -224,7 +240,7 @@ Write-Debug "[`$scriptName] - $relativePath - Done"
224240

225241
$exportsString = $exports | Format-Hashtable
226242

227-
Write-Host ($exportsString | Out-String)
243+
$exportsString | Out-String
228244

229245
$params = @{
230246
Path = $rootModuleFile
@@ -256,12 +272,11 @@ Export-ModuleMember @exports
256272
Write-Host (Show-FileContent -Path $rootModuleFile)
257273
}
258274

259-
LogGroup 'Build root module - Validate - Import' {
260-
Add-PSModulePath -Path (Split-Path -Path $ModuleOutputFolder -Parent)
261-
Import-PSModule -Path $ModuleOutputFolder -ModuleName $ModuleName
262-
}
275+
# LogGroup 'Build root module - Validate - Import' {
276+
# Install-PSModule -Path $ModuleOutputFolder
277+
# }
263278

264-
LogGroup 'Build root module - Validate - File list' {
265-
(Get-ChildItem -Path $ModuleOutputFolder -Recurse -Force).FullName | Sort-Object
266-
}
279+
# LogGroup 'Build root module - Validate - File list' {
280+
# Get-ChildItem -Path $ModuleOutputFolder -Recurse -Force | Resolve-Path -Relative | Sort-Object
281+
# }
267282
}

scripts/helpers/Build/ConvertTo-Hashtable.ps1

Lines changed: 0 additions & 32 deletions
This file was deleted.

scripts/helpers/Build/Import-PSModule.ps1

Lines changed: 0 additions & 53 deletions
This file was deleted.

0 commit comments

Comments
 (0)