tasks/container.tasks.ps1
# ContainersToBuild must be an array of hashtables of the following structure: # @( # @{ # Dockerfile = "<path-to-dockerfile>" # ImageName = "<container-image-name-without-tag>" # ContextDir = "<path-to-docker-build-context-dir>" # Arguments = @{ Name = "Value" } # } # ) $ContainersToBuild = @() $UseAcrTasks = $false $SkipPublishContainerImages = $false # Allows any containers to be built with a custom version tag, rather than the default SemVer provided by GitVersion $ContainerImageVersionOverride = $null $ContainerRegistryPublishPrefix = $null $ContainerImageTagArtefactPath = Join-Path $PWD "image-tag" # Default settings for Docker Registry publishing $DockerRegistryFqdn = "docker.io" $DockerRegistryUsername = $null $DockerRegistryPassword = $null $DockerConfigPath = "~/.docker/config.json" # Synopsis: Build Container Images task BuildContainerImages -If {!$SkipContainerImages -and $ContainersToBuild} GenerateContainerBuildTag,{ foreach ($buildInfo in $ContainersToBuild) { $contextDir = $buildInfo.ContainsKey("ContextDir") ? $buildInfo.ContextDir : (Split-Path -Parent $buildInfo.Dockerfile) $buildTag = "{0}:{1}" -f $buildInfo.ImageName.ToLower(), $containerBuildTag $containerBuildArgs = $null if ($buildInfo.Arguments) { $containerBuildArgs = $buildInfo.Arguments.Keys | % { # Construct the command-line arguments required by 'docker build' and 'az acr build' "--build-arg $_=$($buildInfo.Arguments[$_])" } } # Setup common build parameters $buildParameters = @( "--file $($buildInfo.Dockerfile)" ) if ($containerBuildArgs) { $buildParameters += $containerBuildArgs -join " " } if ($UseAcrTasks) { if (!(Test-AzCliConnection)) { throw "You must be logged in to Azure CLI to build using ACR Tasks" } Write-Build White "Building & publishing image with ACR Tasks" $acrPublishTag = $ContainerRegistryPublishPrefix ? ` "$ContainerRegistryPublishPrefix/$buildTag" : ` $buildTag # Set command-line for building via ACR Tasks $buildParameters += @( "-t $acrPublishTag" "--registry $ContainerRegistryFqdn" ) $buildCmd = "az acr build" } else { # Set command-line for building with docker $buildParameters += "-t $buildTag" $buildCmd = "docker build" } # Add the final positional command-line argument $buildParameters += $contextDir # Form the command-line $buildCmdline = "$buildCmd $($buildParameters -join " ")" Write-Verbose "buildCmdline: $buildCmdline" exec { Invoke-Expression $buildCmdline } } } # Synopsis: Set the container image version task GenerateContainerBuildTag Version,{ if ($ContainerImageVersionOverride) { Write-Host "Overriding default container image version tag: $ContainerImageVersionOverride" $script:containerBuildTag = $ContainerImageVersionOverride } else { $script:containerBuildTag = ($script:GitVersion).SemVer } } # Synopsis: Publish Container Images to a Docker Registry task PublishContainerImagesToDocker -If { $ContainerRegistryType -eq "docker" } GenerateContainerBuildTag,{ if (!$DockerRegistryUsername) { throw "The variable 'DockerRegistryUsername' must be defined when publishing to a Docker Registry" } # Check to see if the user is already logged-in to the Docker Registry $dockerConfig = (Test-Path $DockerConfigPath) ? ` (Get-Content -Raw $DockerConfigPath | ConvertFrom-Json -AsHashtable -Depth 10) : ` @{auths=@{}} if ( !($dockerConfig.auths.Keys | Where-Object { $_ -match $DockerRegistryFqdn }) ) { if (!$DockerRegistryPassword) { throw "Unable to login to Docker Registry '$DockerRegistryFqdn', missing value for 'DockerRegistryPassword'" } exec { $DockerRegistryPassword | docker login $DockerRegistryFqdn --username $DockerRegistryUsername --password-stdin } } foreach ($buildInfo in $ContainersToBuild) { $buildTag = "{0}:{1}" -f $buildInfo.ImageName.ToLower(), $containerBuildTag $publishTag = $ContainerRegistryPublishPrefix ? ` "$DockerRegistryFqdn/$ContainerRegistryPublishPrefix/$buildTag" : ` "$DockerRegistryFqdn/$DockerRegistryUsername/$buildTag" Write-Host "Publishing Container: $publishTag" exec { docker tag $buildTag $publishTag docker push $publishTag } } } # Synopsis: Publish Container Images to GHCR task PublishContainerImagesToGhcr -If { $ContainerRegistryType -eq "ghcr" } GenerateContainerBuildTag,{ foreach ($buildInfo in $ContainersToBuild) { $buildTag = "{0}:{1}" -f $buildInfo.ImageName, $containerBuildTag $publishTag = $ContainerRegistryPublishPrefix ? ` "docker.pkg.github.com/$ContainerRegistryPublishPrefix/$buildTag" : ` "docker.pkg.github.com/$(gh repo view --json nameWithOwner | ConvertFrom-Json | Select-Object -ExpandProperty nameWithOwner)/$buildTag" Write-Host "Publishing Container: $publishTag" exec { docker tag $buildTag $publishTag docker push $publishTag } } } # Synopsis: Publish Container Images to Azure Container Registry task PublishContainerImagesToAcr -If { $ContainerRegistryType -eq "acr" -and !$UseAcrTasks} GenerateContainerBuildTag, { if (!$ContainerRegistryFqdn) { throw "Missing value for 'ContainerRegistryFqdn' - this is required when publishing to Azure Container Registry" } if (!(Test-AzCliConnection)) { throw "You must be logged in to Azure CLI to publish to ACR" } Write-Host "Logging-in to ACR" exec { az acr login -n $ContainerRegistryFqdn } foreach ($buildInfo in $ContainersToBuild) { $buildTag = "{0}:{1}" -f $buildInfo.ImageName, $containerBuildTag $publishTag = $ContainerRegistryPublishPrefix ? ` "$ContainerRegistryFqdn/$ContainerRegistryPublishPrefix/$buildTag" : ` "$ContainerRegistryFqdn/$buildTag" Write-Host "Publishing Container: $publishTag" exec { & docker tag $buildTag $publishTag } exec { docker push $publishTag } } } # Synopsis: Outputs the tag used for the built container images (e.g. local file, Build Server output variable) task OutputContainerImageTagArtefact { if ($containerBuildTag) { Write-Host "Creating build artefact to record the container image tag" Set-Content -Path $ContainerImageTagArtefactPath -Value $containerBuildTag Write-Host "ContainerImageTagArtefactPath: $ContainerImageTagArtefactPath" Write-Host "ContainerImageTag: $containerBuildTag" # Ensure we give a full path to the artefact/file $artefactFilePath = [IO.Path]::GetFullPath($ContainerImageTagArtefactPath) Write-Host "artefactFilePath: $artefactFilePath" if ($IsAzureDevops) { Write-Host "Sending container image tag details to Azure Pipelines..." Write-Host "##vso[task.uploadsummary]$artefactFilePath" Write-Host "##vso[task.setvariable variable=ContainerImageTagArtefactPath]$artefactFilePath" Write-Host "##vso[task.setvariable variable=ContainerImageTag]$containerBuildTag" } elseif ($IsGitHubActions) { Write-Host "Sending container image tag details to GitHub Actions..." "ContainerImageTagArtefactPath=$artefactFilePath" | Out-File -Encoding utf8 -Append $env:GITHUB_OUTPUT "ContainerImageTag=$containerBuildTag" | Out-File -Encoding utf8 -Append $env:GITHUB_OUTPUT } } } task PublishContainerImages -If { !$SkipPublishContainerImages } PublishContainerImagesToAcr, PublishContainerImagesToGhcr, PublishContainerImagesToDocker, OutputContainerImageTagArtefact |