Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
80 commits
Select commit Hold shift + click to select a range
954834d
chore: build Windows 2022 images from a Windows Server Core 2025 agent
lemeurherve Nov 27, 2025
435bb65
feat: add Windows 2025 images
lemeurherve Nov 27, 2025
11b2e9e
build only nanoserver & windows-server-core 2022 & 2025 images for now
lemeurherve Nov 30, 2025
daf8336
add `docker info` to `init-docker` Makefile target
lemeurherve Nov 30, 2025
dcf1118
add `docker-init` target to `build.ps1` script
lemeurherve Nov 30, 2025
f656480
call `docker-init` for both Linux & Windows
lemeurherve Nov 30, 2025
7cba9eb
correct test description
lemeurherve Nov 30, 2025
f8ea469
show `IMAGE_TAG` instead of `IMAGE_NAME` in Windows test descriptions
lemeurherve Nov 30, 2025
30f1c86
move slow Windows image build test after the quicker ones
lemeurherve Nov 30, 2025
2dae8e7
better Windows image build with custom buid args test description
lemeurherve Nov 30, 2025
eeaa260
quote invoked expression in `Initialize-Docker`
lemeurherve Nov 30, 2025
f3d5c49
debug: add Debug-ContainerHost.ps1 from https://github.com/MicrosoftD…
lemeurherve Nov 30, 2025
3eb6165
debug: remove docker daemon config of the docker-root pointing to Z:\…
lemeurherve Dec 1, 2025
52049bd
comment out `disableConcurrentBuilds(abortPrevious: true)` for now
lemeurherve Dec 1, 2025
809e4a4
move comment
lemeurherve Dec 1, 2025
7aefe02
set new SystemTemp instead of deleting docker daemon config
lemeurherve Dec 1, 2025
781303d
space
lemeurherve Dec 1, 2025
4a0a26c
fixup path
lemeurherve Dec 1, 2025
503b79c
rename
lemeurherve Dec 1, 2025
e5c9048
fixup mklink
lemeurherve Dec 1, 2025
e39fa6d
Push/Pop-Location
lemeurherve Dec 1, 2025
cc7c07e
data-root value from docker daemon config as new SystemTemp folder
lemeurherve Dec 1, 2025
2b0820f
delete docker daemon config for now
lemeurherve Dec 1, 2025
815eff6
fixup remove path not content
lemeurherve Dec 1, 2025
6646c61
restart docker service after docker daemon config deletion
lemeurherve Dec 1, 2025
2b95407
retrieve powershell from wsc base image instead of powershell:nanoser…
lemeurherve Dec 2, 2025
889a417
allow passing multiple versions with `WINDOWS_VERSION_OVERRIDE`
lemeurherve Dec 2, 2025
c30b84d
remove Debug-ContainerHost.ps1
lemeurherve Dec 2, 2025
09fd91f
Merge branch 'master' into helpdesk4971-windows-2025
lemeurherve Dec 2, 2025
5ad8847
move Get-ChildItem env: to its own powershell call so it doesn't over…
lemeurherve Dec 2, 2025
2d5356d
install powershell 7 in nanoserver
lemeurherve Dec 2, 2025
9006052
fixup
lemeurherve Dec 2, 2025
b5e68a8
use CMD continuation syntax
lemeurherve Dec 2, 2025
cd5e23e
prevent docker bake progress stderr (output by default)
lemeurherve Dec 2, 2025
64f52b3
cmd.exe /c mkdir
lemeurherve Dec 2, 2025
8c67bdf
fixup ^ &&
lemeurherve Dec 2, 2025
789bf58
fixup last PATH
lemeurherve Dec 2, 2025
d23361f
cmd multiline
lemeurherve Dec 2, 2025
24552a6
heredoc
lemeurherve Dec 2, 2025
44ffc38
build only jdk25 for now
lemeurherve Dec 2, 2025
1313596
full pwsh path in SHELL
lemeurherve Dec 2, 2025
7e6600f
proper final pwsh path
lemeurherve Dec 2, 2025
e4078de
pwsh.exe path with / instead of \
lemeurherve Dec 2, 2025
5bf9a73
debug env
lemeurherve Dec 2, 2025
cb1ba82
fixup SHELL cmd
lemeurherve Dec 2, 2025
3bb09e5
Revert "debug env"
lemeurherve Dec 2, 2025
e1ef504
COPY later, and conditionally for netapi32.dll
lemeurherve Dec 2, 2025
d086b98
distinct RUN for now
lemeurherve Dec 2, 2025
1d22e5a
show CPU name in `Initialize-Docker`
lemeurherve Dec 2, 2025
83980df
add back env vars in Initialize-Docker
lemeurherve Dec 2, 2025
6fe9fe1
curl pwsh.zip to temp
lemeurherve Dec 2, 2025
bd1fc72
set env=arg
lemeurherve Dec 2, 2025
35a8682
use C:/windows/TEMP instead of C:/temp
lemeurherve Dec 2, 2025
c456981
backslashes for `del`
lemeurherve Dec 2, 2025
b74043c
restore powershell folder
lemeurherve Dec 2, 2025
233c794
conditional COPY after the normal ones
lemeurherve Dec 2, 2025
0de390c
copy netapi32.dll in C:/windows/TEMP
lemeurherve Dec 2, 2025
acb2d13
wsc2022 & wsc2025 OK, commenting them out for now
lemeurherve Dec 2, 2025
1b57ea1
C:/temp for netapi32.dll
lemeurherve Dec 2, 2025
0182f40
free space before and after build
lemeurherve Dec 2, 2025
35d7987
temp dir
lemeurherve Dec 2, 2025
506d412
use PSHOME as temp folder for netapi32.dll
lemeurherve Dec 2, 2025
a3493ef
combine conditions
lemeurherve Dec 2, 2025
9694c21
fixup hardcode ProgramFiles
lemeurherve Dec 2, 2025
4402ddf
quote env:PSHOME
lemeurherve Dec 2, 2025
b98c2f8
quote %PSHOME%
lemeurherve Dec 2, 2025
561986e
no quote on env
lemeurherve Dec 2, 2025
7236745
again
lemeurherve Dec 2, 2025
3da3a5e
escape space
lemeurherve Dec 2, 2025
d943b16
measurements
lemeurherve Dec 2, 2025
a54fb33
get rid of ENV ProgramFiles
lemeurherve Dec 2, 2025
d5acb85
one RUN for cmd
lemeurherve Dec 3, 2025
8d79b70
define ENV PSHOME
lemeurherve Dec 3, 2025
9b3018b
comment about netapi32.dll & nanoserver-ltsc2025
lemeurherve Dec 3, 2025
2884d85
no powershell:nanoserver-ltsc2025 available (there won't be), using a…
lemeurherve Dec 4, 2025
018c448
restore powershell retrieval from a powershell image instead of gh re…
lemeurherve Dec 4, 2025
7ac4e56
fixup missing )
lemeurherve Dec 4, 2025
d626974
verbose tests
lemeurherve Dec 4, 2025
95404bd
Revert "restore powershell retrieval from a powershell image instead …
lemeurherve Dec 4, 2025
df81f0f
retry with powershell from powershell:nanoserver image, but with cond…
lemeurherve Dec 4, 2025
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
38 changes: 26 additions & 12 deletions Jenkinsfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ final String cronExpr = env.BRANCH_IS_PRIMARY ? '@daily' : ''

properties([
buildDiscarder(logRotator(numToKeepStr: '10')),
disableConcurrentBuilds(abortPrevious: true),
// disableConcurrentBuilds(abortPrevious: true),
pipelineTriggers([cron(cronExpr)]),
])

Expand All @@ -17,9 +17,9 @@ def agentSelector(String imageType) {
return 'docker-highmem'
}
}
// Windows Server Core 2022 agent
if (imageType.contains('2022')) {
return 'windows-2022'
// Windows Server Core 2025 can build both 2022 and 2025 images
if (imageType.contains('2022') || imageType.contains('2025')) {
return 'windows-2025'
}
// Windows Server Core 2019 agent (for nanoserver 1809 & ltsc2019 and for windowservercore ltsc2019)
return 'windows-2019'
Expand All @@ -43,13 +43,15 @@ def spotAgentSelector(String agentLabel, int counter) {
// Specify parallel stages
def parallelStages = [failFast: false]
[
'linux',
'nanoserver-1809',
// 'linux',
// 'nanoserver-1809',
'nanoserver-ltsc2019',
'nanoserver-ltsc2022',
'windowsservercore-1809',
'windowsservercore-ltsc2019',
'windowsservercore-ltsc2022'
'nanoserver-ltsc2025',
// 'windowsservercore-1809',
// 'windowsservercore-ltsc2019',
// 'windowsservercore-ltsc2022',
// 'windowsservercore-ltsc2025'
].each { imageType ->
parallelStages[imageType] = {
withEnv([
Expand All @@ -64,9 +66,13 @@ def parallelStages = [failFast: false]
node(resolvedAgentLabel) {
timeout(time: 60, unit: 'MINUTES') {
checkout scm
if (imageType == "linux") {
stage('Prepare Docker') {
stage('Prepare Docker') {
if (isUnix()) {
sh 'make docker-init'
} else {
// Check CPU name
powershell 'Get-CimInstance -ClassName Win32_Processor | Out-String'
powershell './build.ps1 docker-init'
}
}
// This function is defined in the jenkins-infra/pipeline-library
Expand Down Expand Up @@ -94,15 +100,23 @@ def parallelStages = [failFast: false]
if (isUnix()) {
sh 'make build'
} else {
// Free space before building images
powershell 'Invoke-Command -ScriptBlock { ((Get-PSDrive -Name C).Free / 1GB) }'
powershell '& ./build.ps1 build'
// Free space remaining after building images
powershell 'Invoke-Command -ScriptBlock { ((Get-PSDrive -Name C).Free / 1GB) }'
archiveArtifacts artifacts: 'build-windows.yaml', allowEmptyArchive: true
}
}
stage('Test') {
if (isUnix()) {
sh 'make test'
} else {
powershell '& ./build.ps1 test'
// Free space before testing images
powershell 'Invoke-Command -ScriptBlock { ((Get-PSDrive -Name C).Free / 1GB) }'
powershell '& ./build.ps1 test -TestsDebug verbose'
// Free space remaining after testing images
powershell 'Invoke-Command -ScriptBlock { ((Get-PSDrive -Name C).Free / 1GB) }'
}
junit(allowEmptyResults: true, keepLongStdio: true, testResults: 'target/**/junit-results.xml')
}
Expand Down
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ else
docker buildx create --use --bootstrap --driver docker-container
endif
docker run --rm --privileged multiarch/qemu-user-static --reset -p yes
docker info

build: check-reqs
@set -x; $(bake_cli) $(shell make --silent list) --set '*.platform=linux/$(ARCH)'
Expand Down
30 changes: 28 additions & 2 deletions build.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ function Test-Image {
$env:JAVA_VERSION = "$javaVersion"

$targetPath = '.\target\{0}' -f $imageTag
if(Test-Path $targetPath) {
if (Test-Path $targetPath) {
Remove-Item -Recurse -Force $targetPath
}
New-Item -Path $targetPath -Type Directory | Out-Null
Expand All @@ -116,6 +116,28 @@ function Test-Image {
return $failed
}

function Initialize-Docker() {
# Cf https://github.com/jenkins-infra/jenkins-infra/blob/production/modules/profile/templates/jenkinscontroller/casc/clouds-ec2.yaml.erb
$dockerDaemonConfigPath = 'C:\ProgramData\Docker\config\daemon.json'
if (Test-Path $dockerDaemonConfigPath) {
$dockerDaemonConfig = Get-Content -Path $dockerDaemonConfigPath -Raw | ConvertFrom-Json
Write-Host "${dockerDaemonConfigPath} file content:"
$dockerDaemonConfig | ConvertTo-Json
# Remove docker daemon config setting "data-root" to Z:\docker (NVMe mount) to avoid hitting moby/moby#48093
Remove-Item -Path $dockerDaemonConfigPath
Restart-Service docker
# Push-Location -Path 'C:\Windows'
# Rename-Item SystemTemp SystemTemp.old
# cmd.exe /c 'mklink /D SystemTemp {0}' -f $dockerDaemonConfig.PSObject.Properties['data-root'].Value
# Pop-Location
}
Get-ComputerInfo | Select-Object OsName, OsBuildNumber, WindowsVersion
Get-WindowsFeature Containers | Out-String
Invoke-Expression 'docker info'
Get-CimInstance -ClassName Win32_Processor
Get-ChildItem env: | Select-Object Name, Value
}

function Initialize-DockerComposeFile {
$baseDockerBakeCmd = 'docker buildx bake --progress=plain --file=docker-bake.hcl'

Expand Down Expand Up @@ -146,7 +168,7 @@ function Initialize-DockerComposeFile {

Write-Host "= PREPARE: Docker compose file generation command`n$generateDockerComposeFileCmd"

Invoke-Expression $generateDockerComposeFileCmd
Invoke-Expression $generateDockerComposeFileCmd | Out-Null

# Remove override
Remove-Item env:\WINDOWS_VERSION_OVERRIDE
Expand All @@ -157,6 +179,10 @@ Test-CommandExists 'docker-compose'
Test-CommandExists 'docker buildx'
Test-CommandExists 'yq'

if($target -eq 'docker-init') {
Initialize-Docker
}

# Generate the docker compose file if it doesn't exists or if the parameter OverwriteDockerComposeFile is set
if ((Test-Path $dockerComposeFile) -and -not $OverwriteDockerComposeFile) {
Write-Host "= PREPARE: The docker compose file '$dockerComposeFile' containing the image definitions already exists."
Expand Down
15 changes: 10 additions & 5 deletions docker-bake.hcl
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ group "linux-ppc64le" {
}

variable "jdks_to_build" {
default = [17, 21, 25]
# default = [17, 21, 25]
default = [25]
}

variable "default_jdk" {
Expand Down Expand Up @@ -80,6 +81,7 @@ variable "DEBIAN_RELEASE" {
}

# Set this value to a specific Windows version to override Windows versions to build returned by windowsversions function
# Accept multiple coma-separated versions, ex: ltsc2022,ltsc2025
variable "WINDOWS_VERSION_OVERRIDE" {
default = ""
}
Expand Down Expand Up @@ -120,24 +122,27 @@ function "debian_platforms" {

# Return array of Windows version(s) to build
# There is no mcr.microsoft.com/windows/servercore:1809 image
# Can be overriden by setting WINDOWS_VERSION_OVERRIDE to a specific Windows version
# Can be overriden by setting WINDOWS_VERSION_OVERRIDE to one or many specific Windows version
# Ex: WINDOWS_VERSION_OVERRIDE=1809 docker buildx bake windows
function "windowsversions" {
params = [flavor]
result = (notequal(WINDOWS_VERSION_OVERRIDE, "")
? [WINDOWS_VERSION_OVERRIDE]
? split(",", WINDOWS_VERSION_OVERRIDE)
: (equal(flavor, "windowsservercore")
? ["ltsc2019", "ltsc2022"]
: ["1809", "ltsc2019", "ltsc2022"]))
: ["1809", "ltsc2019", "ltsc2022", "ltsc2025"]))
}

# Return the Windows version to use as base image for the Windows version passed as parameter
# There is no mcr.microsoft.com/powershell ltsc2019 base image, using a "1809" instead
# There is no mcr.microsoft.com/powershell ltsc2025 base image, using a ltsc2022 instead
function "toolsversion" {
params = [version]
result = (equal("ltsc2019", version)
? "1809"
: version)
: (equal("ltsc2025", version)
? "ltsc2022"
: version))
}

target "alpine" {
Expand Down
4 changes: 4 additions & 0 deletions tests/sshAgent.Tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ $global:TOOLSWINDOWSVERSION = $items[1]
if ($items[1] -eq 'ltsc2019') {
$global:TOOLSWINDOWSVERSION = '1809'
}
# There is no mcr.microsoft.com/powershell:*-ltsc2025 docker images unfortunately, using a ltsc2022 instead
if ($items[1] -eq 'ltsc2025') {
$global:TOOLSWINDOWSVERSION = 'ltsc2022'
}

# TODO: make this name unique for concurency
$global:CONTAINERNAME = 'pester-jenkins-ssh-agent-{0}' -f $global:IMAGE_TAG
Expand Down
27 changes: 23 additions & 4 deletions windows/nanoserver/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,26 @@ RUN New-Item -ItemType Directory -Path C:\temp | Out-Null ; `
$proc.WaitForExit() ; `
Remove-Item -Path C:\temp -Recurse | Out-Null

# FROM mcr.microsoft.com/windows/nanoserver:"${WINDOWS_VERSION_TAG}"

# SHELL ["cmd.exe", "/c"]

# ARG JAVA_HOME

# # Download and install PowerShell 7
# ARG POWERSHELL_VERSION=7.5.4
# ENV POWERSHELL_VERSION=${POWERSHELL_VERSION}
# ENV PATH="C:\Windows\system32;C:\Windows;C:\Program Files\Powershell;"
# RUN curl.exe --silent --location "https://github.com/PowerShell/PowerShell/releases/download/v%POWERSHELL_VERSION%/PowerShell-%POWERSHELL_VERSION%-win-x64.zip" --output C:/windows/TEMP/pwsh.zip `
# && mkdir "C:\Program Files\Powershell" `
# && tar.exe -xf C:\windows\TEMP\pwsh.zip -C "C:\Program Files\Powershell" `
# && if exist "C:\windows\TEMP\pwsh.zip" del "C:\windows\TEMP\pwsh.zip"

# SHELL ["pwsh.exe", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"]
# USER ContainerAdministrator

# ENV PSHOME="C:\Program Files\PowerShell"

FROM mcr.microsoft.com/powershell:nanoserver-"${TOOLS_WINDOWS_VERSION}" AS pwsh-source

FROM mcr.microsoft.com/windows/nanoserver:"${WINDOWS_VERSION_TAG}"
Expand All @@ -47,13 +67,12 @@ ENV PSHOME="C:\Program Files\PowerShell"
ENV PATH="C:\Windows\system32;C:\Windows;${PSHOME};"

# The nanoserver image is nice and small, but we need a couple of things to get SSH working
COPY --from=jdk-core /windows/system32/netapi32.dll /windows/system32/netapi32.dll
COPY --from=jdk-core /windows/system32/whoami.exe /windows/system32/whoami.exe
COPY --from=jdk-core $JAVA_HOME $JAVA_HOME
COPY --from=pwsh-source $PSHOME $PSHOME

SHELL ["pwsh.exe", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"]
USER ContainerAdministrator
# While nanoserver-ltsc2025 includes netapi32.dll, older versions don't
COPY --from=jdk-core /windows/system32/netapi32.dll $PSHOME/netapi32.dll
RUN If (!(Test-Path 'C:/windows/system32/netapi32.dll') -And (Test-Path "$env:PSHOME/netapi32.dll")) { Move-Item "$env:PSHOME/netapi32.dll" 'C:/windows/system32/netapi32.dll' } Else { Write-Host "No $env:PSHOME/netapi32.dll or windows/system32/netapi32.dll alreay exists" }

# Backward compatibility with version <= 5.x: create a symlink to the "new" JAVA_HOME
RUN $javaMajorVersion = $env:JAVA_HOME.Substring($env:JAVA_HOME.Length - 2); `
Expand Down