diff --git a/.vscode/settings.json b/.vscode/settings.json index ebc73a4..3786285 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,3 +1,8 @@ { "frontMatter.dashboard.openOnStart": true, + "files.trimTrailingWhitespace": true, + "files.insertFinalNewline": true, + "editor.insertSpaces": true, + "editor.tabSize": 2, + "powershell.codeFormatting.preset": "OTBS" } \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json index a75af11..7f6bd90 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -45,5 +45,14 @@ "isDefault": true } }, + { + "label": "Test", + "type": "shell", + "command": "${cwd}/build.ps1 -Task Test -Verbose", + "group": { + "kind": "test", + "isDefault": true + } + }, ] -} \ No newline at end of file +} diff --git a/docs/tutorial-basics/property-overrides.md b/docs/tutorial-basics/parameters-properties.md similarity index 58% rename from docs/tutorial-basics/property-overrides.md rename to docs/tutorial-basics/parameters-properties.md index 885fafc..a953187 100644 --- a/docs/tutorial-basics/property-overrides.md +++ b/docs/tutorial-basics/parameters-properties.md @@ -1,49 +1,79 @@ ---- -description: "How to override a property in your build script." -sidebar_position: 11 ---- - -# Properties - -You can override a property in your build script using the `properties` -parameter of the Invoke-psake function. The following is an example: - -```powershell -Invoke-psake .\properties.ps1 -properties @{"x"="1";"y"="2"} -``` - -The example above runs the build script called "properties.ps1" and passes in -parameters 'x' and 'y' with values '1' and '2'. The parameter value for the -"properties" parameter is a PowerShell hashtable where the name and value of -each property is specified. Note: You don't need to use the "$" character when -specifying the property names in the hashtable. - -The "properties.ps1" build script looks like this: - -```powershell -properties { - $x = $null - $y = $null - $z = $null -} - -task default -depends TestProperties - -task TestProperties { - Assert ($x -ne $null) "x should not be null" - Assert ($y -ne $null) "y should not be null" - Assert ($z -eq $null) "z should be null" -} -``` - -The value of $x should be 1 and $y should be 2 by the time the "TestProperties" -task is executed. The value of $z was not over-ridden so it should still be -$null. - -To summarize the differences between passing parameters and properties to the -Invoke-psake function: - -* Parameters and "properties" can both be passed to the Invoke-psake function - simultaneously -* Parameters are set before any "properties" blocks are run -* Properties are set after all "properties" blocks have run +--- +description: "How to use parameters and properties in your build script." +sidebar_position: 11 +--- + +# Parameters & Properties + +To summarize the differences between passing parameters and properties to the +`Invoke-psake` function: + +* Parameters and "properties" can both be passed to the Invoke-psake function + simultaneously +* Parameters are set before any "properties" blocks are run +* Properties are set after all "properties" blocks have run + +## Parameters + +You can pass parameters to your build script using the "parameters" parameter of +the Invoke-psake function. The following is an example: + +```powershell +Invoke-psake .\parameters.ps1 -parameters @{"p1"="v1";"p2"="v2"} +``` + +The example above runs the build script called "parameters.ps1" and passes in +parameters 'p1' and 'p2' with values 'v1' and 'v2'. The parameter value for the +"parameters" parameter (say that 10 times really fast!) is a PowerShell +hashtable where the name and value of each parameter is specified. Note: You +don't need to use the "$" character when specifying the parameter names in the +hashtable. + +```powershell title="parameters.ps1" +properties { + $my_property = $p1 + $p2 +} + +task default -depends TestParams + +task TestParams { + Assert ($my_property -ne $null) '$my_property should not be null' +} +``` + +## Properties + +You can override a property in your build script using the `properties` +parameter of the Invoke-psake function. The following is an example: + +```powershell +Invoke-psake .\properties.ps1 -properties @{"x"="1";"y"="2"} +``` + +The example above runs the build script called "properties.ps1" and passes in +parameters 'x' and 'y' with values '1' and '2'. The parameter value for the +"properties" parameter is a PowerShell hashtable where the name and value of +each property is specified. Note: You don't need to use the "$" character when +specifying the property names in the hashtable. + +The "properties.ps1" build script looks like this: + +```powershell +properties { + $x = $null + $y = $null + $z = $null +} + +task default -depends TestProperties + +task TestProperties { + Assert ($x -ne $null) "x should not be null" + Assert ($y -ne $null) "y should not be null" + Assert ($z -eq $null) "z should be null" +} +``` + +The value of $x should be 1 and $y should be 2 by the time the "TestProperties" +task is executed. The value of $z was not over-ridden so it should still be +$null. diff --git a/docs/tutorial-basics/pass-parameters.md b/docs/tutorial-basics/parameters.md similarity index 96% rename from docs/tutorial-basics/pass-parameters.md rename to docs/tutorial-basics/parameters.md index 7a7e483..970f853 100644 --- a/docs/tutorial-basics/pass-parameters.md +++ b/docs/tutorial-basics/parameters.md @@ -1,30 +1,30 @@ ---- -sidebar_position: 6 ---- -# Parameters - -You can pass parameters to your build script using the "parameters" parameter of -the Invoke-psake function. The following is an example: - -```powershell -Invoke-psake .\parameters.ps1 -parameters @{"p1"="v1";"p2"="v2"} -``` - -The example above runs the build script called "parameters.ps1" and passes in -parameters 'p1' and 'p2' with values 'v1' and 'v2'. The parameter value for the -"parameters" parameter (say that 10 times really fast!) is a PowerShell -hashtable where the name and value of each parameter is specified. Note: You -don't need to use the "$" character when specifying the parameter names in the -hashtable. - -```powershell title="parameters.ps1" -properties { - $my_property = $p1 + $p2 -} - -task default -depends TestParams - -task TestParams { - Assert ($my_property -ne $null) '$my_property should not be null' -} -``` +--- +sidebar_position: 6 +--- +# Parameters + +You can pass parameters to your build script using the "parameters" parameter of +the Invoke-psake function. The following is an example: + +```powershell +Invoke-psake .\parameters.ps1 -parameters @{"p1"="v1";"p2"="v2"} +``` + +The example above runs the build script called "parameters.ps1" and passes in +parameters 'p1' and 'p2' with values 'v1' and 'v2'. The parameter value for the +"parameters" parameter (say that 10 times really fast!) is a PowerShell +hashtable where the name and value of each parameter is specified. Note: You +don't need to use the "$" character when specifying the parameter names in the +hashtable. + +```powershell title="parameters.ps1" +properties { + $my_property = $p1 + $p2 +} + +task default -depends TestParams + +task TestParams { + Assert ($my_property -ne $null) '$my_property should not be null' +} +``` diff --git a/docs/tutorial-basics/conditional-task.md b/docs/tutorial-basics/tasks.md similarity index 62% rename from docs/tutorial-basics/conditional-task.md rename to docs/tutorial-basics/tasks.md index 1ca9b85..e218907 100644 --- a/docs/tutorial-basics/conditional-task.md +++ b/docs/tutorial-basics/tasks.md @@ -1,51 +1,91 @@ ---- -sidebar_position: 4 ---- -# Conditional Tasks - -You can conditionally run a task by using the "precondition" parameter of the -"task" function. The "precondition" parameter expects a scriptblock as its value -and that scriptblock should return a $true or $false. - -The following is an example build script that uses the "precondition" parameter -of the task function: - -```powershell -task default -depends A,B,C - -task A { - "TaskA" -} - -task B -precondition { return $false } { - "TaskB" -} - -task C -precondition { return $true } { - "TaskC" -} -``` - -The output from running the above build script looks like the following: - -```powershell -Executing task: A -TaskA -Precondition was false not executing B -Executing task: C -TaskC - -Build Succeeded! - ----------------------------------------------------------------------- -Build Time Report ----------------------------------------------------------------------- -Name Duration ----- -------- -A 00:00:00.0231283 -B 0 -C 00:00:00.0043444 -Total: 00:00:00.1405840 -``` - -Notice how task "B" was not executed and its run-time duration was 0 secs. +--- +sidebar_position: 4 +--- +# Tasks + +At the core of psake is the task. In it's simplest form you have a task with a +name and an action. + +```powershell +task Hello { + "Hello world" +} +``` + +This is the equivalent: + +```powershell +Task -Name "Hello" -Action { + "Hello world" +} +``` + +## Dependencies + +The power of psake is in it's ability to support dependencies. You can add +`-Depends` to your task and give it a list of other tasks that need to run +before it does. + +```powershell +Task PBJ -Depends Toast, PB, Jelly { + "Enjoy sandwich!" +} +Task Toast { + "Toast 2 pieces of bread" +} +Task PB { + "Spread some peanut butter" +} +Task Jelly { + "Spread some jelly" +} +``` + +## Conditional Tasks + +You can conditionally run a task by using the "precondition" parameter of the +"task" function. The "precondition" parameter expects a scriptblock as its value +and that scriptblock should return a $true or $false. + +The following is an example build script that uses the "precondition" parameter +of the task function: + +```powershell +task default -depends A,B,C + +task A { + "TaskA" +} + +task B -precondition { return $false } { + "TaskB" +} + +task C -precondition { return $true } { + "TaskC" +} +``` + +The output from running the above build script looks like the following: + +```powershell +Executing task: A +TaskA +Precondition was false not executing B +Executing task: C +TaskC + +Build Succeeded! + +---------------------------------------------------------------------- +Build Time Report +---------------------------------------------------------------------- +Name Duration +---- -------- +A 00:00:00.0231283 +B 0 +C 00:00:00.0043444 +Total: 00:00:00.1405840 +``` + +Notice how task "B" was not executed and its run-time duration was 0 secs. diff --git a/docusaurus.config.ts b/docusaurus.config.ts index 54d7a97..c989961 100644 --- a/docusaurus.config.ts +++ b/docusaurus.config.ts @@ -1,3 +1,4 @@ +// cSpell:ignore Untruncated import { themes as prismThemes } from 'prism-react-renderer'; import type { Config } from '@docusaurus/types'; import type * as Preset from '@docusaurus/preset-classic'; diff --git a/psakeFile.ps1 b/psakeFile.ps1 index a9c2a54..ea2cdf2 100644 --- a/psakeFile.ps1 +++ b/psakeFile.ps1 @@ -1,31 +1,14 @@ +#require -Version 7 Properties { -} - -Task Default -depends Build - -Task Init { - yarn install -} - -Task Build -depends Init, GenerateCommandReference { - yarn run build - if ($LastExitCode -ne 0) { - throw "NPM Build failed" - } -} + $script:OutputPath = $null + $script:OutputFormat = 'Nunit' + $script:psakeVersion = (Get-Module psake).Version -Task Server -depends Build { - yarn run serve -} - -# TODO: Come up with a way to gen tasks from package scripts... -Task GenerateCommandReference { - # Copied from the amazing Pester team! https://github.com/pester/docs/blob/main/generate-command-reference.ps1 # ----------------------------------------------------------------------------- # Use below settings to manipulate the rendered MDX files # ----------------------------------------------------------------------------- - $psakeVersion = (Get-Module psake).Version - $docusaurusOptions = @{ + + $script:docusaurusOptions = @{ Module = "Psake" DocsFolder = "./docs" SideBar = "commands" @@ -48,31 +31,85 @@ Contributions are welcome in [Psake-repo](https://github.com/psake/psake). *This page was generated using comment-based help in [Psake $($psakeVersion)](https://github.com/psake/psake).* "@ } + $script:docsOutputFolder = Join-Path -Path $docusaurusOptions.DocsFolder -ChildPath $docusaurusOptions.Sidebar | Join-Path -ChildPath "*.*" +} - # ----------------------------------------------------------------------------- - # Generate the new MDX files - # ----------------------------------------------------------------------------- - Push-Location $PSScriptRoot - Write-Host (Get-Location) +FormatTaskName { + param($taskName) + Write-Host 'Task: ' -ForegroundColor Cyan -NoNewline + Write-Host $taskName.ToUpper() -ForegroundColor Blue +} + +Task Default -depends Build + +Task Init -description "Initial action to setup the further action." -action { + yarn install +} +Task Build -depends Init, GenerateCommandReference { + yarn run build + if ($LastExitCode -ne 0) { + throw "NPM Build failed" + } +} + +Task Server -depends Build -description "Run the docusaurus server." { + yarn run serve +} + +Task Test { + $configuration = [PesterConfiguration]::Default + $configuration.Output.Verbosity = 'Detailed' + $configuration.Run.PassThru = $true + $configuration.Run.Path = "$PSScriptRoot\tests" + + try { + $testResult = Invoke-Pester -Configuration $configuration -Verbose + } finally { + } + + if ($testResult.FailedCount -gt 0) { + throw 'One or more Pester tests failed' + } +} + +(Get-Content ".\package.json" | ConvertFrom-Json -AsHashtable).scripts.Keys | ForEach-Object { + $action = [scriptblock]::create("yarn run $($_)") + $taskSplat = @{ + name = "yarn_$($_)" + action = $action + depends = @('Init') + description = "Automatic: A script defined in your package.json" + } + Task @taskSplat +} + +#region Command Reference Generation Tasks +# Copied from the amazing Pester team! https://github.com/pester/docs/blob/main/generate-command-reference.ps1 +$taskSplat = @{ + description = "Use Alt3.Docusaurus.Powershell module to generate our reference docs." + depends = 'GenerateCommandReference-Gen' +} +Task -name 'GenerateCommandReference' @taskSplat + +Task -name 'GenerateCommandReference-Clean' -action { Write-Host "Removing existing MDX files" -ForegroundColor Magenta - $outputFolder = Join-Path -Path $docusaurusOptions.DocsFolder -ChildPath $docusaurusOptions.Sidebar | Join-Path -ChildPath "*.*" - if (Test-Path -Path $outputFolder) { - Remove-Item -Path $outputFolder + if (Test-Path -Path $script:docsOutputFolder) { + Remove-Item -Path $script:docsOutputFolder } +} +Task -name "GenerateCommandReference-Gen" -depends 'GenerateCommandReference-Clean' { Write-Host "Generating new MDX files" -ForegroundColor Magenta New-DocusaurusHelp @docusaurusOptions - + # Fix the links - Get-ChildItem $outputFolder | ForEach-Object { + Get-ChildItem $script:docsOutputFolder | ForEach-Object { $path = $_.FullName Write-Host "Fixing relative links for: $path" Get-Content $path | ForEach-Object { $_ -replace "\[(.+)\]\(\)", '[$1]($1.mdx)' } | Set-Content $path } - - Write-Host "Render completed successfully" -BackgroundColor DarkGreen - Pop-Location -} \ No newline at end of file +} +#region Command Reference Generation Tasks diff --git a/sidebars.ts b/sidebars.ts index 5132855..1c0d558 100644 --- a/sidebars.ts +++ b/sidebars.ts @@ -13,12 +13,61 @@ import commands from "./docs/commands/docusaurus.sidebar.js"; const sidebars: SidebarsConfig = { // By default, Docusaurus generates a sidebar from the docs folder structure tutorialSidebar: [ - { type: 'autogenerated', dirName: '.' }, + 'intro', + { + type: 'category', + label: 'Tutorial - Basics', + items: [ + 'tutorial-basics/installing', + 'tutorial-basics/getting-help', + 'tutorial-basics/run-psake', + 'tutorial-basics/tasks', + 'tutorial-basics/parameters-properties', + 'tutorial-basics/default-build-files', + 'tutorial-basics/how-to-fail-a-build', + 'tutorial-basics/nested-build', + ], + }, + { + type: 'category', + label: 'Tutorial - Advanced', + items: [ + 'tutorial-advanced/access-functions-in-another-file', + 'tutorial-advanced/build-script-resilience', + 'tutorial-advanced/debug-script', + 'tutorial-advanced/logging-errors', + 'tutorial-advanced/print-psake-task-name', + 'tutorial-advanced/retry-rules', + 'tutorial-advanced/structure-of-a-psake-build-script', + 'tutorial-advanced/variable-referencing', + ], + }, + { + type: 'category', + label: 'Build Types', + items: [ + 'build-types/dot-net-solution' + ] + }, + { + type: 'category', + label: 'CI Examples', + items: [ + 'ci-examples/hudson', + 'ci-examples/cruise-control', + 'ci-examples/team-city', + ] + }, { type: 'category', label: 'Command Reference', items: commands }, + { + type: 'doc', + label: 'Code of Conduct', + id: 'code_of_conduct' + }, ], // But you can create a sidebar manually diff --git a/tests/Docs.Tests.ps1 b/tests/Docs.Tests.ps1 new file mode 100644 index 0000000..f2c8048 --- /dev/null +++ b/tests/Docs.Tests.ps1 @@ -0,0 +1,23 @@ +Describe "Documentation" { + Context "Sidebar" { + BeforeDiscovery { + $docsDir = Resolve-Path "$PSScriptRoot\..\docs" -Relative + $script:docs = Get-ChildItem -Recurse $docsDir -File -Filter "*.md*" | Where-Object { + # Exclude commands dir since that's added via an import + $_.DirectoryName -notlike '*commands' + } + $script:sidebar = Resolve-Path "$PSScriptRoot\..\sidebars.ts" + } + # This confirms that all our docs are linked in the sidebar.ts file + It "<_> is linked in the sidebar" -ForEach $script:docs { + $dirName = Split-Path -Path $_.DirectoryName -Leaf + if ($dirName -eq "docs") { + # Root dir isn't needed + $ts_format = $_.BaseName + } else { + $ts_format = "{0}/{1}" -f $dirName, $_.BaseName + } + $sidebar | Should -FileContentMatch $ts_format + } + } +}