diff --git a/Chronometer/chronometer.psd1 b/Chronometer/chronometer.psd1 new file mode 100644 index 0000000..545e536 Binary files /dev/null and b/Chronometer/chronometer.psd1 differ diff --git a/Chronometer/chronometer.psm1 b/Chronometer/chronometer.psm1 new file mode 100644 index 0000000..1fa434a --- /dev/null +++ b/Chronometer/chronometer.psm1 @@ -0,0 +1,22 @@ +Write-Verbose "Importing Functions" + +# Import everything in sub folders folder +foreach($folder in @('private', 'public', 'classes')) +{ + $root = Join-Path -Path $PSScriptRoot -ChildPath $folder + if(Test-Path -Path $root) + { + Write-Verbose "processing folder $root" + $files = Get-ChildItem -Path $root -Filter *.ps1 + + # dot source each file + $files | where-Object{ $_.name -NotLike '*.Tests.ps1'} | + ForEach-Object{Write-Verbose $_.name; . $_.FullName} + } +} + +Export-ModuleMember -function (Get-ChildItem -Path "$PSScriptRoot\public\*.ps1").basename + +# Hack for my build system that had a conflit with the keyword node +New-Alias -Name 'DiGraph' -Value 'Graph' -ErrorAction SilentlyContinue +Export-ModuleMember -Alias 'DiGraph' diff --git a/example.ps1 b/ScratchFiles/example.ps1 similarity index 100% rename from example.ps1 rename to ScratchFiles/example.ps1 diff --git a/profiler.ps1 b/ScratchFiles/profiler.ps1 similarity index 100% rename from profiler.ps1 rename to ScratchFiles/profiler.ps1 diff --git a/profiler2.ps1 b/ScratchFiles/profiler2.ps1 similarity index 100% rename from profiler2.ps1 rename to ScratchFiles/profiler2.ps1 diff --git a/profiler3.ps1 b/ScratchFiles/profiler3.ps1 similarity index 100% rename from profiler3.ps1 rename to ScratchFiles/profiler3.ps1 diff --git a/tests.ps1 b/ScratchFiles/tests.ps1 similarity index 100% rename from tests.ps1 rename to ScratchFiles/tests.ps1 diff --git a/Tests/Help.Tests.ps1 b/Tests/Help.Tests.ps1 new file mode 100644 index 0000000..6f4d3fb --- /dev/null +++ b/Tests/Help.Tests.ps1 @@ -0,0 +1,29 @@ +$projectRoot = Resolve-Path "$PSScriptRoot\.." +$moduleRoot = Split-Path (Resolve-Path "$projectRoot\*\*.psm1") +$moduleName = Split-Path $moduleRoot -Leaf + +Import-Module (Join-Path $moduleRoot "$moduleName.psm1") -force + +Describe "Help tests for $moduleName" -Tags Build { + + $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 + } + } + } + } +} diff --git a/Tests/Project.Tests.ps1 b/Tests/Project.Tests.ps1 new file mode 100644 index 0000000..5ed72b3 --- /dev/null +++ b/Tests/Project.Tests.ps1 @@ -0,0 +1,25 @@ +$projectRoot = Resolve-Path "$PSScriptRoot\.." +$moduleRoot = Split-Path (Resolve-Path "$projectRoot\*\*.psd1") +$moduleName = Split-Path $moduleRoot -Leaf + +Describe "General project validation: $moduleName" -Tags Build { + + $scripts = Get-ChildItem $projectRoot -Include *.ps1,*.psm1,*.psd1 -Recurse + + # TestCases are splatted to the script so we need hashtables + $testCase = $scripts | Foreach-Object{@{file=$_}} + It "Script 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 "Module '$moduleName' can import cleanly" { + {Import-Module (Join-Path $moduleRoot "$moduleName.psm1") -force } | Should Not Throw + } +} diff --git a/appveyor.yml b/appveyor.yml new file mode 100644 index 0000000..4918e7a --- /dev/null +++ b/appveyor.yml @@ -0,0 +1,19 @@ +# See http://www.appveyor.com/docs/appveyor-yml for many more options + +environment: + NugetApiKey: + secure: sqj8QGRYue5Vq3vWm2GdcCttqyOkt7NOheKlnmIUq1UcgVrmQezFArp/2Z1+G3oT + +# Allow WMF5 (i.e. PowerShellGallery functionality) +os: WMF 5 + +# Skip on updates to the readme. +# We can force this by adding [skip ci] or [ci skip] anywhere in commit message +skip_commits: + message: /updated (readme|doc).*|update (readme|doc).*s/ + +build: false + +#Kick off the CI/CD pipeline +test_script: + - ps: . .\build.ps1 \ No newline at end of file diff --git a/build.ps1 b/build.ps1 new file mode 100644 index 0000000..ef97c13 --- /dev/null +++ b/build.ps1 @@ -0,0 +1,21 @@ +<# +.Description +Installs and loads all the required modules for the build. +.Author +Warren F. (RamblingCookieMonster) +#> + +[cmdletbinding()] +param ($Task = 'Default') + +# Grab nuget bits, install modules, set build variables, start build. +Get-PackageProvider -Name NuGet -ForceBootstrap | Out-Null + +Install-Module Psake, PSDeploy, BuildHelpers -force +Install-Module Pester -Force -SkipPublisherCheck +Import-Module Psake, BuildHelpers + +Set-BuildEnvironment + +Invoke-psake -buildFile .\psake.ps1 -taskList $Task -nologo +exit ( [int]( -not $psake.build_success ) ) \ No newline at end of file diff --git a/deploy.PSDeploy.ps1 b/deploy.PSDeploy.ps1 new file mode 100644 index 0000000..65a21d9 --- /dev/null +++ b/deploy.PSDeploy.ps1 @@ -0,0 +1,29 @@ +# Generic module deployment. +# This stuff should be moved to psake for a cleaner deployment view + +# ASSUMPTIONS: + + # folder structure of: + # - RepoFolder + # - This PSDeploy file + # - ModuleName + # - ModuleName.psd1 + + # Nuget key in $ENV:NugetApiKey + + # Set-BuildEnvironment from BuildHelpers module has populated ENV:BHProjectName + +# find a folder that has psd1 of same name... + +if($ENV:BHProjectName -and $ENV:BHProjectName.Count -eq 1) +{ + Deploy Module { + By PSGalleryModule { + FromSource $ENV:BHProjectName + To PSGallery + WithOptions @{ + ApiKey = $ENV:NugetApiKey + } + } + } +} \ No newline at end of file diff --git a/psake.ps1 b/psake.ps1 new file mode 100644 index 0000000..45076bd --- /dev/null +++ b/psake.ps1 @@ -0,0 +1,115 @@ +# PSake makes variables declared here available in other scriptblocks +# Init some things +Properties { + # Find the build folder based on build system + $ProjectRoot = $ENV:BHProjectPath + if(-not $ProjectRoot) + { + $ProjectRoot = $PSScriptRoot + } + + $Timestamp = Get-date -uformat "%Y%m%d-%H%M%S" + $PSVersion = $PSVersionTable.PSVersion.Major + $TestFile = "TestResults_PS$PSVersion`_$TimeStamp.xml" + $lines = '----------------------------------------------------------------------' + + $Verbose = @{} + if($ENV:BHCommitMessage -match "!verbose") + { + $Verbose = @{Verbose = $True} + } +} + +Task Default -Depends Deploy + +Task Init { + $lines + Set-Location $ProjectRoot + "Build System Details:" + Get-Item ENV:BH* | Format-List + "`n" + "Check for node conflict" + Get-Command node | Select-Object * +} + +Task UnitTests -Depends Init { + $lines + 'Running quick unit tests to fail early if there is an error' + $TestResults = Invoke-Pester -Path $ProjectRoot\Tests\*unit* -PassThru -Tag Build -Show Failed + + if($TestResults.FailedCount -gt 0) + { + Write-Error "Failed '$($TestResults.FailedCount)' tests, build failed" + } + "`n" +} + +Task Test -Depends UnitTests { + $lines + "`n`tSTATUS: Testing with PowerShell $PSVersion" + + # Gather test results. Store them in a variable and file + $TestResults = Invoke-Pester -Path $ProjectRoot\Tests -PassThru -OutputFormat NUnitXml -OutputFile "$ProjectRoot\$TestFile" -Tag Build -Show Failed + + # In Appveyor? Upload our tests! #Abstract this into a function? + If($ENV:BHBuildSystem -eq 'AppVeyor') + { + "Uploading $ProjectRoot\$TestFile to AppVeyor" + "JobID: $env:APPVEYOR_JOB_ID" + (New-Object 'System.Net.WebClient').UploadFile( + "https://ci.appveyor.com/api/testresults/nunit/$($env:APPVEYOR_JOB_ID)", + (Resolve-Path "$ProjectRoot\$TestFile" ) + ) + } + + Remove-Item "$ProjectRoot\$TestFile" -Force -ErrorAction SilentlyContinue + + # Failed tests? + # Need to tell psake or it will proceed to the deployment. Danger! + if($TestResults.FailedCount -gt 0) + { + Write-Error "Failed '$($TestResults.FailedCount)' tests, build failed" + } + "`n" +} + +Task Build -Depends Test { + $lines + + $functions = Get-ChildItem "$PSScriptRoot\$env:BHProjectName\Public\*.ps1" | + Where-Object{ $_.name -notmatch 'Tests'} | + Select-Object -ExpandProperty basename + + # Load the module, read the exported functions, update the psd1 FunctionsToExport + Set-ModuleFunctions -Name $env:BHPSModuleManifest -FunctionsToExport $functions + + # Bump the module version + $Version = Get-NextPSGalleryVersion -Name $env:BHProjectName + Update-Metadata -Path $env:BHPSModuleManifest -PropertyName ModuleVersion -Value $Version +} + +Task Deploy -Depends Build { + $lines + + # Gate deployment + if( + $ENV:BHBuildSystem -ne 'Unknown' -and + $ENV:BHBranchName -eq "master" -and + $ENV:BHCommitMessage -match '!deploy' + ) + { + $Params = @{ + Path = $ProjectRoot + Force = $true + } + + Invoke-PSDeploy @Verbose @Params + } + 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* Your commit message includes !deploy (Current: $ENV:BHCommitMessage)" + } +}