Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
297 changes: 248 additions & 49 deletions docs/tutorial-basics/parameters-properties.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,87 +4,286 @@ description: "How to use parameters and properties in your build script."
sidebar_position: 11
---

To summarize the differences between passing parameters and properties to the
`Invoke-psake` function:
Parameters and properties are two different ways to pass values into your psake build scripts. Understanding when to use each one is crucial for creating flexible, maintainable build automation.

* 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
## Quick Decision Guide

## Parameters
**Use Parameters when:**
- You need to pass external values that your properties blocks will use to compute derived values
- You want to provide inputs that determine how properties are calculated
- You're passing configuration from CI/CD systems or command-line arguments

You can pass parameters to your build script using the "parameters" parameter of
the Invoke-psake function. The following is an example:
**Use Properties when:**
- You need to override final property values after all computations are complete
- You want to replace default values defined in your build script
- You're overriding environment-specific settings (like connection strings or paths)

```powershell
Invoke-psake .\parameters.ps1 -parameters @{"p1"="v1";"p2"="v2"}
## Execution Flow & Lifespan

Understanding the execution order is key to choosing between parameters and properties:

```mermaid
sequenceDiagram
participant Invoke as Invoke-psake
participant Params as Parameters
participant Props as Properties Blocks
participant Override as Properties Override
participant Tasks as Task Execution

Invoke->>Params: 1. Set -parameters hashtable values
Note over Params: Variables available to script
Invoke->>Props: 2. Execute all properties { } blocks
Note over Props: Compute values using parameters
Invoke->>Override: 3. Apply -properties hashtable overrides
Note over Override: Replace computed values
Invoke->>Tasks: 4. Execute tasks
Note over Tasks: Use final property values
```

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.
**Key Insight:** Parameters are set **before** properties blocks run, while property overrides are applied **after** all properties blocks have executed.

:::note
## When to Use Each

You don't need to use the "$" character when specifying the parameter names in
the hashtable.
### Use Parameters For: Input Values

:::
Parameters provide **input values** that your build script can use during the properties block execution phase. They're ideal for:

- Build configuration values (Debug/Release)
- Version numbers to be incorporated into file paths
- Feature flags that affect property calculations
- CI/CD system variables

**Example:** Using parameters to compute derived properties

```powershell title="parameters.ps1"
properties {
$my_property = $p1 + $p2
$config = $configuration # Use parameter value
$outputPath = "bin\$config" # Compute derived path
$version = "$majorVersion.$minorVersion.0" # Build version string
}

task default -depends TestParams
task default -depends Build

task TestParams {
Assert ($my_property -ne $null) '$my_property should not be null'
task Build {
Write-Host "Building to: $outputPath"
Write-Host "Version: $version"
}
```

The Assert in this example would pass because when it runs, `$my_property`
would be set to `v1v2` and not be `$null`.
```powershell title="Invocation"
# Pass input values that properties blocks will use
Invoke-psake .\parameters.ps1 -parameters @{
"configuration" = "Release"
"majorVersion" = "2"
"minorVersion" = "1"
}

## Properties
# Output:
# Building to: bin\Release
# Version: 2.1.0
```

You can override a property in your build script using the `properties`
parameter of the Invoke-psake function. The following is an example:
### Use Properties For: Final Value Overrides

```powershell
Invoke-psake .\properties.ps1 -properties @{"x"="1";"y"="2"}
Properties provide **final value overrides** that replace values after all properties blocks have run. They're ideal for:

- Overriding default values for different environments
- Replacing computed values in specific scenarios
- Emergency hotfix values that bypass normal logic

**Example:** Overriding final property values

```powershell title="properties.ps1"
properties {
$server = "localhost" # Default value
$database = "DevDB" # Default value
$connectionString = "Server=$server;Database=$database"
}

task default -depends Deploy

task Deploy {
Write-Host "Deploying to: $connectionString"
}
```

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.
```powershell title="Invocation"
# Override final values after properties blocks run
Invoke-psake .\properties.ps1 -properties @{
"server" = "prod-sql-01"
"database" = "ProductionDB"
}

# Output:
# Deploying to: Server=prod-sql-01;Database=ProductionDB
# Note: $connectionString still has the OLD computed value!
```

:::note
:::warning Properties Don't Recompute Derived Values

You don't need to use the "$" character when specifying the property names in
the hashtable.
When you override a property, any derived values that were computed from it in the properties block are **NOT** automatically recalculated. In the example above, `$connectionString` would still contain the original computed value unless you override it directly as well.

:::

```powershell title="properties.ps1"
## Comparison: Side by Side

Let's see the difference with a concrete example:

```powershell title="build.ps1"
properties {
$env = $environment # Will be set if passed as parameter
$deployPath = "C:\Deploy\$env" # Computed from $env
}

task default -depends Info

task Info {
Write-Host "Environment: $env"
Write-Host "Deploy Path: $deployPath"
}
```

### Using Parameters (Input Values)

```powershell
Invoke-psake .\build.ps1 -parameters @{"environment"="Production"}

# Output:
# Environment: Production
# Deploy Path: C:\Deploy\Production
```

✅ The `$deployPath` property is correctly computed using the parameter value.

### Using Properties (Override After Computation)

```powershell
Invoke-psake .\build.ps1 -properties @{"environment"="Production"}

# Output:
# Environment: Production
# Deploy Path: C:\Deploy\
```

❌ The `$deployPath` is computed BEFORE the override, so it uses `$null` for `$env`.

### Using Both Together

```powershell
Invoke-psake .\build.ps1 `
-parameters @{"environment"="Production"} `
-properties @{"deployPath"="\\FileServer\Builds\Prod"}

# Output:
# Environment: Production
# Deploy Path: \\FileServer\Builds\Prod
```

✅ Parameter provides input for computation, property overrides the final value.

## Comparison Table

| Aspect | Parameters | Properties |
|--------|-----------|-----------|
| **Timing** | Set before properties blocks run | Applied after all properties blocks complete |
| **Purpose** | Provide inputs for computation | Override final computed values |
| **Derived Values** | Can be used to compute other properties | Do NOT trigger recomputation |
| **Best For** | Configuration inputs, build settings | Environment-specific overrides |
| **Use Case** | "I need this value to calculate others" | "I need to replace this final value" |

## Best Practices

### 1. Prefer Parameters for Inputs

When you need to pass values that affect multiple properties, use parameters:

```powershell
# ✅ Good: Use parameters for inputs
Invoke-psake .\build.ps1 -parameters @{
"configuration" = "Release"
"platform" = "x64"
}

# Properties block can use these to compute paths
properties {
$config = $configuration
$plat = $platform
$outputPath = "bin\$plat\$config"
}
```

### 2. Use Properties for Environment-Specific Overrides

When deploying to different environments, use properties to override specific values:

```powershell
# ✅ Good: Override environment-specific values
Invoke-psake .\deploy.ps1 `
-parameters @{"environment"="Production"} `
-properties @{
"serverName" = "prod-web-01"
"connectionString" = "Server=prod-sql-01;..."
}
```

### 3. Document Which Approach Your Script Expects

In your build script, document which values should be passed as parameters vs properties:

```powershell
<#
.SYNOPSIS
Build automation script

.PARAMETER parameters
Expected parameters:
- configuration: Build configuration (Debug/Release)
- version: Version number for the build

.PARAMETER properties
Optional property overrides:
- outputPath: Override computed output path
- deployServer: Override target deployment server
#>

properties {
$x = $null
$y = $null
$z = $null
$config = $configuration # From -parameters
$ver = $version # From -parameters
$outputPath = "bin\$config\$ver" # Computed
$deployServer = "localhost" # Default (can override with -properties)
}
```

task default -depends TestProperties
### 4. Avoid Overriding Properties That Other Properties Depend On

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"
If you override a property that other properties are computed from, the dependent properties won't update:

```powershell
# ❌ Bad: Overriding $buildRoot won't affect $outputPath
properties {
$buildRoot = "C:\Builds"
$outputPath = "$buildRoot\Output"
}

Invoke-psake .\build.ps1 -properties @{"buildRoot"="D:\Builds"}
# Result: $buildRoot = "D:\Builds", but $outputPath = "C:\Builds\Output"

# ✅ Good: Pass as parameter so computation uses the right value
Invoke-psake .\build.ps1 -parameters @{"buildRoot"="D:\Builds"}
# Result: $buildRoot = "D:\Builds" AND $outputPath = "D:\Builds\Output"
```

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 overridden so it
should still be `$null`.
## Summary

- **Parameters** = inputs set **before** properties blocks run → use for values that affect computations
- **Properties** = overrides applied **after** properties blocks run → use to replace final values
- Both can be used together for maximum flexibility
- When in doubt, prefer parameters for inputs and reserve properties for environment-specific overrides

:::tip Rule of Thumb

Ask yourself: "Does this value need to be used to calculate other properties?"
- **Yes** → Use `-parameters`
- **No** → Use `-properties`

:::
7 changes: 7 additions & 0 deletions docusaurus.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,13 @@ const config: Config = {
locales: ['en'],
},

// Enable mermaid diagrams in markdown
markdown: {
mermaid: true,
},

themes: ['@docusaurus/theme-mermaid'],

presets: [
[
'classic',
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
"dependencies": {
"@docusaurus/core": "^3.8.1",
"@docusaurus/preset-classic": "^3.8.1",
"@docusaurus/theme-mermaid": "3.8.1",
"@mdx-js/react": "^3.0.0",
"@signalwire/docusaurus-plugin-llms-txt": "^1.2.2",
"clsx": "^2.0.0",
Expand Down
Loading