Modules/businessdev.ALbuild.RuntimePackages/Public/Build-BcRuntimePackages.ps1

function Build-BcRuntimePackages {
    <#
    .SYNOPSIS
        Builds runtime packages for one or more apps across Business Central platform versions (licensed).
 
    .DESCRIPTION
        Implements the batched/incremental runtime-package engine: for each target platform version
        it creates a single container, publishes all apps into it, generates each app's runtime
        package and packs a runtime NuGet package (id '<publisher>.<name>.runtime-<appversion>',
        package version = platform version, resolvable by platform version), then removes the
        container. One container per version (not per app x version) minimises spin-ups; running
        this per version on separate agents provides the parallel dimension. A valid ALbuild license
        is required.
 
    .PARAMETER App
        The apps to process. Each item: @{ AppFile; Name; Publisher; Version }.
 
    .PARAMETER PlatformVersion
        Platform versions to build for (typically from Get-BcRuntimePackageBuildPlan).
 
    .PARAMETER Type
        Artifact type: OnPrem (default) or Sandbox.
 
    .PARAMETER Country
        Artifact country. Default 'w1'.
 
    .PARAMETER Credential
        Container admin credential.
 
    .PARAMETER OutputFolder
        Output root for the runtime apps/packages. Default: ./runtime-output.
 
    .PARAMETER DockerExecutable
        The Docker executable to use (default 'docker').
 
    .OUTPUTS
        PSCustomObject per produced runtime package (Version, App, RuntimeApp, NuGetPackage).
    #>

    [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseSingularNouns', '',
        Justification = 'Builds multiple runtime packages in one invocation; the plural noun is intentional.')]
    [CmdletBinding()]
    [OutputType([PSCustomObject])]
    param(
        [Parameter(Mandatory)] [object[]] $App,
        [Parameter(Mandatory)] [string[]] $PlatformVersion,
        [ValidateSet('OnPrem', 'Sandbox')] [string] $Type = 'OnPrem',
        [string] $Country = 'w1',
        [pscredential] $Credential,
        [string] $OutputFolder = (Join-Path (Get-Location) 'runtime-output'),
        [string] $DockerExecutable = 'docker'
    )

    Assert-ALbuildLicensed -Feature 'RuntimePackages'
    Test-BcPlatform -Require | Out-Null

    $normalize = { param($v) ($v -replace '[^A-Za-z0-9_\-]', '') }
    $produced = @()

    foreach ($version in ($PlatformVersion | Sort-Object -Property @{ Expression = { ConvertTo-BcVersion $_ } })) {
        $artifactUrl = Find-BcArtifactUrl -Type $Type -Country $Country -Version $version -Select Closest
        if (-not $artifactUrl) { Write-ALbuildLog -Level Warning "No artifact found for $version; skipping."; continue }

        $versionOutput = Join-Path $OutputFolder $version
        $containerName = "albuild-rt-$([guid]::NewGuid().ToString('N').Substring(0, 8))"
        Write-ALbuildLog "Building runtime packages for platform $version ..."
        try {
            New-BcContainer -Name $containerName -ArtifactUrl $artifactUrl -Credential $Credential -DockerExecutable $DockerExecutable | Out-Null

            foreach ($app in $App) {
                Publish-BcContainerApp -Name $containerName -AppFile $app.AppFile -Sync -Install -SkipVerification -DockerExecutable $DockerExecutable

                $runtimeApp = New-BcRuntimePackage -Name $containerName -AppName $app.Name -AppPublisher $app.Publisher `
                    -AppVersion $app.Version -OutputFolder $versionOutput -DockerExecutable $DockerExecutable

                $packageId = "$(& $normalize $app.Publisher).$(& $normalize $app.Name).runtime-$($app.Version -replace '\.', '-')"
                $range = Get-BcRuntimeNuGetRange -PlatformVersion $version
                $nupkg = New-BcNuGetPackage -AppFile $runtimeApp -PackageId $packageId -Version $version `
                    -Description "Runtime package for $($app.Name) $($app.Version) on platform $version (application $($range.ApplicationRange))." `
                    -OutputFolder $versionOutput

                $produced += [PSCustomObject]@{
                    Version       = $version
                    App           = $app.Name
                    RuntimeApp    = $runtimeApp
                    NuGetPackage  = $nupkg
                    PackageId     = $packageId
                }
            }
        }
        catch {
            Write-ALbuildLog -Level Error "Runtime package build failed for $version`: $($_.Exception.Message)"
        }
        finally {
            Remove-BcContainer -Name $containerName -DockerExecutable $DockerExecutable -Confirm:$false -ErrorAction SilentlyContinue
        }
    }

    return $produced
}