diff --git a/.github/workflows/BuildMissingImages.yaml b/.github/workflows/BuildMissingImages.yaml index a496da0..c0cbbd4 100644 --- a/.github/workflows/BuildMissingImages.yaml +++ b/.github/workflows/BuildMissingImages.yaml @@ -31,66 +31,15 @@ jobs: RUNNUMBEROFFSET: ${{ vars.RUNNUMBEROFFSET }} PushToProd: ${{ github.event.inputs.PushToProd }} run: | - $erroractionpreference = "STOP" - try { - $bctags = @('ltsc2016','ltsc2019','ltsc2022','ltsc2025') - $servercoretags = @{ - "ltsc2016" = "4.8-windowsservercore-ltsc2016" - "ltsc2019" = "4.8-windowsservercore-ltsc2019" - "ltsc2022" = "4.8.1-windowsservercore-ltsc2022" - "ltsc2025" = "4.8.1-windowsservercore-ltsc2025" - } - $pushToProd = $true - if ($env:GITHUB_EVENT_NAME -eq "workflow_dispatch") { + $pushToProd = $true + if ($env:GITHUB_EVENT_NAME -eq "workflow_dispatch") { $pushToProd = $env:PushToProd -eq 'True' - } - $tags = @($bctags | ForEach-Object { "$_-dev"; "$_-filesonly-dev" }) - if ($prod) { - $tags += @($bctags | ForEach-Object { "$_"; "$_-filesonly" }) - } - $digests = $tags | ForEach-Object { - Write-Host -NoNewline "$_ : " - $manifest = docker manifest inspect mcr.microsoft.com/businesscentral:$_ -v | ConvertFrom-Json - $manifest.Descriptor.digest - } | Select-Object -Unique - Set-Location "generic" - $rootPath = Get-Location - $genericTag = (Get-Content -Raw -Path (Join-Path $RootPath 'tag.txt')).Trim(@(13,10,32)) - $tagver = [System.Version]$genericTag - $revision = [int]($ENV:GITHUB_RUN_NUMBER)-[int]($ENV:RUNNUMBEROFFSET) - $genericTag = "$($tagver.Major).$($tagver.Minor).$($tagver.Build).$revision" - Write-Host "Using generic Tag $genericTag" - $webclient = New-Object System.Net.WebClient - $webclient.Headers.Add('Accept', "application/json") - $neededBcTags = $bctags | ForEach-Object { - $osVersion = [System.Version](($webclient.DownloadString("https://mcr.microsoft.com/v2/dotnet/framework/runtime/manifests/$($serverCoreTags."$_")") | ConvertFrom-Json).history[0].v1Compatibility | ConvertFrom-Json)."os.version" - "$osVersion-$genericTag|mcr.microsoft.com/dotnet/framework/runtime:$($serverCoreTags."$_")|$_" - "$osVersion-$genericTag-filesonly|mcr.microsoft.com/dotnet/framework/runtime:$($serverCoreTags."$_")|$_" - } - Write-Host "Needed Tags ($($neededBcTags.Count))" - $neededBcTags | ForEach-Object { Write-Host "- $_" } - $alltags = (($webclient.DownloadString("https://mcr.microsoft.com/v2/businesscentral/tags/list") | ConvertFrom-Json)).tags - $imagesBcTags = @($neededBcTags | Where-Object { $alltags -notcontains $_ }) - Write-Host "Image Tags ($($imagesBcTags.Count))" - if ($imagesBcTags) { - $imagesBcTags | ForEach-Object { Write-Host "- $_" } - } - else { - Write-Host '- none' - } - $buildImagesJson = ConvertTo-Json -InputObject $imagesBcTags -Compress - $digestsJson = ConvertTo-Json -InputObject $digests -Compress - Add-Content -encoding utf8 -Path $ENV:GITHUB_OUTPUT -Value "digestsJson=$digestsJson" - Write-Host "digestsJson=$digestsJson" - Add-Content -encoding utf8 -Path $ENV:GITHUB_OUTPUT -Value "genericTag=$genericTag" - Write-Host "genericTag=$genericTag" - Add-Content -encoding utf8 -Path $ENV:GITHUB_OUTPUT -Value "buildImagesJson=$buildImagesJson" - Write-Host "buildImagesJson=$buildImagesJson" - } - catch { - Write-Host "::Error::Error analyzing images. Error was $($_.Exception.Message)" - $host.SetShouldExit(1) } + [int] $revisionNumber = ([int]($ENV:GITHUB_RUN_NUMBER) - [int]($ENV:RUNNUMBEROFFSET)) + + . ${{ github.workspace }}/build/analyzeimages.ps1 ` + -RevisionNumber $revisionNumber ` + -PushToProd:$pushToProd BuildImages: runs-on: [ Windows-2025 ] @@ -113,85 +62,29 @@ jobs: - name: Build Image env: + Tag: ${{ matrix.tag }} PushToProd: ${{ github.event.inputs.PushToProd }} GenericTag: ${{ needs.AnalyzeImages.outputs.genericTag }} run: | - $erroractionpreference = "STOP" - Set-StrictMode -version 2.0 - try { - $pushRegistry = "mcrbusinesscentral.azurecr.io" - az acr login --name $pushRegistry - Set-Location "generic" - $rootPath = Get-Location - $genericTag = $env:GenericTag - $pushToProd = $true - if ($env:GITHUB_EVENT_NAME -eq "workflow_dispatch") { + $filesonly = ($env:Tag -like '*-filesonly|*') + $only24 = ($env:Tag -like '*-24|*' -or $env:Tag -like '*-24-filesonly|*') + $baseImage = $env:Tag.split('|')[1] + $ltscTag = $env:Tag.split('|')[2] + + $pushToProd = $true + if ($env:GITHUB_EVENT_NAME -eq "workflow_dispatch") { $pushToProd = $env:PushToProd -eq 'True' - } - $osversion = '${{ matrix.tag }}'.split('|')[0].split('-')[0] - $filesonly = ('${{ matrix.tag }}' -like '*-filesonly|*') - $only24 = ('${{ matrix.tag }}' -like '*-24|*' -or '${{ matrix.tag }}' -like '*-24-filesonly|*') - $baseImage = '${{ matrix.tag }}'.split('|')[1] - $ltscTag = '${{ matrix.tag }}'.split('|')[2] - $setupUrlsFile = Join-Path $rootPath "Run/SetupUrls.ps1" - Get-Content -Path $setupUrlsFile | Out-Host - $dockerfile = Join-Path $rootPath "DOCKERFILE" - $strFilesOnly = '' - $str24 = '' - if ($only24) { - $str24 = "-24" - } - if ($filesOnly) { - $strFilesOnly = "-filesonly" - $dockerfile += '-filesonly' - } - $image = "my:$osversion-$genericTag$str24$strFilesOnly" - $newtags = @( - "$pushRegistry/public/businesscentral:$osversion$str24$strFilesonly-dev" - "$pushRegistry/public/businesscentral:$ltscTag$str24$strFilesonly-dev" - ) - if ($pushToProd) { - $newtags += @( - "$pushRegistry/public/businesscentral:$osversion$str24$strFilesonly" - "$pushRegistry/public/businesscentral:$osversion-$genericTag$str24$strFilesonly" - "$pushRegistry/public/businesscentral:$ltscTag$str24$strFilesonly" - ) - } - $newTags | out-host - $created = [DateTime]::Now.ToUniversalTime().ToString("yyyyMMddHHmm") - docker pull $baseimage - $inspect = docker inspect $baseimage | ConvertFrom-Json - $success = $false - docker build --build-arg baseimage=$baseimage ` - --build-arg created=$created ` - --build-arg tag="$genericTag" ` - --build-arg osversion="$osversion" ` - --build-arg filesonly="$filesonly" ` - --build-arg only24="$only24" ` - --isolation=hyperv ` - --memory 8G ` - --tag $image ` - --file $dockerfile ` - $RootPath | % { - $_ | Out-Host - if ($_ -like "Successfully built*") { - $success = $true - } - } - if (!$success) { - throw "Error building image" - } - $newtags | ForEach-Object { - Write-Host "Push $_" - docker tag $image $_ - docker push $_ - } - } - catch { - Write-Host "::Error::Error building images. Error was $($_.Exception.Message)" - $host.SetShouldExit(1) } + . ${{ github.workspace }}/build/build.ps1 ` + -BaseImage $baseImage ` + -LtscTag $ltscTag ` + -FilesOnly $filesonly ` + -Only24 $only24 ` + -GenericTag $env:GenericTag ` + -PushToDev ` + -PushToProd:$pushToProd + MarkOldImagesStale: runs-on: [ Windows-Latest ] needs: [ AnalyzeImages, BuildImages ] @@ -215,16 +108,4 @@ jobs: run: | $erroractionpreference = "STOP" $digests = $env:digestsJson | ConvertFrom-Json - $version = "1.2.0" - $filename = Join-Path $env:TEMP "oras_$($version)_windows_amd64.zip" - Invoke-RestMethod -Method GET -UseBasicParsing -Uri "https://github.com/oras-project/oras/releases/download/v$($version)/oras_$($version)_windows_amd64.zip" -OutFile $filename - Expand-Archive -Path $filename -DestinationPath temp - $pushRegistry = "mcrbusinesscentral.azurecr.io" - $staleDate = [System.DateTime]::Today.AddDays(-1).ToString('yyyy-MM-dd') - az acr login --name $pushRegistry - $digests | ForEach-Object { - $image = "$pushRegistry/public/businesscentral@$_" - Write-Host "Stale $image on $staleDate" - ./temp/oras.exe attach --artifact-type application/vnd.microsoft.artifact.lifecycle --annotation "vnd.microsoft.artifact.lifecycle.end-of-life.date=$staleDate" $image - } - + . ${{ github.workspace }}/build/markstale.ps1 -Digests $digests \ No newline at end of file diff --git a/.github/workflows/MarkStale.yaml b/.github/workflows/MarkStale.yaml index d908c92..2b95ec9 100644 --- a/.github/workflows/MarkStale.yaml +++ b/.github/workflows/MarkStale.yaml @@ -38,16 +38,4 @@ jobs: run: | $erroractionpreference = "STOP" $digests = "$env:digests".Split(",").Trim() | Select-Object -Unique - $version = "1.2.0" - $filename = Join-Path $env:TEMP "oras_$($version)_windows_amd64.zip" - Invoke-RestMethod -Method GET -UseBasicParsing -Uri "https://github.com/oras-project/oras/releases/download/v$($version)/oras_$($version)_windows_amd64.zip" -OutFile $filename - Expand-Archive -Path $filename -DestinationPath temp - $pushRegistry = "mcrbusinesscentral.azurecr.io" - $staleDate = [System.DateTime]::Today.AddDays(-1).ToString('yyyy-MM-dd') - az acr login --name $pushRegistry - $digests | ForEach-Object { - $image = "$pushRegistry/public/businesscentral@$_" - Write-Host "Stale $image on $staleDate" - ./temp/oras.exe attach --artifact-type application/vnd.microsoft.artifact.lifecycle --annotation "vnd.microsoft.artifact.lifecycle.end-of-life.date=$staleDate" $image - } - + . ${{ github.workspace }}/build/markstale.ps1 -Digests $digests diff --git a/.github/workflows/PRBuild.yaml b/.github/workflows/PRBuild.yaml new file mode 100644 index 0000000..9345296 --- /dev/null +++ b/.github/workflows/PRBuild.yaml @@ -0,0 +1,61 @@ +name: Pull Request Build + +on: + pull_request: + branches: [ master ] + +permissions: + contents: read + +defaults: + run: + shell: PowerShell + +jobs: + AnalyzeImages: + runs-on: [ windows-latest ] + outputs: + genericTag: ${{ steps.Analyze.outputs.genericTag }} + buildImagesJson: ${{ steps.Analyze.outputs.buildImagesJson }} + digestsJson: ${{ steps.Analyze.outputs.digestsJson }} + steps: + - uses: actions/checkout@v4 + + - name: Analyze + id: Analyze + env: + RUNNUMBEROFFSET: ${{ vars.RUNNUMBEROFFSET }} + run: | + [int] $revisionNumber = ([int]($ENV:GITHUB_RUN_NUMBER) - [int]($ENV:RUNNUMBEROFFSET)) + + . ${{ github.workspace }}/build/analyzeimages.ps1 ` + -RevisionNumber $revisionNumber + + BuildImages: + runs-on: [ Windows-2025 ] + needs: [ AnalyzeImages ] + strategy: + matrix: + tag: ${{ fromJson(needs.AnalyzeImages.outputs.buildImagesJson) }} + fail-fast: false + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Build Image + env: + Tag: ${{ matrix.tag }} + GenericTag: ${{ needs.AnalyzeImages.outputs.genericTag }} + run: | + $osversion = $env:Tag.split('|')[0].split('-')[0] + $filesonly = ($env:Tag -like '*-filesonly|*') + $only24 = ($env:Tag -like '*-24|*' -or $env:Tag -like '*-24-filesonly|*') + $baseImage = $env:Tag.split('|')[1] + $ltscTag = $env:Tag.split('|')[2] + + . ${{ github.workspace }}/build/build.ps1 ` + -BaseImage $baseImage ` + -LtscTag $ltscTag ` + -FilesOnly $filesonly ` + -Only24 $only24 ` + -GenericTag $env:GenericTag diff --git a/LOCAL_DEV_ENV.md b/LOCAL_DEV_ENV.md new file mode 100644 index 0000000..b826b81 --- /dev/null +++ b/LOCAL_DEV_ENV.md @@ -0,0 +1,28 @@ +# How to build and test images locally + +## Prerequisites +- Install and run [Docker Desktop](https://docs.docker.com/desktop/install/windows-install/). Make sure it is running Windows containers. +- Install [BcContainerHelper PS module](https://www.powershellgallery.com/packages/BcContainerHelper) (latest available version). +`Install-Module BCContainerHelper -AllowPrerelease` would do. + +## Build a new image locally + +If you want to build a new docker image locally you can use the build.ps1 script. The following will produce a new docker image based on Windows Server Core 2025. +```powershell + $GenericTag = "1.2.3.4" + $baseImage = "mcr.microsoft.com/dotnet/framework/runtime:4.8.1-windowsservercore-ltsc2025" + $imageName = ./build/build.ps1 -BaseImage $baseImage -LtscTag 'ltsc2025' -FilesOnly $false -Only24 $false -GenericTag $GenericTag +``` + +If you'd rather use a different base image, you can also use one of the following: +* mcr.microsoft.com/dotnet/framework/runtime:4.8-windowsservercore-ltsc2016 +* mcr.microsoft.com/dotnet/framework/runtime:4.8-windowsservercore-ltsc2019 +* mcr.microsoft.com/dotnet/framework/runtime:4.8.1-windowsservercore-ltsc2022 +* mcr.microsoft.com/dotnet/framework/runtime:4.8.1-windowsservercore-ltsc2025 + +## Create a docker container with the image + +Once you have a local image you can use New-BCContainer to spin up a Business Central container that uses your image. +```powershell + New-BcContainer -accept_eula -accept_insiderEula -containerName "MyTestContainer" -artifactUrl (Get-BCArtifactUrl -select NextMajor -accept_insiderEula -country W1) -useGenericImage $imageName +``` \ No newline at end of file diff --git a/build/analyzeimages.ps1 b/build/analyzeimages.ps1 new file mode 100644 index 0000000..111d179 --- /dev/null +++ b/build/analyzeimages.ps1 @@ -0,0 +1,88 @@ +param( + [Parameter(Mandatory = $false)] + [int] $RevisionNumber, + [Parameter(Mandatory = $false)] + [switch] $PushToProd +) + +try { + $repositoryRoot = Join-Path $PSScriptRoot "..\" + Push-Location (Join-Path $repositoryRoot "generic") + $rootPath = Get-Location + + # List of the base image tags used for the Business Central images + # https://mcr.microsoft.com/en-us/artifact/mar/dotnet/framework/runtime + $baseImage = "dotnet/framework/runtime" + $baseImageTags = @{ + "ltsc2016" = "4.8-windowsservercore-ltsc2016" + "ltsc2019" = "4.8-windowsservercore-ltsc2019" + "ltsc2022" = "4.8.1-windowsservercore-ltsc2022" + "ltsc2025" = "4.8.1-windowsservercore-ltsc2025" + } + + # List of the Business Central tags to be used + $bctags = @('ltsc2016', 'ltsc2019', 'ltsc2022', 'ltsc2025') + + # Get the tags for the Business Central images + $tags = @($bctags | ForEach-Object { "$_-dev"; "$_-filesonly-dev" }) + if ($PushToProd) { + $tags += @($bctags | ForEach-Object { "$_"; "$_-filesonly" }) + } + + # Get the digests for the tags from the Microsoft Container Registry + $digests = $tags | ForEach-Object { + $tag = $_ + $manifest = docker manifest inspect mcr.microsoft.com/businesscentral:$tag -v | ConvertFrom-Json + $digest = $manifest.Descriptor.digest + Write-Host "Digest for tag $($tag): $digest" -ForegroundColor Cyan + return $manifest.Descriptor.digest + } | Select-Object -Unique + Write-Host "Found $($digests.Count) digests will be marked as stale:" + + # Get the generic tag to use for the images + $genericTag = (Get-Content -Raw -Path (Join-Path $RootPath 'tag.txt')).Trim(@(13, 10, 32)) + $tagver = [System.Version]$genericTag + $genericTag = "$($tagver.Major).$($tagver.Minor).$($tagver.Build).$RevisionNumber" + Write-Host "Using generic Tag $genericTag" + + + # Build a list of strings that contain the necessary information to build the Business Central images + # The format is: "osVersion-genericTag|mcr.microsoft.com/baseImage:baseImageTag|bctag" + # This will be used in the later steps to build the images + $webclient = New-Object System.Net.WebClient + $webclient.Headers.Add('Accept', "application/json") + $neededBcTags = $bctags | ForEach-Object { + $osVersion = [System.Version](($webclient.DownloadString("https://mcr.microsoft.com/v2/$baseImage/manifests/$($baseImageTags."$_")") | ConvertFrom-Json).history[0].v1Compatibility | ConvertFrom-Json)."os.version" + "$osVersion-$genericTag|mcr.microsoft.com/$($baseImage):$($baseImageTags."$_")|$_" + "$osVersion-$genericTag-filesonly|mcr.microsoft.com/$($baseImage):$($baseImageTags."$_")|$_" + } + Write-Host "Needed Tags ($($neededBcTags.Count))" + $neededBcTags | ForEach-Object { Write-Host "- $_" } + $alltags = (($webclient.DownloadString("https://mcr.microsoft.com/v2/businesscentral/tags/list") | ConvertFrom-Json)).tags + $imagesBcTags = @($neededBcTags | Where-Object { $alltags -notcontains $_ }) + Write-Host "Image Tags ($($imagesBcTags.Count))" + if ($imagesBcTags) { + $imagesBcTags | ForEach-Object { Write-Host "- $_" } + } + else { + Write-Host '- none' + } + + # Output digests, generic tag and build images as JSON to be used in the GitHub Actions workflow + $buildImagesJson = ConvertTo-Json -InputObject $imagesBcTags -Compress + $digestsJson = ConvertTo-Json -InputObject $digests -Compress + Write-Host "genericTag=$genericTag" -ForegroundColor Green + Write-Host "digestsJson=$digestsJson" -ForegroundColor Green + Write-Host "buildImagesJson=$buildImagesJson" -ForegroundColor Green + + # Check if this is running in a GitHub Actions environment + if ($ENV:GITHUB_OUTPUT) { + Add-Content -encoding utf8 -Path $ENV:GITHUB_OUTPUT -Value "genericTag=$genericTag" + Add-Content -encoding utf8 -Path $ENV:GITHUB_OUTPUT -Value "digestsJson=$digestsJson" + Add-Content -encoding utf8 -Path $ENV:GITHUB_OUTPUT -Value "buildImagesJson=$buildImagesJson" + } + +} +finally { + Pop-Location +} \ No newline at end of file diff --git a/build/build.ps1 b/build/build.ps1 new file mode 100644 index 0000000..26f43a3 --- /dev/null +++ b/build/build.ps1 @@ -0,0 +1,157 @@ +<# + .SYNOPSIS + Build a Docker image for Business Central. + + .DESCRIPTION + This script builds a Docker image for Business Central using the specified parameters. + It also pushes the image to a specified Azure Container Registry if requested. + + .PARAMETER BaseImage + The base image to use for building the Docker image (mcr.microsoft.com/dotnet/framework/runtime or mcr.microsoft.com/windows/servercore) + Example: mcr.microsoft.com/dotnet/framework/runtime:4.8.1-windowsservercore-ltsc2025 + + .PARAMETER LtscTag + The LTSC tag to use for the image. + For example: ltsc2016, ltsc2019, ltsc2022 or ltsc2025 + + .PARAMETER FilesOnly + A switch indicating whether to build only the files. + + .PARAMETER Only24 + A switch indicating whether to build the BC24 image. + + .PARAMETER GenericTag + The generic tag to use for the image. + Example: 1.2.3.4 + + .PARAMETER PushRegistry + The Azure Container Registry to push the image to (default: mcrbusinesscentral.azurecr.io). + + .PARAMETER PushToDev + A switch indicating whether to push the image to the development registry. + + .PARAMETER PushToProd + A switch indicating whether to push the image to the production registry. + + .EXAMPLE + ./build.ps1 -BaseImage 'mcr.microsoft.com/dotnet/framework/runtime:4.8.1-windowsservercore-ltsc2025' -LtscTag ltsc2025 -FilesOnly $false -Only24 $false -GenericTag "1.2.3.5" +#> +param( + [Parameter(Mandatory = $true)] + [string] $BaseImage, + [Parameter(Mandatory = $true)] + [string] $LtscTag, + [Parameter(Mandatory = $true)] + [bool] $FilesOnly, + [Parameter(Mandatory = $true)] + [bool] $Only24, + [Parameter(Mandatory = $true)] + [string] $GenericTag, + [Parameter(Mandatory = $false)] + [string] $PushRegistry = "mcrbusinesscentral.azurecr.io", + [Parameter(Mandatory = $false)] + [switch] $PushToDev, + [Parameter(Mandatory = $false)] + [switch] $PushToProd +) + +$erroractionpreference = "STOP" +Set-StrictMode -version 2.0 + +# Print all the parameters +Write-Host "Building Image with the following parameters:" -ForegroundColor Green +Write-Host "BaseImage: $BaseImage" -ForegroundColor Green +Write-Host "LtscTag: $LtscTag" -ForegroundColor Green +Write-Host "FilesOnly: $FilesOnly" -ForegroundColor Green +Write-Host "Only24: $Only24" -ForegroundColor Green +Write-Host "GenericTag: $GenericTag" -ForegroundColor Green +Write-Host "PushRegistry: $PushRegistry" -ForegroundColor Green +Write-Host "PushToDev: $PushToDev" -ForegroundColor Green +Write-Host "PushToProd: $PushToProd" -ForegroundColor Green + +function Get-OsVersion { + param( + [string]$Baseimage + ) + $imageInspect = docker inspect $Baseimage + $imageInspect | Out-Host + $osversion = ($imageInspect | ConvertFrom-Json).OSVersion + + # Test if the OS version is empty + if ([string]::IsNullOrEmpty($osversion)) { + throw "OS version is empty. Please inspect the base image: $Baseimage" + } + + + return $osversion +} + +try { + Push-Location "generic" + $rootPath = Get-Location + + $setupUrlsFile = Join-Path $rootPath "Run/SetupUrls.ps1" + Get-Content -Path $setupUrlsFile | Out-Host + $dockerfile = Join-Path $rootPath "DOCKERFILE" + + + $strFilesOnly = '' + $str24 = '' + if ($only24) { + $str24 = "-24" + } + if ($filesOnly) { + $strFilesOnly = "-filesonly" + $dockerfile += '-filesonly' + } + $created = [DateTime]::Now.ToUniversalTime().ToString("yyyyMMddHHmm") + docker pull $baseimage + $osversion = Get-OsVersion -Baseimage $baseimage + + $success = $false + $image = "my:$osversion-$GenericTag$str24$strFilesOnly" + docker build --build-arg baseimage=$baseimage ` + --build-arg created=$created ` + --build-arg tag="$GenericTag" ` + --build-arg osversion="$osversion" ` + --build-arg filesonly="$filesonly" ` + --build-arg only24="$only24" ` + --isolation=hyperv ` + --memory 8G ` + --tag $image ` + --file $dockerfile ` + $RootPath | ForEach-Object { + $_ | Out-Host + if ($_ -like "Successfully built*") { + $success = $true + } + } + if (!$success) { + throw "Error building image" + } +} finally { + Pop-Location +} + +if ($PushToDev -or $PushToProd) { + $newtags = @( + "$PushRegistry/public/businesscentral:$osversion$str24$strFilesonly-dev" + "$PushRegistry/public/businesscentral:$ltscTag$str24$strFilesonly-dev" + ) + if ($PushToProd) { + $newtags += @( + "$PushRegistry/public/businesscentral:$osversion$str24$strFilesonly" + "$PushRegistry/public/businesscentral:$osversion-$GenericTag$str24$strFilesonly" + "$PushRegistry/public/businesscentral:$ltscTag$str24$strFilesonly" + ) + } + + az acr login --name $PushRegistry + $newtags | ForEach-Object { + Write-Host "Pushing $image with tag $_" + docker tag $image $_ + docker push $_ + } +} + +return $image \ No newline at end of file diff --git a/build/markstale.ps1 b/build/markstale.ps1 new file mode 100644 index 0000000..5ee44f4 --- /dev/null +++ b/build/markstale.ps1 @@ -0,0 +1,19 @@ +param( + [Parameter(Mandatory = $true)] + [string]$Digests, # $digests = $env:digestsJson | ConvertFrom-Json + [Parameter(Mandatory = $false)] + [string]$PushRegistry = "mcrbusinesscentral.azurecr.io" +) + +if (-not (Get-Command -name "oras" -ErrorAction SilentlyContinue)) { + throw "Please install the ORAS CLI before running this script e.g. via 'winget install oras-cli' or 'choco install oras-cli'" +} + +az acr login --name $PushRegistry + +$staleDate = [System.DateTime]::Today.AddDays(-1).ToString('yyyy-MM-dd') +foreach ($digest in $Digests) { + $image = "$PushRegistry/public/businesscentral@$digest" + Write-Host "Stale $image on $staleDate" + oras attach --artifact-type application/vnd.microsoft.artifact.lifecycle --annotation "vnd.microsoft.artifact.lifecycle.end-of-life.date=$staleDate" $image +} \ No newline at end of file