Skip to content

Commit

Permalink
Support script blocks as File, resolve #78
Browse files Browse the repository at this point in the history
  • Loading branch information
nightroman committed Jul 7, 2017
1 parent 794c78a commit 4963636
Show file tree
Hide file tree
Showing 16 changed files with 197 additions and 100 deletions.
6 changes: 6 additions & 0 deletions Invoke-Build-Help.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,12 @@
this location it may return the full path of a special build script.
If the file is still not found then parent directories are searched.
INLINE SCRIPT
`File` is a script block as a build script. It is used in order to
assemble a build on the fly without creating an extra build script.
Dynamic parameters and persistent builds are not used in this case.
'@
Checkpoint = @'
Specifies the checkpoint file and makes the build persistent. It is
Expand Down
22 changes: 13 additions & 9 deletions Invoke-Build.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ specific language governing permissions and limitations under the License.
#.ExternalHelp Invoke-Build-Help.xml
param(
[Parameter(Position=0)][string[]]$Task,
[Parameter(Position=1)][string]$File,
[Parameter(Position=1)]$File,
[string]$Checkpoint,
$Result,
[switch]$Safe,
Expand Down Expand Up @@ -57,6 +57,7 @@ New-Variable * -Description IB ([PSCustomObject]@{
Elapsed = $null
Error = $null
Task = $null
File = $BuildFile = $PSBoundParameters['File']
Checkpoint = $PSBoundParameters['Checkpoint']
Safe = $PSBoundParameters['Safe']
Summary = $PSBoundParameters['Summary']
Expand All @@ -80,7 +81,10 @@ New-Variable * -Description IB ([PSCustomObject]@{
Header = {Write-Build 11 "Task $($args[0])"}
})
$BuildTask = $PSBoundParameters['Task']
$BuildFile = $PSBoundParameters['File']
if ($BuildFile -is [scriptblock]) {
$BuildFile = $BuildFile.File
return
}

if ($BuildTask -eq '**') {
if (![System.IO.Directory]::Exists(($_ = *Path $BuildFile))) {throw "Missing directory '$_'."}
Expand All @@ -102,6 +106,7 @@ elseif ($BuildFile) {
elseif (!($BuildFile = Get-BuildFile ${*}.CD)) {
throw 'Missing default script.'
}
${*}.File = $BuildFile

if (!($_ = (Get-Command $BuildFile -ErrorAction 1).Parameters)) {
& $BuildFile
Expand Down Expand Up @@ -285,7 +290,7 @@ catch {
}

#.ExternalHelp Invoke-Build-Help.xml
function Get-BuildVersion {[Version]'3.5.3'}
function Get-BuildVersion {[Version]'3.6.0'}

function *My {
$_.InvocationInfo.ScriptName -eq $MyInvocation.ScriptName
Expand Down Expand Up @@ -638,13 +643,12 @@ try {
function Import-Build([Parameter()][scriptblock]$Script) {${*}.Import = $Script}
function Set-BuildHeader([Parameter()][scriptblock]$Script) {${*}.Header = $Script}

*SL ($BuildRoot = Split-Path $BuildFile)
*SL ($BuildRoot = if ($BuildFile) {Split-Path $BuildFile} else {${*}.CD})
$_ = ${*}.SP
if (${private:**} = . $BuildFile @_) {
foreach($_ in ${**}) {
Write-Warning "Unexpected output: $_."
if ($_ -is [scriptblock]) {throw "Dangling scriptblock at $($_.File):$($_.StartPosition.StartLine)"}
}
${private:**} = @(. ${*}.File @_)
foreach($_ in ${**}) {
Write-Warning "Unexpected output: $_."
if ($_ -is [scriptblock]) {throw "Dangling scriptblock at $($_.File):$($_.StartPosition.StartLine)"}
}
if (!(${**} = ${*}.All).Count) {throw "No tasks in '$BuildFile'."}

Expand Down
4 changes: 4 additions & 0 deletions Release-Notes.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@

# Invoke-Build Release Notes

## v3.6.0

Support script block as `File` (#78).

## v3.5.3

Improved product selection logic in `Resolve-MSBuild` (#77).
Expand Down
6 changes: 6 additions & 0 deletions Tasks/Inline/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@

## How to assemble builds using script blocks

- [app1.ps1](app1.ps1) adds before/after tasks to a build script before invoking.
- [app2.ps1](app2.ps1) sets custom build blocks for a build script.
- [app3.ps1](app3.ps1) creates and invokes some test tasks.
20 changes: 20 additions & 0 deletions Tasks/Inline/app1.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@

<#
.Synopsis
Import a build and alter tasks.
#>

Invoke-Build Test {
# import build script
. ./my.build.ps1

# alter task `Test`
task BeforeTest -Before Test {
Write-Host '@BeforeTest'
}

# alter task `Test`
task AfterTest -After Test {
Write-Host '@AfterTest'
}
}
17 changes: 17 additions & 0 deletions Tasks/Inline/app2.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@

<#
.Synopsis
Import a build and set build blocks.
#>

Invoke-Build Test {
# import build script
. ./my.build.ps1

# set build block
Set-BuildHeader {
param($Path)
Write-Build Cyan "Task $Path"
Write-Build Magenta "# Synopsis: $(Get-BuildSynopsis $Task)"
}
}
19 changes: 19 additions & 0 deletions Tasks/Inline/app3.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@

<#
.Synopsis
Inline build with some tests.
#>

$MyFile = $MyInvocation.MyCommand.Path
$MyRoot = Split-Path $MyFile

Invoke-Build * -Summary {
task TestBuildFile {
$BuildFile
equals $BuildFile $MyFile
}
task TestBuildRoot {
$BuildRoot
equals $BuildRoot $MyRoot
}
}
5 changes: 5 additions & 0 deletions Tasks/Inline/my.build.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@

# Synopsis: Some task.
task Test {
Write-Host '@Test'
}
1 change: 1 addition & 0 deletions Tasks/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
- [Direct](Direct) How to make build scripts invokable directly.
- [Header](Header) How to print more task details in task headers.
- [Import](Import) How to share and import tasks from external task scripts including exported by modules.
- [Inline](Inline) How to assemble a whole build inline as a script block without creating an extra script.
- [Param](Param) How to create tasks which perform similar actions with some differences defined by parameters.

**Custom tasks**
Expand Down
29 changes: 20 additions & 9 deletions Tests/.build.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -171,16 +171,27 @@ task TestExitCode {
equals $LastExitCode 1
}

# Synopsis: Test the internally defined alias Invoke-Build.
# It is recommended for nested calls instead of the script name. In a new (!)
# session set ${*}, build, check for the alias. It also covers work around
# "Default Host" exception on setting colors.
# Synopsis: Test alias Invoke-Build and more.
# In a new (!) session set ${*}, build, check for the alias. It also covers
# work around "Default Host" exception on setting colors and the case with
# null $BuildFile.
task TestSelfAlias {
'task . { (Get-Alias Invoke-Build -ea Stop).Definition }' > z.build.ps1
$log = [PowerShell]::Create().AddScript("`${*} = 42; Invoke-Build . '$BuildRoot\z.build.ps1'").Invoke() | Out-String
$log
assert ($log.Contains('Build succeeded'))
Remove-Item z.build.ps1
$script = {
${*} = 42
Invoke-Build . {
task . {
# null?
equals $BuildFile
# defined?
(Get-Alias Invoke-Build -ErrorAction Stop).Definition
}
}
# two errors on setting ForegroundColor
foreach($_ in $Error) {"$_"}
}

($log = [PowerShell]::Create().AddScript($script).Invoke() | Out-String)
assert $log.Contains('Build succeeded')
}

# Synopsis: Test a build invoked from a background job just to be sure it works.
Expand Down
47 changes: 18 additions & 29 deletions Tests/Errors.test.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,13 @@

# The last task ${*}.Task should be reset before Exit-Build.
task 'Exit-Build error should have no task' {
{
Invoke-Build . -Safe -Result Result {
task Test {42}
Exit-Build {throw 13}
} > z.build.ps1

Invoke-Build . z.build.ps1 -Safe -Result Result
}

equals $Result.Errors.Count 1
equals $Result.Errors[0].Task

Remove-Item z.build.ps1
}

<#
Expand All @@ -45,45 +41,38 @@ added to errors ($Task), not the last (${*}.Task). In the latter this test used
to add 3 identical errors for the task Test1.
#>
task 'Custom child errors added for parent tasks' {
{
. ..\Tasks\Test\Test.tasks.ps1
Invoke-Build Test3 -Result Result {
. ../Tasks/Test/Test.tasks.ps1
test Test1 {throw 'Oops Test1'}
test Test2 Test1, {assert 0}
test Test3 Test2, {assert 0}
} > z.build.ps1

Invoke-Build Test3 z.build.ps1 -Result Result
}

equals $Result.Errors.Count 3
equals $Result.Errors[0].Task.Name 'Test1'
equals $Result.Errors[1].Task.Name 'Test2'
equals $Result.Errors[2].Task.Name 'Test3'

Remove-Item z.build.ps1
equals $Result.Errors[0].Task.Name Test1
equals $Result.Errors[1].Task.Name Test2
equals $Result.Errors[2].Task.Name Test3
}

task Warnings {
{
$file = {
Write-Warning demo-file-warning
task t1 {Write-Warning demo-task-warning}
} > z.build.ps1

($r = Invoke-Build t1 z.build.ps1 -Result Result)
}
($r = Invoke-Build t1 $file -Result Result)

# output
assert ($r[-3] -clike 'WARNING: demo-file-warning File: *\z.build.ps1.')
assert ($r[-2] -clike 'WARNING: demo-task-warning Task: t1. File: *\z.build.ps1.')
assert ($r[-3] -clike 'WARNING: demo-file-warning File: *Errors.test.ps1.')
assert ($r[-2] -clike 'WARNING: demo-task-warning Task: t1. File: *Errors.test.ps1.')
assert ($r[-1] -clike 'Build succeeded with warnings. 1 tasks, 0 errors, 2 warnings *')

# result
equals $Result.Warnings.Count 2
$1, $2 = $Result.Warnings
equals $1.Message 'demo-file-warning'
assert ($1.File -like '*\z.build.ps1')
equals $1.Message demo-file-warning
equals $1.File $BuildFile
equals $1.Task
equals $2.Message 'demo-task-warning'
assert ($2.File -like '*\z.build.ps1')
equals $2.Task.Name 't1'

Remove-Item z.build.ps1
equals $2.Message demo-task-warning
equals $2.File $BuildFile
equals $2.Task.Name t1
}
10 changes: 4 additions & 6 deletions Tests/Events.test.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -103,22 +103,21 @@ task InvalidEvents {

# If a task fails then its $Task.Error is available in Exit-BuildJob.
task FailedTaskErrorInExitBuildJob {
Set-Content z.ps1 {
$file = {
Exit-BuildJob {
assert $Task.Error
}
task . {
throw 42
}
}
($r = try {Invoke-Build . z.ps1} catch {$_})
($r = try {Invoke-Build . $file} catch {$_})
equals $r[-1].FullyQualifiedErrorId '42'
Remove-Item z.ps1
}

# Task and job events cannot assign the constant variable $Task.
task CannotAssignTaskInEvents {
Set-Content z.ps1 {
$file = {
function Assert-CannotSetTask {
($r = try {$Task = 1} catch {$_})
equals $r.FullyQualifiedErrorId VariableNotWritable
Expand All @@ -141,6 +140,5 @@ task CannotAssignTaskInEvents {
}
task . {}
}
Invoke-Build . z.ps1
Remove-Item z.ps1
Invoke-Build . $file
}
Loading

0 comments on commit 4963636

Please sign in to comment.