You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/pipelines/scripts/cross-platform-scripting.md
+47-74Lines changed: 47 additions & 74 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -3,26 +3,24 @@ title: Cross-platform scripting
3
3
description: Patterns for safe cross-platform scripting
4
4
ms.topic: conceptual
5
5
ms.assetid: 96b7da24-617e-4a58-b65f-040c374e60e2
6
-
ms.date: 11/02/2023
6
+
ms.date: 09/12/2025
7
7
monikerRange: '<= azure-devops'
8
+
#customer intent: As an Azure Pipelines user, I want to understand how cross-platform scripting works so I can easily support different build platforms in my pipelines.
With Azure Pipelines, you can run your builds on macOS, Linux, and Windows machines. If you develop on cross-platform technologies such as .NET Core, Node.js and Python, these capabilities bring both benefits and challenges.
15
+
Azure Pipelinescan run pipelines on Linux, macOS, and Windows machines. If you use cross-platform development technologies like .NET Core, Node.js, or Python, these cross-platform build capabilities bring both benefits and challenges. For example, most pipelines include one or more scripts to run during the build process, but script syntax often differs over platforms.
15
16
16
-
For example, most pipelines include one or more scripts that you want to run during the build process.
17
-
But scripts often don't run the same way on different platforms. You can use the `script` keyword shortcut to make writing scripts easier and also can use conditions to target specific platforms with your scripts.
17
+
This article explains how you can use cross-platform scripting to support different build platforms. You can use an Azure Pipelines `script` step to ease writing cross-platform scripts. You can also use [conditions](../process/conditions.md) to target scripts to specific platforms.
18
18
19
-
## Run cross-platform tools with a script step
19
+
## Script step
20
20
21
-
The script keyword is a shortcut for the [command line task](/azure/devops/pipelines/tasks/reference/cmd-line-v2). The `script` keyword runs Bash on Linux and macOS and cmd.exe on Windows.
21
+
The [script](../get-started/key-pipelines-concepts.md#scripts) keyword is a shortcut for the [command line task](/azure/devops/pipelines/tasks/reference/cmd-line-v2), which runs Bash on Linux and macOS or cmd.exe on Windows.
22
22
23
-
Using `script` can be useful when your task just passes arguments to a cross-platform tool. For instance, calling
24
-
`npm` with a set of arguments can be easily accomplished with a `script` step.
25
-
`script` runs in each platform's native script interpreter: Bash on macOS and Linux, cmd.exe on Windows.
23
+
You can use `script` to easily pass arguments to a cross-platform tool. The `script` step runs in each platform's native script interpreter, Bash on macOS and Linux or cmd.exe on Windows. The following example uses a `script` step to call `npm` with a set of arguments.
26
24
27
25
#### [YAML](#tab/yaml/)
28
26
```yaml
@@ -35,31 +33,29 @@ steps:
35
33
#### [Classic](#tab/classic/)
36
34
1. Add a **Command Line** task to your pipeline.
37
35
38
-
2. Replace the body of the script with:
36
+
1. Replace the body of the script with:
39
37
```
40
38
npm install
41
39
npm test
42
40
```
43
41
44
-
* * *
45
-
## Handle environment variables
42
+
---
43
+
44
+
## Environment variables
45
+
46
+
Command line, PowerShell, and Bash resolve [environment variables](../process/variables.md#environment-variables) differently. To access a system-provided value like PATH, you must use a different syntax per platform.
46
47
47
-
Environment variables throw the first wrinkle into writing cross-platform scripts.
48
-
Command line, PowerShell, and Bash each have different ways of reading environment variables.
49
-
If you need to access an operating system-provided value like PATH, you'll need different techniques per platform.
48
+
Azure Pipelines uses [macro syntax](../process/variables.md#macro-syntax-variables) as a cross-platform way to refer to variables at runtime. Variables with macro syntax get processed before a task executes during runtime. The variable expands before the platform shell encounters it.
50
49
51
-
However, Azure Pipelines offers a cross-platform way to refer to variables that
52
-
it knows about called [macro syntax](../process/variables.md#understand-variable-syntax). By surrounding a variable name in `$( )`, it's expanded
53
-
before the platform's shell ever sees it. For instance, if you want to echo out
54
-
the ID of the pipeline, the following script is cross-platform friendly:
50
+
To use macro syntax in a pipeline, surround the variable name as follows: `$(<variable name>)`. The following cross-platform example script echoes the ID of the pipeline.
55
51
56
52
#### [YAML](#tab/yaml/)
57
53
```yaml
58
54
steps:
59
55
- script: echo This is pipeline $(System.DefinitionId)
60
56
```
61
57
62
-
This also works for variables you specify in the pipeline.
58
+
This syntax also works for variables you define within the pipeline.
63
59
64
60
```yaml
65
61
variables:
@@ -72,22 +68,18 @@ steps:
72
68
#### [Classic](#tab/classic/)
73
69
1. Add a **Command Line** task to your pipeline.
74
70
75
-
2. Replace the body of the script with:
71
+
1. Replace the body of the script with:
76
72
```
77
73
echo This is pipeline $(System.DefinitionId)
78
74
```
79
75
80
-
* * *
81
-
## Consider Bash or pwsh
76
+
---
77
+
78
+
## Bash task
82
79
83
-
If you have more complex scripting needs than the examples shown above, then consider writing them in Bash.
84
-
Most macOS and Linux agents have Bash as an available shell, and Windows agents include Git Bash or [Windows Subsystem for Linux](/windows/wsl/about) Bash.
85
-
::: moniker range=">=azure-devops-2020"
86
-
For Azure Pipelines, the Microsoft-hosted agents always have Bash available.
87
-
::: moniker-end
80
+
If you need more complex scripts, consider writing them in Bash and using the [Bash task](/azure/devops/pipelines/tasks/reference/bash-v3) in your pipeline. Most macOS and Linux agents use Bash as a shell, and Windows agents can use Git Bash or [Windows Subsystem for Linux](/windows/wsl/about) Bash. [Microsoft-hosted agents](../agents/hosted.md) have Bash preinstalled by default.
88
81
89
-
For example, if you need to make a decision about whether your build is triggered by a pull
90
-
request:
82
+
The following example runs a Bash task that helps make a decision about whether to trigger a build.
91
83
92
84
#### [YAML](#tab/yaml/)
93
85
```yaml
@@ -110,10 +102,8 @@ steps:
110
102
111
103
#### [Classic](#tab/classic/)
112
104
1. Add a **Bash** task to your pipeline.
113
-
114
-
2. For the **Type**, select Inline.
115
-
116
-
3. Replace the body of the script with:
105
+
1. For **Type**, select **Inline**.
106
+
1. Replace the body of the script with:
117
107
```bash
118
108
if [ -n "$SYSTEM_PULLREQUEST_PULLREQUESTNUMBER" ]; then
119
109
echo This is for pull request $SYSTEM_PULLREQUEST_PULLREQUESTNUMBER
@@ -122,22 +112,16 @@ steps:
122
112
fi
123
113
```
124
114
125
-
* * *
126
-
PowerShell Core (`pwsh`) is also an option.
127
-
It requires each agent to have PowerShell Core installed.
115
+
---
128
116
129
-
## Switch based on platform
117
+
>[!NOTE]
118
+
>PowerShell is also an option for scripts. The [`pwsh`](/azure/devops/pipelines/yaml-schema/steps-pwsh) shortcut runs PowerShell 7.x on macOS, Linux, or Windows. Agents must have PowerShell 7.x installed. [Microsoft-hosted agents](../agents/hosted.md) have PowerShell 7.x installed by default.
130
119
131
-
In general, we recommend that you avoid platform-specific scripts to avoid problems such as duplication of your pipeline logic. Duplication causes extra work and extra risk of bugs.
132
-
However, if there's no way to avoid platform-specific scripting, then you can use a `condition` to detect what platform you're on.
120
+
## Platform-based switching
133
121
134
-
For example, suppose that for some reason you need the IP address of the build
135
-
agent.
136
-
On Windows, `ipconfig` gets that information.
137
-
On macOS, it's `ifconfig`.
138
-
And on Ubuntu Linux, it's `ip addr`.
122
+
Platform-specific scripting to duplicate pipeline logic causes extra work and increased error risk. But if you can't avoid platform-specific scripting, you can use [conditions](../process/conditions.md) to detect what platform you're on.
139
123
140
-
Set up the below pipeline, then try running it against agents on different platforms.
124
+
For example, to get the IP address of the build agent, you must use `ifconfig` on macOS, `ip addr` on Ubuntu Linux, and the `Get-NetIPAddress` cmdlet on Windows PowerShell. The following pipeline gets that information from agents on different platforms by using conditions.
1. Expand **Control Options**, select **Custom conditions** for **Run this task**, and in the **Custom condition** field, enter `eq( variables['Agent.OS'], 'Linux' )`.
181
165
182
-
4. Change the value of **Run this task** to "Custom conditions".
183
-
184
-
5. In the **Custom condition** field that appears, enter "eq( variables['Agent.OS'], 'Linux' )".
185
-
186
-
Next, add a macOS script.
166
+
Add the macOS script:
187
167
188
-
1. Repeat the above steps, but for the body of the script, enter:
168
+
1. Repeat the preceding steps, but for the body of the script, enter:
1. Expand **Control Options**, select **Custom conditions** for **Run this task**, and in the **Custom condition** field, enter `eq( variables['Agent.OS'], 'Darwin' )`.
193
174
194
-
2. For the **Custom condition**, enter "eq( variables['Agent.OS'], 'Darwin' )".
1. Expand **Control Options**, select **Custom conditions** for **Run this task**, and in the **Custom condition** field, enter `eq( variables['Agent.OS'], 'Windows_NT' )`.
207
185
208
-
4. Change the value of **Run this task** to "Custom conditions".
209
-
210
-
5. In the **Custom condition** field that appears, enter "eq( variables['Agent.OS'], 'Windows_NT' )".
211
-
212
-
Finally, add a task that uses the value, no matter how we got it.
0 commit comments