diff --git a/.pipelines/PowerShell-Docker-Image-Build-Official.yml b/.pipelines/PowerShell-Docker-Image-Build-Official.yml index 2272dba3c..9fb0ed9a2 100644 --- a/.pipelines/PowerShell-Docker-Image-Build-Official.yml +++ b/.pipelines/PowerShell-Docker-Image-Build-Official.yml @@ -5,6 +5,10 @@ parameters: default: 'v7.4.0-preview.5' - name: 'releaseChannel' default: 'preview' +- name: 'whatIf' + displayName: 'Skip publishing to MCR, but show what would get published and attached' + type: boolean + default: false variables: - name: POWERSHELL_TELEMETRY_OPTOUT value: 1 @@ -16,6 +20,8 @@ variables: value: ${{ parameters.releaseChannel }} - name: releaseChannelPath value: '' +- name: whatIf + value: ${{ parameters.whatIf }} - name: runCodesignValidationInjection value: false - name: DisableDockerDetector @@ -129,6 +135,7 @@ extends: $info = @{} $info.Add("channel", $env:RELEASECHANNEL) $info.Add("releaseVersionTag", $env:RELEASEVERSIONTAG) + $info.Add("whatIf", $env:WHATIF) $info | ConvertTo-Json | Out-File -Encoding utf8NoBOM -FilePath ./BuildInfo.json displayName: 'Write build info to file' - task: CopyFiles@2 diff --git a/.pipelines/PowerShell-Docker-Image-Release-Official.yml b/.pipelines/PowerShell-Docker-Image-Release-Official.yml index c3498c8be..29c8fd32c 100644 --- a/.pipelines/PowerShell-Docker-Image-Release-Official.yml +++ b/.pipelines/PowerShell-Docker-Image-Release-Official.yml @@ -63,9 +63,11 @@ extends: $currentChannel = $($buildMetadata.channel) $currentVersion = $($buildMetadata.releaseVersionTag) $finalVersion = $currentVersion.Trim("v") - Write-Verbose -Verbose "version: $finalVersion and channel: $currentChannel" + $whatIfSwitch = $($buildMetadata.whatIf) + Write-Verbose -Verbose "version: $finalVersion and channel: $currentChannel and whatIf: $whatIf" Write-Host "##vso[task.setvariable variable=channel;isOutput=true]$currentChannel" Write-Host "##vso[task.setvariable variable=version;isOutput=true]$finalVersion" + Write-Host "##vso[task.setvariable variable=whatIf;isOutput=true]$whatIfSwitch" displayName: 'Get channel from buildInfo.json' name: setChannelStep - job: DownloadImageArtifactFromBuild @@ -275,6 +277,8 @@ extends: value: $[ stageDependencies.GetBuildArtifacts.DownloadMetaArtifactFromBuild.outputs['setChannelStep.channel'] ] - name: version value: $[ stageDependencies.GetBuildArtifacts.DownloadMetaArtifactFromBuild.outputs['setChannelStep.version'] ] + - name: whatIf + value: $[ stageDependencies.GetBuildArtifacts.DownloadMetaArtifactFromBuild.outputs['setChannelStep.whatIf'] ] pool: timeoutInMinutes: 30 type: windows @@ -299,6 +303,7 @@ extends: $pathToImageMetadataFile = Join-Path -Path $pathToParametersFolder -ChildPath 'ImageMetadata.json' $pathToChannelJsonFile = Join-Path -Path $pathToParametersFolder -ChildPath 'ChannelInfo.json' $currentChannel = '$(channel)' + $currentWhatIfSwitch = '$(whatIf)' $channelHash = @{channel=$currentChannel} $channelHash | ConvertTo-Json | Out-File $pathToChannelJsonFile diff --git a/EV2Specs/ServiceGroupRoot/Shell/Run/Run.ps1 b/EV2Specs/ServiceGroupRoot/Shell/Run/Run.ps1 index 07df55c65..edd4c4665 100644 --- a/EV2Specs/ServiceGroupRoot/Shell/Run/Run.ps1 +++ b/EV2Specs/ServiceGroupRoot/Shell/Run/Run.ps1 @@ -123,11 +123,15 @@ try { Write-Verbose -Verbose "Getting channel info" $channelJsonFileContent = Get-Content -Path $pathToChannelJson | ConvertFrom-Json $channel = $channelJsonFileContent.channel + $whatIf = $channelJsonFileContent.whatIf Write-Verbose -Verbose "Getting image info" $imgJsonFileContent = Get-Content -Path $pathToImgMetadataJson | ConvertFrom-Json $images = $imgJsonFileContent.$channel + # Create variables for lifecycle annotations + $endOfLifeDate = Get-Date -Format "yyyy-MM-ddTHH:mm:00Z" + Write-Verbose -Verbose "Push images to ACR" foreach ($image in $images) { @@ -151,11 +155,63 @@ try { foreach ($tag in $tags) { Write-Verbose -Verbose "tag: $tag" + + # check if this rolling tag is associated with an image + $mcrImageFullName = "mcr.microsoft.com/powershell:$tag" + oras manifest fetch $mcrImageFullName > $null + $rollingTagExists = $? + + if ($rollingTagExists) + { + # If the lineage's rolling tag is already associated with an existing image, then only attach lifecycle metadata to the existing image to indicate that it is outdated + # Resolve image's digest + $imageDigest = oras resolve $mcrImageName + + # Import (old) image by digest from MCR into our ACR + $mcrImageNameDigest = "mcr.microsoft.com/powershell@$imageDigest" + $acrEOLImageTag = "$tag-EOL" + if (!$whatIf) + { + az acr import --name $env:DESTINATION_ACR_NAME --source $mcrImageNameDigest --image $acrEOLImageTag + } + else { + Write-Verbose -Verbose "az acr import --name $env:DESTINATION_ACR_NAME --source $mcrImageNameDigest --image $acrEOLImageTag" + } + + # Attach lifecycle annotation, which will eventually get synced to MCR + $acrImageNameDigest = "$env:DESTINATION_ACR_NAME.azurecr.io/public/powershell@$imageDigest" + if (!$whatIf) + { + oras attach --artifact-type "application/vnd.microsoft.artifact.lifecycle" --annotation "vnd.microsoft.artifact.lifecycle.end-of-life.date=$endOfLifeDate" $acrImageNameDigest + } + else { + Write-Verbose -Verbose "oras attach --artifact-type `"application/vnd.microsoft.artifact.lifecycle`" --annotation `"vnd.microsoft.artifact.lifecycle.end-of-life.date=$endOfLifeDate`" $acrImageNameDigest" + } + + if (!$whatIf) + { + $imageAnnotation = oras discover --format json --artifact-type "application/vnd.microsoft.artifact.lifecycle" $acrImageNameDigest + $imageAnnotationJson = $imageAnnotation | ConvertFrom-Json + $eolDateAttached = $imageAnnotationJson.manifests.annotations."vnd.microsoft.artifact.lifecycle.end-of-life.date".ToString("yyyy-MM-ddTHH:mm:00Z") + Write-Verbose -Verbose "date attached: $endOfLifeDate, date found in annotation: $eolDateAttached, match: $($eolDateAttached -eq $endOfLifeDate)" + } + else { + Write-Verbose -Verbose "oras discover --format json --artifact-type `"application/vnd.microsoft.artifact.lifecycle`" $acrImageNameDigest" + } + } + # Need to push image for each tag $destination_image_full_name = "$env:DESTINATION_ACR_NAME.azurecr.io/public/powershell:${tag}" Write-Verbose -Verbose "dest img full name: $destination_image_full_name" Write-Verbose -Verbose "Pushing file $tarballFilePath to $destination_image_full_name" - ./crane push $tarballFilePath $destination_image_full_name + if (!$whatIf) + { + ./crane push $tarballFilePath $destination_image_full_name + } + else { + Write-Verbose "./crane push $tarballFilePath $destination_image_full_name" + } + Write-Verbose -Verbose "done pushing for tag: $tag" } }