Security change on December 1, 2026: TLS 1.2 will become the minimum standard for 365 business Print Agent. Details and system requirements
365 business development
Azure DevOps Extension

Release tasks

Release tasks deploy and distribute the app — to per-tenant and dev endpoints, on-premise environments, NuGet feeds, runtime packages and Microsoft Marketplace (AppSource). All except Publish NuGet Package require a valid ALbuild license for your Azure DevOps organization (see Licensing & tiers).

Tasks in this category

TaskReference namePurpose
Build Runtime PackagesBuildRuntimePackages@0Builds runtime packages for one or more apps across Business Central platform versions.
Publish Dev ExtensionPublishDevExtension@0Publishes an app to a Business Central development service endpoint.
Publish On-Prem AppPublishOnPremApp@0Publishes, synchronises and installs an app on an on-premises Business Central server instance.
Publish On-Prem Container AppPublishOnPremContainerApp@0Publishes, synchronises and installs an app on a Business Central server instance running inside a Docker container.
Publish NuGet PackagePublishPackage@0Pushes a NuGet package to a feed.
Publish Per-Tenant ExtensionPublishPerTenantExtension@0Publishes an app as a per-tenant extension to a Business Central environment via the Automation API.
Submit to MarketplaceSubmitMarketplace@0Submits an app to Microsoft Marketplace (AppSource) via Partner Center and optionally promotes it.

Build Runtime Packages

Reference name: BuildRuntimePackages@0

Licensed task

Requires a valid ALbuild license for your Azure DevOps organization. The license check runs on entry to the task; without a license it fails with remediation guidance.

Builds runtime packages for one or more apps across Business Central platform versions.

Note: Wraps Build-BcRuntimePackages from the businessdev.ALbuild module (licensed). Provide one .app file per line and one or more platform versions.

Underlying cmdlet: Build-BcRuntimePackages

Example

YAMLCode
- task: BuildRuntimePackages@0 displayName: 'Build runtime packages' inputs: appFile: | # one .app per line (or a folder) $(bcAppFile) platformVersion: '$(appVersion)' type: 'OnPrem' country: 'w1' outputFolder: '$(Build.ArtifactStagingDirectory)/runtime'

Inputs

InputTypeRequiredDefaultDescription
appFilemultiLineNo—App (.app) file(s) (one per line)
platformVersionstringNo—Platform version(s) (comma separated)
typepickListNoOnPremArtifact type Options: OnPrem = OnPrem, Sandbox = Sandbox.
countrystringNow1Country
userNamestringNo$(containerUsername)Container admin user
passwordstringNo$(containerPassword)Container admin password
outputFolderfilePathNo—Output folder

Option values

type

ValueMeaning
OnPremBuild runtime packages for the on-premises platform. Default.
SandboxBuild runtime packages for the sandbox (SaaS) platform.

Note: Compiles each app into a sealed runtime package (runtime .app) for the target platform. appFile is multi-line - one .app (or folder) per line. platformVersion pins the target BC platform; userName/password default to the Create BC Container credentials. This task sets no output variables.


Publish Dev Extension

Reference name: PublishDevExtension@0

Licensed task

Requires a valid ALbuild license for your Azure DevOps organization. The license check runs on entry to the task; without a license it fails with remediation guidance.

Publishes an app to a Business Central development service endpoint.

Note: Wraps Publish-BcDevExtension from the businessdev.ALbuild module.

Underlying cmdlet: Publish-BcDevExtension

Example

YAMLCode
- task: PublishDevExtension@0 displayName: 'Publish dev extension' inputs: devServerUrl: 'https://bcserver' serverInstance: 'BC' appFile: '$(bcAppFile)' userName: '$(BcUser)' password: '$(BcPassword)' schemaUpdateMode: 'synchronize' dependencyPublishingOption: 'ignore'

Inputs

InputTypeRequiredDefaultDescription
devServerUrlstringNo—Dev server URL
serverInstancestringNo—Server instance
appFilestringNo$(bcAppFile)App (.app) file
userNamestringNo—User name
passwordstringNo—Password
schemaUpdateModepickListNosynchronizeSchema update mode Options: synchronize = synchronize, recreate = recreate, forcesync = forcesync.
dependencyPublishingOptionpickListNoignoreDependency publishing Options: ignore = ignore, default = default, strict = strict.

Option values

schemaUpdateMode

ValueMeaning
synchronizeApply non-breaking schema changes, keeping existing data. Default.
recreateDrop and recreate the app's tables - discards their data.
forcesyncForce the schema sync even for breaking changes (data loss possible).

dependencyPublishingOption

ValueMeaning
ignoreDo not publish dependencies - publish only this app. Default.
defaultPublish dependencies as needed alongside the app.
strictRequire all dependencies to be satisfied; fail otherwise.

Note: Publishes the app to a Business Central server's development endpoint (like VS Code F5) - a replaceable dev extension that can be re-published without a version bump. Targets devServerUrl + serverInstance with the given credentials. This task sets no output variables.


Publish On-Prem App

Reference name: PublishOnPremApp@0

Licensed task

Requires a valid ALbuild license for your Azure DevOps organization. The license check runs on entry to the task; without a license it fails with remediation guidance.

Publishes, synchronises and installs an app on an on-premises Business Central server instance.

Note: Wraps Publish-BcOnPremApp from the businessdev.ALbuild module.

Underlying cmdlet: Publish-BcOnPremApp

Example

YAMLCode
# Runs on the BC server host (self-hosted agent) against a locally installed BC server instance. - task: PublishOnPremApp@0 displayName: 'Publish app to on-prem server' inputs: serverInstance: 'BC' appFile: '$(bcAppFile)' scope: 'Global' syncMode: 'Add' install: true skipVerification: false

Inputs

InputTypeRequiredDefaultDescription
serverInstancestringNo—Server instance
appFilestringNo$(bcAppFile)Path to a single .app file, or a folder of built apps (a release artifact). A folder is searched recursively for *.app files (including runtime packages) and each is published, synced and installed/upgraded.
scopepickListNoGlobalGlobal / Tenant publish + sync + install via the management cmdlets. Dev publishes via the server's development endpoint (like VS Code) as a replaceable dev extension - re-publishable without a version bump, for test environments; requires a BC user + password (below). Options: Global = Global, Tenant = Tenant, Dev = Dev (development endpoint).
syncModepickListNoAddFor Global/Tenant: Sync-NAVApp mode. For Dev: mapped to the dev schema-update mode (Add/Development=synchronize, Clean=recreate, ForceSync=forcesync). Options: Add = Add, Clean = Clean, Development = Development, ForceSync = ForceSync.
tenantstringNodefaultTenant
skipVerificationbooleanNofalseSkip signature verification (Shown when: scope != Dev.)
installbooleanNotrueInstall after sync (Shown when: scope != Dev.)
usernamestringNo—BC user to authenticate to the development endpoint. (Shown when: scope = Dev.)
passwordstringNo—Password for the dev-endpoint BC user. Prefer mapping a secret pipeline variable to the ALBUILD_DEV_PASSWORD environment variable (secret variables do not reach task inputs). (Shown when: scope = Dev.)
devServerUrlstringNo—Development service base URL, e.g. https://bcserver:7049. Leave blank to auto-resolve https://localhost:<DeveloperServicesPort> or http://localhost:<DeveloperServicesPort> from the local server config (agent runs on the BC server). (Shown when: scope = Dev.)

Option values

scope

ValueMeaning
GlobalPublish + sync + install globally via the management cmdlets (all tenants). Default.
TenantPublish + sync + install for a single tenant (tenant).
DevPublish via the server's development endpoint (like VS Code) as a replaceable dev extension - re-publishable without a version bump, for test environments; requires a BC user + password.

syncMode

ValueMeaning
AddAdditive schema sync - only non-breaking changes; data kept. Default.
CleanRecreate the app's tables with a clean schema, discarding their data.
DevelopmentDevelopment sync (rapid application development); table data may be lost.
ForceSyncForce the schema sync through breaking changes (data loss possible).

Note: Publishes the app to a locally installed on-prem BC server instance (wraps Publish-BcOnPremApp) - the agent must run on the BC server host. With scope: Dev, devServerUrl sets the development service base URL (blank = auto-resolve localhost:<DeveloperServicesPort> from the local server config). This task sets no output variables.


Publish On-Prem Container App

Reference name: PublishOnPremContainerApp@0

Free of license

This task does not require an ALbuild license.

Publishes, synchronises and installs an app on a Business Central server instance running inside a Docker container.

Note: Wraps Publish-BcOnPremContainerApp from the businessdev.ALbuild module. Use this when the on-premises BC server runs in a Docker container on the deployment host; use 'Publish On-Prem App' for a directly installed server instance.

Example

YAMLCode
- task: PublishOnPremContainerApp@0 displayName: 'Publish app to on-prem container' inputs: containerName: '$(containerName)' appFile: '$(bcAppFile)' serverInstance: 'BC' scope: 'Global' syncMode: 'Add' install: true skipVerification: false

Inputs

InputTypeRequiredDefaultDescription
containerNamestringNo$(containerName)Name of the Business Central Docker container to deploy into. Falls back to the containerName pipeline variable.
appFilestringNo$(bcAppFile)Path to a single .app file, or a folder of built apps (a release artifact). A folder is searched recursively for *.app files (including runtime packages) and each is published, synced and installed/upgraded.
serverInstancestringNoBCBC server instance inside the container.
scopepickListNoGlobalGlobal / Tenant publish + sync + install via the management cmdlets. Dev publishes via the container's development endpoint (like VS Code) as a replaceable dev extension - re-publishable without a version bump, for test environments; requires a BC user + password (below). Options: Global = Global, Tenant = Tenant, Dev = Dev (development endpoint).
syncModepickListNoAddFor Global/Tenant: Sync-NAVApp mode. For Dev: mapped to the dev schema-update mode (Add/Development=synchronize, Clean=recreate, ForceSync=forcesync). Options: Add = Add, Clean = Clean, Development = Development, ForceSync = ForceSync.
tenantstringNodefaultTenant
skipVerificationbooleanNofalseSkip signature verification (Shown when: scope != Dev.)
installbooleanNotrueInstall after sync (Shown when: scope != Dev.)
usernamestringNo$(containerUsername)BC user to authenticate to the development endpoint. (Shown when: scope = Dev.)
passwordstringNo—Password for the dev-endpoint BC user. Prefer mapping a secret pipeline variable to the ALBUILD_DEV_PASSWORD environment variable (secret variables do not reach task inputs). (Shown when: scope = Dev.)

Option values

scope

ValueMeaning
GlobalPublish + sync + install globally via the management cmdlets (all tenants). Default.
TenantPublish + sync + install for a single tenant (tenant).
DevPublish via the container's development endpoint (like VS Code) as a replaceable dev extension - re-publishable without a version bump, for test environments; requires a BC user + password.

syncMode

ValueMeaning
AddAdditive schema sync - only non-breaking changes; data kept. Default.
CleanRecreate the app's tables with a clean schema, discarding their data.
DevelopmentDevelopment sync (rapid application development); table data may be lost.
ForceSyncForce the schema sync through breaking changes (data loss possible).

Note: Publishes the app into a BC container's on-prem server instance. With scope: Dev the app is published through the development endpoint and needs username + password. tenant (default default) selects the tenant for Tenant scope. This task sets no output variables.


Publish NuGet Package

Reference name: PublishPackage@0

Free of license

This task does not require an ALbuild license.

Pushes a NuGet package to a feed.

Note: Wraps Publish-BcPackage from the businessdev.ALbuild module.

Underlying cmdlet: Publish-BcPackage

Example

YAMLCode
- task: PublishPackage@0 displayName: 'Publish NuGet package' inputs: packagePath: '$(bcNuGetPackage)' feedUrl: 'https://pkgs.dev.azure.com/365businessdev/_packaging/ALbuild/nuget/v3/index.json' apiKey: '$(System.AccessToken)' failOnConflict: false # true = fail if the version already exists # view: 'Release' # optionally promote to a feed view after push

Inputs

InputTypeRequiredDefaultDescription
packagePathfilePathNo—Package (.nupkg) path
feedUrlstringNo—Feed URL (v3 index.json)
apiKeystringNo—API key / PAT
failOnConflictbooleanNofalseFail if version exists
viewstringNo—Azure DevOps Artifacts feed view to promote the published version to after pushing. Leave blank to publish only. Requires an Azure DevOps feed and a Packaging read/write PAT in 'API key / PAT'.

Note: Pushes a .nupkg to a NuGet feed. failOnConflict (default false) controls whether an already-published version fails the task or is skipped. view optionally promotes the package to a feed view (e.g. Release/Prerelease) after the push. This task sets no output variables.


Publish Per-Tenant Extension

Reference name: PublishPerTenantExtension@0

Licensed task

Requires a valid ALbuild license for your Azure DevOps organization. The license check runs on entry to the task; without a license it fails with remediation guidance.

Publishes an app as a per-tenant extension to a Business Central environment via the Automation API.

Note: Wraps New-BcApiAuthContext + Publish-BcPerTenantExtension from the businessdev.ALbuild module. Choose an authentication method: client secret (S2S), certificate (signed via an Azure Key Vault cert), or a legacy refresh token. Azure DevOps does not pass secret pipeline variables into task inputs, so map secrets via the task 'env:' block: ALBUILD_PTE_CLIENTSECRET, ALBUILD_PTE_REFRESHTOKEN, ALBUILD_PTE_KEYVAULTCLIENTSECRET.

Underlying cmdlet: Publish-BcPerTenantExtension

Example

YAMLCode
- task: PublishPerTenantExtension@0 displayName: 'Publish per-tenant extension' inputs: environment: 'Production' # BC environment (sandbox or production) tenantId: '$(BcTenantId)' authType: 'ClientSecret' clientId: '$(BcClientId)' clientSecret: '$(BcClientSecret)' schemaSyncMode: 'Add' appFile: '$(bcAppFile)' # schedule: 'Current' # when the environment deploys it (default: immediately) # includeTestApp: true # only for a dedicated test tenant - off by default

Inputs

InputTypeRequiredDefaultDescription
environmentstringYes—Business Central environment name (sandbox or production).
tenantIdstringNo—Azure AD tenant id of the environment. Blank = 'common'.
authTypepickListNoClientSecretAuthentication Options: ClientSecret = Client secret (S2S), Certificate = Certificate (Key Vault), RefreshToken = Refresh token (legacy).
clientIdstringNo—Entra app registration (client) id to authenticate as. Optional for refresh token (defaults to the BC PowerShell client id).
clientSecretstringNo—Prefer the env var ALBUILD_PTE_CLIENTSECRET (secret pipeline variables do not reach task inputs). (Shown when: authType = ClientSecret.)
refreshTokenstringNo—Prefer the env var ALBUILD_PTE_REFRESHTOKEN. (Shown when: authType = RefreshToken.)
keyVaultUrlstringNo—Key Vault URL (Shown when: authType = Certificate.)
certificateNamestringNo—Certificate name (Shown when: authType = Certificate.)
keyVaultTenantIdstringNo—Tenant of the service principal used to access Key Vault. Blank = the environment tenant id. (Shown when: authType = Certificate.)
keyVaultClientIdstringNo—Service principal that can read the certificate and sign with it (needs certificates/get + keys/sign). (Shown when: authType = Certificate.)
keyVaultClientSecretstringNo—Prefer the env var ALBUILD_PTE_KEYVAULTCLIENTSECRET. (Shown when: authType = Certificate.)
scopestringNo—OAuth scope. Blank = https://api.businesscentral.dynamics.com/.default.
companyIdstringNo—Optional. Blank = the first company in the environment.
schemaSyncModepickListNoAddSchema sync mode Options: Add = Add, ForceSync = ForceSync.
appFilestringNo—A .app file or a folder of them. Blank = the build artifact staging directory. Test apps and runtime packages are skipped automatically.
schedulepickListNoCurrentThe automation API never installs synchronously - it queues the deployment. This decides what it is queued for: 'Current' deploys against the environment's version now; the others hold the app back until that upgrade runs. Options: Current = Against the current version (immediately), NextMinor = With the next minor version upgrade, NextMajor = With the next major version upgrade.
includeTestAppbooleanNofalseOff by default: a test app belongs in a build container, not in a customer environment, and it pulls in the Microsoft test framework. Turn on only for a dedicated test tenant.
noWaitbooleanNofalseThe deployment runs asynchronously in the environment. By default the task polls extensionDeploymentStatus and fails if an app does not install. With this on, the task reports only what was QUEUED - a failed installation will not fail the release.
timeoutMinutesstringNo15How long to wait for the environment to finish deploying before failing the task.

Option values

authType

ValueMeaning
ClientSecretAuthenticate with an Entra ID app registration client id + secret. Default.
CertificateAuthenticate with a certificate from Azure Key Vault (keyVaultUrl + certificateName + key-vault credentials).
RefreshTokenAuthenticate with a previously obtained OAuth refresh token (refreshToken).

schemaSyncMode

ValueMeaning
AddAdditive schema sync - only non-breaking changes; data is kept. Default.
ForceSyncForce the schema sync through breaking changes (data loss possible).

schedule

ValueMeaning
CurrentDeploy against the environment's current version, i.e. as soon as the environment picks the job up. Default.
NextMinorHold the app back until the environment's next minor version upgrade.
NextMajorHold the app back until the environment's next major version upgrade.

Note: Publishes the app to a Business Central online environment as a per-tenant extension via the Automation API. environment is required. Credentials depend on authType; scope overrides the OAuth scope (blank = https://api.businesscentral.dynamics.com/.default). This task sets no output variables.

Test apps and runtime packages are skipped. appFile defaults to the whole artifact staging folder and is searched recursively, so a build that also produces a test app would otherwise ship it into the customer environment. An app counts as a test app when its manifest carries Target="Test" or it depends on a Microsoft test/assert library — the same rule the AppSource submission uses. Set includeTestApp only for a dedicated test tenant.

Deployment is asynchronous. The Automation API never installs synchronously: uploading the file and posting the upload action only queues the work, which is what schedule selects. The task therefore polls extensionDeploymentStatus and fails if an app does not install, instead of reporting success for something that may fail minutes later inside Business Central. Use noWait to skip that check (the release then cannot detect a failed installation), and timeoutMinutes to bound the wait.


Submit to Marketplace

Reference name: SubmitMarketplace@0

Licensed task

Requires a valid ALbuild license for your Azure DevOps organization. The license check runs on entry to the task; without a license it fails with remediation guidance.

Submits an app to Microsoft Marketplace (AppSource) via Partner Center and optionally promotes it.

Note: Wraps Submit-BcMarketplaceApp from the businessdev.ALbuild module.

Underlying cmdlet: Submit-BcMarketplaceApp

Example

YAMLCode
- task: SubmitMarketplace@0 displayName: 'Submit to AppSource marketplace' inputs: appPath: '$(Build.ArtifactStagingDirectory)' # folder or .app(s); test apps excluded # productName: '' # empty = the main app's manifest name; set to override the offer name # libraryAppPath: '' # library app(s) arriving as a separate artifact (one per line / ';') tenantId: '$(PartnerTenantId)' clientId: '$(PartnerClientId)' clientSecret: '$(PartnerClientSecret)' publisherId: '$(PartnerCenterPublisherId)' autoPromote: false # true = go live automatically after validation timeoutMinutes: '40'

Inputs

InputTypeRequiredDefaultDescription
appPathfilePathNo$(Build.ArtifactStagingDirectory)A folder is scanned for *.app; the main app + its library apps are selected automatically and TEST apps are excluded (never published). No need to name the version-stamped file.
productNamestringNo—Leave empty to use the main app's manifest name. Set it only to override (e.g. when the AppSource offer name differs from the app name).
libraryAppPathstringNo—Optional. Folder(s) or .app file(s) whose apps are submitted as LIBRARY apps, for offers whose main app and library are built by different pipelines and arrive as separate artifacts (e.g. Address Validation + its Extension License library). One path per line or separated by ';'. Test apps are excluded. Only used with 'App path'.
appFilestringNo—Deprecated: an explicit single .app. Ignored when 'App path' is set.
tenantIdstringNo—Partner Center tenant id
clientIdstringNo—Partner Center client id
clientSecretstringNo—Partner Center client secret
publisherIdstringNo—Numeric Seller ID (Partner Center > Settings > Account settings > Identifiers). Required as the x-ms-publisherId header by the ingestion API.
autoPromotebooleanNofalseAuto-promote to live after validation
timeoutMinutesstringNo40Validation timeout (minutes)

Option values

autoPromote

ValueMeaning
falseSubmit and validate only; a human promotes the offer to live in Partner Center. Default.
trueAutomatically promote the offer to live once validation succeeds.

Note: Submits the app to AppSource via the Partner Center API. appPath (folder or .app files; test apps excluded) is the modern input - the singular appFile input is deprecated and ignored when appPath is set. productName defaults to the main app's manifest name; set it only when the AppSource offer name differs. libraryAppPath supplies library apps that arrive as a separate artifact. timeoutMinutes (default 40) bounds the validation wait. This task sets no output variables.


Last modified on