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
22 changes: 22 additions & 0 deletions Source/Private/InitializeBuild.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,28 @@ function InitializeBuild {
) -join ' ')"
$BuildInfo = GetBuildInfo -BuildManifest $BuildManifest -BuildCommandInvocation $BuildCommandInvocation

# Normalize the version (if it was passed in via build.psd1)
if ($BuildInfo.SemVer) {
Write-Verbose "Update the Version, Prerelease, and BuildMetadata from the SemVer (in case it was passed in via build.psd1)"
$BuildInfo = $BuildInfo | Update-Object @{
Version = if (($V = $BuildInfo.SemVer.Split("+")[0].Split("-", 2)[0])) {
[version]$V
}
Prerelease = $BuildInfo.SemVer.Split("+")[0].Split("-", 2)[1]
BuildMetadata = $BuildInfo.SemVer.Split("+", 2)[1]
}
} elseif($BuildInfo.Version) {
Write-Verbose "Calculate the Semantic Version from the Version - Prerelease + BuildMetadata"
$SemVer = "$($BuildInfo.Version)"
if ($BuildInfo.Prerelease) {
$SemVer = "$SemVer-$($BuildInfo.Prerelease)"
}
if ($BuildInfo.BuildMetadata) {
$SemVer = "$SemVer+$($BuildInfo.BuildMetadata)"
}
$BuildInfo = $BuildInfo | Update-Object @{ SemVer = $SemVer }
}

# Override VersionedOutputDirectory with UnversionedOutputDirectory
if ($BuildInfo.UnversionedOutputDirectory -and $BuildInfo.VersionedOutputDirectory) {
$BuildInfo.VersionedOutputDirectory = $false
Expand Down
44 changes: 15 additions & 29 deletions Source/Public/Build-Module.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,6 @@ function Build-Module {
Build-Module -SemVer $gitVersion

This example shows how to use a semantic version from gitversion to version your build.
Note, this is how we version ModuleBuilder, so if you want to see it in action, check out our azure-pipelines.yml
https://github.com/PoshCode/ModuleBuilder/blob/master/azure-pipelines.yml
#>
[Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseApprovedVerbs", "", Justification="Build is approved now")]
[Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseCmdletCorrectly", "")]
Expand Down Expand Up @@ -150,42 +148,30 @@ function Build-Module {
}
process {
try {
# BEFORE we InitializeBuild we need to "fix" the version
if($PSCmdlet.ParameterSetName -ne "SemanticVersion") {
Write-Verbose "Calculate the Semantic Version from the $Version - $Prerelease + $BuildMetadata"
$SemVer = "$Version"
if($Prerelease) {
$SemVer = "$Version-$Prerelease"
}
if($BuildMetadata) {
$SemVer = "$SemVer+$BuildMetadata"
}
}

# Push into the module source (it may be a subfolder)
$ModuleInfo = InitializeBuild $SourcePath
Write-Progress "Building $($ModuleInfo.Name)" -Status "Use -Verbose for more information"
Write-Verbose "Building $($ModuleInfo.Name)"

# Ensure the OutputDirectory (exists for build, or is cleaned otherwise)
$OutputDirectory = $ModuleInfo | ResolveOutputFolder
if ($Target -notmatch "Build") {
if ($ModuleInfo.Target -notmatch "Build") {
return
}
$RootModule = Join-Path $OutputDirectory "$($ModuleInfo.Name).psm1"
$OutputManifest = Join-Path $OutputDirectory "$($ModuleInfo.Name).psd1"
Write-Verbose "Output to: $OutputDirectory"

# Skip the build if it's up to date already
Write-Verbose "Target $Target"
Write-Verbose "Target $($ModuleInfo.Target)"
$NewestBuild = (Get-Item $RootModule -ErrorAction SilentlyContinue).LastWriteTime
$IsNew = Get-ChildItem $ModuleInfo.ModuleBase -Recurse |
Where-Object LastWriteTime -gt $NewestBuild |
Select-Object -First 1 -ExpandProperty LastWriteTime

if ($null -eq $IsNew) {
# This is mostly for testing ...
if ($Passthru) {
if ($ModuleInfo.Passthru) {
Get-Module $OutputManifest -ListAvailable
}
return # Skip the build
Expand Down Expand Up @@ -240,31 +226,31 @@ function Build-Module {
}

try {
if ($Version) {
Write-Verbose "Update Manifest at $OutputManifest with version: $Version"
Update-Metadata -Path $OutputManifest -PropertyName ModuleVersion -Value $Version
if ($ModuleInfo.Version) {
Write-Verbose "Update Manifest at $OutputManifest with version: $($ModuleInfo.Version)"
Update-Metadata -Path $OutputManifest -PropertyName ModuleVersion -Value $ModuleInfo.Version
}
} catch {
Write-Warning "Failed to update version to $Version. $_"
Write-Warning "Failed to update version to $($ModuleInfo.Version). $_"
}

if ($null -ne (Get-Metadata -Path $OutputManifest -PropertyName PrivateData.PSData.Prerelease -ErrorAction SilentlyContinue)) {
if ($Prerelease) {
Write-Verbose "Update Manifest at $OutputManifest with Prerelease: $Prerelease"
Update-Metadata -Path $OutputManifest -PropertyName PrivateData.PSData.Prerelease -Value $Prerelease
if ($ModuleInfo.Prerelease) {
Write-Verbose "Update Manifest at $OutputManifest with Prerelease: $($ModuleInfo.Prerelease)"
Update-Metadata -Path $OutputManifest -PropertyName PrivateData.PSData.Prerelease -Value $ModuleInfo.Prerelease
} elseif ($PSCmdlet.ParameterSetName -eq "SemanticVersion" -or $PSBoundParameters.ContainsKey("Prerelease")) {
Update-Metadata -Path $OutputManifest -PropertyName PrivateData.PSData.Prerelease -Value ""
}
} elseif($Prerelease) {
} elseif ($ModuleInfo.Prerelease) {
Write-Warning ("Cannot set Prerelease in module manifest. Add an empty Prerelease to your module manifest, like:`n" +
' PrivateData = @{ PSData = @{ Prerelease = "" } }')
}

if ($BuildMetadata) {
Write-Verbose "Update Manifest at $OutputManifest with metadata: $BuildMetadata from $SemVer"
if ($ModuleInfo.BuildMetadata) {
Write-Verbose "Update Manifest at $OutputManifest with metadata: $($ModuleInfo.BuildMetadata) from $($ModuleInfo.SemVer)"
$RelNote = Get-Metadata -Path $OutputManifest -PropertyName PrivateData.PSData.ReleaseNotes -ErrorAction SilentlyContinue
if ($null -ne $RelNote) {
$Line = "$($ModuleInfo.Name) v$($SemVer)"
$Line = "$($ModuleInfo.Name) v$($($ModuleInfo.SemVer))"
if ([string]::IsNullOrWhiteSpace($RelNote)) {
Write-Verbose "New ReleaseNotes:`n$Line"
Update-Metadata -Path $OutputManifest -PropertyName PrivateData.PSData.ReleaseNotes -Value $Line
Expand All @@ -284,7 +270,7 @@ function Build-Module {
}

# This is mostly for testing ...
if ($Passthru) {
if ($ModuleInfo.Passthru) {
Get-Module $OutputManifest -ListAvailable
}
} finally {
Expand Down
29 changes: 29 additions & 0 deletions Tests/Integration/Parameters.Tests.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#requires -Module ModuleBuilder
. $PSScriptRoot\..\Convert-FolderSeparator.ps1

Describe "Parameters.Set in build manifest" -Tag Integration {
BeforeAll {
New-Item $PSScriptRoot\Result3\Parameters\ReadMe.md -ItemType File -Force
$Output = Build-Module $PSScriptRoot\Parameters\build.psd1
if ($Output) {
$Module = [IO.Path]::ChangeExtension($Output.Path, "psm1")
$Metadata = Import-Metadata $Output.Path
}
}

It "Passthru works" {
$Output | Should -Not -BeNullOrEmpty
}

It "The Target is Build" {
"$PSScriptRoot\Result3\Parameters\ReadMe.md" | Should -Exist
}

It "The version is set" {
$Metadata.ModuleVersion | Should -Be "3.0.0"
}

It "The PreRelease is set" {
$Metadata.PrivateData.PSData.Prerelease | Should -Be 'alpha001'
}
}
56 changes: 56 additions & 0 deletions Tests/Integration/Parameters/Parameters.psd1
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
@{
# The module version should be SemVer.org compatible
ModuleVersion = "1.0.0"

# PrivateData is where all third-party metadata goes
PrivateData = @{
# PrivateData.PSData is the PowerShell Gallery data
PSData = @{
# Prerelease string should be here, so we can set it
Prerelease = ''

# Release Notes have to be here, so we can update them
ReleaseNotes = '
A test module
'

# Tags applied to this module. These help with module discovery in online galleries.
Tags = 'Authoring','Build','Development','BestPractices'

# A URL to the license for this module.
LicenseUri = 'https://github.com/PoshCode/ModuleBuilder/blob/master/LICENSE'

# A URL to the main website for this project.
ProjectUri = 'https://github.com/PoshCode/ModuleBuilder'

# A URL to an icon representing this module.
IconUri = 'https://github.com/PoshCode/ModuleBuilder/blob/resources/ModuleBuilder.png?raw=true'
} # End of PSData
} # End of PrivateData

# The main script module that is automatically loaded as part of this module
RootModule = 'Parameters.psm1'

# Modules that must be imported into the global environment prior to importing this module
RequiredModules = @()

# Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix.
DefaultCommandPrefix = 'Param'

# Always define FunctionsToExport as an empty @() which will be replaced on build
FunctionsToExport = @()
AliasesToExport = @()

# ID used to uniquely identify this module
GUID = 'a264e183-e0f7-4219-bc80-c30d14e0e98e'
Description = 'A module for authoring and building PowerShell modules'

# Common stuff for all our modules:
CompanyName = 'PoshCode'
Author = 'Joel Bennett'
Copyright = "Copyright 2024 Joel Bennett"

# Minimum version of the Windows PowerShell engine required by this module
PowerShellVersion = '5.1'
CompatiblePSEditions = @('Core','Desktop')
}
7 changes: 7 additions & 0 deletions Tests/Integration/Parameters/Private/GetFinale.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
using module ModuleBuilder

function GetFinale {
[CmdletBinding()]
# [Alias("gf")]
param()
}
1 change: 1 addition & 0 deletions Tests/Integration/Parameters/Private/GetMyAlias.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
New-Alias -Name 'Get-MyAlias' -Value 'Get-ChildItem'
7 changes: 7 additions & 0 deletions Tests/Integration/Parameters/Private/GetPreview.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
using module ModuleBuilder

function GetPreview {
[CmdletBinding()]
# [Alias("gp")]
param()
}
13 changes: 13 additions & 0 deletions Tests/Integration/Parameters/Private/TestUnExportedAliases.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
function TestUnExportedAliases {
[CmdletBinding()]
param()

New-Alias -Name 'New-NotExportedAlias1' -Value 'Write-Verbose'
Set-Alias -Name 'New-NotExportedAlias2' -Value 'Write-Verbose'
}

New-Alias -Name 'New-NotExportedAlias3' -Value 'Write-Verbose' -Scope Global
Set-Alias -Name 'New-NotExportedAlias4' -Value 'Write-Verbose' -Scope Global

New-Alias -Name 'New-NotExportedAlias5' -Value 'Write-Verbose'
Remove-Alias -Name 'New-NotExportedAlias5'
7 changes: 7 additions & 0 deletions Tests/Integration/Parameters/Public/Get-Source.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
using module ModuleBuilder

function Get-Source {
[CmdletBinding()]
[Alias("gs","gsou")]
param()
}
6 changes: 6 additions & 0 deletions Tests/Integration/Parameters/Public/Set-Source.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
function Set-Source {
[CmdletBinding()]
[Alias("ss", "ssou")]
param()
"sto͞o′pĭd"
}
7 changes: 7 additions & 0 deletions Tests/Integration/Parameters/build.psd1
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
@{
Path = "Parameters.psd1"
OutputDirectory = "..\Result3"
SemVer = "3.0.0-alpha001"
Target = "Build"
Passthru = $true
}
Empty file.
54 changes: 39 additions & 15 deletions Tests/Public/Build-Module.Tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -257,21 +257,28 @@ Describe "Build-Module" {
New-Item -ItemType Directory -Path TestDrive:/MyModule/ -Force
New-Item -ItemType Directory -Path "TestDrive:/Output/MyModule/$ExpectedVersion" -Force

Mock InitializeBuild {
# These are actually all the values that we need
Mock ResolveBuildManifest { "TestDrive:/MyModule/build.psd1" }

Mock GetBuildInfo {
[PSCustomObject]@{
OutputDirectory = "TestDrive:/Output"
Name = "MyModule"
Version = $Version
SourcePath = "TestDrive:/MyModule/"
SemVer = $SemVer
Target = $Target
ModuleBase = "TestDrive:/MyModule/"
CopyPaths = @()
Encoding = "UTF8"
PublicFilter = "Public/*.ps1"
VersionedOutputDirectory = $true
}
}

Mock ImportModuleManifest {
[PSCustomObject]@{
Name = "MyModule"
ModuleBase = "TestDrive:/MyModule/"
}
}

$global:Mock_OutputPath = Convert-FolderSeparator "TestDrive:/Output/MyModule/$ExpectedVersion"

Mock Get-ChildItem {
Expand Down Expand Up @@ -356,22 +363,31 @@ Describe "Build-Module" {
$global:ExpectedVersion = "1.0.0"
Push-Location TestDrive:/ -StackName BuildModuleTest
New-Item -ItemType Directory -Path TestDrive:/MyModule/ -Force
New-Item -ItemType Directory -Path "TestDrive:/Output/MyModule/$ExpectedVersion" -Force
New-Item -ItemType Directory -Path "TestDrive:/Output/MyModule" -Force

Mock InitializeBuild {
# These are actually all the values that we need
Mock ResolveBuildManifest { "TestDrive:/MyModule/build.psd1" }

Mock GetBuildInfo {
[PSCustomObject]@{
OutputDirectory = "TestDrive:/Output"
Name = "MyModule"
Version = $Version
Target = $Target
ModuleBase = "TestDrive:/MyModule/"
CopyPaths = @()
SourcePath = "TestDrive:/MyModule/"
Version = "1.0.0"
Prerelease = "beta03"
BuildMetadata = "Sha.22c35ffff166f34addc49a3b80e622b543199cc5.Date.2018-10-11"
Target = "CleanBuild"
CopyPaths = @()
Encoding = "UTF8"
PublicFilter = "Public/*.ps1"
}
}

Mock ImportModuleManifest {
[PSCustomObject]@{
Name = "MyModule"
ModuleBase = "TestDrive:/MyModule/"
}
}

$global:Mock_OutputPath = Convert-FolderSeparator "TestDrive:/Output/MyModule"
Mock Get-ChildItem {
[IO.FileInfo]"$TestDrive/MyModule/Public/Get-MyInfo.ps1"
Expand Down Expand Up @@ -510,20 +526,28 @@ Describe "Build-Module" {
New-Item -ItemType Directory -Path TestDrive:/MyModule/ -Force
New-Item -ItemType Directory -Path "TestDrive:/$ExpectedVersion/" -Force

Mock InitializeBuild {
Mock GetBuildInfo {
# These are actually all the values that we need
[PSCustomObject]@{
OutputDirectory = "TestDrive:/$Version"
Name = "MyModule"
Version = $Version
PreRelease = $PreRelease
Target = $Target
ModuleBase = "TestDrive:/MyModule/"
SourcePath = "TestDrive:/MyModule/"
CopyPaths = @()
Encoding = "UTF8"
PublicFilter = "Public/*.ps1"
}
}

Mock ImportModuleManifest {
[PSCustomObject]@{
Name = "MyModule"
ModuleBase = "TestDrive:/MyModule/"
}
}

$global:Mock_OutputPath = Convert-FolderSeparator "TestDrive:/MyModule/$ExpectedVersion"

Mock Get-ChildItem {
Expand Down