Skip to content

Commit 404759d

Browse files
[main] Update common Docker engineering infrastructure with latest (#1299)
1 parent d965f9b commit 404759d

14 files changed

Lines changed: 214 additions & 172 deletions

eng/docker-tools/CHANGELOG.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,17 @@ All breaking changes and new features in `eng/docker-tools` will be documented i
44

55
---
66

7+
## 2026-03-18: CG build template supports skipping .NET SDK installation
8+
9+
- Issue: [#2029](https://github.com/dotnet/docker-tools/issues/2029)
10+
11+
`cg-build-projects.yml` now accepts `skipDotNetInstall` (boolean, default `false`) and
12+
`initSteps` (stepList, default `[]`) parameters. Setting `skipDotNetInstall: true` skips
13+
the built-in SDK installation. Setting `initSteps` will execute those custom steps
14+
at the beginning of the job.
15+
16+
---
17+
718
## 2026-03-12: Service connection OIDC changes
819

920
- Pull request: [#2013](https://github.com/dotnet/docker-tools/pull/2013)

eng/docker-tools/Install-DotNetSdk.ps1

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ Set-StrictMode -Version Latest
2727
$ErrorActionPreference = 'Stop'
2828

2929
if (!(Test-Path "$InstallPath")) {
30-
mkdir "$InstallPath" | Out-Null
30+
New-Item -ItemType Directory -Path "$InstallPath" -Force | Out-Null
3131
}
3232

3333
$IsRunningOnUnix = $PSVersionTable.contains("Platform") -and $PSVersionTable.Platform -eq "Unix"

eng/docker-tools/templates/jobs/cg-build-projects.yml

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,20 @@ parameters:
77
type: boolean
88
default: false
99
displayName: CG Dry Run
10+
# When true, the job skips the .NET SDK installation.
11+
- name: skipDotNetInstall
12+
type: boolean
13+
default: false
14+
displayName: Skip .NET SDK Installation
1015
# See https://learn.microsoft.com/en-us/dotnet/core/tools/dotnet-install-script#options for possible Channel values
1116
- name: dotnetVersionChannel
1217
type: string
1318
default: '9.0'
1419
displayName: .NET Version
20+
# Additional steps to run before building projects (e.g. custom SDK installation).
21+
- name: initSteps
22+
type: stepList
23+
default: []
1524

1625
jobs:
1726
- job: BuildProjects
@@ -21,9 +30,12 @@ jobs:
2130
image: $(default1ESInternalPoolImage)
2231
os: linux
2332
steps:
24-
- powershell: >
25-
./eng/docker-tools/Install-DotNetSdk.ps1 -Channel ${{ parameters.dotnetVersionChannel }} -InstallPath "$(Build.SourcesDirectory)/.dotnet"
26-
displayName: Run Dotnet Install Script
33+
- ${{ each step in parameters.initSteps }}:
34+
- ${{ step }}
35+
- ${{ if eq(parameters.skipDotNetInstall, false) }}:
36+
- powershell: >
37+
./eng/docker-tools/Install-DotNetSdk.ps1 -Channel ${{ parameters.dotnetVersionChannel }} -InstallPath "$(Build.SourcesDirectory)/.dotnet"
38+
displayName: Install .NET SDK
2739
- script: >
2840
find . -name '*.csproj' | grep $(cgBuildGrepArgs) | xargs -n 1 $(Build.SourcesDirectory)/.dotnet/dotnet build
2941
displayName: Build Projects

eng/docker-tools/templates/jobs/sign-images.yml

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,20 +15,20 @@ jobs:
1515
imageInfoDir: $(Build.ArtifactStagingDirectory)/image-info
1616
steps:
1717

18-
# Install MicroBuild signing plugin for ESRP container image signing
19-
- template: /eng/docker-tools/templates/steps/init-signing-linux.yml@self
20-
parameters:
21-
signType: ${{ parameters.publishConfig.Signing.SignType }}
22-
envFileVariableName: signingEnvFilePath
23-
24-
# Setup docker and ImageBuilder
18+
# Setup docker and ImageBuilder (checkout must happen before init-signing
19+
# so that the Install-DotNetSdk.ps1 script is available)
2520
- template: /eng/docker-tools/templates/steps/init-common.yml@self
2621
parameters:
2722
dockerClientOS: linux
2823
setupImageBuilder: true
2924
customInitSteps: ${{ parameters.customInitSteps }}
3025
publishConfig: ${{ parameters.publishConfig }}
31-
envFilePath: $(signingEnvFilePath)
26+
27+
# Install MicroBuild signing plugin for ESRP container image signing
28+
- template: /eng/docker-tools/templates/steps/init-signing-linux.yml@self
29+
parameters:
30+
signType: ${{ parameters.publishConfig.Signing.SignType }}
31+
dockerRunOptionsVariableName: signingDockerRunOptions
3232

3333
- template: /eng/docker-tools/templates/steps/reference-service-connections.yml@self
3434
parameters:
@@ -47,6 +47,7 @@ jobs:
4747
parameters:
4848
displayName: 🔏 Sign Container Images
4949
internalProjectName: ${{ parameters.internalProjectName }}
50+
linuxOnlyExtraDockerRunArgs: $(signingDockerRunOptions)
5051
args: >-
5152
signImages
5253
$(artifactsPath)/image-info/image-info.json
@@ -57,6 +58,7 @@ jobs:
5758
parameters:
5859
displayName: ✅ Verify Container Image Signatures
5960
internalProjectName: ${{ parameters.internalProjectName }}
61+
linuxOnlyExtraDockerRunArgs: $(signingDockerRunOptions)
6062
args: >-
6163
verifySignatures
6264
$(artifactsPath)/image-info/image-info.json

eng/docker-tools/templates/steps/clean-acr-images.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ parameters:
33
acr: null
44
action: null
55
age: null
6-
customArgs: "--dry-run"
6+
customArgs: ''
77
internalProjectName: null
88
steps:
99
- template: /eng/docker-tools/templates/steps/run-imagebuilder.yml@self
@@ -23,3 +23,4 @@ steps:
2323
--action ${{ parameters.action }}
2424
--age ${{ parameters.age }}
2525
${{ parameters.customArgs }}
26+
$(dryRunArg)

eng/docker-tools/templates/steps/init-common.yml

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -53,12 +53,6 @@ parameters:
5353
type: string
5454
default: "versions"
5555

56-
# Path to an env file for docker --env-file.
57-
# Passed through to init-imagebuilder.yml.
58-
- name: envFilePath
59-
type: string
60-
default: ""
61-
6256
steps:
6357
# Repository Checkout
6458
# Multi-repo checkout is used when a versions repository is needed for caching.
@@ -251,4 +245,3 @@ steps:
251245
publishConfig: ${{ parameters.publishConfig }}
252246
condition: ${{ parameters.condition }}
253247
customInitSteps: ${{ parameters.customInitSteps }}
254-
envFilePath: ${{ parameters.envFilePath }}

eng/docker-tools/templates/steps/init-imagebuilder.yml

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,6 @@ parameters:
2121
type: stepList
2222
default: []
2323

24-
# Path to an env file for docker --env-file.
25-
# When set, --env-file is added to the docker run commands so the container
26-
# receives the environment variables defined in the file.
27-
- name: envFilePath
28-
type: string
29-
default: ""
30-
3124
steps:
3225
# Custom ImageBuilder setup (e.g., bootstrap from source)
3326
- ${{ if gt(length(parameters.customInitSteps), 0) }}:
@@ -106,21 +99,25 @@ steps:
10699
"$(imageBuilderDockerRunExtraOptions)"
107100
)
108101
109-
$envFilePath = "${{ parameters.envFilePath }}"
110-
if ($envFilePath) {
111-
$dockerRunArgs += "--env-file $envFilePath"
112-
}
113-
114102
$authedDockerRunArgs = @(
115103
"-e", 'SYSTEM_ACCESSTOKEN'
116104
"-e", 'SYSTEM_OIDCREQUESTURI'
117105
)
118106
119-
$dockerRunCmd = $dockerRunBaseCmd + $dockerRunArgs + @("$(imageNames.imageBuilder.withrepo)")
120-
$authedDockerRunCmd = $dockerRunBaseCmd + $authedDockerRunArgs + $dockerRunArgs + @("$(imageNames.imageBuilder.withrepo)")
107+
$dockerRunCmd = $dockerRunBaseCmd + $dockerRunArgs
108+
$authedDockerRunCmd = $dockerRunBaseCmd + $authedDockerRunArgs + $dockerRunArgs
109+
110+
# Base commands without image name for templates that need to insert
111+
# extra docker run args before the image name (e.g. signing)
112+
$runImageBuilderBaseCmd = $($dockerRunCmd -join ' ')
113+
$runAuthedImageBuilderBaseCmd = $($authedDockerRunCmd -join ' ')
114+
115+
Write-Host "##vso[task.setvariable variable=runImageBuilderBaseCmd]$runImageBuilderBaseCmd"
116+
Write-Host "##vso[task.setvariable variable=runAuthedImageBuilderBaseCmd]$runAuthedImageBuilderBaseCmd"
121117
122-
$runImageBuilderCmd = $($dockerRunCmd -join ' ')
123-
$runAuthedImageBuilderCmd = $($authedDockerRunCmd -join ' ')
118+
# Full commands with image name for direct invocation by other templates
119+
$runImageBuilderCmd = "$runImageBuilderBaseCmd $imageBuilderImageName"
120+
$runAuthedImageBuilderCmd = "$runAuthedImageBuilderBaseCmd $imageBuilderImageName"
124121
125122
Write-Host "##vso[task.setvariable variable=runImageBuilderCmd]$runImageBuilderCmd"
126123
Write-Host "##vso[task.setvariable variable=runAuthedImageBuilderCmd]$runAuthedImageBuilderCmd"
@@ -138,3 +135,12 @@ steps:
138135
$runImageBuilderCmd = "$(Build.BinariesDirectory)\.Microsoft.DotNet.ImageBuilder\Microsoft.DotNet.ImageBuilder.exe"
139136
Write-Host "##vso[task.setvariable variable=runImageBuilderCmd]$runImageBuilderCmd"
140137
Write-Host "##vso[task.setvariable variable=runAuthedImageBuilderCmd]$runImageBuilderCmd"
138+
# On Windows the base commands are the same as the full commands since
139+
# there is no container image name to append
140+
Write-Host "##vso[task.setvariable variable=runImageBuilderBaseCmd]$runImageBuilderCmd"
141+
Write-Host "##vso[task.setvariable variable=runAuthedImageBuilderBaseCmd]$runImageBuilderCmd"
142+
# Set imageBuilderImageName to empty - on Windows there is no container image
143+
# since ImageBuilder runs as a native exe. run-imagebuilder.yml appends this
144+
# variable to the command line, so it must be defined (but empty) to avoid
145+
# leaving an unexpanded $(imageBuilderImageName) literal in the script.
146+
Write-Host "##vso[task.setvariable variable=imageBuilderImageName]"

eng/docker-tools/templates/steps/init-signing-linux.yml

Lines changed: 62 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -16,31 +16,31 @@ parameters:
1616
type: string
1717
default: $(Agent.TempDirectory)/MicroBuild
1818

19-
# Name of the pipeline variable to set with the signing env file path.
20-
# When set, a signing env file is written after plugin installation and
21-
# the specified pipeline variable is set to its path via logging directive,
22-
# allowing downstream steps to reference it as $(variableName).
23-
# When empty, no env file is created (non-signing jobs).
24-
- name: envFileVariableName
19+
# Name of the pipeline variable to set with the signing docker run options.
20+
# The variable will contain both the MicroBuild plugin volume mount and
21+
# the --env-file flag, ready to pass as extraDockerRunOptions to run-imagebuilder.
22+
- name: dockerRunOptionsVariableName
2523
type: string
26-
default: ""
2724

2825
steps:
29-
# Install .NET SDK on Linux - needed to download the MicroBuild plugin nupkgs when nuget.exe is unavailable.
30-
# Install to an isolated location so the repo's global.json doesn't interfere.
31-
- task: UseDotNet@2
26+
# Install .NET 8.0 SDK for MicroBuild plugin installation using dotnet-install.sh.
27+
# We avoid UseDotNet@2 because it sets DOTNET_ROOT globally, which breaks PowerShell
28+
# (pwsh) on Azure Linux 3 where pwsh requires the .NET 9.0 runtime from the system
29+
# .NET installation. Instead, we install to an isolated directory and only expose it
30+
# to the MicroBuild task via its env block.
31+
- powershell: >
32+
$(engDockerToolsPath)/Install-DotNetSdk.ps1
33+
-InstallPath "${{ parameters.microBuildOutputFolder }}/.dotnet"
34+
-Channel "8.0"
3235
displayName: Install .NET SDK for MicroBuild Plugin
3336
condition: and(succeeded(), ${{ parameters.condition }})
34-
inputs:
35-
packageType: sdk
36-
version: 8.0.x
37-
installationPath: ${{ parameters.microBuildOutputFolder }}/.dotnet
3837

3938
# Create a global.json in the MicroBuild folder that pins to the installed SDK.
40-
# This prevents the repo's global.json from causing SDK resolution failures.
39+
# This prevents the repo's global.json from causing SDK resolution failures
40+
# when MicroBuild runs dotnet restore from this directory.
4141
- script: |
4242
mkdir -p ${{ parameters.microBuildOutputFolder }}
43-
version=$(dotnet --version)
43+
version=$(${{ parameters.microBuildOutputFolder }}/.dotnet/dotnet --version)
4444
cat > ${{ parameters.microBuildOutputFolder }}/global.json << EOF
4545
{
4646
"sdk": {
@@ -69,56 +69,56 @@ steps:
6969
TeamName: $(TeamName)
7070
MicroBuildOutputFolderOverride: $(Agent.TempDirectory)/MicroBuild
7171
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
72+
PATH: ${{ parameters.microBuildOutputFolder }}/.dotnet:$(PATH)
7273

73-
# Configure ImageBuilder docker run options and write env file for signing.
74-
# Sets imageBuilderDockerRunExtraOptions with the plugin volume mount and,
75-
# when envFileVariableName is provided, writes a signing env file and sets
76-
# the named pipeline variable to its path via logging directive.
77-
- ${{ if ne(parameters.envFileVariableName, '') }}:
78-
- task: PowerShell@2
79-
displayName: Configure ImageBuilder Signing Options
80-
condition: and(succeeded(), ${{ parameters.condition }})
81-
inputs:
82-
targetType: 'inline'
83-
script: |
84-
# Mount the MicroBuild signing plugin directory (contains DDSignFiles.dll and esrpcli.dll).
85-
$imageBuilderDockerRunExtraOptions = "-v $env:MBSIGN_APPFOLDER`:/microbuild"
86-
Write-Host "MicroBuild signing enabled, mounting $env:MBSIGN_APPFOLDER to /microbuild"
87-
Write-Host "##vso[task.setvariable variable=imageBuilderDockerRunExtraOptions]$imageBuilderDockerRunExtraOptions"
74+
# Configure docker run options for signing.
75+
# Writes an env file with signing variables and sets $(signingDockerRunOptions)
76+
# with both the MicroBuild plugin volume mount and the --env-file flag.
77+
- task: PowerShell@2
78+
displayName: Configure ImageBuilder Signing Options
79+
condition: and(succeeded(), ${{ parameters.condition }})
80+
inputs:
81+
targetType: 'inline'
82+
script: |
83+
# Write the signing env file for docker --env-file.
84+
# Docker reads this file on the host before creating the container,
85+
# so no volume mount is needed for the file itself.
86+
$envFilePath = "$(Agent.TempDirectory)/imagebuilder-signing.env"
87+
$envFileContent = @(
88+
# MicroBuild plugin variables for DDSignFiles.dll
89+
"MBSIGN_APPFOLDER=/microbuild"
90+
"VSENGESRPSSL"
91+
"USEESRPCLI"
92+
"MBSIGN_CONNECTEDSERVICE"
8893
89-
# Write the signing env file for docker --env-file.
90-
# Docker reads this file on the host before creating the container,
91-
# so no volume mount is needed for the file itself.
92-
$envFilePath = "$(Agent.TempDirectory)/imagebuilder-signing.env"
93-
$envFileContent = @(
94-
# MicroBuild plugin variables for DDSignFiles.dll
95-
"MBSIGN_APPFOLDER=/microbuild"
96-
"VSENGESRPSSL"
97-
"USEESRPCLI"
98-
"MBSIGN_CONNECTEDSERVICE"
94+
# Container-local temp/workspace paths (host paths aren't accessible inside the container)
95+
"MBSIGNTEMPDIR=/tmp/MicroBuildSign"
96+
"PIPELINE_WORKSPACE=$(Build.ArtifactStagingDirectory)"
97+
"AGENT_TEMPDIRECTORY=/tmp"
9998
100-
# Container-local temp/workspace paths (host paths aren't accessible inside the container)
101-
"MBSIGNTEMPDIR=/tmp/MicroBuildSign"
102-
"PIPELINE_WORKSPACE=$(Build.ArtifactStagingDirectory)"
103-
"AGENT_TEMPDIRECTORY=/tmp"
99+
# Azure DevOps pipeline variables for ESRP bearer token auth (ESRPUtils.GetAccountInfo)
100+
"SYSTEM_TEAMFOUNDATIONCOLLECTIONURI"
101+
"BUILD_BUILDID"
102+
"SYSTEM_TEAMPROJECT"
103+
"BUILD_SOURCEBRANCH"
104104
105-
# Azure DevOps pipeline variables for ESRP bearer token auth (ESRPUtils.GetAccountInfo)
106-
"SYSTEM_TEAMFOUNDATIONCOLLECTIONURI"
107-
"BUILD_BUILDID"
108-
"SYSTEM_TEAMPROJECT"
109-
"BUILD_SOURCEBRANCH"
105+
# Azure DevOps pipeline variables for ESRP CLI federated token (ESRPCliDll.GetFederatedTokenData)
106+
"SYSTEM_JOBID"
107+
"SYSTEM_PLANID"
108+
"SYSTEM_TEAMPROJECTID"
109+
"SYSTEM_HOSTTYPE"
110+
"SYSTEM_COLLECTIONURI"
110111
111-
# Azure DevOps pipeline variables for ESRP CLI federated token (ESRPCliDll.GetFederatedTokenData)
112-
"SYSTEM_JOBID"
113-
"SYSTEM_PLANID"
114-
"SYSTEM_TEAMPROJECTID"
115-
"SYSTEM_HOSTTYPE"
116-
"SYSTEM_COLLECTIONURI"
112+
# Azure DevOps pipeline variables for DDSignFilesConfiguration
113+
"BUILD_DEFINITIONNAME"
114+
"BUILD_BUILDNUMBER"
115+
)
117116
118-
# Azure DevOps pipeline variables for DDSignFilesConfiguration
119-
"BUILD_DEFINITIONNAME"
120-
"BUILD_BUILDNUMBER"
121-
)
117+
$envFileContent | Set-Content -Path $envFilePath -Encoding utf8NoBOM
122118
123-
$envFileContent | Set-Content -Path $envFilePath -Encoding utf8NoBOM
124-
Write-Host "##vso[task.setvariable variable=${{ parameters.envFileVariableName }}]$envFilePath"
119+
# Compose docker run options for signing:
120+
# - Volume mount for MicroBuild plugin directory (DDSignFiles.dll and esrpcli.dll)
121+
# - Env file with signing environment variables
122+
$signingDockerRunOptions = "-v $env:MBSIGN_APPFOLDER`:/microbuild --env-file `"$envFilePath`""
123+
Write-Host "signingDockerRunOptions: $signingDockerRunOptions"
124+
Write-Host "##vso[task.setvariable variable=${{ parameters.dockerRunOptionsVariableName }}]$signingDockerRunOptions"

eng/docker-tools/templates/steps/run-imagebuilder.yml

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,15 @@ parameters:
2929
type: string
3030
default: "linux"
3131

32+
# Additional docker run args inserted before the image name (Linux only).
33+
# These are flags passed to `docker run` for the containerized ImageBuilder
34+
# and must not be set for Windows jobs where ImageBuilder runs as a native
35+
# executable. Used for signing (volume mounts, env files) or other
36+
# job-specific docker configuration.
37+
- name: linuxOnlyExtraDockerRunArgs
38+
type: string
39+
default: ""
40+
3241
steps:
3342
- ${{ if and(eq(variables['System.TeamProject'], parameters.internalProjectName), ne(variables['Build.Reason'], 'PullRequest')) }}:
3443

@@ -56,7 +65,7 @@ steps:
5665
$serviceConnectionsArgs += "$($connection.tenantId):$($connection.clientId):$($connection.id)"
5766
}
5867
59-
$(runAuthedImageBuilderCmd) ${{ parameters.args }} @serviceConnectionsArgs
68+
$(runAuthedImageBuilderBaseCmd) ${{ parameters.linuxOnlyExtraDockerRunArgs }} $(imageBuilderImageName) ${{ parameters.args }} @serviceConnectionsArgs
6069
6170
- ${{ else }}:
6271

@@ -69,4 +78,4 @@ steps:
6978
inputs:
7079
targetType: 'inline'
7180
script: >-
72-
$(runImageBuilderCmd) ${{ parameters.args }}
81+
$(runImageBuilderBaseCmd) ${{ parameters.linuxOnlyExtraDockerRunArgs }} $(imageBuilderImageName) ${{ parameters.args }}

0 commit comments

Comments
 (0)