views:

340

answers:

3

I would like to inject command line parameters into my psake build script like: .\build.ps1 Deploy environment="development"

But psake will treat every argument as a Task and will answer "task does not exists"

Is it possible to inject command line arguments in psake?

build.ps1 -->
Import-Module '.\psake.psm1'
Invoke-psake '.\tasks.ps1' $args
Remove-Module psake
A: 

I'm no expert, but I don't think it is possible to pass arguments to Invoke-Psake. Looking on the latest source for Psake the params for the Invoke-Psake function are:

param(
    [Parameter(Position=0,Mandatory=0)]
    [string]$buildFile = 'default.ps1',
    [Parameter(Position=1,Mandatory=0)]
    [string[]]$taskList = @(),
    [Parameter(Position=2,Mandatory=0)]
    [string]$framework = '3.5',   
    [Parameter(Position=3,Mandatory=0)]
    [switch]$docs = $false    
    )

There are 4 parameters, your build file, a list of tasks, the .NET framework version, whether to output docs of your tasks. I'm new to powershell and psake and I'm trying to do the same thing, I am experimenting with doing something like this in my script to achieve the same thing:

properties { 
   $environment = "default"
}

task PublishForLive -precondition { $environment = "Live"; return $true; } -depends Publish {

}

task PublishForStaging -precondition { $environment = "Staging"; return $true; } -depends Publish {

}

task Publish {
    Write-Host "Building and publishing for $environment environment"
    #Publish the project...
}

Then calling psake with PublishForLive or PublishForStaging, whichever I need:

powershell -NoExit -ExecutionPolicy Unrestricted -Command "& {Import-Module .\tools\psake\psake.psm1; Invoke-psake .\psake-common.ps1 PublishForLive }"

But it doesn't seem to work for me! Setting the $environment variable in the task precondition seems to have no effect. Still trying to make this work...

James Allen
Try making the $environment variable assignment visible outside the scriptblock scope e.g. `$script:environment = "Live"`
Keith Hill
It's a race condition in your example Publish will run before PublishForStaging. Another solution would be to call Publish from PublishForStaging, but don't know if it's possible or not?
orjan
This works for me:task PublishStage { $environment = "stage" ExecuteTask("Publish")}
orjan
A: 

A global variable will solve my problem for now and with only one reference to $global:arg_environent it will be easy to change if i find a better way to inject the properties.

build.ps1

param(
    [Parameter(Position=0,Mandatory=0)]
    [string]$task,
    [Parameter(Position=1,Mandatory=0)]
    [string]$environment = 'dev'
)

clear
$global:arg_environent = $environment
Import-Module .\psake.psm1 
Invoke-psake tasks.ps1 $task
Remove-Module psake

tasks.ps1

properties {
    $environment = $global:arg_environent
}

task default -depends Deploy

task Deploy {  
   echo "Copy stuff to $environment"
}
orjan
+3  A: 

The latest release of psake now supports passing parameters to Invoke-psake, e.g.

Invoke-psake .\parameters.ps1 -parameters @{"p1"="v1";"p2"="v2"} 

This feature has just been added. :)

James Allen
Thanks for the feedback it's a better option than a gobal variable
orjan
PS at the time of writing, this new feature is not part of an official 'release': you will have to get the latest source from the trunk (or whatever a trunk is called in GIT)
James Allen