nightroman / Invoke-Build

Build Automation in PowerShell

Home Page:https://github.com/nightroman/Invoke-Build/wiki

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Task condition does not work

GreatTeacherBasshead opened this issue · comments

I have a task:

Enter-Build {
    $branchName = 'master'
}

task Build UpdateRepository

task UpdateRepository -If ($branchName -notmatch "^master|release/.*|dis/dev|dis/main$") {
    Write-Host "branchName: $branchName"
    Write-Host "Condition: " ($branchName -notmatch "^master|release/.*|dis/dev|dis/main$")
}

As mentioned in Conditional tasks, UpdateRepository task should be skipped.
But when I run it in Azure Pipeline it's not:

Task /Build/UpdateRepository
At CoreCI.tasks.ps1:38

branchName: master
Condition:  False

PowerShell: 7.2.7
InvokeBuild: 5.10.3

I think tasks -if are evaluated when the task loads (imported/parsed), not when the task are called (runtime). I had similar issue there I had to move away from -if and do the evaluation in the task instead. But I agree that you would expect the condition to be correctly evaluated. It would have been better if the parameter took a scriptblock that was run when called by Invoke-Build.

Switching to curly braces in the condition helped (UpdateRepository -If {$branchName -notmatch "^master|release/.*|dis/dev|dis/main$"})

@GreatTeacherBasshead @johlju

> . Invoke-Build
> help task -Parameter If

-If
    Specifies the optional condition to be evaluated. If the condition
    evaluates to false then the task is not invoked. The condition is
    defined in one of two ways depending on the requirements.

    Using standard Boolean notation (parenthesis) the condition is checked
    once when the task is defined. A use case for this notation might be
    evaluating a script parameter or another sort of global condition.

        Example:
            task Task1 -If ($Param1 -eq ...) {...}
            task Task2 -If ($PSVersionTable.PSVersion.Major -ge 5) {...}

    Using script block notation (curly braces) the condition is evaluated
    on task invocation. If a task is referenced by several tasks then the
    condition is evaluated each time until it gets true and the task is
    invoked. The script block notation is normally used for a condition
    that may be defined or changed during the build or just expensive.

        Example:
            task SomeTask -If {...} {...}

Thanks, Roman.
But then I have a question why () didn't work in my case?
Is Enter-Build executed later than the evaluation of that condition?

-If () is evaluated when the script is loaded and tasks are being created/added.
Enter-Build is invoked after that before the first task.

Thanks for the explanation!

Alternatively, instead of Enter-Build {...} you may use if (!$WhatIf) {...}. In this case, if (!$WhatIf) {...} is invoked on loading the script (for building, not introspection). If it is defined before a task then your -If () will work "as you expect".

I use Enter-Build {...} for multiple things, including defining script-scoped variables, which used in multiple task.
That's why I prefer to have all such preparations in one place (Enter-Build {...}). And using runtime task conditions is completely fine.