Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings
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
6 changes: 3 additions & 3 deletions 6 PSModuleDevelopment/PSModuleDevelopment.psd1
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

# Version number of this module.

ModuleVersion = '2.2.13.176'
ModuleVersion = '2.2.13.216'

# ID used to uniquely identify this module
GUID = '37dd5fce-e7b5-4d57-ac37-832055ce49d6'
Expand All @@ -28,8 +28,8 @@
# Modules that must be imported into the global environment prior to importing
# this module
RequiredModules = @(
@{ ModuleName = 'PSFramework'; ModuleVersion = '1.12.346' }
@{ ModuleName = 'string'; ModuleVersion = '1.1.5' }
@{ ModuleName = 'PSFramework'; ModuleVersion = '1.13.426' }
@{ ModuleName = 'string'; ModuleVersion = '1.2.13' }
)

# Assemblies that must be loaded prior to importing this module
Expand Down
43 changes: 43 additions & 0 deletions 43 PSModuleDevelopment/changelog.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,48 @@
# Changelog

## 2.2.13.216 (2026-01-16)

+ Upd: Template AzureFunction - Update host.json extension bundle version to `[4.*, 5.0.0)`
+ Upd: Template AzureFunction - PSModulePath ensured to exist correctly
+ Upd: Template AzureFunction - Configuration for Flex Consumption added, changing build behavior
+ Upd: Template AzureFunction - Added Eventgrid Trigger folder to project module
+ Upd: Template AzureFunction - Added readme with setup instructions
+ Upd: Template AzureFunction - Added `-Restart` parameter to the build script, restarting the Function App after deployment
+ Upd: Template AzureFunction - Added psf-build.ps1 for faster build through PSFramework.Nuget
+ Upd: Template AzureFunction - Added option to deploy to Flex Consumption plans, disabling Managed Dependencies
+ Upd: Template DscModule - Reordered import sequence to prioritize resources over other components
+ Upd: Template DscModule - Added support to exclude files from the syntax verification, to address issues with PowerShell Classes
+ Upd: Template MiniModule - Now asks for the Github Account name during invocation (GithubAccount)
+ Upd: Template MiniModule - Improved Readme.md
+ Upd: Template MiniModule - Added Project Uri, License Uri & Readme Uri to the manifest
+ Upd: Template MiniModule - Added `build/psf-prerequisites.ps1` as a faster dependencies alternative
+ Upd: Template MiniModule - Updated `build/vsts-build.ps1`, removing publishing steps and integrating config file
+ Upd: Template MiniModule - Added `build/psf-build.ps1`, an alternative build option using PSFramework.NuGet
+ Upd: Template MiniModule - added ability to auto-populate FunctionsToExport
+ Upd: Template MiniModule - added example project snippets for vscode
+ Upd: Template MiniModule - added example `initialize.ps1` script
+ Upd: Template MiniModule - added example `variables.ps1` script
+ Upd: Template MiniModule - added example project settings for vscode
+ Upd: Template MiniModule - added config file for simple settings that apply to the project
+ Upd: Template MiniModule - added the module variable "$script:ModuleRoo", pointing at the folder the module is in.
+ Upd: Template MiniModule - Added `build/vsts-release.ps1`, allowing to publish a release to Github
+ Upd: Template MiniModule - Added `build/vsts-publish.ps1` as a dedicated publishing step
+ Upd: Template MiniModule - Added `build/psf-publish.ps1` as a dedicated publishing step using `PSFramework.NuGet`. Can skip dependencies check.
+ Upd: Template MiniModule - Added the modules `Microsoft.PowerShell.PlatyPS` and `PSModuleDevelopment` to `build/vsts-prerequisites.ps1` for new build & publish features
+ Upd: Template MiniModule - Added explicit `Export-ModuleMember` call as part of the build step
+ Upd: Template MiniModule - Removed the type test part of the help test, as not relevant in a project unlikely to have Cmdlet exports
+ Upd: Template MiniModule - Updated PR Validation flow to run on PowerShell 7
+ Upd: Template MiniModule - Updated PR Validation flow to use `psf-prerequisites.ps1` by default, improving performance substantially
+ Upd: Template MiniModule - Updated PR Validation flow to use `actions/checkout@v6`
+ Upd: Template MiniModule - Updated Build & Publish flow to use `psf-prerequisites.ps1` by default, improving performance substantially
+ Upd: Template MiniModule - Updated Build & Publish flow to use `actions/checkout@v6`
+ Upd: Template MiniModule - Updated Build & Publish flow, splitting up building the module & publishing it to a repository
+ Upd: Template MiniModule - Updated Build & Publish flow, adding Github Release creation as the final step
+ Upd: Template MiniModule - Added changelog.md
+ Fix: Template AzureFunction - the folder "modules" should be "Modules"
+ Fix: Template DscClassFile - Removed a trailing whitespace that would trigger module tests checking for that.
+ Fix: Template MiniModule - help tests fail on parameters that are part of multiple parametersets but only mandatory in some of them

## 2.2.13.176 (2025-05-04)

+ New: Template AzureFunctionEventGrid - dedicated endpoint template for an EventGrid function
Expand Down
7 changes: 7 additions & 0 deletions 7 templates/AzureFunction/build/build.config.psd1
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
@{
General = @{
# Is this Function App deployed to a Flex COnsumption plan?
# If so, Managed Dependencies cannot be used and must be* disabled!
# *The build script will handle that for you, if setting this to $true
FlexConsumption = $false
}

TimerTrigger = @{
# Default Schedule for timed executions
Schedule = '0 5 * * * *'
Expand Down
80 changes: 73 additions & 7 deletions 80 templates/AzureFunction/build/build.ps1
Original file line number Diff line number Diff line change
@@ -1,13 +1,24 @@
param (
[CmdletBinding()]
param (
[string]
$Repository = 'PSGallery',

[string]
$AppRg,

[string]
$AppName
$AppName,

[switch]
$Restart
)

$ErrorActionPreference = 'Stop'
trap {
Write-Warning "Script failed: $_"
throw $_
}

$workingDirectory = Split-Path $PSScriptRoot
$config = Import-PowerShellDataFile -Path "$PSScriptRoot\build.config.psd1"

Expand All @@ -16,17 +27,63 @@ Remove-Item -Path "$workingDirectory/publish" -Recurse -Force -ErrorAction Ignor
$buildFolder = New-Item -Path $workingDirectory -Name 'publish' -ItemType Directory -Force -ErrorAction Stop
Copy-Item -Path "$workingDirectory/function/*" -Destination $buildFolder.FullName -Recurse -Force

#region Handle Modules
# Process Dependencies
$requiredModules = (Import-PowerShellDataFile -Path "$workingDirectory/þnameþ/þnameþ.psd1").RequiredModules
foreach ($module in $requiredModules) {
Save-Module -Name $module -Path "$($buildFolder.FullName)/modules" -Force -Repository $Repository
if ($module -is [string]) {
Save-Module -Name $module -Path "$($buildFolder.FullName)/modules" -Force -Repository $Repository
continue
}

$saveParam = @{ Name = $module.ModuleName }
if ($module.RequiredVersion) { $saveParam.RequiredVersion = $module.RequiredVersion }
elseif ($module.ModuleVersion) { $saveParam.MinimumVersion = $module.ModuleVersion }

Save-Module @saveParam -Path "$($buildFolder.FullName)/modules" -Force -Repository $Repository
}

#region Handle the Requirements for Flex Consumption Plans
if ($config.General.FlexConsumption) {
# Resolve New Dependencies
$mdepsFile = Join-Path -Path $buildFolder.FullName -ChildPath 'requirements.psd1'
$mDeps = Import-PowerShellDataFile -Path $mdepsFile
$requiredModules = foreach ($name in $mDeps.Keys) {
if ($mDeps.$name -match '\*') {
@{
Name = $name
MinimumVersion = '{0}.0.0' -f $mDeps.$name.Split('.')[0]
MaximumVersion = '{0}.999.999' -f $mDeps.$name.Split('.')[0]
}
}
else {
@{
Name = $name
RequiredVersion = $mDeps.$name
}
}
}

# Inject New Dependencies
foreach ($module in $requiredModules) {
Save-Module @module -Path "$($buildFolder.FullName)/modules" -Force -Repository $Repository
}

# Disable Managed Dependencies
$hostFile = Join-Path -Path $buildFolder.FullName -ChildPath 'host.json'
$hostCfg = Get-Content -Path $hostFile | ConvertFrom-Json
$hostCfg.managedDependency.enabled = $false
$hostCfg | ConvertTo-Json -Depth 99 | Set-Content -Path $hostFile
}
#endregion Handle the Requirements for Flex Consumption Plans

# Process Function Module
Copy-Item -Path "$workingDirectory/þnameþ" -Destination "$($buildFolder.FullName)/modules" -Force -Recurse
$commands = Get-ChildItem -Path "$($buildFolder.FullName)/modules/þnameþ/Functions" -Recurse -Filter *.ps1 | ForEach-Object BaseName
Update-ModuleManifest -Path "$($buildFolder.FullName)/modules/þnameþ/þnameþ.psd1" -FunctionsToExport $commands
#endregion Handle Modules

#region Triggers
# Generate Http Trigger
$httpCode = Get-Content -Path "$PSScriptRoot\functionHttp\run.ps1" | Join-String -Separator "`n"
$httpConfig = Get-Content -Path "$PSScriptRoot\functionHttp\function.json" | Join-String -Separator "`n"
Expand Down Expand Up @@ -74,13 +131,22 @@ foreach ($command in Get-ChildItem -Path "$workingDirectory\þnameþ\functions\t
$timerCode -replace '%COMMAND%',$command.BaseName | Set-Content -Path "$($endpointFolder.FullName)\run.ps1"
$timerConfig -replace '%SCHEDULE%', $schedule | Set-Content -Path "$($endpointFolder.FullName)\function.json"
}
#endregion Triggers

# Package & Cleanup
Remove-Item -Path "$workingDirectory/Function.zip" -Recurse -Force -ErrorAction Ignore
Compress-Archive -Path "$($buildFolder.FullName)/*" -DestinationPath "$workingDirectory/Function.zip"
Remove-Item -Path $buildFolder.FullName -Recurse -Force -ErrorAction Ignore

if ($AppRg -and $AppName) {
Write-Host "Publishing Function App to $AppRg/$AppName"
Publish-AzWebApp -ResourceGroupName $AppRG -Name $AppName -ArchivePath "$workingDirectory/Function.zip" -Confirm:$false -Force
}
if (-not $AppRg -or -not $AppName) { return }

Write-Host "Publishing Function App to $AppRg/$AppName"
$null = Publish-AzWebApp -ResourceGroupName $AppRG -Name $AppName -ArchivePath "$workingDirectory/Function.zip" -Confirm:$false -Force
Write-Host "Publishing Function App to $AppRg/$AppName - Done"

if (-not $Restart) { return }

Write-Host "Restarting Function App"
$null = Stop-AzWebApp -ResourceGroupName $AppRG -Name $AppName
$null = Start-AzWebApp -ResourceGroupName $AppRG -Name $AppName
Write-Host "Restarting Function App - Done"
152 changes: 152 additions & 0 deletions 152 templates/AzureFunction/build/psf-build.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
[CmdletBinding()]
param (
[string]
$Repository = 'PSGallery',

[string]
$AppRg,

[string]
$AppName,

[switch]
$Restart
)

$ErrorActionPreference = 'Stop'
trap {
Write-Warning "Script failed: $_"
throw $_
}

Invoke-WebRequest 'https://raw.githubusercontent.com/PowershellFrameworkCollective/PSFramework.NuGet/refs/heads/master/bootstrap.ps1' -UseBasicParsing | Invoke-Expression

$workingDirectory = Split-Path $PSScriptRoot
$config = Import-PowerShellDataFile -Path "$PSScriptRoot\build.config.psd1"

# Prepare output path and copy function folder
Remove-Item -Path "$workingDirectory/publish" -Recurse -Force -ErrorAction Ignore
$buildFolder = New-Item -Path $workingDirectory -Name 'publish' -ItemType Directory -Force -ErrorAction Stop
Copy-Item -Path "$workingDirectory/function/*" -Destination $buildFolder.FullName -Recurse -Force

#region Handle Modules
# Process Dependencies
$requiredModules = (Import-PowerShellDataFile -Path "$workingDirectory/þnameþ/þnameþ.psd1").RequiredModules
foreach ($module in $requiredModules) {
if ($module -is [string]) {
Save-PSFModule -Name $module -Path "$($buildFolder.FullName)/modules" -Force -Repository $Repository
}
else {
$versionParam = @{}
if ($module.RequiredVersion) { $versionParam.Version = $module.RequiredVersion }
elseif ($module.ModuleVersion) { $versionParam.Version = "[$($module.ModuleVersion)-" }
Save-PSFModule -Name $module.ModuleName @versionParam -Path "$($buildFolder.FullName)/modules" -Force -Repository $Repository
}
}

#region Handle the Requirements for Flex Consumption Plans
if ($config.General.FlexConsumption) {
# Resolve New Dependencies
$mdepsFile = Join-Path -Path $buildFolder.FullName -ChildPath 'requirements.psd1'
$mDeps = Import-PowerShellDataFile -Path $mdepsFile
$requiredModules = foreach ($name in $mDeps.Keys) {
if ($mDeps.$name -match '\*') {
@{
Name = $name
Version = '[{0}.0.0-{1}.0.0)' -f $mDeps.$name.Split('.')[0], (1 + $mDeps.$name.Split('.')[0])
}
}
else {
@{
Name = $name
Version = $mDeps.$name
}
}
}

# Inject New Dependencies
foreach ($module in $requiredModules) {
Save-PSFModule @module -Path "$($buildFolder.FullName)/modules" -Force -Repository $Repository
}

# Disable Managed Dependencies
$hostFile = Join-Path -Path $buildFolder.FullName -ChildPath 'host.json'
$hostCfg = Get-Content -Path $hostFile | ConvertFrom-Json
$hostCfg.managedDependency.enabled = $false
$hostCfg | ConvertTo-Json -Depth 99 | Set-Content -Path $hostFile
}
#endregion Handle the Requirements for Flex Consumption Plans

# Process Function Module
Copy-Item -Path "$workingDirectory/þnameþ" -Destination "$($buildFolder.FullName)/modules" -Force -Recurse
$commands = Get-ChildItem -Path "$($buildFolder.FullName)/modules/þnameþ/Functions" -Recurse -Filter *.ps1 | ForEach-Object BaseName
Update-PSFModuleManifest -Path "$($buildFolder.FullName)/modules/þnameþ/þnameþ.psd1" -FunctionsToExport $commands
#endregion Handle Modules

#region Triggers
# Generate Http Trigger
$httpCode = Get-Content -Path "$PSScriptRoot\functionHttp\run.ps1" | Join-String -Separator "`n"
$httpConfig = Get-Content -Path "$PSScriptRoot\functionHttp\function.json" | Join-String -Separator "`n"
foreach ($command in Get-ChildItem -Path "$workingDirectory\þnameþ\functions\httpTrigger" -Recurse -File -Filter *.ps1) {
$authLevel = $config.HttpTrigger.AuthLevel
if ($config.HttpTrigger.AuthLevelOverrides.$($command.BaseName)) {
$authLevel = $config.HttpTrigger.AuthLevelOverrides.$($command.BaseName)
}
$methods = $config.HttpTrigger.Methods
if ($config.HttpTrigger.MethodOverrides.$($command.BaseName)) {
$methods = $config.HttpTrigger.MethodOverrides.$($command.BaseName)
}
$endpointFolder = New-Item -Path $buildFolder.FullName -Name $command.BaseName -ItemType Directory
$httpCode -replace '%COMMAND%', $command.BaseName | Set-Content -Path "$($endpointFolder.FullName)\run.ps1"
$httpConfig -replace '%AUTHLEVEL%', $authLevel -replace '%METHODS%', ($methods -join '", "') | Set-Content -Path "$($endpointFolder.FullName)\function.json"
}


# Generate Event Grid Trigger
$eventGridCode = Get-Content -Path "$PSScriptRoot\functionEventGrid\run.ps1" | Join-String -Separator "`n"
$eventGridConfig = Get-Content -Path "$PSScriptRoot\functionEventGrid\function.json" | Join-String -Separator "`n"
foreach ($command in Get-ChildItem -Path "$workingDirectory\þnameþ\functions\eventGridTrigger" -Recurse -File -Filter *.ps1) {
$authLevel = $config.EventGridTrigger.AuthLevel
if ($config.EventGridTrigger.AuthLevelOverrides.$($command.BaseName)) {
$authLevel = $config.EventGridTrigger.AuthLevelOverrides.$($command.BaseName)
}
$methods = $config.EventGridTrigger.Methods
if ($config.EventGridTrigger.MethodOverrides.$($command.BaseName)) {
$methods = $config.EventGridTrFigger.MethodOverrides.$($command.BaseName)
}
$endpointFolder = New-Item -Path $buildFolder.FullName -Name $command.BaseName -ItemType Directory
$eventGridCode -replace '%COMMAND%', $command.BaseName | Set-Content -Path "$($endpointFolder.FullName)\run.ps1"
$eventGridConfig -replace '%AUTHLEVEL%', $authLevel -replace '%METHODS%', ($methods -join '", "') | Set-Content -Path "$($endpointFolder.FullName)\function.json"
}

# Generate Timer Trigger
$timerCode = Get-Content -Path "$PSScriptRoot\functionTimer\run.ps1" | Join-String -Separator "`n"
$timerConfig = Get-Content -Path "$PSScriptRoot\functionTimer\function.json" | Join-String -Separator "`n"
foreach ($command in Get-ChildItem -Path "$workingDirectory\þnameþ\functions\timerTrigger" -Recurse -File -Filter *.ps1) {
$schedule = $config.TimerTrigger.Schedule
if ($config.TimerTrigger.ScheduleOverrides.$($command.BaseName)) {
$schedule = $config.TimerTrigger.ScheduleOverrides.$($command.BaseName)
}
$endpointFolder = New-Item -Path $buildFolder.FullName -Name $command.BaseName -ItemType Directory
$timerCode -replace '%COMMAND%', $command.BaseName | Set-Content -Path "$($endpointFolder.FullName)\run.ps1"
$timerConfig -replace '%SCHEDULE%', $schedule | Set-Content -Path "$($endpointFolder.FullName)\function.json"
}
#endregion Triggers

# Package & Cleanup
Remove-Item -Path "$workingDirectory/Function.zip" -Recurse -Force -ErrorAction Ignore
Compress-Archive -Path "$($buildFolder.FullName)/*" -DestinationPath "$workingDirectory/Function.zip"
Remove-Item -Path $buildFolder.FullName -Recurse -Force -ErrorAction Ignore

if (-not $AppRg -or -not $AppName) { return }

Write-Host "Publishing Function App to $AppRg/$AppName"
$null = Publish-AzWebApp -ResourceGroupName $AppRG -Name $AppName -ArchivePath "$workingDirectory/Function.zip" -Confirm:$false -Force
Write-Host "Publishing Function App to $AppRg/$AppName - Done"

if (-not $Restart) { return }

Write-Host "Restarting Function App"
$null = Stop-AzWebApp -ResourceGroupName $AppRG -Name $AppName
$null = Start-AzWebApp -ResourceGroupName $AppRG -Name $AppName
Write-Host "Restarting Function App - Done"
2 changes: 1 addition & 1 deletion 2 templates/AzureFunction/function/host.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,6 @@
},
"extensionBundle": {
"id": "Microsoft.Azure.Functions.ExtensionBundle",
"version": "[3.*, 4.0.0)"
"version": "[4.*, 5.0.0)"
}
}
11 changes: 8 additions & 3 deletions 11 templates/AzureFunction/function/profile.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@ if ($env:MSI_SECRET -and (Get-Module -ListAvailable Az.Accounts))
Connect-AzAccount -Identity
}

# Uncomment the next line to enable legacy AzureRm alias in Azure PowerShell.
# Enable-AzureRmAlias
# You can also define functions or aliases that can be referenced in any of your PowerShell functions.
$pathDelimiter = ';'
if (-not $IsWindows) { $pathDelimiter = ':' }
$modulePaths = $env:PSModulePath -split $pathDelimiter
$ourModulePath = Join-Path -Path $PSScriptRoot -ChildPath Modules

if ($modulePaths -notcontains $ourModulePath) {
$env:PSModulePath = $ourModulePath, $env:PSModulePath -join $pathDelimiter
}
Loading
Morty Proxy This is a proxified and sanitized view of the page, visit original site.