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
2 changes: 1 addition & 1 deletion 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.11.146'
ModuleVersion = '2.2.11.163'

# ID used to uniquely identify this module
GUID = '37dd5fce-e7b5-4d57-ac37-832055ce49d6'
Expand Down
12 changes: 11 additions & 1 deletion PSModuleDevelopment/changelog.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,24 @@
# Changelog

## Unreleased
## 2.2.11.163 (2024-02-25)

+ New: Template ApplockerPipeline - A project that can be used to generate AppLocker policies across environments
+ Upd: Template AzureFunction - Added automatic Endpoint generation based on functions defined in the module
+ Upd: Template PSFProject - Improved PSScriptAnalyzer test results
+ Upd: Template PSFProject - Extended list of blacklisted commands
+ Upd: Template PSFProject - Build logic now also supports compiling the C# solution
+ Upd: Template PSFModule - Improved PSScriptAnalyzer test results
+ Upd: Template PSFModule - Extended list of blacklisted commands
+ Upd: Template PSFHelp - Improved PSScriptAnalyzer test results
+ Upd: Template PSFHelp - Extended list of blacklisted commands
+ Upd: Template MiniModule - Extended list of blacklisted commands
+ Fix: Template PSFProject - Help test fails on PS7.4
+ Fix: Template PSFProject - Help test added ProgressAction to common parameters
+ Fix: Template PSFModule - Help test fails on PS7.4
+ Fix: Template PSFModule - Help test added ProgressAction to common parameters
+ Fix: Template PSFHelp - Help test fails on PS7.4
+ Fix: Template PSFHelp - Help test added ProgressAction to common parameters
+ Fix: Template MiniModule - Help test - added ProgressAction to common parameters

## 2.2.11.146 (2023-05-31)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,11 @@
PS C:\> Invoke-PSMDTemplate -TemplateName "module" -Name "MyModule"

Creates a project based on the module template with the name "MyModule"

.EXAMPLE
PS C:\> Invoke-PSMDTemplate MiniModule -Parameters @{ Author = 'Fred' }

Creates a new project based on the template MiniModule and predefines the value for the "Author" placeholder.
#>
[Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSPossibleIncorrectUsageOfAssignmentOperator", "")]
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSReviewUnusedParameter', '')]
Expand Down
26 changes: 26 additions & 0 deletions templates/AzureFunction/build/build.config.psd1
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
@{
TimerTrigger = @{
# Default Schedule for timed executions
Schedule = '0 5 * * * *'

# Different Schedules for specific timed endpoints
ScheduleOverrides = @{
# 'Update-Whatever' = '0 5 12 * * *'
}
}

HttpTrigger = @{
<#
AuthLevels:
https://learn.microsoft.com/en-us/azure/azure-functions/functions-bindings-http-webhook-trigger?tabs=python-v2%2Cisolated-process%2Cnodejs-v4%2Cfunctionsv2&pivots=programming-language-csharp#http-auth

anonymous: No Token needed (combine with Identity Provider for Entra ID auth without also needing a token)
function: (default) Require a function-endpoint-specific token with the request
admin: Require a Function-App-global admin token (master key) for the request
#>
AuthLevel = 'function'
AuthLevelOverrides = @{
# 'Set-Foo' = 'anonymous'
}
}
}
49 changes: 45 additions & 4 deletions templates/AzureFunction/build/build.ps1
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
param (
[string]
$Repository = 'PSGallery'
[string]
$Repository = 'PSGallery',

[string]
$AppRg,

[string]
$AppName
)
$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
Expand All @@ -12,12 +19,46 @@ Copy-Item -Path "$workingDirectory/function/*" -Destination $buildFolder.FullNam
# 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
Save-Module -Name $module -Path "$($buildFolder.FullName)/modules" -Force -Repository $Repository
}

# 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

# Generate Http Trigger
$httpCode = Get-Content -Path "$PSScriptRoot\functionHttp\run.ps1" | Join-String "`n"
$httpConfig = Get-Content -Path "$PSScriptRoot\functionHttp\function.json" | Join-String "`n"
foreach ($command in Get-ChildItem -Path "$workingDirectory\þnameþ\functions\httpTrigger" -Recurse -File -Filter *.ps1) {
$authLevel = $config.HttpTrigger.AuthLevel
if ($config.HttpTrigger.AuthLevelOverride.$($command.BaseName)) {
$authLevel = $config.HttpTrigger.AuthLevelOverride.$($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 | Set-Content -Path "$($endpointFolder.FullName)\function.json"
}

# Generate Timer Trigger
$timerCode = Get-Content -Path "$PSScriptRoot\functionTimer\run.ps1" | Join-String "`n"
$timerConfig = Get-Content -Path "$PSScriptRoot\functionTimer\function.json" | Join-String "`n"
foreach ($command in Get-ChildItem -Path "$workingDirectory\þnameþ\functions\timerTrigger" -Recurse -File -Filter *.ps1) {
$schedule = $config.TimerTrigger.Schedule
if ($config.TimerTrigger.ScheduleOverride.$($command.BaseName)) {
$schedule = $config.TimerTrigger.ScheduleOverride.$($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"
}

# 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
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
}
20 changes: 20 additions & 0 deletions templates/AzureFunction/build/functionHttp/function.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"bindings": [
{
"authLevel": "%AUTHLEVEL%",
"type": "httpTrigger",
"direction": "in",
"name": "Request",
"methods": [
"get",
"post"
]
},
{
"type": "http",
"direction": "out",
"name": "Response"
}
],
"disabled": false
}
24 changes: 24 additions & 0 deletions templates/AzureFunction/build/functionHttp/run.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
param (
$Request,

$TriggerMetadata
)


Write-Host "Trigger: %COMMAND% has been invoked"

$parameters = Get-RestParameter -Request $Request -Command %COMMAND%

try {
$results = %COMMAND% @parameters -ErrorAction Stop
}
catch {
$_ | Out-String | ForEach-Object {
foreach ($line in ($_ -split "`n")) {
Write-Warning $line
}
}
Write-FunctionResult -Status InternalServerError -Body "$_"
return
}
Write-FunctionResult -Status OK -Body $results
11 changes: 11 additions & 0 deletions templates/AzureFunction/build/functionTimer/function.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"bindings": [
{
"name": "Timer",
"type": "timerTrigger",
"direction": "in",
"schedule": "%SCHEDULE%"
}
],
"disabled": false
}
11 changes: 11 additions & 0 deletions templates/AzureFunction/build/functionTimer/run.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Input bindings are passed in via param block.
param ($Timer)

$ErrorActionPreference = 'Stop'
Write-Host "%COMMAND% start time: $((Get-Date).ToUniversalTime())"
try { %COMMAND% }
catch {
Write-Warning "%COMMAND% failed: $_ $((Get-Date).ToUniversalTime())"
throw "%COMMAND% failed: $_ $((Get-Date).ToUniversalTime())"
}
Write-Host "%COMMAND% end time: $((Get-Date).ToUniversalTime())"
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Functions: http Trigger

Each function placed under this folder will be exposed as an http-trigger function endpoint on build.
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Functions: Non-Published

Functions placed here will not be published as a function endpoint
9 changes: 9 additions & 0 deletions templates/AzureFunction/þnameþ/functions/readme.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
# Functions

Place all your function code here
One file per function, file should have the same name as the function.

There are three subdirectories:

+ httpTrigger: Each function placed in this folder will be exposed via httpTrigger as a function endpoint.
+ timerTrigger: Each function placed in this folder will be registered as a timer-triggered function endpoint.
+ nonPublished: Any function placed here will be exposed by the module, but not as a function endpoint.

The function endpoints are generated while running build.ps1.
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Functions: Timer Trigger

Each function placed under this folder will be exposed as an timer-trigger function endpoint on build.
3 changes: 3 additions & 0 deletions templates/AzureFunction/þnameþ/internal/functions/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Functions (Internal)

Place all your internal helper function code here
3 changes: 3 additions & 0 deletions templates/AzureFunction/þnameþ/internal/scripts/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Scripts

The place where all the code goes that should be run on import only.
4 changes: 1 addition & 3 deletions templates/AzureFunction/þnameþ/þnameþ.psd1
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,7 @@
# NestedModules = @()

# Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export.
FunctionsToExport = @(

)
FunctionsToExport = '*'

# Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export.
# CmdletsToExport = '*'
Expand Down
9 changes: 8 additions & 1 deletion templates/AzureFunction/þnameþ/þnameþ.psm1
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
foreach ($file in Get-ChildItem $PSScriptRoot\functions -Recurse -Filter '*.ps1') {
$script:moduleRoot = $PSScriptRoot
foreach ($file in Get-ChildItem $PSScriptRoot\internal\functions -Recurse -Filter '*.ps1') {
. $file.FullName
}
foreach ($file in Get-ChildItem $PSScriptRoot\functions -Recurse -Filter '*.ps1') {
. $file.FullName
}
foreach ($file in Get-ChildItem $PSScriptRoot\internal\scripts -Recurse -Filter '*.ps1') {
. $file.FullName
}
14 changes: 14 additions & 0 deletions templates/MiniModule/tests/general/FileIntegrity.Exceptions.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,20 @@ $global:BannedCommands = @(

# Use Get-WinEvent instead
'Get-EventLog'

# User Preference should not be used in automation
'Clear-Host' # Console Screen belongs to the user
'Set-Location' # Console path belongs to the user. Use $PSScriptRoot instead.

# Dynamic Variables are undesirable. Use hashtable instead.
'Get-Variable'
'Set-Variable'
'Clear-Variable'
'Remove-Variable'
'New-Variable'

# Dynamic Code execution should not require this
'Invoke-Expression' # Consider splatting instead. Yes, you can splat parameters for external applications!
)

<#
Expand Down
2 changes: 1 addition & 1 deletion templates/MiniModule/tests/general/Help.Tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ foreach ($command in $commands) {

Context "Test parameter help for $commandName" {

$common = 'Debug', 'ErrorAction', 'ErrorVariable', 'InformationAction', 'InformationVariable', 'OutBuffer', 'OutVariable', 'PipelineVariable', 'Verbose', 'WarningAction', 'WarningVariable'
$common = 'Debug', 'ErrorAction', 'ErrorVariable', 'InformationAction', 'InformationVariable', 'OutBuffer', 'OutVariable', 'PipelineVariable', 'Verbose', 'WarningAction', 'WarningVariable', 'ProgressAction'

$parameters = $command.ParameterSets.Parameters | Sort-Object -Property Name -Unique | Where-Object Name -notin $common
$parameterNames = $parameters.Name
Expand Down
2 changes: 1 addition & 1 deletion templates/PSFProject/PSMDTemplate.ps1
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
@{
TemplateName = 'PSFProject'
Version = "1.3.3"
Version = "1.3.4"
AutoIncrementVersion = $true
Tags = 'module','psframework'
Author = 'Friedrich Weinmann'
Expand Down
13 changes: 12 additions & 1 deletion templates/PSFProject/build/vsts-build.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@ param (
$SkipPublish,

[switch]
$AutoVersion
$AutoVersion,

[switch]
$Build
)

#region Handle Working Directory Defaults
Expand All @@ -33,6 +36,14 @@ if (-not $WorkingDirectory)
if (-not $WorkingDirectory) { $WorkingDirectory = Split-Path $PSScriptRoot }
#endregion Handle Working Directory Defaults

# Build Library
if ($Build) {
dotnet build "$WorkingDirectory\library\þnameþ.sln"
if ($LASTEXITCODE -ne 0) {
throw "Failed to build þnameþ.dll!"
}
}

# Prepare publish folder
Write-PSFMessage -Level Important -Message "Creating and populating publishing directory"
$publishDir = New-Item -Path $WorkingDirectory -Name publish -ItemType Directory -Force
Expand Down
14 changes: 14 additions & 0 deletions templates/PSFTests/general/FileIntegrity.Exceptions.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,20 @@ $global:BannedCommands = @(

# Use Get-WinEvent instead
'Get-EventLog'

# User Preference should not be used in automation
'Clear-Host' # Console Screen belongs to the user
'Set-Location' # Console path belongs to the user. Use $PSScriptRoot instead.

# Dynamic Variables are undesirable. Use hashtable instead.
'Get-Variable'
'Set-Variable'
'Clear-Variable'
'Remove-Variable'
'New-Variable'

# Dynamic Code execution should not require this
'Invoke-Expression' # Consider splatting instead. Yes, you can splat parameters for external applications!
)

<#
Expand Down
2 changes: 1 addition & 1 deletion templates/PSFTests/general/Help.Tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ foreach ($command in $commands) {

Context "Test parameter help for $commandName" {

$common = 'Debug', 'ErrorAction', 'ErrorVariable', 'InformationAction', 'InformationVariable', 'OutBuffer', 'OutVariable', 'PipelineVariable', 'Verbose', 'WarningAction', 'WarningVariable'
$common = 'Debug', 'ErrorAction', 'ErrorVariable', 'InformationAction', 'InformationVariable', 'OutBuffer', 'OutVariable', 'PipelineVariable', 'Verbose', 'WarningAction', 'WarningVariable', 'ProgressAction'

$parameters = $command.ParameterSets.Parameters | Sort-Object -Property Name -Unique | Where-Object Name -notin $common
$parameterNames = $parameters.Name
Expand Down