Psake ignores properties and parameters
Asked Answered
S

1

6

Using psake 4.5.0 I've tried to run my default.ps1 file many different ways, passing both -properties and -parameters, but those values are just ignored in the root-scope of the .ps1-script.

Execute relative (with psake in a subfolder):

.\psake-4.5.0\psake.ps1 .\default.ps1 BuildSolution -properties @{"a"="a";"b"="b";"c"="c";"d"="d"} -parameters @{"w"="w";"x"="x";"y"="y";"z"="z"}

Execute with imported module:

Import-Module .\psake-4.5.0\psake.psm1

Invoke-Psake .\default.ps1 BuildSolution -properties @{"a"="a";"b"="b";"c"="c";"d"="d"} -parameters @{"w"="w";"x"="x";"y"="y";"z"="z"}

Execute through installed Chocolatey-package:

psake .\default.ps1 BuildSolution -properties "@{'a'='a';'b'='b';'c'='c';'d'='d'}" -parameters "@{'w'='w';'x'='x';'y'='y';'z'='z'}"

Execute through cmd.exe:

psake-4.5.0\psake.cmd default.ps1 BuildSolution -properties "@{'a'='a';'b'='b';'c'='c';'d'='d'}" -parameters "@{'w'='w';'x'='x';'y'='y';'z'='z'}"

Right now, the default.ps1 is simply just debugging all these values:

// Since "properties" doesn't get populated, I also try "Param"
Param(
    $w = $w, // Trying to populate from passed param
    $x = $null, // Trying to default to null-value
    $y // Trying another syntax, hoping for population
    // "$z" left out, hoping for population
)

properties {
    $a = $a
    $b = $null
    $c
}

Write-Host "a: $a"
Write-Host "b: $b"
Write-Host "c: $c"
Write-Host "d: $d"
Write-Host "w: $w"
Write-Host "x: $x"
Write-Host "y: $y"
Write-Host "z: $z"

Task BuildSolution -Depends Clean {
    Write-Host "Running BuildSolution"
}

Task Clean {
    Write-Host "Running Clean"
}

The output is in all cases:

a: 
b: 
c: 
d: 
w: 
x: 
y: 
z:

What is the proper syntax to pass properties and/or parameters to psake?

Spool answered 9/2, 2016 at 12:17 Comment(2)
does this help at all? github.com/psake/psake/tree/master/examples/…Granados
@Granados Not really, it's a very theoretical example, while mine is very concrete.Spool
G
0

I did not look into this too long but it seems as long as you declare the $variable in properties { ... here ... } or in Param (... here ... ) so psake can populate them, they come though okay. You missed $z. Unless im missing something fundamental about why your using parameters and properties together?

default.ps1

properties {
        $a = $null,
        $b = $null,
        $c = $null,
        $w = $null,
        $x = $null,
        $y = $null,
        $z = $null
    }

Task default -Depends BuildSolution 

Task BuildSolution -Depends Clean {
    Write-Host "Running BuildSolution"
    echo "x -> $x"
    echo "y -> $y"
    echo "z -> $z"
}

Task Clean {
    Write-Host "Running Clean"
    echo "a -> $a"
    echo "b -> $b"
    echo "c -> $c"
}

invoke code sample (psake installed via chocolatey to c:)

Import-Module C:\ProgramData\chocolatey\lib\psake\tools\psake.psm1

Invoke-Psake .\default.ps1  BuildSolution -properties @{'a'="a";"b"="b";"c"="c";'x'="x";'y'="y";'z'="z"} 

EDIT:

This is the Properties function Line 256 in psake.psm1, notice it takes a scriptblock args and adds it to properties array on the context stack found on $psake, still script blocks here

function Properties {
    [CmdletBinding()]
    param(
        [Parameter(Position=0,Mandatory=1)][scriptblock]$properties
    )
    $psake.context.Peek().properties += $properties
}

Line 372 of Invoke-psake function in psake.psm1 Loads your default.ps1 build script to scope ( at this point you see your write-host calls but no variables loaded )

. $psake.build_script_file.FullName

Line 394 and Line 397 Loads the script blocks from parameters and properties to the scope.

 foreach ($key in $parameters.keys) {
            if (test-path "variable:\$key") {
                set-item -path "variable:\$key" -value $parameters.$key -WhatIf:$false -Confirm:$false | out-null
            } else {
                new-item -path "variable:\$key" -value $parameters.$key -WhatIf:$false -Confirm:$false | out-null
            }
        }

...

foreach ($key in $properties.keys) {
            if (test-path "variable:\$key") {
                set-item -path "variable:\$key" -value $properties.$key -WhatIf:$false -Confirm:$false | out-null
            }
        }

Line 420 and 423 calls invoke-Task (Line 198) which in turn uses the variables defined above, also there is an assert that the variables are not null in this function.

I don't think the expected use case involved loading these variables into root scope, when the script is first . sourced into scope it spits out the write-host calls then, design probably intended you to declare Task method first so the scope can pass the variables into it and it should be noted.

Granados answered 18/2, 2016 at 18:20 Comment(3)
I've clarified the question a bit from your follow-up questions. All your examples has the properties inside Tasks. My problem is that nothing is populated in the root-scope for debugging.Spool
I'll take a look tonight about root scope issue but try add $z first to confirm still broken. Also in meantime just a suggestion but why not make a task for your global scope to run before clean?Granados
Tried it and it doesn't work for the root-scope. I can make it work through Task-scope, but this question is about highlighting why it doesn't work in the root-scope and why there is nothing in the documentation about it.Spool

© 2022 - 2024 — McMap. All rights reserved.