diff --git a/Jenkinsfile b/Jenkinsfile index be119b85..58801b65 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -3,115 +3,82 @@ pipeline { options { buildDiscarder(logRotator(daysToKeepStr: '10')) - timestamps() } stages { - stage('Build') { - parallel { - stage('Windows') { - options { - timeout(time: 60, unit: 'MINUTES') + stage('docker-inbound-agent') { + failFast true + matrix { + axes { + axis { + name 'AGENT_TYPE' + values 'linux', 'windows-2019' } - environment { - DOCKERHUB_ORGANISATION = "${infra.isTrusted() ? 'jenkins' : 'jenkins4eval'}" - } - stages { - stage('Build and Test') { - // This stage is the "CI" and should be run on all code changes triggered by a code change - when { - not { buildingTag() } + } + stages { + stage('Main') { + agent { + label env.AGENT_TYPE + } + options { + timeout(time: 30, unit: 'MINUTES') + } + environment { + DOCKERHUB_ORGANISATION = "${infra.isTrusted() ? 'jenkins' : 'jenkins4eval'}" + } + stages { + stage('Prepare Docker') { + when { + environment name: 'AGENT_TYPE', value: 'linux' + } + steps { + sh ''' + docker buildx create --use + docker run --rm --privileged multiarch/qemu-user-static --reset -p yes + ''' + } } - steps { - script { - def parallelBuilds = [:] - def images = ['jdk11-windowsservercore-ltsc2019', 'jdk11-nanoserver-1809', 'jdk17-windowsservercore-ltsc2019', 'jdk17-nanoserver-1809'] - for (unboundImage in images) { - def image = unboundImage // Bind variable before the closure - // Prepare a map of the steps to run in parallel - parallelBuilds[image] = { - // Allocate a node for each image to avoid filling disk - node('docker-windows') { - checkout scm - powershell '& ./make.ps1 -Build ' + image + ' test' - junit(allowEmptyResults: true, keepLongStdio: true, testResults: 'target/**/junit-results.xml') - } + stage('Build and Test') { + // This stage is the "CI" and should be run on all code changes triggered by a code change + when { + not { buildingTag() } + } + steps { + script { + if(isUnix()) { + sh 'make build' + sh 'make test' + // If the tests are passing for Linux AMD64, then we can build all the CPU architectures + sh 'docker buildx bake --file docker-bake.hcl linux' + } else { + powershell "& ./build.ps1 test" } } - // Peform the parallel execution - parallel parallelBuilds } - } - } - stage('Deploy to DockerHub') { - agent { - label 'docker-windows' - } - // This stage is the "CD" and should only be run when a tag triggered the build - when { - buildingTag() - } - steps { - script { - // This function is defined in the jenkins-infra/pipeline-library - infra.withDockerCredentials { - powershell '& ./make.ps1 -PushVersions -VersionTag $env:TAG_NAME publish' + post { + always { + junit(allowEmptyResults: true, keepLongStdio: true, testResults: 'target/**/junit-results.xml') } } } - } - } - } - stage('Linux') { - agent { - label "docker&&linux" - } - options { - timeout(time: 30, unit: 'MINUTES') - } - environment { - JENKINS_REPO = "${infra.isTrusted() ? 'jenkins' : 'jenkins4eval'}/inbound-agent" - } - stages { - stage('Prepare Docker') { - steps { - sh ''' - docker buildx create --use - docker run --rm --privileged multiarch/qemu-user-static --reset -p yes - ''' - } - } - stage('Build and Test') { - // This stage is the "CI" and should be run on all code changes triggered by a code change - when { - not { buildingTag() } - } - steps { - sh 'make build' - sh 'make test' - // If the tests are passing for Linux AMD64, then we can build all the CPU architectures - sh 'docker buildx bake --file docker-bake.hcl linux' - } - post { - always { - junit(allowEmptyResults: true, keepLongStdio: true, testResults: 'target/*.xml') + stage('Deploy to DockerHub') { + // This stage is the "CD" and should only be run when a tag triggered the build + when { + buildingTag() } - } - } - stage('Deploy to DockerHub') { - // This stage is the "CD" and should only be run when a tag triggered the build - when { - buildingTag() - } - steps { - script { - // This function is defined in the jenkins-infra/pipeline-library - infra.withDockerCredentials { - sh ''' - export IMAGE_TAG="${TAG_NAME}" - export ON_TAG=true - docker buildx bake --push --file docker-bake.hcl linux - ''' + steps { + script { + infra.withDockerCredentials { + if (isUnix()) { + sh ''' + export IMAGE_TAG="${TAG_NAME}" + export ON_TAG=true + docker buildx bake --push --file docker-bake.hcl linux + ''' + } else { + powershell "& ./build.ps1 -PushVersions -VersionTag $env:TAG_NAME publish" + } + } } } } diff --git a/build-windows.yaml b/build-windows.yaml new file mode 100644 index 00000000..85bf0a9c --- /dev/null +++ b/build-windows.yaml @@ -0,0 +1,33 @@ +services: + jdk11-nanoserver: + image: jdk11-nanoserver-${NANOSERVER_VERSION_NAME} + build: + context: ./ + dockerfile: ./windows/nanoserver/Dockerfile + args: + version: ${PARENT_IMAGE_VERSION} + WINDOWS_VERSION_TAG: ${NANOSERVER_VERSION_TAG} + jdk17-nanoserver: + image: jdk17-nanoserver-${NANOSERVER_VERSION_NAME} + build: + context: ./ + dockerfile: ./windows/nanoserver/Dockerfile + args: + version: ${PARENT_IMAGE_VERSION} + WINDOWS_VERSION_TAG: ${NANOSERVER_VERSION_TAG} + jdk11-windowsservercore: + image: jdk11-windowsservercore-${WINDOWS_VERSION_NAME} + build: + context: ./ + dockerfile: ./windows/windowsservercore/Dockerfile + args: + version: ${PARENT_IMAGE_VERSION} + WINDOWS_VERSION_TAG: ${WINDOWS_VERSION_TAG} + jdk17-windowsservercore: + image: jdk17-windowsservercore-${WINDOWS_VERSION_NAME} + build: + context: ./ + dockerfile: ./windows/windowsservercore/Dockerfile + args: + version: ${PARENT_IMAGE_VERSION} + WINDOWS_VERSION_TAG: ${WINDOWS_VERSION_TAG} diff --git a/build.ps1 b/build.ps1 new file mode 100644 index 00000000..75014b9c --- /dev/null +++ b/build.ps1 @@ -0,0 +1,262 @@ +[CmdletBinding()] +Param( + [Parameter(Position=1)] + [String] $Target = "build", + [String] $Build = '', + [String] $ParentImageVersion = '3131.vf2b_b_798b_ce99-4', + [String] $BuildNumber = '1', + [switch] $PushVersions = $false +) + +$ErrorActionPreference ='Stop' +$Repository = 'inbound-agent' +$Organization = 'jenkins' +$AgentType = 'windows-2019' + +if(![String]::IsNullOrWhiteSpace($env:DOCKERHUB_REPO)) { + $Repository = $env:DOCKERHUB_REPO +} + +if(![String]::IsNullOrWhiteSpace($env:DOCKERHUB_ORGANISATION)) { + $Organization = $env:DOCKERHUB_ORGANISATION +} + +if(![String]::IsNullOrWhiteSpace($env:PARENT_IMAGE_VERSION)) { + $ParentImageVersion = $env:PARENT_IMAGE_VERSION +} + +if(![String]::IsNullOrWhiteSpace($env:AGENT_TYPE)) { + $AgentType = $env:AGENT_TYPE +} + +# Check for required commands +Function Test-CommandExists { + # From https://devblogs.microsoft.com/scripting/use-a-powershell-function-to-see-if-a-command-exists/ + Param ( + [String] $command + ) + + $oldPreference = $ErrorActionPreference + $ErrorActionPreference = 'stop' + try { + if(Get-Command $command){ + Write-Debug "$command exists" + } + } + Catch { + "$command does not exist" + } + Finally { + $ErrorActionPreference=$oldPreference + } +} + +# # this is the jdk version that will be used for the 'bare tag' images, e.g., jdk8-windowsservercore-1809 -> windowsserver-1809 +$defaultJdk = '11' +$builds = @{} +$env:PARENT_IMAGE_VERSION = "$ParentImageVersion" +$env:WINDOWS_VERSION_NAME = $AgentType.replace('windows-', 'ltsc') +$env:NANOSERVER_VERSION_NAME = $env:WINDOWS_VERSION_NAME +$env:WINDOWS_VERSION_TAG = $env:WINDOWS_VERSION_NAME +$env:NANOSERVER_VERSION_TAG = $env:WINDOWS_VERSION_NAME +# We need to keep the `jdkN-nanoserver-1809` images for now, cf https://github.com/jenkinsci/docker-agent/issues/451 +if ($AgentType -eq 'windows-2019') { + $env:NANOSERVER_VERSION_TAG = 1809 + $env:NANOSERVER_VERSION_NAME = 1809 +} +$ProgressPreference = 'SilentlyContinue' # Disable Progress bar for faster downloads + +Test-CommandExists "docker" +Test-CommandExists "docker-compose" +Test-CommandExists "yq" + +$baseDockerCmd = 'docker-compose --file=build-windows.yaml' +$baseDockerBuildCmd = '{0} build --parallel --pull' -f $baseDockerCmd + +Invoke-Expression "$baseDockerCmd config --services" 2>$null | ForEach-Object { + $image = '{0}-{1}' -f $_, $env:WINDOWS_VERSION_NAME + # Special case for nanoserver-1809 images + $image = $image.replace('nanoserver-ltsc2019', 'nanoserver-1809') + $items = $image.Split("-") + # Remove the 'jdk' prefix (3 first characters) + $jdkMajorVersion = $items[0].Remove(0,3) + $windowsType = $items[1] + $windowsVersion = $items[2] + + $baseImage = "${windowsType}-${windowsVersion}" + $versionTag = "${ParentImageVersion}-${BuildNumber}-${image}" + $tags = @( $image, $versionTag ) + if($jdkMajorVersion -eq "$defaultJdk") { + $tags += $baseImage + } + + $builds[$image] = @{ + 'Tags' = $tags; + } +} + +Write-Host '= PREPARE: List of images and tags to be processed:' +ConvertTo-Json $builds + +if(![System.String]::IsNullOrWhiteSpace($Build) -and $builds.ContainsKey($Build)) { + Write-Host "= BUILD: Building image ${Build}..." + $dockerBuildCmd = '{0} {1}' -f $baseDockerBuildCmd, $Build + Invoke-Expression $dockerBuildCmd + Write-Host "= BUILD: Finished building image ${Build}" +} else { + Write-Host "= BUILD: Building all images..." + Invoke-Expression $baseDockerBuildCmd + Write-Host "= BUILD: Finished building all image" +} + +if($lastExitCode -ne 0) { + exit $lastExitCode +} + +function Test-Image { + param ( + $ImageName + ) + + Write-Host "= TEST: Testing image ${ImageName}:" + + $env:AGENT_IMAGE = $ImageName + $serviceName = $ImageName.SubString(0, $ImageName.LastIndexOf('-')) + $env:BUILD_CONTEXT = Invoke-Expression "$baseDockerCmd config" 2>$null | yq -r ".services.${serviceName}.build.context" + $env:version = $ParentImageVersion + + Write-Host "= TEST: image folder ${env:BUILD_CONTEXT}, version ${env:version}" + + if(Test-Path ".\target\$ImageName") { + Remove-Item -Recurse -Force ".\target\$ImageName" + } + New-Item -Path ".\target\$ImageName" -Type Directory | Out-Null + $configuration.TestResult.OutputPath = ".\target\$ImageName\junit-results.xml" + $TestResults = Invoke-Pester -Configuration $configuration + if ($TestResults.FailedCount -gt 0) { + Write-Host "There were $($TestResults.FailedCount) failed tests in $ImageName" + $testFailed = $true + } else { + Write-Host "There were $($TestResults.PassedCount) passed tests out of $($TestResults.TotalCount) in $ImageName" + } + Remove-Item env:\AGENT_IMAGE + Remove-Item env:\BUILD_CONTEXT + Remove-Item env:\VERSION +} + +if($target -eq "test") { + Write-Host "= TEST: Starting test harness" + + # Only fail the run afterwards in case of any test failures + $testFailed = $false + $mod = Get-InstalledModule -Name Pester -MinimumVersion 5.3.0 -MaximumVersion 5.3.3 -ErrorAction SilentlyContinue + if($null -eq $mod) { + Write-Host "= TEST: Pester 5.3.x not found: installing..." + $module = "c:\Program Files\WindowsPowerShell\Modules\Pester" + if(Test-Path $module) { + takeown /F $module /A /R + icacls $module /reset + icacls $module /grant Administrators:'F' /inheritance:d /T + Remove-Item -Path $module -Recurse -Force -Confirm:$false + } + Install-Module -Force -Name Pester -MaximumVersion 5.3.3 + } + + Import-Module Pester + Write-Host "= TEST: Setting up Pester environment..." + $configuration = [PesterConfiguration]::Default + $configuration.Run.PassThru = $true + $configuration.Run.Path = '.\tests' + $configuration.Run.Exit = $true + $configuration.TestResult.Enabled = $true + $configuration.TestResult.OutputFormat = 'JUnitXml' + $configuration.Output.Verbosity = 'Diagnostic' + $configuration.CodeCoverage.Enabled = $false + + if(![System.String]::IsNullOrWhiteSpace($Build) -and $builds.ContainsKey($Build)) { + Test-Image $Build + } else { + Write-Host "= TEST: Testing all images" + foreach($image in $builds.Keys) { + Test-Image $image + } + } + + # Fail if any test failures + if($testFailed -ne $false) { + Write-Error "Test stage failed!" + exit 1 + } else { + Write-Host "Test stage passed!" + } +} + +function Publish-Image { + param ( + [String] $Build, + [String] $ImageName + ) + Write-Host "= PUBLISH: Tagging $Build => full name = $ImageName" + docker tag "$Build" "$ImageName" + + Write-Host "= PUBLISH: Publishing $ImageName..." + docker push "$ImageName" +} + + +if($target -eq "publish") { + # Only fail the run afterwards in case of any issues when publishing the docker images + $publishFailed = 0 + if(![System.String]::IsNullOrWhiteSpace($Build) -and $builds.ContainsKey($Build)) { + foreach($tag in $Builds[$Build]['Tags']) { + Publish-Image "$Build" "${Organization}/${Repository}:${tag}" + if($lastExitCode -ne 0) { + $publishFailed = 1 + } + + if($PushVersions) { + $buildTag = "$ParentImageVersion-$BuildNumber-$tag" + if($tag -eq 'latest') { + $buildTag = "$ParentImageVersion-$BuildNumber" + } + Publish-Image "$Build" "${Organization}/${Repository}:${buildTag}" + if($lastExitCode -ne 0) { + $publishFailed = 1 + } + } + } + } else { + foreach($b in $builds.Keys) { + foreach($tag in $Builds[$b]['Tags']) { + Publish-Image "$b" "${Organization}/${Repository}:${tag}" + if($lastExitCode -ne 0) { + $publishFailed = 1 + } + + if($PushVersions) { + $buildTag = "$ParentImageVersion-$BuildNumber-$tag" + if($tag -eq 'latest') { + $buildTag = "$ParentImageVersion-$BuildNumber" + } + Publish-Image "$b" "${Organization}/${Repository}:${buildTag}" + if($lastExitCode -ne 0) { + $publishFailed = 1 + } + } + } + } + } + + # Fail if any issues when publising the docker images + if($publishFailed -ne 0) { + Write-Error "Publish failed!" + exit 1 + } +} + +if($lastExitCode -ne 0) { + Write-Error "Build failed!" +} else { + Write-Host "Build finished successfully" +} +exit $lastExitCode diff --git a/docker-bake.hcl b/docker-bake.hcl index 362d1d6a..76601963 100644 --- a/docker-bake.hcl +++ b/docker-bake.hcl @@ -30,7 +30,7 @@ variable "IMAGE_TAG" { default = "3071.v7e9b_0dc08466-1" } -#### This is for the "parent" image version to use (jenkins/agent:-) +#### This is for the "parent" image version to use (jenkins/agent:-) variable "PARENT_IMAGE_VERSION" { default = "3131.vf2b_b_798b_ce99-4" } diff --git a/make.ps1 b/make.ps1 deleted file mode 100644 index 0253807b..00000000 --- a/make.ps1 +++ /dev/null @@ -1,237 +0,0 @@ -[CmdletBinding()] -Param( - [Parameter(Position=1)] - [String] $Target = "build", - [String] $Build = '', - [String] $VersionTag = '3071.v7e9b_0dc08466-1', - [String] $DockerAgentVersion = '3131.vf2b_b_798b_ce99-4', - [switch] $PushVersions = $false -) - -$Repository = 'inbound-agent' -$Organization = 'jenkins' - -if(![String]::IsNullOrWhiteSpace($env:DOCKERHUB_REPO)) { - $Repository = $env:DOCKERHUB_REPO -} - -if(![String]::IsNullOrWhiteSpace($env:DOCKERHUB_ORGANISATION)) { - $Organization = $env:DOCKERHUB_ORGANISATION -} - -# this is the jdk version that will be used for the 'bare tag' images, e.g., jdk8-windowsservercore-1809 -> windowsserver-1809 -$defaultBuild = '11' -$builds = @{} - -# TODO: use docker-compose / tooling like with docker-agent -$images = 'jdk11-nanoserver-1809', 'jdk11-windowsservercore-ltsc2019', 'jdk17-nanoserver-1809', 'jdk17-windowsservercore-ltsc2019' -Foreach($image in $images) { - $items = $image.Split('-') - # Remove the 'jdk' prefix (3 first characters) - $jdkMajorVersion = $items[0].Remove(0,3) - $windowsFlavor = $items[1] - $windowsVersion = $items[2] - $baseImage = "${windowsFlavor}-${windowsVersion}" - $dir = "windows/${baseImage}" - - Write-Host "New windows image to build: jenkins/jenkins:${baseImage} with JDK ${jdkMajorVersion} in ${dir}" - - $tags = @( $image ) - if($jdkMajorVersion -eq $defaultBuild) { - $tags += $baseImage - } - - $builds[$image] = @{ - 'Folder' = $dir; - 'Tags' = $tags; - 'JdkMajorVersion' = $jdkMajorVersion; - } -} - -function Build-Image { - param ( - [String] $Build, - [String] $ImageName, - [String] $RemotingVersion, - [String] $JdkMajorVersion, - [String] $Folder - ) - - Write-Host "Building $Build with name $imageName" - docker build --build-arg "version=${RemotingVersion}" --build-arg "JAVA_MAJOR_VERSION=${JdkMajorVersion}" --tag="${ImageName}" --file="${Folder}/Dockerfile" ./ -} - -$exitCodes = 0 -if(![System.String]::IsNullOrWhiteSpace($Build) -and $builds.ContainsKey($Build)) { - foreach($tag in $builds[$Build]['Tags']) { - Build-Image -Build $Build -ImageName "${Organization}/${Repository}:${tag}" -RemotingVersion $DockerAgentVersion -JdkMajorVersion $builds[$Build]['JdkMajorVersion'] -Folder $builds[$Build]['Folder'] - $exitCodes += $lastExitCode - - if($PushVersions) { - $buildTag = "$VersionTag-$tag" - if($tag -eq 'latest') { - $buildTag = "$VersionTag" - } - Build-Image -Build $Build -ImageName "${Organization}/${Repository}:${buildTag}" -RemotingVersion $DockerAgentVersion -JdkMajorVersion $builds[$Build]['JdkMajorVersion'] -Folder $builds[$Build]['Folder'] - $exitCodes += $lastExitCode - } - } -} else { - foreach($b in $builds.Keys) { - foreach($tag in $builds[$b]['Tags']) { - Build-Image -Build $Build -ImageName "${Organization}/${Repository}:${tag}" -RemotingVersion $DockerAgentVersion -JdkMajorVersion $builds[$b]['JdkMajorVersion'] -Folder $builds[$b]['Folder'] - $exitCodes += $lastExitCode - - if($PushVersions) { - $buildTag = "$VersionTag-$tag" - if($tag -eq 'latest') { - $buildTag = "$VersionTag" - } - Build-Image -Build $Build -ImageName "${Organization}/${Repository}:${buildTag}" -RemotingVersion $DockerAgentVersion -JdkMajorVersion $builds[$b]['JdkMajorVersion'] -Folder $builds[$b]['Folder'] - $exitCodes += $lastExitCode - } - } - } -} - -if($exitCodes -ne 0) { - Write-Host "Image build stage failed!" - exit 1 -} else { - Write-Host "Image build stage passed!" -} - -if($Target -eq "test") { - # Only fail the run afterwards in case of any test failures - $testFailed = $false - - $mod = Get-InstalledModule -Name Pester -MinimumVersion 5.3.0 -MaximumVersion 5.3.3 -ErrorAction SilentlyContinue - if($null -eq $mod) { - $module = "c:\Program Files\WindowsPowerShell\Modules\Pester" - if(Test-Path $module) { - takeown /F $module /A /R - icacls $module /reset - icacls $module /grant Administrators:'F' /inheritance:d /T - Remove-Item -Path $module -Recurse -Force -Confirm:$false - } - Install-Module -Force -Name Pester -MaximumVersion 5.3.3 - } - - Import-Module Pester - $configuration = [PesterConfiguration]::Default - $configuration.Run.PassThru = $true - $configuration.Run.Path = '.\tests' - $configuration.Run.Exit = $true - $configuration.TestResult.Enabled = $true - $configuration.TestResult.OutputFormat = 'JUnitXml' - $configuration.Output.Verbosity = 'Diagnostic' - $configuration.CodeCoverage.Enabled = $false - - if(![System.String]::IsNullOrWhiteSpace($Build) -and $builds.ContainsKey($Build)) { - $folder = $builds[$Build]['Folder'] - $env:AGENT_IMAGE = $Build - $env:FOLDER = $folder - $env:JAVA_MAJOR_VERSION = $builds[$Build]['JdkMajorVersion'] - $env:VERSION = $DockerAgentVersion - - if(Test-Path ".\target\$folder") { - Remove-Item -Recurse -Force ".\target\$folder" - } - New-Item -Path ".\target\$folder" -Type Directory | Out-Null - $configuration.TestResult.OutputPath = ".\target\$folder\junit-results.xml" - $TestResults = Invoke-Pester -Configuration $configuration - if ($TestResults.FailedCount -gt 0) { - Write-Host "There were $($TestResults.FailedCount) failed tests in $Build" - $testFailed = $true - } else { - Write-Host "There were $($TestResults.PassedCount) passed tests out of $($TestResults.TotalCount) in $Build" - } - Remove-Item env:\AGENT_IMAGE - Remove-Item env:\FOLDER - Remove-Item env:\JAVA_MAJOR_VERSION - Remove-Item env:\VERSION - } else { - foreach($b in $builds.Keys) { - $folder = $builds[$b]['Folder'] - $env:AGENT_IMAGE = $b - $env:FOLDER = $folder - $env:JAVA_MAJOR_VERSION = $builds[$Build]['JdkMajorVersion'] - $env:VERSION = $DockerAgentVersion - if(Test-Path ".\target\$folder") { - Remove-Item -Recurse -Force ".\target\$folder" - } - New-Item -Path ".\target\$folder" -Type Directory | Out-Null - $configuration.TestResult.OutputPath = ".\target\$folder\junit-results.xml" - $TestResults = Invoke-Pester -Configuration $configuration - if ($TestResults.FailedCount -gt 0) { - Write-Host "There were $($TestResults.FailedCount) failed tests in $Build" - $testFailed = $true - } else { - Write-Host "There were $($TestResults.PassedCount) passed tests out of $($TestResults.TotalCount) in $Build" - } - Remove-Item env:\AGENT_IMAGE - Remove-Item env:\FOLDER - Remove-Item env:\JAVA_MAJOR_VERSION - Remove-Item env:\VERSION - } - } - - # Fail if any test failures - if($testFailed -ne $false) { - Write-Error "Test stage failed!" - exit 1 - } else { - Write-Host "Test stage passed!" - } -} - -$exitCodes = 0 -if($Target -eq "publish") { - if(![System.String]::IsNullOrWhiteSpace($Build) -and $builds.ContainsKey($Build)) { - foreach($tag in $Builds[$Build]['Tags']) { - Write-Host "Publishing $Build => tag=$tag" - $cmd = "docker push {0}/{1}:{2}" -f $Organization, $Repository, $tag - Invoke-Expression $cmd - $exitCodes += $lastExitCode - - if($PushVersions) { - $buildTag = "$VersionTag-$tag" - if($tag -eq 'latest') { - $buildTag = "$VersionTag" - } - Write-Host "Publishing $Build => tag=$buildTag" - $cmd = "docker push {0}/{1}:{2}" -f $Organization, $Repository, $buildTag - Invoke-Expression $cmd - $exitCodes += $lastExitCode - } - } - } else { - foreach($b in $builds.Keys) { - foreach($tag in $Builds[$b]['Tags']) { - Write-Host "Publishing $b => tag=$tag" - $cmd = "docker push {0}/{1}:{2}" -f $Organization, $Repository, $tag - Invoke-Expression $cmd - $exitCodes += $lastExitCode - - if($PushVersions) { - $buildTag = "$VersionTag-$tag" - if($tag -eq 'latest') { - $buildTag = "$VersionTag" - } - Write-Host "Publishing $Build => tag=$buildTag" - $cmd = "docker push {0}/{1}:{2}" -f $Organization, $Repository, $buildTag - Invoke-Expression $cmd - $exitCodes += $lastExitCode - } - } - } - } - - if($exitCodes -ne 0) { - Write-Error "Publish stage failed!" - } else { - Write-Host "Publish stage passed!" - } -} - -exit $exitCodes diff --git a/tests/inboundAgent.Tests.ps1 b/tests/inboundAgent.Tests.ps1 index 4ac1989b..7a47b59a 100644 --- a/tests/inboundAgent.Tests.ps1 +++ b/tests/inboundAgent.Tests.ps1 @@ -1,25 +1,27 @@ Import-Module -DisableNameChecking -Force $PSScriptRoot/test_helpers.psm1 $global:AGENT_IMAGE = Get-EnvOrDefault 'AGENT_IMAGE' '' -$global:FOLDER = Get-EnvOrDefault 'FOLDER' '' -$global:JAVA_MAJOR_VERSION = Get-EnvOrDefault 'JAVA_MAJOR_VERSION' '' -$global:VERSION = Get-EnvOrDefault 'VERSION' '' +$global:BUILD_CONTEXT = Get-EnvOrDefault 'BUILD_CONTEXT' '' +$global:version = Get-EnvOrDefault 'VERSION' '' +$global:WINDOWS_VERSION_TAG = Get-EnvOrDefault 'WINDOWS_VERSION_TAG' '' # TODO: make this name unique for concurency $global:CONTAINERNAME = 'pester-jenkins-inbound-agent-{0}' -f $global:AGENT_IMAGE -$REAL_FOLDER=Resolve-Path -Path "$PSScriptRoot/../${global:FOLDER}" - $items = $global:AGENT_IMAGE.Split("-") # Remove the 'jdk' prefix (3 first characters) -$global:JDKMAJORVERSION = $items[0].Remove(0,3) +$global:JAVA_MAJOR_VERSION = $items[0].Remove(0,3) $global:WINDOWSFLAVOR = $items[1] $global:WINDOWSVERSION = $items[2] $global:CONTAINERSHELL="powershell.exe" if($global:WINDOWSFLAVOR -eq 'nanoserver') { $global:CONTAINERSHELL = "pwsh.exe" + # Special case for nanoserver-1809 + if($global:WINDOWSVERSION -eq '1809') { + $global:WINDOWS_VERSION_TAG = '1809' + } } @@ -27,11 +29,11 @@ Cleanup($global:CONTAINERNAME) Cleanup("nmap") CleanupNetwork("jnlp-network") -BuildNcatImage +BuildNcatImage($global:WINDOWS_VERSION_TAG) Describe "[$global:AGENT_IMAGE] build image" { It 'builds image' { - $exitCode, $stdout, $stderr = Run-Program 'docker' "build --build-arg version=${global:VERSION} --build-arg JAVA_MAJOR_VERSION=${global:JAVA_MAJOR_VERSION} --tag=${global:AGENT_IMAGE} --file $global:FOLDER/Dockerfile ./" + $exitCode, $stdout, $stderr = Run-Program 'docker' "build --build-arg version=${global:version} --build-arg `"WINDOWS_VERSION_TAG=${global:WINDOWS_VERSION_TAG}`" --build-arg JAVA_MAJOR_VERSION=${global:JAVA_MAJOR_VERSION} --tag=${global:AGENT_IMAGE} --file ./windows/${global:WINDOWSFLAVOR}/Dockerfile ${global:BUILD_CONTEXT}" $exitCode | Should -Be 0 } } @@ -114,15 +116,15 @@ Describe "[$global:AGENT_IMAGE] custom build args" { BeforeAll { Push-Location -StackName 'agent' -Path "$PSScriptRoot/.." # Old version used to test overriding the build arguments. - # This old version must have the same tag suffixes as the current 4 windows images (`-jdk11-nanoserver` etc.) - $TEST_VERSION = "3046.v38db_38a_b_7a_86" - $DOCKER_AGENT_VERSION_SUFFIX = "1" - $ARG_TEST_VERSION = "${TEST_VERSION}-${DOCKER_AGENT_VERSION_SUFFIX}" + # This old version must have the same tag suffixes as the current windows images (`-jdk11-nanoserver` etc.), and the same Windows version (2019, 2022, etc.) + $TEST_VERSION = "3131.vf2b_b_798b_ce99" + $PARENT_IMAGE_VERSION_SUFFIX = "4" + $ARG_TEST_VERSION = "${TEST_VERSION}-${PARENT_IMAGE_VERSION_SUFFIX}" $customImageName = "custom-${global:AGENT_IMAGE}" } It 'builds image with arguments' { - $exitCode, $stdout, $stderr = Run-Program 'docker' "build --build-arg version=${ARG_TEST_VERSION} --build-arg JAVA_MAJOR_VERSION=${global:JAVA_MAJOR_VERSION} --tag=${customImageName} --file=${global:FOLDER}/Dockerfile ./" + $exitCode, $stdout, $stderr = Run-Program 'docker' "build --build-arg version=${ARG_TEST_VERSION} --build-arg `"WINDOWS_VERSION_TAG=${global:WINDOWS_VERSION_TAG}`" --build-arg JAVA_MAJOR_VERSION=${global:JAVA_MAJOR_VERSION} --tag=${customImageName} --file=./windows/${global:WINDOWSFLAVOR}/Dockerfile ${global:BUILD_CONTEXT}" $exitCode | Should -Be 0 $exitCode, $stdout, $stderr = Run-Program 'docker' "run --detach --tty --name $global:CONTAINERNAME $customImageName -Cmd $global:CONTAINERSHELL" @@ -165,7 +167,7 @@ Describe "[$global:AGENT_IMAGE] passing JVM options (slow test)" { Is-ContainerRunning $global:CONTAINERNAME | Should -BeTrue $exitCode, $stdout, $stderr = Run-Program 'docker' "logs $global:CONTAINERNAME" $exitCode | Should -Be 0 - $stdout | Should -Match "OpenJDK Runtime Environment Temurin-${global:JDKMAJORVERSION}" + $stdout | Should -Match "OpenJDK Runtime Environment Temurin-${global:JAVA_MAJOR_VERSION}" } AfterAll { diff --git a/tests/netcat-helper/Dockerfile-windows b/tests/netcat-helper/Dockerfile-windows index d42d5244..e8e18811 100644 --- a/tests/netcat-helper/Dockerfile-windows +++ b/tests/netcat-helper/Dockerfile-windows @@ -22,7 +22,8 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. -FROM mcr.microsoft.com/windows/servercore:1809 +ARG WINDOWS_VERSION_TAG=1809 +FROM mcr.microsoft.com/windows/servercore:"${WINDOWS_VERSION_TAG}" SHELL ["powershell.exe", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"] diff --git a/tests/test_helpers.psm1 b/tests/test_helpers.psm1 index 69395da0..5edb8067 100644 --- a/tests/test_helpers.psm1 +++ b/tests/test_helpers.psm1 @@ -114,19 +114,19 @@ function Run-Program($cmd, $params, $quiet=$false, $debug=$false) { $stderr = $proc.StandardError.ReadToEnd() $proc.WaitForExit() if(($proc.ExitCode -ne 0) -and (-not $quiet)) { - Write-Host "`n`nstdout:`n$stdout`n`nstderr:`n$stderr`n`n" + Write-Host "`n`nstdout:`n$stdout`n`nstderr:`n$stderr`n`n`cmd:`n$cmd`n`nparams:`n$params`n`n" } return $proc.ExitCode, $stdout, $stderr } -function BuildNcatImage() { - Write-Host "Building nmap image for testing" +function BuildNcatImage($windowsVersionTag) { + Write-Host "Building nmap image (Windows version '${windowsVersionTag}') for testing" $exitCode, $stdout, $stderr = Run-Program 'docker.exe' "inspect --type=image nmap" $true if($exitCode -ne 0) { Push-Location -StackName 'agent' -Path "$PSScriptRoot/.." - $exitCode, $stdout, $stderr = Run-Program 'docker.exe' "build -t nmap -f ./tests/netcat-helper/Dockerfile-windows ./tests/netcat-helper" + $exitCode, $stdout, $stderr = Run-Program 'docker.exe' "build -t nmap --build-arg `"WINDOWS_VERSION_TAG=${windowsVersionTag}`" -f ./tests/netcat-helper/Dockerfile-windows ./tests/netcat-helper" $exitCode | Should -Be 0 Pop-Location -StackName 'agent' } -} \ No newline at end of file +} diff --git a/tests/tests.bats b/tests/tests.bats index fd4633e9..72605188 100755 --- a/tests/tests.bats +++ b/tests/tests.bats @@ -45,14 +45,14 @@ SUT_IMAGE="$(get_sut_image)" @test "[${SUT_IMAGE}] use build args correctly" { cd "${BATS_TEST_DIRNAME}"/.. || false - local TEST_VERSION DOCKER_AGENT_VERSION_SUFFIX ARG_TEST_VERSION TEST_USER sut_image sut_cid + local TEST_VERSION PARENT_IMAGE_VERSION_SUFFIX ARG_TEST_VERSION TEST_USER sut_image sut_cid # Old version used to test overriding the build arguments. # This old version must have the same tag suffixes as the ones defined in the docker-bake file (`-jdk17`, `jdk11`, etc.) - TEST_VERSION="3046.v38db_38a_b_7a_86" - DOCKER_AGENT_VERSION_SUFFIX="1" + TEST_VERSION="3131.vf2b_b_798b_ce99" + PARENT_IMAGE_VERSION_SUFFIX="4" - ARG_TEST_VERSION="${TEST_VERSION}-${DOCKER_AGENT_VERSION_SUFFIX}" + ARG_TEST_VERSION="${TEST_VERSION}-${PARENT_IMAGE_VERSION_SUFFIX}" TEST_USER="root" sut_image="${SUT_IMAGE}-tests-${BATS_TEST_NUMBER}" diff --git a/updatecli/updatecli.d/jenkins-agent-parent.yaml b/updatecli/updatecli.d/docker-agent.yaml similarity index 72% rename from updatecli/updatecli.d/jenkins-agent-parent.yaml rename to updatecli/updatecli.d/docker-agent.yaml index 38ca58a5..ac2df7fd 100644 --- a/updatecli/updatecli.d/jenkins-agent-parent.yaml +++ b/updatecli/updatecli.d/docker-agent.yaml @@ -100,8 +100,8 @@ conditions: tag: '{{source "lastVersion" }}-jdk17-windowsservercore-ltsc2019' targets: - setJdk11AlpineDockerImage: - name: Bump the parent image `jenkins/agent` version on JDK11 Alpine + setAlpineDockerImage: + name: Bump the parent image `jenkins/agent` version on Alpine kind: dockerfile spec: file: alpine/Dockerfile @@ -109,8 +109,8 @@ targets: keyword: ARG matcher: version scmid: default - setJdk11DebianDockerImage: - name: Bump the parent image `jenkins/agent` version on JDK11 Debian + setDebianDockerImage: + name: Bump the parent image `jenkins/agent` version on Debian kind: dockerfile spec: file: debian/Dockerfile @@ -118,56 +118,20 @@ targets: keyword: ARG matcher: version scmid: default - setJdk11WindowsNanoserver1809DockerImage: - name: Bump the parent image `jenkins/agent` version on JDK11 Windows Nanoserver 1809 + setsNanoserverDockerImage: + name: Bump the parent image `jenkins/agent` version on Windows Nanoserver kind: dockerfile spec: - file: windows/nanoserver-1809/Dockerfile + file: windows/nanoserver/Dockerfile instruction: keyword: ARG matcher: version scmid: default - setJdk11WindowsServer2019DockerImage: - name: Bump the parent image `jenkins/agent` version on JDK11 Windows Server 2019 + setWindowsServerCoreDockerImage: + name: Bump the parent image `jenkins/agent` version on Windows Server Core kind: dockerfile spec: - file: windows/windowsservercore-ltsc2019/Dockerfile - instruction: - keyword: ARG - matcher: version - scmid: default - setJdk17AlpineDockerImage: - name: Bump the parent image `jenkins/agent` version on JDK17 Alpine - kind: dockerfile - spec: - file: alpine/Dockerfile - instruction: - keyword: ARG - matcher: version - scmid: default - setJdk17DebianDockerImage: - name: Bump the parent image `jenkins/agent` version on JDK17 Debian - kind: dockerfile - spec: - file: debian/Dockerfile - instruction: - keyword: ARG - matcher: version - scmid: default - setJdk17WindowsNanoserver1809DockerImage: - name: Bump the parent image `jenkins/agent` version on JDK17 Windows Nanoserver 1809 - kind: dockerfile - spec: - file: windows/nanoserver-1809/Dockerfile - instruction: - keyword: ARG - matcher: version - scmid: default - setJdk17WindowsServer2019DockerImage: - name: Bump the parent image `jenkins/agent` version on JDK17 Windows Server 2019 - kind: dockerfile - spec: - file: windows/windowsservercore-ltsc2019/Dockerfile + file: windows/windowsservercore/Dockerfile instruction: keyword: ARG matcher: version @@ -182,11 +146,11 @@ targets: replacepattern: >- variable${1}"PARENT_IMAGE_VERSION"${2}{${3}${4}${5}default${6}= "{{ source "lastVersion" }}" scmid: default - setWindowsMakePwshParentImage: - name: Bump the parent image `jenkins/agent` version on the windows make.ps1 file + setWindowsBuildPwshParentImage: + name: Bump the parent image `jenkins/agent` version on the Windows build.ps1 powershell script kind: file spec: - file: make.ps1 + file: build.ps1 matchpattern: >- \$DockerAgentVersion(.*)=(.*), replacepattern: >- diff --git a/windows/nanoserver-1809/Dockerfile b/windows/nanoserver/Dockerfile similarity index 96% rename from windows/nanoserver-1809/Dockerfile rename to windows/nanoserver/Dockerfile index ff455861..f71e02ba 100644 --- a/windows/nanoserver-1809/Dockerfile +++ b/windows/nanoserver/Dockerfile @@ -23,7 +23,8 @@ ARG version=3131.vf2b_b_798b_ce99-4 ARG JAVA_MAJOR_VERSION=17 -FROM jenkins/agent:"${version}"-jdk"${JAVA_MAJOR_VERSION}"-nanoserver-1809 +ARG WINDOWS_VERSION_TAG=1809 +FROM jenkins/agent:"${version}"-jdk"${JAVA_MAJOR_VERSION}"-nanoserver-"${WINDOWS_VERSION_TAG}" ARG version=3131.vf2b_b_798b_ce99-4 LABEL Description="This is a base image, which allows connecting Jenkins agents via JNLP protocols on Windows" Vendor="Jenkins Project" Version="$version" diff --git a/windows/windowsservercore-ltsc2019/Dockerfile b/windows/windowsservercore/Dockerfile similarity index 95% rename from windows/windowsservercore-ltsc2019/Dockerfile rename to windows/windowsservercore/Dockerfile index f97fd2c5..af38ac64 100644 --- a/windows/windowsservercore-ltsc2019/Dockerfile +++ b/windows/windowsservercore/Dockerfile @@ -23,7 +23,8 @@ ARG version=3131.vf2b_b_798b_ce99-4 ARG JAVA_MAJOR_VERSION=17 -FROM jenkins/agent:"${version}"-jdk"${JAVA_MAJOR_VERSION}"-windowsservercore-ltsc2019 +ARG WINDOWS_VERSION_TAG=ltsc2019 +FROM jenkins/agent:"${version}"-jdk"${JAVA_MAJOR_VERSION}"-windowsservercore-"${WINDOWS_VERSION_TAG}" ARG version=3131.vf2b_b_798b_ce99-4 LABEL Description="This is a base image, which allows connecting Jenkins agents via JNLP protocols on Windows" Vendor="Jenkins Project" Version="$version"