Merge pull request #19 from KevinMarquette/commonfiles !deploy
Add Commonfiles
This commit is contained in:
43
.gitignore
vendored
Normal file
43
.gitignore
vendored
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
/output/
|
||||||
|
/debug*.ps1
|
||||||
|
/temp*.ps1
|
||||||
|
|
||||||
|
# Most of these heavily cannibalized by Travis Drake from https://gist.github.com/kmorcinek/2710267
|
||||||
|
|
||||||
|
# C# VS build detritus
|
||||||
|
/.vs/
|
||||||
|
/*/[Bb]in/
|
||||||
|
/*/[Oo]bj/
|
||||||
|
**/packages/*
|
||||||
|
|
||||||
|
# Except this, this needs to be checked in when present
|
||||||
|
!**/packages/build/
|
||||||
|
|
||||||
|
# More C# / Visual Studio detritus
|
||||||
|
*.suo
|
||||||
|
*.user
|
||||||
|
*.sln.docstates
|
||||||
|
*.psess
|
||||||
|
*.vsp
|
||||||
|
*.vspx
|
||||||
|
project.lock.json
|
||||||
|
_UpgradeReport_Files/
|
||||||
|
UpgradeLog*.XML
|
||||||
|
UpgradeLog*.htm
|
||||||
|
|
||||||
|
# SASS Compiler cache
|
||||||
|
.sass-cache
|
||||||
|
|
||||||
|
# Mac OS stuff
|
||||||
|
.DS_Store*
|
||||||
|
Icon?
|
||||||
|
|
||||||
|
# Windows image file caches
|
||||||
|
Thumbs.db
|
||||||
|
ehthumbs.db
|
||||||
|
|
||||||
|
# Folder config file
|
||||||
|
Desktop.ini
|
||||||
|
|
||||||
|
# Recycle Bin used on file shares
|
||||||
|
$RECYCLE.BIN/
|
||||||
28
.vscode/settings.json
vendored
28
.vscode/settings.json
vendored
@@ -1,4 +1,28 @@
|
|||||||
// Place your settings in this file to overwrite default and user settings.
|
// Place your settings in this file to overwrite default and user settings.
|
||||||
{
|
{
|
||||||
"powershell.codeFormatting.preset": "Allman"
|
//-------- Editor configuration --------
|
||||||
}
|
"editor.insertSpaces": true,
|
||||||
|
"editor.tabSize": 4,
|
||||||
|
|
||||||
|
//-------- Files configuration --------
|
||||||
|
"files.autoGuessEncoding": false,
|
||||||
|
"files.insertFinalNewline": true,
|
||||||
|
"files.trimTrailingWhitespace": true,
|
||||||
|
"search.exclude": {
|
||||||
|
"**/Tests/Data*": true
|
||||||
|
},
|
||||||
|
|
||||||
|
//-------- PowerShell configuration --------
|
||||||
|
"powershell.codeFormatting.alignPropertyValuePairs": true,
|
||||||
|
"powershell.codeFormatting.preset": "Allman",
|
||||||
|
"powershell.scriptAnalysis.settingsPath": "./ScriptAnalyzerSettings.psd1",
|
||||||
|
|
||||||
|
//-------- Language configuration --------
|
||||||
|
"[json]": {
|
||||||
|
"editor.tabSize": 2
|
||||||
|
},
|
||||||
|
|
||||||
|
"[xml]": {
|
||||||
|
"editor.tabSize": 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
95
.vscode/tasks.json
vendored
Normal file
95
.vscode/tasks.json
vendored
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
// Available variables which can be used inside of strings:
|
||||||
|
// ${workspaceRoot}: The root folder of the team
|
||||||
|
// ${file}: The current opened file
|
||||||
|
// ${relativeFile}: The current opened file relative to workspaceRoot
|
||||||
|
// ${fileBasename}: The current opened file's basename
|
||||||
|
// ${fileDirname}: The current opened file's dirname
|
||||||
|
// ${fileExtname}: The current opened file's extension
|
||||||
|
// ${cwd}: The current working directory of the spawned process
|
||||||
|
{
|
||||||
|
"version": "2.0.0",
|
||||||
|
"windows": {
|
||||||
|
"options": {
|
||||||
|
"shell": {
|
||||||
|
"executable": "powershell.exe",
|
||||||
|
"args": [ "-NoProfile", "-ExecutionPolicy", "Bypass", "-Command" ]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"linux": {
|
||||||
|
"options": {
|
||||||
|
"shell": {
|
||||||
|
"executable": "/usr/bin/pwsh",
|
||||||
|
"args": [ "-NoProfile", "-Command" ]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"osx": {
|
||||||
|
"options": {
|
||||||
|
"shell": {
|
||||||
|
"executable": "/usr/local/bin/pwsh",
|
||||||
|
"args": [ "-NoProfile", "-Command" ]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"tasks": [
|
||||||
|
{
|
||||||
|
"label": "Default",
|
||||||
|
"type": "shell",
|
||||||
|
"problemMatcher": [ "$msCompile" ],
|
||||||
|
"group": {
|
||||||
|
"kind": "build",
|
||||||
|
"isDefault": true
|
||||||
|
},
|
||||||
|
"command": "Invoke-Build -Task Default -File './Module.build.ps1'"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "Analyze",
|
||||||
|
"type": "shell",
|
||||||
|
"problemMatcher": [ "$msCompile" ],
|
||||||
|
"command": "Invoke-Build -Task Analyze -File './Module.build.ps1'"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "Build",
|
||||||
|
"type": "shell",
|
||||||
|
"problemMatcher": [ "$msCompile" ],
|
||||||
|
"command": "Invoke-Build -Task Build -File './Module.build.ps1'"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "Clean",
|
||||||
|
"type": "shell",
|
||||||
|
"problemMatcher": [ "$msCompile" ],
|
||||||
|
"command": "Invoke-Build -Task Clean -File './Module.build.ps1'"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "Helpify",
|
||||||
|
"type": "shell",
|
||||||
|
"problemMatcher": [ "$msCompile" ],
|
||||||
|
"command": "Invoke-Build -Task Helpify -File './Module.build.ps1'"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "Install",
|
||||||
|
"type": "shell",
|
||||||
|
"problemMatcher": [ "$msCompile" ],
|
||||||
|
"command": "Invoke-Build -Task Install -File './Module.build.ps1'"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "Test",
|
||||||
|
"type": "shell",
|
||||||
|
"problemMatcher": [ "$msCompile" ],
|
||||||
|
"command": "Invoke-Build -Task Test -File './Module.build.ps1'"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "Uninstall",
|
||||||
|
"type": "shell",
|
||||||
|
"problemMatcher": [ "$msCompile" ],
|
||||||
|
"command": "Invoke-Build -Task Uninstall -File './Module.build.ps1'"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "?",
|
||||||
|
"type": "shell",
|
||||||
|
"problemMatcher": [],
|
||||||
|
"command": "Invoke-Build -Task ? -File './Module.build.ps1'"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
17
BuildTasks/Analyze.Task.ps1
Normal file
17
BuildTasks/Analyze.Task.ps1
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
task Analyze {
|
||||||
|
$params = @{
|
||||||
|
IncludeDefaultRules = $true
|
||||||
|
Path = $ManifestPath
|
||||||
|
Settings = "$BuildRoot\ScriptAnalyzerSettings.psd1"
|
||||||
|
Severity = 'Warning'
|
||||||
|
}
|
||||||
|
|
||||||
|
"Analyzing $ManifestPath..."
|
||||||
|
$results = Invoke-ScriptAnalyzer @params
|
||||||
|
if ($results)
|
||||||
|
{
|
||||||
|
'One or more PSScriptAnalyzer errors/warnings were found.'
|
||||||
|
'Please investigate or add the required SuppressMessage attribute.'
|
||||||
|
$results | Format-Table -AutoSize
|
||||||
|
}
|
||||||
|
}
|
||||||
18
BuildTasks/BuildManifest.Task.ps1
Normal file
18
BuildTasks/BuildManifest.Task.ps1
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
|
||||||
|
taskx BuildManifest @{
|
||||||
|
Inputs = (Get-ChildItem -Path $Source -Recurse -File)
|
||||||
|
Outputs = $ManifestPath
|
||||||
|
Jobs = {
|
||||||
|
"Updating [$ManifestPath]..."
|
||||||
|
Copy-Item -Path "$Source\$ModuleName.psd1" -Destination $ManifestPath
|
||||||
|
|
||||||
|
$functions = Get-ChildItem -Path "$ModuleName\Public\*.ps1" -ErrorAction 'Ignore' |
|
||||||
|
Where-Object 'Name' -notmatch 'Tests'
|
||||||
|
|
||||||
|
if ($functions)
|
||||||
|
{
|
||||||
|
'Setting FunctionsToExport...'
|
||||||
|
Set-ModuleFunctions -Name $ManifestPath -FunctionsToExport $functions.BaseName
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
214
BuildTasks/BuildModule.Task.ps1
Normal file
214
BuildTasks/BuildModule.Task.ps1
Normal file
@@ -0,0 +1,214 @@
|
|||||||
|
|
||||||
|
# namespaces for Move-Statement
|
||||||
|
using namespace System.Collections.Generic
|
||||||
|
using namespace System.IO
|
||||||
|
using namespace System.Management.Automation
|
||||||
|
|
||||||
|
function Import-ClassOrder
|
||||||
|
{
|
||||||
|
[cmdletbinding()]
|
||||||
|
param($cName,$Map)
|
||||||
|
Write-Verbose "Checking on [$cName]"
|
||||||
|
if($Map.ContainsKey($cName) -and $Map[$cName].Imported -ne $true)
|
||||||
|
{
|
||||||
|
if($Map[$cName].Base)
|
||||||
|
{
|
||||||
|
Write-Verbose " Base class [$($Map[$cName].Base)]"
|
||||||
|
Import-ClassOrder $Map[$cName].Base $Map
|
||||||
|
}
|
||||||
|
$cPath = $Map[$cName].Path
|
||||||
|
Write-Verbose "Dot Sourcing [$cPath]"
|
||||||
|
$cPath
|
||||||
|
$Map[$cName].Imported = $true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Temporarily added this here to be refactored/replaced by LDModuleBuilder Module
|
||||||
|
|
||||||
|
|
||||||
|
function Move-Statement
|
||||||
|
{
|
||||||
|
<#
|
||||||
|
.SYNOPSIS
|
||||||
|
Moves statements containing a specified token to the specified index in a file.
|
||||||
|
.DESCRIPTION
|
||||||
|
Move-Statement moves statements containing a specified token, to the specified index
|
||||||
|
in a file. This can be used when building a module to move any using directives and
|
||||||
|
#Requires statements to the top of a file.
|
||||||
|
.PARAMETER Path
|
||||||
|
Specifies the path to an item to get its contents.
|
||||||
|
.PARAMETER Type
|
||||||
|
Specifies the type of tokens to examine. Accepted values include "Comment" and "Keyword".
|
||||||
|
.PARAMETER Token
|
||||||
|
Specifies the contents to filter on when examining a supplied token.
|
||||||
|
.PARAMETER Index
|
||||||
|
Specifies the line to move a statement to. Each line in an item has a corresponding
|
||||||
|
index, starting from 0.
|
||||||
|
.EXAMPLE
|
||||||
|
Move-Statement -Path $Path -Type 'Comment', 'Keyword' -Token '#Requires', 'using' -Index 0
|
||||||
|
|
||||||
|
Moves any using directives or #Requires statements to the top of a file.
|
||||||
|
.NOTES
|
||||||
|
Copy/Paste from LDModuleBuilder
|
||||||
|
#>
|
||||||
|
[CmdletBinding(SupportsShouldProcess)]
|
||||||
|
|
||||||
|
param(
|
||||||
|
[Parameter(Mandatory,
|
||||||
|
Position = 0,
|
||||||
|
ValueFromPipeline,
|
||||||
|
ValueFromPipelineByPropertyName)]
|
||||||
|
[ValidateNotNullOrEmpty()]
|
||||||
|
[ValidateScript({ Test-Path -Path $PSItem })]
|
||||||
|
[string] $Path,
|
||||||
|
|
||||||
|
[Parameter(Position = 1,
|
||||||
|
ValueFromPipelineByPropertyName)]
|
||||||
|
[ValidateNotNullOrEmpty()]
|
||||||
|
[ValidateSet('Comment', 'Keyword')]
|
||||||
|
[string[]] $Type = ('Comment', 'Keyword'),
|
||||||
|
|
||||||
|
[Parameter(Position = 2,
|
||||||
|
ValueFromPipelineByPropertyName)]
|
||||||
|
[ValidateNotNullOrEmpty()]
|
||||||
|
[string[]] $Token = ('#Requires', 'using'),
|
||||||
|
|
||||||
|
[Parameter(Position = 3,
|
||||||
|
ValueFromPipelineByPropertyName)]
|
||||||
|
[ValidateNotNullOrEmpty()]
|
||||||
|
[int] $Index = 0
|
||||||
|
)
|
||||||
|
|
||||||
|
process
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
$statements = [SortedSet[String]]::new(
|
||||||
|
[StringComparer]::InvariantCultureIgnoreCase
|
||||||
|
)
|
||||||
|
|
||||||
|
Write-Verbose -Message "Reading content from $Path..."
|
||||||
|
$content = [List[String]] ([File]::ReadLines($Path))
|
||||||
|
|
||||||
|
Write-Verbose -Message "Tokenizing content from $Path..."
|
||||||
|
$tokens = [PSParser]::Tokenize($content, [ref] $null)
|
||||||
|
|
||||||
|
$match = $Token -join '|'
|
||||||
|
|
||||||
|
Write-Verbose -Message 'Matching tokens...'
|
||||||
|
Write-Verbose -Message "Type = [$Type]; Token = [$Token]"
|
||||||
|
$keywords = $tokens.Where({
|
||||||
|
$PSItem.Type -in $Type -and
|
||||||
|
$PSItem.Content -imatch "^(?:$match)"
|
||||||
|
})
|
||||||
|
|
||||||
|
if (-not $keywords) {
|
||||||
|
Write-Verbose -Message 'No matching tokens found! Returning...'
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
$offset = 1
|
||||||
|
foreach ($keyword in $keywords)
|
||||||
|
{
|
||||||
|
$line = $keyword.StartLine - $offset
|
||||||
|
|
||||||
|
Write-Verbose -Message "Moving [$($content[$line])] to Index [$Index]..."
|
||||||
|
$null = $statements.Add($content[$line]),
|
||||||
|
$content.RemoveAt($line)
|
||||||
|
$offset++
|
||||||
|
}
|
||||||
|
|
||||||
|
[string[]] $comments, [string[]] $statements = $statements.Where({
|
||||||
|
$PSItem -match '^#'
|
||||||
|
}, 'Split')
|
||||||
|
|
||||||
|
foreach ($item in ($statements, $comments))
|
||||||
|
{
|
||||||
|
$content.Insert($Index, '')
|
||||||
|
$content.InsertRange($Index, $item)
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($PSCmdlet.ShouldProcess($Path, $MyInvocation.MyCommand.Name))
|
||||||
|
{
|
||||||
|
Write-Verbose -Message "Writing content to $Path..."
|
||||||
|
[File]::WriteAllLines($Path, $content)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
$PSCmdlet.ThrowTerminatingError($PSItem)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
taskx BuildModule @{
|
||||||
|
Inputs = (Get-ChildItem -Path $Source -Recurse -Filter *.ps1)
|
||||||
|
Outputs = $ModulePath
|
||||||
|
Jobs = {
|
||||||
|
$sb = [Text.StringBuilder]::new()
|
||||||
|
$null = $sb.AppendLine('$Script:PSModuleRoot = $PSScriptRoot')
|
||||||
|
|
||||||
|
# Class importer
|
||||||
|
$root = Join-Path -Path $source -ChildPath 'Classes'
|
||||||
|
"Load classes from [$root]"
|
||||||
|
$classFiles = Get-ChildItem -Path $root -Filter '*.ps1' -Recurse |
|
||||||
|
Where-Object Name -notlike '*.Tests.ps1'
|
||||||
|
|
||||||
|
$classes = @{}
|
||||||
|
|
||||||
|
foreach($file in $classFiles)
|
||||||
|
{
|
||||||
|
$name = $file.BaseName
|
||||||
|
$classes[$name] = @{
|
||||||
|
Name = $name
|
||||||
|
Path = $file.FullName
|
||||||
|
}
|
||||||
|
$data = Get-Content $file.fullname
|
||||||
|
foreach($line in $data)
|
||||||
|
{
|
||||||
|
if($line -match "\s+($Name)\s*(:|requires)\s*(?<baseclass>\w*)")
|
||||||
|
{
|
||||||
|
$classes[$name].Base = $Matches.baseclass
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$importOrder = foreach($className in $classes.Keys)
|
||||||
|
{
|
||||||
|
Import-ClassOrder $className $classes
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach($class in $importOrder)
|
||||||
|
{
|
||||||
|
"Importing [$class]..."
|
||||||
|
$null = $sb.AppendLine("# .$class")
|
||||||
|
$null = $sb.AppendLine([IO.File]::ReadAllText($class))
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($folder in ($Folders -ne 'Classes'))
|
||||||
|
{
|
||||||
|
if (Test-Path -Path "$Source\$folder")
|
||||||
|
{
|
||||||
|
$null = $sb.AppendLine("# Importing from [$Source\$folder]")
|
||||||
|
$files = Get-ChildItem -Path "$Source\$folder\*.ps1" |
|
||||||
|
Where-Object 'Name' -notlike '*.Tests.ps1'
|
||||||
|
|
||||||
|
foreach ($file in $files)
|
||||||
|
{
|
||||||
|
$name = $file.Fullname.Replace($buildroot, '')
|
||||||
|
|
||||||
|
"Importing [$($file.FullName)]..."
|
||||||
|
$null = $sb.AppendLine("# .$name")
|
||||||
|
$null = $sb.AppendLine([IO.File]::ReadAllText($file.FullName))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
"Creating Module [$ModulePath]..."
|
||||||
|
$null = New-Item -Path (Split-path $ModulePath) -ItemType Directory -ErrorAction SilentlyContinue -Force
|
||||||
|
Set-Content -Path $ModulePath -Value $sb.ToString() -Encoding 'UTF8'
|
||||||
|
|
||||||
|
'Moving "#Requires" statements and "using" directives...'
|
||||||
|
Move-Statement -Path $ModulePath -Type 'Comment', 'Keyword' -Token '#Requires', 'using' -Index 0
|
||||||
|
}
|
||||||
|
}
|
||||||
12
BuildTasks/Clean.Task.ps1
Normal file
12
BuildTasks/Clean.Task.ps1
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
task Clean {
|
||||||
|
if (Test-Path $Output)
|
||||||
|
{
|
||||||
|
"Cleaning Output files in [$Output]..."
|
||||||
|
$null = Get-ChildItem -Path $Output -File -Recurse |
|
||||||
|
Remove-Item -Force -ErrorAction 'Ignore'
|
||||||
|
|
||||||
|
"Cleaning Output directories in [$Output]..."
|
||||||
|
$null = Get-ChildItem -Path $Output -Directory -Recurse |
|
||||||
|
Remove-Item -Recurse -Force -ErrorAction 'Ignore'
|
||||||
|
}
|
||||||
|
}
|
||||||
14
BuildTasks/Compile.Task.ps1
Normal file
14
BuildTasks/Compile.Task.ps1
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
taskx Compile @{
|
||||||
|
If = (Get-ChildItem -Path $BuildRoot -Include *.csproj -Recurse)
|
||||||
|
Inputs = {
|
||||||
|
Get-ChildItem $BuildRoot -Recurse -File -Include *.cs
|
||||||
|
}
|
||||||
|
Outputs = "$Destination\bin\$ModuleName.dll"
|
||||||
|
Jobs = {
|
||||||
|
# This build command requires .Net Core
|
||||||
|
"Building Module"
|
||||||
|
$csproj = Get-ChildItem -Path $BuildRoot -Include *.csproj -Recurse
|
||||||
|
$folder = Split-Path $csproj
|
||||||
|
dotnet build $folder -c Release -o $Destination\bin
|
||||||
|
}
|
||||||
|
}
|
||||||
29
BuildTasks/Copy.Task.ps1
Normal file
29
BuildTasks/Copy.Task.ps1
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
|
||||||
|
task Copy {
|
||||||
|
"Creating Directory [$Destination]..."
|
||||||
|
$null = New-Item -ItemType 'Directory' -Path $Destination -ErrorAction 'Ignore'
|
||||||
|
|
||||||
|
$files = Get-ChildItem -Path $Source -File |
|
||||||
|
Where-Object 'Name' -notmatch "$ModuleName\.ps[dm]1"
|
||||||
|
|
||||||
|
foreach ($file in $files)
|
||||||
|
{
|
||||||
|
'Creating [.{0}]...' -f $file.FullName.Replace($buildroot, '')
|
||||||
|
Copy-Item -Path $file.FullName -Destination $Destination -Force
|
||||||
|
}
|
||||||
|
|
||||||
|
$directories = Get-ChildItem -Path $Source -Directory |
|
||||||
|
Where-Object 'Name' -notin $Folders
|
||||||
|
|
||||||
|
foreach ($directory in $directories)
|
||||||
|
{
|
||||||
|
'Creating [.{0}]...' -f $directory.FullName.Replace($buildroot, '')
|
||||||
|
Copy-Item -Path $directory.FullName -Destination $Destination -Recurse -Force
|
||||||
|
}
|
||||||
|
|
||||||
|
$license = Join-Path -Path $buildroot -ChildPath 'LICENSE'
|
||||||
|
if ( Test-Path -Path $license -PathType Leaf )
|
||||||
|
{
|
||||||
|
Copy-Item -Path $license -Destination $Destination
|
||||||
|
}
|
||||||
|
}
|
||||||
23
BuildTasks/GenerateHelp.Task.ps1
Normal file
23
BuildTasks/GenerateHelp.Task.ps1
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
|
||||||
|
task GenerateHelp {
|
||||||
|
if (-not(Get-ChildItem -Path $DocsPath -Filter '*.md' -Recurse -ErrorAction 'Ignore'))
|
||||||
|
{
|
||||||
|
"No Markdown help files to process. Skipping help file generation..."
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
$locales = (Get-ChildItem -Path $DocsPath -Directory).Name
|
||||||
|
foreach ($locale in $locales)
|
||||||
|
{
|
||||||
|
$params = @{
|
||||||
|
ErrorAction = 'SilentlyContinue'
|
||||||
|
Force = $true
|
||||||
|
OutputPath = "$Destination\en-US"
|
||||||
|
Path = "$DocsPath\en-US"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Generate the module's primary MAML help file.
|
||||||
|
"Creating new External help for [$ModuleName]..."
|
||||||
|
$null = New-ExternalHelp @params
|
||||||
|
}
|
||||||
|
}
|
||||||
41
BuildTasks/GenerateMarkdown.Task.ps1
Normal file
41
BuildTasks/GenerateMarkdown.Task.ps1
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
|
||||||
|
task GenerateMarkdown {
|
||||||
|
$module = Import-Module -FullyQualifiedName $ManifestPath -Force -PassThru
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if ($module.ExportedFunctions.Count -eq 0)
|
||||||
|
{
|
||||||
|
'No functions have been exported for this module. Skipping Markdown generation...'
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Get-ChildItem -Path $DocsPath -Filter '*.md' -Recurse)
|
||||||
|
{
|
||||||
|
$items = Get-ChildItem -Path $DocsPath -Directory -Recurse
|
||||||
|
foreach ($item in $items)
|
||||||
|
{
|
||||||
|
"Updating Markdown help in [$($item.BaseName)]..."
|
||||||
|
$null = Update-MarkdownHelp -Path $item.FullName -AlphabeticParamsOrder
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$params = @{
|
||||||
|
AlphabeticParamsOrder = $true
|
||||||
|
ErrorAction = 'SilentlyContinue'
|
||||||
|
Locale = 'en-US'
|
||||||
|
Module = $ModuleName
|
||||||
|
OutputFolder = "$DocsPath\en-US"
|
||||||
|
WithModulePage = $true
|
||||||
|
}
|
||||||
|
|
||||||
|
# ErrorAction is set to SilentlyContinue so this
|
||||||
|
# command will not overwrite an existing Markdown file.
|
||||||
|
"Creating new Markdown help for [$ModuleName]..."
|
||||||
|
$null = New-MarkdownHelp @params
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
Remove-Module -Name $ModuleName -Force
|
||||||
|
}
|
||||||
|
}
|
||||||
4
BuildTasks/ImportDevModule.Task.ps1
Normal file
4
BuildTasks/ImportDevModule.Task.ps1
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
|
||||||
|
task ImportDevModule {
|
||||||
|
ImportModule -Path "$Source\$ModuleName.psd1" -Force
|
||||||
|
}
|
||||||
33
BuildTasks/ImportModule.Task.ps1
Normal file
33
BuildTasks/ImportModule.Task.ps1
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
function ImportModule
|
||||||
|
{
|
||||||
|
param(
|
||||||
|
[string]$path,
|
||||||
|
[switch]$PassThru
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
if (-not(Test-Path -Path $path))
|
||||||
|
{
|
||||||
|
"Cannot find [$path]."
|
||||||
|
Write-Error -Message "Could not find module manifest [$path]"
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$file = Get-Item $path
|
||||||
|
$name = $file.BaseName
|
||||||
|
|
||||||
|
$loaded = Get-Module -Name $name -All -ErrorAction Ignore
|
||||||
|
if ($loaded)
|
||||||
|
{
|
||||||
|
"Unloading Module [$name] from a previous import..."
|
||||||
|
$loaded | Remove-Module -Force
|
||||||
|
}
|
||||||
|
|
||||||
|
"Importing Module [$name] from [$($file.fullname)]..."
|
||||||
|
Import-Module -Name $file.fullname -Force -PassThru:$PassThru
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
task ImportModule {
|
||||||
|
ImportModule -Path $ManifestPath
|
||||||
|
}
|
||||||
21
BuildTasks/Install.Task.ps1
Normal file
21
BuildTasks/Install.Task.ps1
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
|
||||||
|
task Install Uninstall, {
|
||||||
|
$version = [version] (Get-Metadata -Path $manifestPath -PropertyName 'ModuleVersion')
|
||||||
|
|
||||||
|
$path = $env:PSModulePath.Split(';').Where({
|
||||||
|
$_ -like 'C:\Users\*'
|
||||||
|
}, 'First', 1)
|
||||||
|
|
||||||
|
if ($path -and (Test-Path -Path $path))
|
||||||
|
{
|
||||||
|
"Using [$path] as base path..."
|
||||||
|
$path = Join-Path -Path $path -ChildPath $ModuleName
|
||||||
|
$path = Join-Path -Path $path -ChildPath $version
|
||||||
|
|
||||||
|
"Creating directory at [$path]..."
|
||||||
|
New-Item -Path $path -ItemType 'Directory' -Force -ErrorAction 'Ignore'
|
||||||
|
|
||||||
|
"Copying items from [$Destination] to [$path]..."
|
||||||
|
Copy-Item -Path "$Destination\*" -Destination $path -Recurse -Force
|
||||||
|
}
|
||||||
|
}
|
||||||
31
BuildTasks/InvokeBuildInit.ps1
Normal file
31
BuildTasks/InvokeBuildInit.ps1
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
Write-Verbose "Initializing build variables" -Verbose
|
||||||
|
Write-Verbose " Existing BuildRoot [$BuildRoot]" -Verbose
|
||||||
|
|
||||||
|
$Script:DocsPath = Join-Path -Path $BuildRoot -ChildPath 'Docs'
|
||||||
|
Write-Verbose " DocsPath [$DocsPath]" -Verbose
|
||||||
|
|
||||||
|
$Script:Output = Join-Path -Path $BuildRoot -ChildPath 'Output'
|
||||||
|
Write-Verbose " Output [$Output]" -Verbose
|
||||||
|
|
||||||
|
$Script:Source = Join-Path -Path $BuildRoot -ChildPath $ModuleName
|
||||||
|
Write-Verbose " Source [$Source]" -Verbose
|
||||||
|
|
||||||
|
$Script:Destination = Join-Path -Path $Output -ChildPath $ModuleName
|
||||||
|
Write-Verbose " Destination [$Destination]" -Verbose
|
||||||
|
|
||||||
|
$Script:ManifestPath = Join-Path -Path $Destination -ChildPath "$ModuleName.psd1"
|
||||||
|
Write-Verbose " ManifestPath [$ManifestPath]" -Verbose
|
||||||
|
|
||||||
|
$Script:ModulePath = Join-Path -Path $Destination -ChildPath "$ModuleName.psm1"
|
||||||
|
Write-Verbose " ModulePath [$ModulePath]" -Verbose
|
||||||
|
|
||||||
|
$Script:Folders = 'Classes', 'Includes', 'Internal', 'Private', 'Public', 'Resources'
|
||||||
|
Write-Verbose " Folders [$Folders]" -Verbose
|
||||||
|
|
||||||
|
$Script:TestFile = "$BuildRoot\Output\TestResults_PS$PSVersion`_$TimeStamp.xml"
|
||||||
|
Write-Verbose " TestFile [$TestFile]" -Verbose
|
||||||
|
|
||||||
|
$Script:PSRepository = 'PSGallery'
|
||||||
|
Write-Verbose " PSRepository [$TestFile]" -Verbose
|
||||||
|
|
||||||
|
function taskx($Name, $Parameters) { task $Name @Parameters -Source $MyInvocation }
|
||||||
34
BuildTasks/Pester.Task.ps1
Normal file
34
BuildTasks/Pester.Task.ps1
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
task Pester {
|
||||||
|
$requiredPercent = $Script:CodeCoveragePercent
|
||||||
|
|
||||||
|
$params = @{
|
||||||
|
OutputFile = $testFile
|
||||||
|
OutputFormat = 'NUnitXml'
|
||||||
|
PassThru = $true
|
||||||
|
Path = 'Tests'
|
||||||
|
Show = 'Failed', 'Fails', 'Summary'
|
||||||
|
Tag = 'Build'
|
||||||
|
}
|
||||||
|
|
||||||
|
if($requiredPercent -gt 0.00)
|
||||||
|
{
|
||||||
|
$params['CodeCoverage'] = 'Output\*\*.psm1'
|
||||||
|
$params['CodeCoverageOutputFile'] = 'Output\codecoverage.xml'
|
||||||
|
}
|
||||||
|
|
||||||
|
$results = Invoke-Pester @params
|
||||||
|
if ($results.FailedCount -gt 0)
|
||||||
|
{
|
||||||
|
Write-Error -Message "Failed [$($results.FailedCount)] Pester tests."
|
||||||
|
}
|
||||||
|
|
||||||
|
if($results.codecoverage.NumberOfCommandsAnalyzed -gt 0)
|
||||||
|
{
|
||||||
|
$codeCoverage = $results.codecoverage.NumberOfCommandsExecuted / $results.codecoverage.NumberOfCommandsAnalyzed
|
||||||
|
|
||||||
|
if($codeCoverage -lt $requiredPercent)
|
||||||
|
{
|
||||||
|
Write-Error ("Failed Code Coverage [{0:P}] below {1:P}" -f $codeCoverage,$requiredPercent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
31
BuildTasks/PublishModule.Task.ps1
Normal file
31
BuildTasks/PublishModule.Task.ps1
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
task PublishModule {
|
||||||
|
|
||||||
|
if ( $ENV:BHBuildSystem -ne 'Unknown' -and
|
||||||
|
$ENV:BHBranchName -eq "master" -and
|
||||||
|
-not [string]::IsNullOrWhiteSpace($ENV:nugetapikey))
|
||||||
|
{
|
||||||
|
$publishModuleSplat = @{
|
||||||
|
Path = $Destination
|
||||||
|
NuGetApiKey = $ENV:nugetapikey
|
||||||
|
Verbose = $true
|
||||||
|
Force = $true
|
||||||
|
Repository = $PSRepository
|
||||||
|
ErrorAction = 'Stop'
|
||||||
|
}
|
||||||
|
"Files in module output:"
|
||||||
|
Get-ChildItem $Destination -Recurse -File |
|
||||||
|
Select-Object -Expand FullName
|
||||||
|
|
||||||
|
"Publishing [$Destination] to [$PSRepository]"
|
||||||
|
|
||||||
|
Publish-Module @publishModuleSplat
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
"Skipping deployment: To deploy, ensure that...`n" +
|
||||||
|
"`t* You are in a known build system (Current: $ENV:BHBuildSystem)`n" +
|
||||||
|
"`t* You are committing to the master branch (Current: $ENV:BHBranchName) `n" +
|
||||||
|
"`t* The repository APIKey is defined in `$ENV:nugetapikey (Current: $(![string]::IsNullOrWhiteSpace($ENV:nugetapikey))) `n" +
|
||||||
|
"`t* This is not a pull request"
|
||||||
|
}
|
||||||
|
}
|
||||||
7
BuildTasks/PublishVersion.Task.ps1
Normal file
7
BuildTasks/PublishVersion.Task.ps1
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
task PublishVersion {
|
||||||
|
[version] $sourceVersion = (Get-Metadata -Path $manifestPath -PropertyName 'ModuleVersion')
|
||||||
|
"##vso[build.updatebuildnumber]$sourceVersion"
|
||||||
|
|
||||||
|
# Do the same for appveyor
|
||||||
|
# https://www.appveyor.com/docs/build-worker-api/#update-build-details
|
||||||
|
}
|
||||||
125
BuildTasks/SetVersion.Task.ps1
Normal file
125
BuildTasks/SetVersion.Task.ps1
Normal file
@@ -0,0 +1,125 @@
|
|||||||
|
function GetModulePublicInterfaceMap
|
||||||
|
{
|
||||||
|
param($Path)
|
||||||
|
$module = ImportModule -Path $Path -PassThru
|
||||||
|
$exportedCommands = @(
|
||||||
|
$module.ExportedFunctions.values
|
||||||
|
$module.ExportedCmdlets.values
|
||||||
|
$module.ExportedAliases.values
|
||||||
|
)
|
||||||
|
|
||||||
|
foreach($command in $exportedCommands)
|
||||||
|
{
|
||||||
|
foreach ($parameter in $command.Parameters.Keys)
|
||||||
|
{
|
||||||
|
if($false -eq $command.Parameters[$parameter].IsDynamic)
|
||||||
|
{
|
||||||
|
'{0}:{1}' -f $command.Name, $command.Parameters[$parameter].Name
|
||||||
|
foreach ($alias in $command.Parameters[$parameter].Aliases)
|
||||||
|
{
|
||||||
|
'{0}:{1}' -f $command.Name, $alias
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
task SetVersion {
|
||||||
|
$version = [version]"0.1.0"
|
||||||
|
$publishedModule = $null
|
||||||
|
$bumpVersionType = 'Patch'
|
||||||
|
$versionStamp = (git rev-parse origin/master) + (git rev-parse head)
|
||||||
|
|
||||||
|
"Load current version"
|
||||||
|
[version] $sourceVersion = (Get-Metadata -Path $manifestPath -PropertyName 'ModuleVersion')
|
||||||
|
" Source version [$sourceVersion]"
|
||||||
|
|
||||||
|
$downloadFolder = Join-Path -Path $output downloads
|
||||||
|
$null = New-Item -ItemType Directory -Path $downloadFolder -Force -ErrorAction Ignore
|
||||||
|
|
||||||
|
$versionFile = Join-Path $downloadFolder versionfile
|
||||||
|
if(Test-Path $versionFile)
|
||||||
|
{
|
||||||
|
$versionFileData = Get-Content $versionFile -raw
|
||||||
|
if($versionFileData -eq $versionStamp)
|
||||||
|
{
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
"Checking for published version"
|
||||||
|
$publishedModule = Find-Module -Name $ModuleName -ErrorAction 'Ignore' |
|
||||||
|
Sort-Object -Property {[version]$_.Version} -Descending |
|
||||||
|
Select -First 1
|
||||||
|
|
||||||
|
if($null -ne $publishedModule)
|
||||||
|
{
|
||||||
|
[version] $publishedVersion = $publishedModule.Version
|
||||||
|
" Published version [$publishedVersion]"
|
||||||
|
|
||||||
|
$version = $publishedVersion
|
||||||
|
|
||||||
|
"Downloading published module to check for breaking changes"
|
||||||
|
$publishedModule | Save-Module -Path $downloadFolder
|
||||||
|
|
||||||
|
[System.Collections.Generic.HashSet[string]] $publishedInterface = @(GetModulePublicInterfaceMap -Path (Join-Path $downloadFolder $ModuleName))
|
||||||
|
[System.Collections.Generic.HashSet[string]] $buildInterface = @(GetModulePublicInterfaceMap -Path $ManifestPath)
|
||||||
|
|
||||||
|
if (-not $publishedInterface.IsSubsetOf($buildInterface))
|
||||||
|
{
|
||||||
|
$bumpVersionType = 'Major'
|
||||||
|
}
|
||||||
|
elseif ($publishedInterface.count -ne $buildInterface.count)
|
||||||
|
{
|
||||||
|
$bumpVersionType = 'Minor'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($version -lt ([version] '1.0.0'))
|
||||||
|
{
|
||||||
|
"Module is still in beta; don't bump major version."
|
||||||
|
if ($bumpVersionType -eq 'Major')
|
||||||
|
{
|
||||||
|
$bumpVersionType = 'Minor'
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$bumpVersionType = 'Patch'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
" Steping version [$bumpVersionType]"
|
||||||
|
$version = [version] (Step-Version -Version $version -Type $bumpVersionType)
|
||||||
|
|
||||||
|
" Comparing to source version [$sourceVersion]"
|
||||||
|
if($sourceVersion -gt $version)
|
||||||
|
{
|
||||||
|
" Using existing version"
|
||||||
|
$version = $sourceVersion
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( -not [string]::IsNullOrEmpty( $env:Build_BuildID ) )
|
||||||
|
{
|
||||||
|
$build = $env:Build_BuildID
|
||||||
|
$version = [version]::new($version.Major, $version.Minor, $version.Build, $build)
|
||||||
|
}
|
||||||
|
elseif ( -not [string]::IsNullOrEmpty( $env:APPVEYOR_BUILD_ID ) )
|
||||||
|
{
|
||||||
|
$build = $env:APPVEYOR_BUILD_ID
|
||||||
|
$version = [version]::new($version.Major, $version.Minor, $version.Build, $build)
|
||||||
|
}
|
||||||
|
|
||||||
|
" Setting version [$version]"
|
||||||
|
Update-Metadata -Path $ManifestPath -PropertyName 'ModuleVersion' -Value $version
|
||||||
|
|
||||||
|
(Get-Content -Path $ManifestPath -Raw -Encoding UTF8) |
|
||||||
|
ForEach-Object {$_.TrimEnd()} |
|
||||||
|
Set-Content -Path $ManifestPath -Encoding UTF8
|
||||||
|
|
||||||
|
Set-Content -Path $versionFile -Value $versionStamp -NoNewline -Encoding UTF8
|
||||||
|
|
||||||
|
if(Test-Path $BuildRoot\fingerprint)
|
||||||
|
{
|
||||||
|
Remove-Item $BuildRoot\fingerprint
|
||||||
|
}
|
||||||
|
}
|
||||||
28
BuildTasks/Uninstall.Task.ps1
Normal file
28
BuildTasks/Uninstall.Task.ps1
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
|
||||||
|
task Uninstall {
|
||||||
|
'Unloading Modules...'
|
||||||
|
Get-Module -Name $ModuleName -ErrorAction 'Ignore' | Remove-Module -Force
|
||||||
|
|
||||||
|
'Uninstalling Module packages...'
|
||||||
|
$modules = Get-Module $ModuleName -ErrorAction 'Ignore' -ListAvailable
|
||||||
|
foreach ($module in $modules)
|
||||||
|
{
|
||||||
|
Uninstall-Module -Name $module.Name -RequiredVersion $module.Version -ErrorAction 'Ignore'
|
||||||
|
}
|
||||||
|
|
||||||
|
'Cleaning up manually installed Modules...'
|
||||||
|
$path = $env:PSModulePath.Split(';').Where({
|
||||||
|
$_ -like 'C:\Users\*'
|
||||||
|
}, 'First', 1)
|
||||||
|
|
||||||
|
$path = Join-Path -Path $path -ChildPath $ModuleName
|
||||||
|
if ($path -and (Test-Path -Path $path))
|
||||||
|
{
|
||||||
|
'Removing files... (This may fail if any DLLs are in use.)'
|
||||||
|
Get-ChildItem -Path $path -File -Recurse |
|
||||||
|
Remove-Item -Force | ForEach-Object 'FullName'
|
||||||
|
|
||||||
|
'Removing folders... (This may fail if any DLLs are in use.)'
|
||||||
|
Remove-Item $path -Recurse -Force
|
||||||
|
}
|
||||||
|
}
|
||||||
6
BuildTasks/UpdateSource.Task.ps1
Normal file
6
BuildTasks/UpdateSource.Task.ps1
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
task UpdateSource {
|
||||||
|
Copy-Item -Path $ManifestPath -Destination "$Source\$ModuleName.psd1"
|
||||||
|
|
||||||
|
$content = Get-Content -Path "$Source\$ModuleName.psd1" -Raw -Encoding UTF8
|
||||||
|
$content.Trim() | Set-Content -Path "$Source\$ModuleName.psd1" -Encoding UTF8
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
# Module manifest for module 'chronometer'
|
# Module manifest for module 'chronometer'
|
||||||
# Generated by: Kevin Marquette
|
# Generated by: Kevin Marquette
|
||||||
# Generated on: 2/2/2017
|
# Generated on: 2/2/2017
|
||||||
|
|
||||||
@@ -8,7 +8,7 @@
|
|||||||
RootModule = 'chronometer.psm1'
|
RootModule = 'chronometer.psm1'
|
||||||
|
|
||||||
# Version number of this module.
|
# Version number of this module.
|
||||||
ModuleVersion = '0.5.2'
|
ModuleVersion = '1.0.0'
|
||||||
|
|
||||||
# ID used to uniquely identify this module
|
# ID used to uniquely identify this module
|
||||||
GUID = 'f3719c3c-008a-4b25-b94d-fc9f587f62dd'
|
GUID = 'f3719c3c-008a-4b25-b94d-fc9f587f62dd'
|
||||||
@@ -17,7 +17,7 @@ GUID = 'f3719c3c-008a-4b25-b94d-fc9f587f62dd'
|
|||||||
Author = 'Kevin Marquette'
|
Author = 'Kevin Marquette'
|
||||||
|
|
||||||
# Copyright statement for this module
|
# Copyright statement for this module
|
||||||
Copyright = '(c) 2017 Kevin Marquette. All rights reserved.'
|
Copyright = '(c) 2019 Kevin Marquette. All rights reserved.'
|
||||||
|
|
||||||
# Description of the functionality provided by this module
|
# Description of the functionality provided by this module
|
||||||
Description = 'Performs a line by line measurement of execution times for scripts'
|
Description = 'Performs a line by line measurement of execution times for scripts'
|
||||||
@@ -26,7 +26,7 @@ Description = 'Performs a line by line measurement of execution times for script
|
|||||||
PowerShellVersion = '5.0'
|
PowerShellVersion = '5.0'
|
||||||
|
|
||||||
# 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.
|
# 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 = @('Get-Chronometer','Format-Chronometer')
|
FunctionsToExport = @('Format-Chronometer','Get-Chronometer')
|
||||||
|
|
||||||
# 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.
|
# 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 = @()
|
CmdletsToExport = @()
|
||||||
@@ -55,4 +55,3 @@ PrivateData = @{
|
|||||||
|
|
||||||
} # End of PrivateData hashtable
|
} # End of PrivateData hashtable
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
126
Docs/en-US/Format-Chronometer.md
Normal file
126
Docs/en-US/Format-Chronometer.md
Normal file
@@ -0,0 +1,126 @@
|
|||||||
|
---
|
||||||
|
external help file: chronometer-help.xml
|
||||||
|
Module Name: chronometer
|
||||||
|
online version:
|
||||||
|
schema: 2.0.0
|
||||||
|
---
|
||||||
|
|
||||||
|
# Format-Chronometer
|
||||||
|
|
||||||
|
## SYNOPSIS
|
||||||
|
|
||||||
|
## SYNTAX
|
||||||
|
|
||||||
|
### Script (Default)
|
||||||
|
```
|
||||||
|
Format-Chronometer [-InputObject <MonitoredScript[]>] [-WarningAt <Int32>] [-ErrorAt <Int32>] [-ShowAll]
|
||||||
|
[<CommonParameters>]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Line
|
||||||
|
```
|
||||||
|
Format-Chronometer [-Line <ScriptLine[]>] [-WarningAt <Int32>] [-ErrorAt <Int32>] [-ShowAll]
|
||||||
|
[<CommonParameters>]
|
||||||
|
```
|
||||||
|
|
||||||
|
## DESCRIPTION
|
||||||
|
Generates a report from a Chronometer
|
||||||
|
|
||||||
|
## EXAMPLES
|
||||||
|
|
||||||
|
### EXAMPLE 1
|
||||||
|
```
|
||||||
|
$script = ls C:\workspace\PSGraph\PSGraph -Recurse -Filter *.ps1
|
||||||
|
```
|
||||||
|
|
||||||
|
$resultes = Get-Chronometer -Path $script.fullname -ScriptBlock {Invoke-Pester C:\workspace\PSGraph}
|
||||||
|
$results | Format-Chronometer -WarnAt 20 -ErrorAt 200
|
||||||
|
|
||||||
|
## PARAMETERS
|
||||||
|
|
||||||
|
### -ErrorAt
|
||||||
|
If the average time of a comamand is more than this, the output is red
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
Type: Int32
|
||||||
|
Parameter Sets: (All)
|
||||||
|
Aliases:
|
||||||
|
|
||||||
|
Required: False
|
||||||
|
Position: Named
|
||||||
|
Default value: 200
|
||||||
|
Accept pipeline input: False
|
||||||
|
Accept wildcard characters: False
|
||||||
|
```
|
||||||
|
|
||||||
|
### -InputObject
|
||||||
|
This is a MonitoredScript object from Get-Chronometer
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
Type: MonitoredScript[]
|
||||||
|
Parameter Sets: Script
|
||||||
|
Aliases:
|
||||||
|
|
||||||
|
Required: False
|
||||||
|
Position: Named
|
||||||
|
Default value: None
|
||||||
|
Accept pipeline input: True (ByValue)
|
||||||
|
Accept wildcard characters: False
|
||||||
|
```
|
||||||
|
|
||||||
|
### -Line
|
||||||
|
This is a ScriptLine object from a MonitoredScript object
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
Type: ScriptLine[]
|
||||||
|
Parameter Sets: Line
|
||||||
|
Aliases:
|
||||||
|
|
||||||
|
Required: False
|
||||||
|
Position: Named
|
||||||
|
Default value: None
|
||||||
|
Accept pipeline input: True (ByValue)
|
||||||
|
Accept wildcard characters: False
|
||||||
|
```
|
||||||
|
|
||||||
|
### -ShowAll
|
||||||
|
Forces the report to show scripts with no execution time
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
Type: SwitchParameter
|
||||||
|
Parameter Sets: (All)
|
||||||
|
Aliases:
|
||||||
|
|
||||||
|
Required: False
|
||||||
|
Position: Named
|
||||||
|
Default value: False
|
||||||
|
Accept pipeline input: False
|
||||||
|
Accept wildcard characters: False
|
||||||
|
```
|
||||||
|
|
||||||
|
### -WarningAt
|
||||||
|
If the average time of a command is more than this, the output is yellow
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
Type: Int32
|
||||||
|
Parameter Sets: (All)
|
||||||
|
Aliases:
|
||||||
|
|
||||||
|
Required: False
|
||||||
|
Position: Named
|
||||||
|
Default value: 20
|
||||||
|
Accept pipeline input: False
|
||||||
|
Accept wildcard characters: False
|
||||||
|
```
|
||||||
|
|
||||||
|
### CommonParameters
|
||||||
|
This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable.
|
||||||
|
For more information, see about_CommonParameters (http://go.microsoft.com/fwlink/?LinkID=113216).
|
||||||
|
|
||||||
|
## INPUTS
|
||||||
|
|
||||||
|
## OUTPUTS
|
||||||
|
|
||||||
|
## NOTES
|
||||||
|
|
||||||
|
## RELATED LINKS
|
||||||
88
Docs/en-US/Get-Chronometer.md
Normal file
88
Docs/en-US/Get-Chronometer.md
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
---
|
||||||
|
external help file: chronometer-help.xml
|
||||||
|
Module Name: chronometer
|
||||||
|
online version:
|
||||||
|
schema: 2.0.0
|
||||||
|
---
|
||||||
|
|
||||||
|
# Get-Chronometer
|
||||||
|
|
||||||
|
## SYNOPSIS
|
||||||
|
|
||||||
|
## SYNTAX
|
||||||
|
|
||||||
|
```
|
||||||
|
Get-Chronometer [-Path <Object[]>] [-LineNumber <Int32[]>] [[-ScriptBlock] <ScriptBlock>] [<CommonParameters>]
|
||||||
|
```
|
||||||
|
|
||||||
|
## DESCRIPTION
|
||||||
|
Loads a script and then tracks the line by line execution times
|
||||||
|
|
||||||
|
## EXAMPLES
|
||||||
|
|
||||||
|
### EXAMPLE 1
|
||||||
|
```
|
||||||
|
Get-Chronometer -Path .\example.ps1 -Script {
|
||||||
|
```
|
||||||
|
|
||||||
|
.\example.ps1
|
||||||
|
}
|
||||||
|
|
||||||
|
## PARAMETERS
|
||||||
|
|
||||||
|
### -LineNumber
|
||||||
|
Line numbers within the script file to measure
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
Type: Int32[]
|
||||||
|
Parameter Sets: (All)
|
||||||
|
Aliases:
|
||||||
|
|
||||||
|
Required: False
|
||||||
|
Position: Named
|
||||||
|
Default value: None
|
||||||
|
Accept pipeline input: False
|
||||||
|
Accept wildcard characters: False
|
||||||
|
```
|
||||||
|
|
||||||
|
### -Path
|
||||||
|
Script file to measure execution times on
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
Type: Object[]
|
||||||
|
Parameter Sets: (All)
|
||||||
|
Aliases:
|
||||||
|
|
||||||
|
Required: False
|
||||||
|
Position: Named
|
||||||
|
Default value: None
|
||||||
|
Accept pipeline input: True (ByValue)
|
||||||
|
Accept wildcard characters: False
|
||||||
|
```
|
||||||
|
|
||||||
|
### -ScriptBlock
|
||||||
|
The script to start the scrupt or execute other commands
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
Type: ScriptBlock
|
||||||
|
Parameter Sets: (All)
|
||||||
|
Aliases: Script, CommandScript
|
||||||
|
|
||||||
|
Required: False
|
||||||
|
Position: 1
|
||||||
|
Default value: None
|
||||||
|
Accept pipeline input: False
|
||||||
|
Accept wildcard characters: False
|
||||||
|
```
|
||||||
|
|
||||||
|
### CommonParameters
|
||||||
|
This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable.
|
||||||
|
For more information, see about_CommonParameters (http://go.microsoft.com/fwlink/?LinkID=113216).
|
||||||
|
|
||||||
|
## INPUTS
|
||||||
|
|
||||||
|
## OUTPUTS
|
||||||
|
|
||||||
|
## NOTES
|
||||||
|
|
||||||
|
## RELATED LINKS
|
||||||
19
Docs/en-US/chronometer.md
Normal file
19
Docs/en-US/chronometer.md
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
---
|
||||||
|
Module Name: chronometer
|
||||||
|
Module Guid: f3719c3c-008a-4b25-b94d-fc9f587f62dd
|
||||||
|
Download Help Link: {{Please enter FwLink manually}}
|
||||||
|
Help Version: {{Please enter version of help manually (X.X.X.X) format}}
|
||||||
|
Locale: en-US
|
||||||
|
---
|
||||||
|
|
||||||
|
# chronometer Module
|
||||||
|
## Description
|
||||||
|
{{Manually Enter Description Here}}
|
||||||
|
|
||||||
|
## chronometer Cmdlets
|
||||||
|
### [Format-Chronometer](Format-Chronometer.md)
|
||||||
|
{{Manually Enter Format-Chronometer Description Here}}
|
||||||
|
|
||||||
|
### [Get-Chronometer](Get-Chronometer.md)
|
||||||
|
{{Manually Enter Get-Chronometer Description Here}}
|
||||||
|
|
||||||
2
LICENSE
2
LICENSE
@@ -1,6 +1,6 @@
|
|||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2017 Kevin Marquette
|
Copyright (c) 2019 Kevin Marquette
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|||||||
15
Module.build.ps1
Normal file
15
Module.build.ps1
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
$Script:ModuleName = Get-ChildItem .\*\*.psm1 | Select-object -ExpandProperty BaseName
|
||||||
|
$Script:CodeCoveragePercent = 0.0 # 0 to 1
|
||||||
|
. $psscriptroot\BuildTasks\InvokeBuildInit.ps1
|
||||||
|
|
||||||
|
task Default Build, Helpify, Test, UpdateSource
|
||||||
|
task Build Copy, Compile, BuildModule, BuildManifest, SetVersion
|
||||||
|
task Helpify GenerateMarkdown, GenerateHelp
|
||||||
|
task Test Build, ImportModule, Pester
|
||||||
|
task Publish Build, PublishVersion, Helpify, Test, PublishModule
|
||||||
|
task TFS Clean, Build, PublishVersion, Helpify, Test
|
||||||
|
task DevTest ImportDevModule, Pester
|
||||||
|
|
||||||
|
Write-Host 'Import common tasks'
|
||||||
|
Get-ChildItem -Path $buildroot\BuildTasks\*.Task.ps1 |
|
||||||
|
ForEach-Object {Write-Host $_.FullName;. $_.FullName}
|
||||||
34
ScriptAnalyzerSettings.psd1
Normal file
34
ScriptAnalyzerSettings.psd1
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
@{
|
||||||
|
# Use Severity when you want to limit the generated diagnostic records to a
|
||||||
|
# subset of: Error, Warning and Information.
|
||||||
|
# Uncomment the following line if you only want Errors and Warnings but
|
||||||
|
# not Information diagnostic records.
|
||||||
|
Severity = @('Error','Warning')
|
||||||
|
|
||||||
|
# Use IncludeRules when you want to run only a subset of the default rule set.
|
||||||
|
#IncludeRules = @('PSAvoidDefaultValueSwitchParameter',
|
||||||
|
# 'PSMisleadingBacktick',
|
||||||
|
# 'PSMissingModuleManifestField',
|
||||||
|
# 'PSReservedCmdletChar',
|
||||||
|
# 'PSReservedParams',
|
||||||
|
# 'PSShouldProcess',
|
||||||
|
# 'PSUseApprovedVerbs',
|
||||||
|
# 'PSUseDeclaredVarsMoreThanAssigments')
|
||||||
|
|
||||||
|
# Use ExcludeRules when you want to run most of the default set of rules except
|
||||||
|
# for a few rules you wish to "exclude". Note: if a rule is in both IncludeRules
|
||||||
|
# and ExcludeRules, the rule will be excluded.
|
||||||
|
ExcludeRules = @('PSUseToExportFieldsInManifest','PSMissingModuleManifestField')
|
||||||
|
|
||||||
|
# You can use the following entry to supply parameters to rules that take parameters.
|
||||||
|
# For instance, the PSAvoidUsingCmdletAliases rule takes a whitelist for aliases you
|
||||||
|
# want to allow.
|
||||||
|
Rules = @{
|
||||||
|
# Do not flag 'cd' alias.
|
||||||
|
PSAvoidUsingCmdletAliases = @{Whitelist = @('Where','Select')}
|
||||||
|
|
||||||
|
# Check if your script uses cmdlets that are compatible on PowerShell Core,
|
||||||
|
# version 6.0.0-alpha, on Linux.
|
||||||
|
# PSUseCompatibleCmdlets = @{Compatibility = @("core-6.0.0-alpha-linux")}
|
||||||
|
}
|
||||||
|
}
|
||||||
16
Tests/Classes/MonitoredScript.Tests.ps1
Normal file
16
Tests/Classes/MonitoredScript.Tests.ps1
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
InModuleScope Chronometer {
|
||||||
|
|
||||||
|
Describe "Class: MonitoredScript" -Tag Build {
|
||||||
|
|
||||||
|
It "Creates an object" {
|
||||||
|
{[MonitoredScript]::New()} | Should Not Throw
|
||||||
|
}
|
||||||
|
|
||||||
|
It "SetScript()" {
|
||||||
|
|
||||||
|
$monitor = [MonitoredScript]::New()
|
||||||
|
{$monitor.SetScript("$PSScriptRoot\..\..\scratchfiles\example.ps1")} | Should Not Throw
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
16
Tests/Classes/ScriptLine.Tests.ps1
Normal file
16
Tests/Classes/ScriptLine.Tests.ps1
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
InModuleScope Chronometer {
|
||||||
|
Describe "Class: ScriptLine" -Tag Build {
|
||||||
|
|
||||||
|
It "Creates an Object" {
|
||||||
|
{[ScriptLine]::New()} | Should Not Throw
|
||||||
|
}
|
||||||
|
|
||||||
|
It "ToString()" {
|
||||||
|
{[ScriptLine]::New().toString()} | Should Not Throw
|
||||||
|
}
|
||||||
|
|
||||||
|
It "Creates an Object" {
|
||||||
|
{[ScriptLine]::New().AddExecutionTime(1)} | Should Not Throw
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
13
Tests/Classes/ScriptProfiler.Tests.ps1
Normal file
13
Tests/Classes/ScriptProfiler.Tests.ps1
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
InModuleScope Chronometer {
|
||||||
|
|
||||||
|
Describe "Class: ScriptProfiler" -Tag Build {
|
||||||
|
|
||||||
|
It "Creates an Object" {
|
||||||
|
{[ScriptProfiler]::New()} | Should Not Throw
|
||||||
|
}
|
||||||
|
|
||||||
|
It "Start()" {
|
||||||
|
{[ScriptProfiler]::Start()} | Should Not Throw
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
11
Tests/Format-Chronometer.Tests.ps1
Normal file
11
Tests/Format-Chronometer.Tests.ps1
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
Describe "Function: Format-Chronometer" -Tag Build {
|
||||||
|
|
||||||
|
It "Does not throw" {
|
||||||
|
{$null | Format-Chronometer } | Should Not Throw
|
||||||
|
}
|
||||||
|
|
||||||
|
It "Can process a result object without throwing" {
|
||||||
|
$results = Get-Chronometer -Path $PSScriptRoot\..\ScratchFiles\example.ps1 -Script {. "$PSScriptRoot\..\ScratchFiles\example.ps1"}
|
||||||
|
$results | Format-Chronometer *>&1 | Should Not BeNullOrEmpty
|
||||||
|
}
|
||||||
|
}
|
||||||
23
Tests/Get-Chronometer.Tests.ps1
Normal file
23
Tests/Get-Chronometer.Tests.ps1
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
Describe "Function: Get-Chronometer" -Tag Build {
|
||||||
|
It "Does not throw" {
|
||||||
|
# Get-Chronometer -Path ScratchFiles\example.ps1 -Script {"Test"}
|
||||||
|
{Get-Chronometer -Path $PSScriptRoot\..\ScratchFiles\example.ps1 -Script {"Test"} } | Should Not Throw
|
||||||
|
}
|
||||||
|
|
||||||
|
It "Executes a script and gives results" {
|
||||||
|
# Get-Chronometer -Path ScratchFiles\example.ps1 -Script {"Test"}
|
||||||
|
$results = Get-Chronometer -Path $PSScriptRoot\..\ScratchFiles\example.ps1 -Script {. "$PSScriptRoot\..\ScratchFiles\example.ps1"}
|
||||||
|
$results | Should Not BeNullOrEmpty
|
||||||
|
}
|
||||||
|
|
||||||
|
It "Executes a script with line numbers and gives results" {
|
||||||
|
# Get-Chronometer -Path ScratchFiles\example.ps1 -Script {"Test"}
|
||||||
|
$params = @{
|
||||||
|
Path = "$PSScriptRoot\..\ScratchFiles\example.ps1"
|
||||||
|
Script = {. "$PSScriptRoot\..\ScratchFiles\example.ps1"}
|
||||||
|
LineNumber = 2,3,5,6
|
||||||
|
}
|
||||||
|
$results = Get-Chronometer @params
|
||||||
|
$results | Should Not BeNullOrEmpty
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
$projectRoot = Resolve-Path "$PSScriptRoot\.."
|
|
||||||
$moduleRoot = Split-Path (Resolve-Path "$projectRoot\*\*.psm1")
|
|
||||||
$moduleName = Split-Path $moduleRoot -Leaf
|
|
||||||
|
|
||||||
|
|
||||||
Describe "Help tests for $moduleName" -Tags Build {
|
|
||||||
|
|
||||||
Import-Module (Join-Path $moduleRoot "$moduleName.psm1") -force
|
|
||||||
|
|
||||||
$functions = Get-Command -Module $moduleName
|
|
||||||
$help = $functions | %{Get-Help $_.name}
|
|
||||||
foreach($node in $help)
|
|
||||||
{
|
|
||||||
Context $node.name {
|
|
||||||
|
|
||||||
it "has a description" {
|
|
||||||
$node.description | Should Not BeNullOrEmpty
|
|
||||||
}
|
|
||||||
it "has an example" {
|
|
||||||
$node.examples | Should Not BeNullOrEmpty
|
|
||||||
}
|
|
||||||
foreach($parameter in $node.parameters.parameter)
|
|
||||||
{
|
|
||||||
it "parameter $($parameter.name) has a description" {
|
|
||||||
$parameter.Description.text | Should Not BeNullOrEmpty
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
$projectRoot = Resolve-Path "$PSScriptRoot\.."
|
|
||||||
$moduleRoot = Split-Path (Resolve-Path "$projectRoot\*\*.psd1")
|
|
||||||
$moduleName = Split-Path $moduleRoot -Leaf
|
|
||||||
|
|
||||||
Describe "General project validation: $moduleName" -Tags Build {
|
|
||||||
|
|
||||||
Context "Valid Powershell" {
|
|
||||||
$scripts = Get-ChildItem $projectRoot -Include *.ps1,*.psm1,*.psd1 -Recurse | where fullname -notmatch 'classes'
|
|
||||||
# TestCases are splatted to the script so we need hashtables
|
|
||||||
$testCase = $scripts | Foreach-Object{@{file=$_}}
|
|
||||||
|
|
||||||
It "Script <file> should be valid powershell" -TestCases $testCase {
|
|
||||||
param($file)
|
|
||||||
|
|
||||||
$file.fullname | Should Exist
|
|
||||||
|
|
||||||
$contents = Get-Content -Path $file.fullname -ErrorAction Stop
|
|
||||||
$errors = $null
|
|
||||||
$null = [System.Management.Automation.PSParser]::Tokenize($contents, [ref]$errors)
|
|
||||||
$errors.Count | Should Be 0
|
|
||||||
}
|
|
||||||
|
|
||||||
It "Classes are valid" {
|
|
||||||
$classes = Get-ChildItem $projectRoot -Include *.ps1,*.psm1,*.psd1 -Recurse | where fullname -match 'classes'
|
|
||||||
|
|
||||||
# Must be imported togehter incase they depend on each other
|
|
||||||
$contents = Get-Content -Path $classes.FullName | Out-String
|
|
||||||
|
|
||||||
$errors = $null
|
|
||||||
$null = [System.Management.Automation.PSParser]::Tokenize($contents, [ref]$errors)
|
|
||||||
$errors.Count | Should Be 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Context "ScriptAnalyzer" {
|
|
||||||
|
|
||||||
$scripts = Get-ChildItem $moduleRoot -Include *.ps1,*.psm1,*.psd1 -Recurse | where fullname -notmatch 'classes'
|
|
||||||
$testCase = $scripts | Foreach-Object{@{file=$_}}
|
|
||||||
|
|
||||||
it "Script <file> should pass ScriptAnalyzer rules" -TestCases $testCase {
|
|
||||||
param($file)
|
|
||||||
|
|
||||||
$file.fullname | Should Exist
|
|
||||||
Invoke-ScriptAnalyzer $file| Should BeNullOrEmpty
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
It "Module '$moduleName' can import cleanly" {
|
|
||||||
{Import-Module (Join-Path $moduleRoot "$moduleName.psm1") -force } | Should Not Throw
|
|
||||||
}
|
|
||||||
}
|
|
||||||
33
Tests/Project/Help.Tests.ps1
Normal file
33
Tests/Project/Help.Tests.ps1
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
$Script:ModuleRoot = Split-Path -Path (Split-Path -Path $PSScriptRoot -Parent) -Parent
|
||||||
|
$Script:ModuleName = $Script:ModuleName = Get-ChildItem $ModuleRoot\*\*.psm1 | Select-object -ExpandProperty BaseName
|
||||||
|
|
||||||
|
Describe "Public commands have comment-based or external help" -Tags 'Build' {
|
||||||
|
$functions = Get-Command -Module $ModuleName
|
||||||
|
$help = foreach ($function in $functions) {
|
||||||
|
Get-Help -Name $function.Name
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($node in $help)
|
||||||
|
{
|
||||||
|
Context $node.Name {
|
||||||
|
It "Should have a Description or Synopsis" {
|
||||||
|
($node.Description + $node.Synopsis) | Should Not BeNullOrEmpty
|
||||||
|
}
|
||||||
|
|
||||||
|
It "Should have an Example" {
|
||||||
|
$node.Examples | Should Not BeNullOrEmpty
|
||||||
|
$node.Examples | Out-String | Should -Match ($node.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($parameter in $node.Parameters.Parameter)
|
||||||
|
{
|
||||||
|
if ($parameter -notmatch 'WhatIf|Confirm')
|
||||||
|
{
|
||||||
|
It "Should have a Description for Parameter [$($parameter.Name)]" {
|
||||||
|
$parameter.Description.Text | Should Not BeNullOrEmpty
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
45
Tests/Project/Module.Tests.ps1
Normal file
45
Tests/Project/Module.Tests.ps1
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
$Script:ModuleRoot = Split-Path -Path (Split-Path -Path $PSScriptRoot -Parent) -Parent
|
||||||
|
$Script:ModuleName = $Script:ModuleName = Get-ChildItem $ModuleRoot\*\*.psm1 | Select-object -ExpandProperty BaseName
|
||||||
|
|
||||||
|
$Script:SourceRoot = Join-Path -Path $ModuleRoot -ChildPath $ModuleName
|
||||||
|
|
||||||
|
Describe "All commands pass PSScriptAnalyzer rules" -Tag 'Build' {
|
||||||
|
$rules = "$ModuleRoot\ScriptAnalyzerSettings.psd1"
|
||||||
|
$scripts = Get-ChildItem -Path $SourceRoot -Include '*.ps1', '*.psm1', '*.psd1' -Recurse |
|
||||||
|
Where-Object FullName -notmatch 'Classes'
|
||||||
|
|
||||||
|
foreach ($script in $scripts)
|
||||||
|
{
|
||||||
|
Context $script.FullName {
|
||||||
|
$results = Invoke-ScriptAnalyzer -Path $script.FullName -Settings $rules
|
||||||
|
if ($results)
|
||||||
|
{
|
||||||
|
foreach ($rule in $results)
|
||||||
|
{
|
||||||
|
It $rule.RuleName {
|
||||||
|
$message = "{0} Line {1}: {2}" -f $rule.Severity, $rule.Line, $rule.Message
|
||||||
|
$message | Should Be ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
It "Should not fail any rules" {
|
||||||
|
$results | Should BeNullOrEmpty
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Describe "Public commands have Pester tests" -Tag 'Build' {
|
||||||
|
$commands = Get-Command -Module $ModuleName
|
||||||
|
|
||||||
|
foreach ($command in $commands.Name)
|
||||||
|
{
|
||||||
|
$file = Get-ChildItem -Path "$ModuleRoot\Tests" -Include "$command.Tests.ps1" -Recurse
|
||||||
|
It "Should have a Pester test for [$command]" {
|
||||||
|
$file.FullName | Should Not BeNullOrEmpty
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,83 +0,0 @@
|
|||||||
$projectRoot = Resolve-Path "$PSScriptRoot\.."
|
|
||||||
$moduleRoot = Split-Path (Resolve-Path "$projectRoot\*\*.psd1")
|
|
||||||
$moduleName = Split-Path $moduleRoot -Leaf
|
|
||||||
|
|
||||||
Describe "Basic unit tests" -Tags Build {
|
|
||||||
|
|
||||||
Import-Module (Join-Path $moduleRoot "$moduleName.psm1") -force
|
|
||||||
|
|
||||||
Context "Function: Get-Chronometer" {
|
|
||||||
it "Does not throw" {
|
|
||||||
# Get-Chronometer -Path ScratchFiles\example.ps1 -Script {"Test"}
|
|
||||||
{Get-Chronometer -Path $PSScriptRoot\..\ScratchFiles\example.ps1 -Script {"Test"} } | Should Not Throw
|
|
||||||
}
|
|
||||||
|
|
||||||
it "Executes a script and gives results" {
|
|
||||||
# Get-Chronometer -Path ScratchFiles\example.ps1 -Script {"Test"}
|
|
||||||
$results = Get-Chronometer -Path $PSScriptRoot\..\ScratchFiles\example.ps1 -Script {. "$PSScriptRoot\..\ScratchFiles\example.ps1"}
|
|
||||||
$results | Should Not BeNullOrEmpty
|
|
||||||
}
|
|
||||||
|
|
||||||
it "Executes a script with linenumbers and gives results" {
|
|
||||||
# Get-Chronometer -Path ScratchFiles\example.ps1 -Script {"Test"}
|
|
||||||
$params = @{
|
|
||||||
Path = "$PSScriptRoot\..\ScratchFiles\example.ps1"
|
|
||||||
Script = {. "$PSScriptRoot\..\ScratchFiles\example.ps1"}
|
|
||||||
LineNumber = 2,3,5,6
|
|
||||||
}
|
|
||||||
$results = Get-Chronometer @params
|
|
||||||
$results | Should Not BeNullOrEmpty
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Context "Function: Format-Chronometer" {
|
|
||||||
|
|
||||||
it "Does not throw" {
|
|
||||||
{$null | Format-Chronometer } | Should Not Throw
|
|
||||||
}
|
|
||||||
|
|
||||||
it "Can process a result object without throwing" {
|
|
||||||
$results = Get-Chronometer -Path $PSScriptRoot\..\ScratchFiles\example.ps1 -Script {. "$PSScriptRoot\..\ScratchFiles\example.ps1"}
|
|
||||||
$results | Format-Chronometer *>&1 | Should Not BeNullOrEmpty
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
InModuleScope $moduleName {
|
|
||||||
Context "Class: ScriptLine" {
|
|
||||||
|
|
||||||
it "Creates an Object" {
|
|
||||||
{[ScriptLine]::New()} | Should Not Throw
|
|
||||||
}
|
|
||||||
it "ToString()" {
|
|
||||||
{[ScriptLine]::New().toString()} | Should Not Throw
|
|
||||||
}
|
|
||||||
it "Creates an Object" {
|
|
||||||
{[ScriptLine]::New().AddExecutionTime(1)} | Should Not Throw
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Context "Class: ScriptProfiler" {
|
|
||||||
|
|
||||||
it "Creates an Object" {
|
|
||||||
{[ScriptProfiler]::New()} | Should Not Throw
|
|
||||||
}
|
|
||||||
it "Start()" {
|
|
||||||
{[ScriptProfiler]::Start()} | Should Not Throw
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Context "Class: MonitoredScript" {
|
|
||||||
it "Creates an object" {
|
|
||||||
{[MonitoredScript]::New()} | Should Not Throw
|
|
||||||
}
|
|
||||||
|
|
||||||
it "SetScript()" {
|
|
||||||
pushd $projectRoot
|
|
||||||
$monitor = [MonitoredScript]::New()
|
|
||||||
{$monitor.SetScript(".\scratchfiles\example.ps1")} | Should Not Throw
|
|
||||||
popd
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -16,4 +16,4 @@ build: false
|
|||||||
|
|
||||||
#Kick off the CI/CD pipeline
|
#Kick off the CI/CD pipeline
|
||||||
test_script:
|
test_script:
|
||||||
- ps: . .\build.ps1
|
- ps: . .\build.ps1
|
||||||
|
|||||||
25
azure-pipelines.yml
Normal file
25
azure-pipelines.yml
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
# Starter pipeline
|
||||||
|
# Start with a minimal pipeline that you can customize to build and deploy your code.
|
||||||
|
# Add steps that build, run tests, deploy, and more:
|
||||||
|
# https://aka.ms/yaml
|
||||||
|
|
||||||
|
#resources:
|
||||||
|
#- repo: self
|
||||||
|
# clean: true
|
||||||
|
# fetchDepth: 1
|
||||||
|
|
||||||
|
trigger:
|
||||||
|
batch: true
|
||||||
|
branches:
|
||||||
|
include:
|
||||||
|
- master
|
||||||
|
|
||||||
|
pool:
|
||||||
|
vmImage: 'Ubuntu 16.04'
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- script: pwsh -File build.ps1 Publish
|
||||||
|
displayName: 'Build and Publish Module'
|
||||||
|
env:
|
||||||
|
nugetapikey: $(nugetapikey)
|
||||||
|
|
||||||
47
build.ps1
47
build.ps1
@@ -1,21 +1,38 @@
|
|||||||
<#
|
[CmdletBinding()]
|
||||||
.Description
|
|
||||||
Installs and loads all the required modules for the build.
|
|
||||||
.Author
|
|
||||||
Warren F. (RamblingCookieMonster)
|
|
||||||
#>
|
|
||||||
|
|
||||||
[cmdletbinding()]
|
param($Task = 'Default')
|
||||||
param ($Task = 'Default')
|
|
||||||
|
|
||||||
# Grab nuget bits, install modules, set build variables, start build.
|
$Script:Modules = @(
|
||||||
Get-PackageProvider -Name NuGet -ForceBootstrap | Out-Null
|
'BuildHelpers',
|
||||||
|
'InvokeBuild',
|
||||||
|
'Pester',
|
||||||
|
'platyPS',
|
||||||
|
'PSScriptAnalyzer',
|
||||||
|
'DependsOn'
|
||||||
|
)
|
||||||
|
|
||||||
Install-Module Psake, PSDeploy, BuildHelpers, PSScriptAnalyzer -force
|
$Script:ModuleInstallScope = 'CurrentUser'
|
||||||
Install-Module Pester -Force -SkipPublisherCheck
|
|
||||||
Import-Module Psake, BuildHelpers, PSScriptAnalyzer
|
'Starting build...'
|
||||||
|
'Installing module dependencies...'
|
||||||
|
|
||||||
|
Get-PackageProvider -Name 'NuGet' -ForceBootstrap | Out-Null
|
||||||
|
|
||||||
|
Install-Module -Name $Script:Modules -Scope $Script:ModuleInstallScope -Force -SkipPublisherCheck
|
||||||
|
|
||||||
Set-BuildEnvironment
|
Set-BuildEnvironment
|
||||||
|
Get-ChildItem Env:BH*
|
||||||
|
Get-ChildItem Env:APPVEYOR*
|
||||||
|
|
||||||
Invoke-psake -buildFile .\psake.ps1 -taskList $Task -nologo
|
$Error.Clear()
|
||||||
exit ( [int]( -not $psake.build_success ) )
|
|
||||||
|
'Invoking build...'
|
||||||
|
|
||||||
|
Invoke-Build $Task -Result 'Result'
|
||||||
|
if ($Result.Error)
|
||||||
|
{
|
||||||
|
$Error[-1].ScriptStackTrace | Out-String
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
exit 0
|
||||||
|
|||||||
Reference in New Issue
Block a user