Modules/businessdev.ALbuild.Marketplace/Public/Submit-BcMarketplaceApp.ps1
|
function Submit-BcMarketplaceApp { <# .SYNOPSIS Submits an AL app to Microsoft Marketplace (AppSource) end to end. .DESCRIPTION Orchestrates a Marketplace submission: authenticates (Partner Center and product-ingestion scopes), resolves the product by name, uploads the app (and library apps) and creates a submission, waits for validation, and optionally promotes it to live. Requires a valid ALbuild license. .PARAMETER ProductName The Marketplace product (offer) name. OPTIONAL - defaults to the main app's manifest name. Provide it only to override (e.g. when the offer name differs from the app name). .PARAMETER AppPath A folder of built .app files, or a single .app file. The main app and its library (dependency) apps are selected automatically and TEST apps are excluded - so a task can just point at the build output folder without naming a specific, version-stamped file. .PARAMETER AppFile (Legacy) An explicit main .app file. Prefer -AppPath. Ignored when -AppPath is given. .PARAMETER LibraryAppFile Optional dependent/library .app files (only used with the legacy -AppFile). .PARAMETER TenantId Azure AD tenant id for the Partner Center service principal. .PARAMETER ClientId Service principal client id. .PARAMETER ClientSecret Service principal client secret. .PARAMETER PublisherId Numeric publisher/Seller ID (Partner Center > Settings > Account settings > Identifiers). Required by the Partner Center ingestion API (sent as the 'x-ms-publisherId' header). .PARAMETER AutoPromote Promote to live after successful validation. .PARAMETER TimeoutMinutes Validation timeout. Default 30. .OUTPUTS PSCustomObject with ProductId, SubmissionId, State, Substate, Promoted. #> [CmdletBinding(SupportsShouldProcess, DefaultParameterSetName = 'Path')] [OutputType([PSCustomObject])] param( [string] $ProductName, [Parameter(Mandatory, ParameterSetName = 'Path')] [string] $AppPath, [Parameter(Mandatory, ParameterSetName = 'Legacy')] [string] $AppFile, [Parameter(ParameterSetName = 'Legacy')] [string[]] $LibraryAppFile = @(), [Parameter(Mandatory)] [string] $TenantId, [Parameter(Mandatory)] [string] $ClientId, [Parameter(Mandatory)] [object] $ClientSecret, [Parameter(Mandatory)] [string] $PublisherId, [switch] $AutoPromote, [int] $TimeoutMinutes = 30 ) Assert-ALbuildLicensed -Feature 'Marketplace' # Resolve the apps to submit. -AppPath (folder or file) auto-selects the main app + library apps and # drops test apps; -AppFile is the explicit legacy path. if ($PSCmdlet.ParameterSetName -eq 'Path') { $set = Resolve-BcMarketplaceAppSet -Path $AppPath $AppFile = $set.MainApp.File $LibraryAppFile = @($set.LibraryApps | ForEach-Object { $_.File }) if (-not $ProductName) { $ProductName = $set.MainApp.Name Write-ALbuildLog "No product name supplied; using the main app's manifest name '$ProductName'." } } elseif (-not $ProductName) { # Legacy path with no explicit name: derive it from the app's manifest. $ProductName = (Expand-BcAppFile -Path $AppFile).Name Write-ALbuildLog "No product name supplied; using the app's manifest name '$ProductName'." } if (-not $ProductName) { throw 'Could not determine the Marketplace product name (no -ProductName and no readable app manifest).' } # Product lookup uses the Graph product-ingestion scope; the submission uses the Partner Center scope # (which requires the PublisherId / x-ms-publisherId header). $graphAuth = New-BcMarketplaceAuthContext -TenantId $TenantId -ClientId $ClientId -ClientSecret $ClientSecret -Scope 'https://graph.microsoft.com/.default' -PublisherId $PublisherId $partnerAuth = New-BcMarketplaceAuthContext -TenantId $TenantId -ClientId $ClientId -ClientSecret $ClientSecret -Scope 'https://api.partner.microsoft.com/.default' -PublisherId $PublisherId Write-ALbuildLog "Resolving product '$ProductName' ..." $products = @(Get-BcMarketplaceProduct -AuthContext $graphAuth -Name $ProductName) if ($products.Count -eq 0) { throw "Marketplace product '$ProductName' was not found (product name = the offer 'alias')." } if ($products.Count -gt 1) { throw "Multiple products match '$ProductName' ($(($products | ForEach-Object { $_.alias }) -join ', ')); use a more specific name." } $product = $products[0] Write-ALbuildLog "Product '$($product.alias)' ($($product.id))." if (-not $PSCmdlet.ShouldProcess($product.alias, 'Create and validate Marketplace submission')) { return } # New-BcMarketplaceSubmission uploads the package(s), creates the preview submission, waits for # validation and (with -AutoPromote) promotes to live - the proven Publish-AppSourceApp flow. return New-BcMarketplaceSubmission -AuthContext $partnerAuth -ProductId $product.id ` -AppFile $AppFile -LibraryAppFile $LibraryAppFile -AutoPromote:$AutoPromote -TimeoutMinutes $TimeoutMinutes } |