Apps module
Module: businessdev.ALbuild.Apps • Tier: Free • Cmdlets: 36
The Apps module covers everything you do with an AL app: compile (container or container-less), publish/sync/install/uninstall/unpublish, sign, run tests, validate, manage app versions, install 365 business development apps, and create/sync/validate XLIFF translations.
Cmdlets in this module
| Cmdlet | Description |
|---|---|
Convert-BcCodeCoverage | Converts raw Business Central code coverage (.dat CSV from Invoke-BcContainerTest -CodeCoverage) into ALbuild JSON, Cobertura XML and/or a Markdown summary. |
Get-BcCodeCoverageDelta | Computes "patch coverage" -- how well the lines you changed (vs a git baseline) are covered by tests. |
Get-BcCodeCoverageSummary | Returns the ALbuild code-coverage summary (and per-object lines) without writing report files. |
Get-BcContainerAppDiagnostic | Explains why publishing, installing or synchronising an app in a container fails. |
Get-BcTestQuality | Heuristically assesses the QUALITY of AL tests (assertions, arrange/act/assert) -- not their coverage. |
Get-BcTranslationUnit | Lists the translation units of an AL XLIFF file as structured objects (the read surface behind albuild translation list). |
Get-BcVersionComponents | Splits a Business Central version into its components plus a 3-part SemVer form. |
Import-BcTranslationMemory | Builds (and caches) a deterministic translation-memory index from prioritised reference XLIFFs. |
Install-Bc365App | Installs one or more 365 business development apps into a Business Central container. |
Install-BcAlTool | Ensures the cross-platform AL Tool CLI is installed (as a .NET global tool) and on PATH. |
Install-BcAzureSignTool | |
Install-BcContainerApp | Installs a published AL app in a Business Central container. |
Install-BcContainerDependency | Publishes and installs an AL project's resolved dependency apps into a container, in dependency order. |
Invoke-BcAppSigning | Signs one or more AL .app files using AzureSignTool and an Azure Key Vault certificate. |
Invoke-BcCompiler | Compiles an AL project into an .app package. |
Invoke-BcContainerTest | Runs AL tests in a Business Central container and collects/parses the results. |
Invoke-BcTranslationSync | Syncs a project's target-language XLFs from its generated .g.xlf and fills them from the translation memory (the orchestration behind albuild translation sync). |
Invoke-BcValidation | Validates an AL app by compiling it against one or more Business Central versions (licensed). |
Merge-BcCodeCoverage | Merges raw Business Central coverage (.dat) from several runs into one dataset (union, max hits per line). |
Merge-BcTranslationMemory | Fills untranslated units in a target XLIFF from a translation-memory index (deterministic, exact). |
New-BcTranslationFile | Creates a new AL XLIFF target-language file from a generated base file. |
Publish-BcAppToDevEndpoint | POSTs an .app to a Business Central development service endpoint (the VS Code 'Publish' mechanism). |
Publish-BcContainerApp | Publishes an AL app (.app) to a Business Central container, optionally syncing/installing. |
Publish-BcTestinyResult | Publishes a JUnit test result file to Testiny via the Testiny importer CLI. |
Resolve-BcAnalyzerConfig | Determines the code analyzers and ruleset for a compile, layering the sources by precedence. |
Set-BcAppVersion | Sets the version of one or more Business Central apps by updating their app.json. |
Set-BcTranslationUnit | Sets the target text (and state) of a single translation unit in an AL XLIFF file. |
Start-BcContainerAppDataUpgrade | Runs the data upgrade for a published AL app version in a Business Central container. |
Sync-BcContainerApp | Synchronises a published AL app's schema in a Business Central container. |
Sync-BcTranslation | Synchronises an AL XLIFF target file from a generated base file (.g.xlf). |
Test-BcAppBreakingChange | Checks an AL app for breaking changes against the baseline declared in its AppSourceCop.json. |
Test-BcCodeCoverageThreshold | Gates a build on code-coverage thresholds -- overall and (optionally) per object. |
Test-BcTranslation | Checks AL XLIFF translation files for missing and "needs-work" translations. |
Uninstall-BcContainerApp | Uninstalls an AL app in a Business Central container. |
Unpublish-BcContainerApp | Unpublishes an AL app from a Business Central container. |
Update-BcAppManifest | Prepares an AL app manifest (app.json) for a target BC version: version features + preprocessor symbols. |
Convert-BcCodeCoverage
Converts raw Business Central code coverage (.dat CSV from Invoke-BcContainerTest -CodeCoverage) into ALbuild JSON, Cobertura XML and/or a Markdown summary.
The raw rows are VariableText CSV: ObjectType, ObjectID, LineNo, CoverageStatus, NoOfHits. This aggregates them per object (max hit count per line - union semantics across chunks), attaches each object to its source file via the workspace AL object map, computes line coverage, and emits the requested formats. With -WorkspaceRoot the result is restricted to objects whose source is in the workspace (your app code); without it, every tracked object is included.
Syntax
Code
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
-CoveragePath | String | Yes | A folder of raw *.dat files (or a single .dat file) produced by the coverage-enabled test run. |
-WorkspaceRoot | String | No | AL source root. Restricts/maps coverage to your app objects and sets file paths. |
-Format | String[] | No | One or more of ALbuildJson, Cobertura, Markdown, Html. 'Html' writes a self-contained report to '<OutputFolder>/html/index.html' - the directory the Azure DevOps coverage tab renders. The '##vso[codecoverage.publish]' logging command uploads that directory but does NOT generate it, which is why the tab stayed empty without this format. Allowed values: ALbuildJson, Cobertura, Markdown, Html. Default: @('ALbuildJson'). |
-DenominatorMode | String | No | Allowed values: Auto, Source, CoveredOnly. Default: 'Auto'. |
-OutputFolder | String | No | Where to write the output files. Default: the current location. Default: (Get-Location).Path. |
-TestQuality | Object | No | The result of Get-BcTestQuality, included in the Markdown and HTML reports. Coverage measures which lines RAN; it cannot tell whether a wrong result would have been caught, because a [Test] method that asserts nothing still covers every line it touches. Reporting the percentage on its own therefore overstates what the suite proves, so the assertion figures belong next to it. Omit it and, when -WorkspaceRoot is known, it is computed automatically - the report carries the caveat by default rather than only when someone remembers to ask. Pass a value to avoid scanning the workspace twice when the caller already has it. |
-ExcludeNeverExecutedObjects | switch | No | Leave objects that no test touched out of the calculation, restoring the behaviour of module 2.23 and earlier. Business Central reports lines only for objects LOADED during the run, so by default such an object produced no rows, never entered the result, and could not lower the percentage - the figure answered "how much of the code the tests loaded is covered" rather than "how much of the app is covered". They are now counted with zero covered lines. Use this only where the workspace holds product apps that are deliberately not published into the test container; there the objects genuinely cannot be exercised and counting them would be unfair. Objects without executable lines are never added either way. |
-ExcludeProjects | String[] | No | Project folder leaf names to leave out of the measurement entirely - the same names as the repo-root albuild.json 'excludeProjects' and Get-BcProjectBuildOrder. Omit it and the workspace-root albuild.json is read, so a repository that already excludes an app from the build excludes it from coverage too without any pipeline change. Pass a list to add the pipeline's own parameter on top. |
Output
PSCustomObject: Summary, Objects, TestQuality, Outputs (the written file paths).
Get-BcCodeCoverageDelta
Computes "patch coverage" -- how well the lines you changed (vs a git baseline) are covered by tests.
Overall coverage rewards a big tested codebase even when new code is untested; patch coverage answers the question that matters on a pull request: are the lines I just added/changed actually exercised? This diffs the workspace against a git baseline ref, keeps the added/modified .al lines that BC would treat as executable (Get-BcAlExecutableLines), and checks each against the coverage data. Files/objects with no executable changes are ignored.
Syntax
Code
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
-BaselineRef | String | Yes | Git ref to diff against (e.g. 'origin/main', a merge-base SHA, 'HEAD~1'). |
-HeadRef | String | No | Optional second ref; default is the working tree (uncommitted changes included). |
-WorkspaceRoot | String | Yes | AL source root (inside a git repo). Coverage is mapped to objects here and the diff is scoped to it. |
-CoveragePath | String | Yes | Raw *.dat folder/file from a coverage-enabled run (converted with the honest denominator). |
-SummaryPath | String | Yes | Alternatively, an existing coverage-summary.json (must have been produced with -WorkspaceRoot so it carries per-line data). |
Output
PSCustomObject: Summary { changedExecutableLines, coveredChangedLines, deltaCoverage, fileCount }, Files[].
Get-BcCodeCoverageSummary
Returns the ALbuild code-coverage summary (and per-object lines) without writing report files.
A read-only convenience over the coverage data: point it at raw *.dat (with -WorkspaceRoot for the honest source-based denominator) or at an existing coverage-summary.json. Returns the same { lineCoverage, coveredLines, totalExecutableLines, objectCount, denominatorMode } summary plus the per-object breakdown, so agents and scripts can inspect coverage without re-emitting Cobertura/Markdown.
Syntax
Code
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
-CoveragePath | String | Yes | Folder of raw *.dat files (or a single .dat file) from a coverage-enabled test run. |
-WorkspaceRoot | String | No | AL source root -- restricts/maps coverage to your app objects and enables the honest denominator. |
-DenominatorMode | String | No | Allowed values: Auto, Source, CoveredOnly. Default: 'Auto'. |
-SummaryPath | String | Yes | Alternatively, an existing coverage-summary.json (or its folder) to read back. |
Output
PSCustomObject: Summary, Objects.
Get-BcContainerAppDiagnostic
Explains why publishing, installing or synchronising an app in a container fails.
A failed publish reports a symptom ("an earlier version was already installed", "the extension is not synchronized") but never the state that produced it. From outside the container that state is invisible, so the caller is left guessing which of several very different situations it is in.
This collects the evidence in one pass and turns it into named blockers:
- every PUBLISHED version of the app (Get-NAVAppInfo on the server instance), and
- per version, the TENANT's view (Get-NAVAppInfo -TenantSpecificProperties): IsInstalled, SyncState, NeedsUpgrade and ExtensionDataVersion - the version the tenant's DATA is at, which is what actually decides whether an install or a data upgrade is required, and
- the tail of the Business Central server event log, which is where schema-sync failures record the offending table/field.
Every blocker carries a stable code (DATA_UPGRADE_REQUIRED, VERSION_ALREADY_PUBLISHED, NOT_SYNCHRONIZED, SCHEMA_CONFLICT) and the command that clears it, so a caller can branch on the cause instead of pattern-matching a PowerShell message that changes between BC versions.
Read-only: it publishes, installs, syncs and removes nothing.
Syntax
Code
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
-Name | String | Yes | Container name. |
-AppName | String | No | Limit the diagnosis to one app. Omit to diagnose every non-Microsoft app in the container. |
-ServerInstance | String | No | BC server instance inside the container. Default 'BC'. Default: 'BC'. |
-Tenant | String | No | Tenant to read tenant-specific state from. Default 'default'. Default: 'default'. |
-EventLogEntries | Int32 | No | How many recent server event-log entries to return. Default 20; 0 skips the event log. Default: 20. |
-DockerExecutable | String | No | The Docker executable to use (default 'docker'). Default: 'docker'. |
Output
PSCustomObject with Container, Apps, SyncErrors, EventLog and Blockers.
Examples
Example 1
Code
Get-BcTestQuality
Heuristically assesses the QUALITY of AL tests (assertions, arrange/act/assert) -- not their coverage.
Code coverage is not test quality: a [Test] method can execute every line of the code under test and still assert nothing, so it would show as "covered" while catching no regression. This scans the AL [Test] methods in a workspace and flags quality smells per test:
- NoAssertions - the body contains no assertion (no Assert/LibraryAssert call, no TestField, no asserterror, no guard Error()), so it cannot fail on a wrong result.
- Empty - the body has no executable statements.
- NoAct - the body asserts but never invokes anything outside the assertion library (a test that only checks constants).
It returns a per-test breakdown and a suite summary with a 0-100 quality score (share of tests that actually assert, penalised for empty tests). The heuristics are intentionally conservative and documented; treat the score as a smell detector, not a grade.
Syntax
Code
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
-WorkspaceRoot | String | Yes | AL source root to scan for [Test] methods (skips tooling folders, like Get-BcAlObjectMap). |
-Path | String | Yes | A single .al file to assess instead of a whole workspace. |
Output
PSCustomObject: Summary, Tests[].
Get-BcTranslationUnit
Lists the translation units of an AL XLIFF file as structured objects (the read surface behind albuild translation list).
Projects each trans-unit to { id, source, developerNote, context (Xliff-Generator note), currentTarget, state, tmOrigin } using the shared Get-BcXliffUnit reader. This is the stable input a consumer uses to translate the remaining open strings. -OnlyMissing returns just the units that still need a translation (empty target or a needs-translation/-adaptation state); -State filters by an explicit target state.
Syntax
Code
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
-Path | String | Yes | The XLIFF file to read. |
-OnlyMissing | switch | No | Return only units that still need a translation. |
-State | String | No | Return only units whose target state equals this value. |
Output
PSCustomObject per unit: { id, source, developerNote, context, currentTarget, state, tmOrigin }.
Get-BcVersionComponents
Splits a Business Central version into its components plus a 3-part SemVer form.
Pure helper (no I/O, unit-testable) used by the Stamp Build Version task to expose the version as individual pipeline variables. Missing lower components are normalised to 0 (a 2-part '1.2' yields Build 0, Revision 0). The 'Short' value (Major.Minor.Build) is a valid 3-part SemVer for feeds that reject a 4-part version - e.g. Azure Universal Packages, which require X.Y.Z.
Syntax
Code
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
-Version | Version | Yes | The version to split (e.g. '1.2.588.26440'). Accepts anything [version] can parse. |
Output
PSCustomObject: Major, Minor, Build, Revision (int) and Short (string 'Major.Minor.Build').
Import-BcTranslationMemory
Builds (and caches) a deterministic translation-memory index from prioritised reference XLIFFs.
Reads a prioritised, ordered list of reference XLIFF files and builds an in-memory index of known source->target translations, for Merge-BcTranslationMemory to apply to new units. Two keys per unit: a context-sensitive "GenNote|source" (e.g. "Table Vendor - Field No.|No.") and a plain "source" fallback. On a key collision the higher-priority reference wins (equal priority: the earlier reference wins), so an app's own / sibling-app terms override the Microsoft BC base.
The index is cached under LOCALAPPDATA/ALbuild/tm (or ~/.local/share/ALbuild/tm) keyed by the reference files' paths + last-write-times + sizes, so the large BC base XLF (>100k units) is only re-parsed when a reference actually changed. Deterministic and offline: no network, no LLM.
Syntax
Code
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
-Reference | Object[] | Yes | Ordered reference descriptors (highest priority first is NOT required - Priority decides). Each: [pscustomobject]@{ Files = <string[] paths or globs>; Origin = '<self|app |
-ContextAware | Boolean | No | Also index the context-sensitive "GenNote|source" key. Default: $true. Default: $true. |
-CacheDir | String | No | Override the cache directory (tests pass a temp dir). |
-NoCache | switch | No | Build fresh and do not read/write the cache. |
Output
PSCustomObject { ContextAware, Count, Entries (hashtable key -> { Target, Origin, Priority }) }.
Install-Bc365App
Installs one or more 365 business development apps into a Business Central container.
Installs 365 business development dependency apps (by app id) into a build container using the 365 business development app installer. The installer script is downloaded inside the container and run with the requested app ids; it resolves and installs each app for the container's BC version. Requires Windows + a running Docker engine. Native replacement for the V1 Install365App task.
Syntax
Code
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
-Name | String | Yes | Container name. |
-AppId | String[] | Yes | One or more 365 app ids to install. |
-InstallerUrl | String | No | URL of the installer script. Defaults to the ALBUILD_365APP_INSTALLER_URL environment variable, or the public 365 business development installer. |
-DockerExecutable | String | No | The Docker executable to use. Default 'docker'. Default: 'docker'. |
Output
PSCustomObject: Container, AppId, InstallerUrl.
Examples
Example 1
Code
Install-BcAlTool
Ensures the cross-platform AL Tool CLI is installed (as a .NET global tool) and on PATH.
Installs 'Microsoft.Dynamics.BusinessCentral.Development.Tools' as a dotnet tool so the 'al' command (which wraps the AL compiler, alc) is available to Invoke-BcCompiler's AlTool engine on a build agent. Requires the .NET SDK ('dotnet').
VERSION MATTERS. The AL Tool's MAJOR version is the AL runtime it can compile (17.x -> runtime 17 = BC28, 18.x -> runtime 18 = BC29); a compiler older than the app's declared runtime fails with AL1043 ("The runtime version 'x' is not supported by the AL compiler"). Pass -BcVersion (or -RuntimeVersion) and the required version is derived and resolved for you - including the PRERELEASE compiler that is the only one available while a BC major is still in preview (NextMajor). See Resolve-BcAlToolVersion.
Given a required runtime, the tool is installed into a PER-VERSION folder under the ALbuild base cache (--tool-path) instead of the machine-wide global tool. Build agents run several stages (Current / NextMinor / NextMajor) against different BC majors, often concurrently, and a single global tool cannot serve them: one stage would silently re-point the compiler of another - and a shipping product would get built by a beta compiler. The per-version folder is reused across builds, so this costs one download per runtime major per agent.
Idempotent: an AL Tool that already satisfies the requirement is left alone (unless -Force). Without any version requirement the historical behaviour is unchanged - a global install that no-ops whenever some 'al' is already resolvable - and after installing, the global-tools folder is added to PATH for the current session.
Syntax
Code
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
-PackageId | String | No | The dotnet tool package id. Default 'Microsoft.Dynamics.BusinessCentral.Development.Tools'. Default: 'Microsoft.Dynamics.BusinessCentral.Development.Tools'. |
-Version | String | No | Optional specific version to pin; otherwise the latest (matching the required runtime, when one is given) is installed. |
-BcVersion | String | No | The Business Central version being compiled against (e.g. '29.0.53586.0' or '29'). The required AL runtime major is derived from it as (BC major - 11), matching Update-BcAppManifest. |
-RuntimeVersion | String | No | The AL runtime to support (e.g. '18.0'), when it is known directly instead of via -BcVersion. Takes precedence over -BcVersion. |
-Prerelease | String | No | How to treat prerelease AL Tool versions when resolving one for the required runtime: Auto (default) prefers a stable release and falls back to a prerelease only when the required major has none (the NextMajor case); Always takes the newest even if prerelease; Never refuses to use one. Allowed values: Auto, Always, Never. Default: 'Auto'. |
-ToolPath | String | No | Install into this folder (dotnet tool --tool-path) instead of the global tool store. Set automatically to a per-version folder when a runtime requirement is given. |
-Global | switch | No | Force a machine-wide global install even when a runtime requirement is given. Affects every other build on the agent - prefer the default per-version isolation. |
-Force | switch | No | Reinstall/update even when the AL Tool is already available. |
-Source | String | No | NuGet package source to install the AL Tool from, passed as --add-source. Defaults to nuget.org so the install works even when the agent has no NuGet sources configured (a fresh agent often has none, which fails with "No NuGet sources are defined or enabled"). Set to '' to rely solely on the agent's nuget.config, or to an internal feed URL for offline agents. Default: 'https://api.nuget.org/v3/index.json'. |
-DotNetExecutable | String | No | The .NET CLI executable. Default 'dotnet'. Default: 'dotnet'. |
Output
PSCustomObject: Installed (bool), Path, Version, RequiredRuntimeMajor, Prerelease, ToolPath.
Examples
Example 1
Code
Example 2
Code
Install-BcAzureSignTool
Syntax
Code
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
-PackageId | String | No | Default: 'AzureSignTool'. |
-Version | String | No | |
-Force | switch | No | |
-Source | String | No | Default: 'https://api.nuget.org/v3/index.json'. |
-DotNetExecutable | String | No | Default: 'dotnet'. |
Install-BcContainerApp
Installs a published AL app in a Business Central container.
Syntax
Code
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
-Name | String | Yes | Container name. |
-AppName | String | Yes | The app name. |
-AppVersion | String | No | Optional app version. |
-ServerInstance | String | No | BC server instance. Default 'BC'. Default: 'BC'. |
-Tenant | String | No | Tenant. Default 'default'. Default: 'default'. |
-DockerExecutable | String | No | The Docker executable to use (default 'docker'). Default: 'docker'. |
Install-BcContainerDependency
Publishes and installs an AL project's resolved dependency apps into a container, in dependency order.
The runtime counterpart to compile-time symbol resolution: an app can only be installed and tested once the apps it depends on are installed. This stages the .app packages found in -PackageFolder into the container's shared folder, then - inside the container - reads each package with Get-NAVAppInfo (which handles both regular and encrypted runtime packages, unlike a host-side ZIP reader), orders them so each app is published after the apps it depends on, and publishes/synchronises/installs each. Apps already installed (e.g. Microsoft first-party / the toolkit) are skipped; dependencies outside the set are assumed already present. Requires Windows + Docker.
Syntax
Code
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
-Name | String | Yes | Container name. |
-PackageFolder | String[] | No | One or more folders of dependency .app files to install (searched recursively). Use this only when there is no resolver lock file: a developer's local .alpackages accumulates many historical versions/variants - prefer -PackageFile with the resolver-chosen set. |
-PackageFile | String[] | No | Explicit dependency .app file paths to install (e.g. the files named in the resolver lock file). Preferred over -PackageFolder so only the resolved versions are installed. At least one of -PackageFolder/-PackageFile is required. |
-ServerInstance | String | No | BC server instance inside the container. Default 'BC'. Default: 'BC'. |
-SkipVerification | Boolean | No | Publish without signature verification. Default $true. Default: $true. |
-OperationTimeoutSeconds | Int32 | No | Maximum seconds to allow a single app's publish/sync/install before abandoning it and recording a failure. Prevents a hung operation (e.g. a deadlocked schema sync) from freezing the build. Default 600. Default: 600. |
-DockerExecutable | String | No | The Docker executable to use (default 'docker'). Default: 'docker'. |
Output
System.String lines describing what was installed/skipped.
Invoke-BcAppSigning
Signs one or more AL .app files using AzureSignTool and an Azure Key Vault certificate.
Signs the given .app file(s) with AzureSignTool, authenticating to Key Vault with a service principal. When AzureSignTool is not on PATH it is auto-installed as a .NET global tool (as ALbuild V1 did); pass -SkipAutoInstall to require a pre-installed tool, or -SignToolPath to point at a specific executable.
Syntax
Code
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
-Path | String[] | Yes | One or more .app files (or folders/wildcards) to sign. |
-KeyVaultUrl | String | Yes | The Key Vault URL. |
-TenantId | String | Yes | Azure AD tenant id. |
-ClientId | String | Yes | Service principal application (client) id. |
-ClientSecret | String | Yes | Service principal client secret. |
-CertificateName | String | Yes | The certificate name in Key Vault. |
-TimestampUrl | String | No | RFC3161 timestamp server. Default DigiCert. Default: 'http://timestamp.digicert.com'. |
-SignToolPath | String | No | The AzureSignTool executable. Default 'azuresigntool'. Default: 'azuresigntool'. |
-SkipAutoInstall | switch | No | Do not auto-install AzureSignTool when it is missing; require it to be present already. |
Examples
Example 1
Code
Invoke-BcCompiler
Compiles an AL project into an .app package.
Compiles an AL project using either the cross-platform AL compiler (default) or a container's compiler: -Engine AlTool (default) invokes the AL compiler executable (alc) on the host. Symbols are taken from the package cache (.alpackages), which Resolve-BcDependencies populates; the AL compiler does not download dependencies itself. -Engine Container runs the compiler inside a Business Central container via the exec seam. The output file name follows the BC convention "<publisher><name><version>.app", derived from app.json.
Syntax
Code
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
-ProjectFolder | String | Yes | The AL project folder (contains app.json). |
-OutputFolder | String | No | Where to write the compiled .app. Default: <ProjectFolder>/output. |
-Engine | String | No | AlTool (default) or Container. Allowed values: AlTool, Container. Default: 'AlTool'. |
-CompilerPath | String | No | (AlTool) The AL compiler executable. Default 'alc'. Default: 'alc'. |
-ContainerName | String | No | (Container) The container to compile in. |
-ContainerCompilerPath | String | No | (Container) The AL compiler path inside the container. Default 'alc.exe'. Default: 'alc.exe'. |
-PackageCachePath | String[] | No | Symbol package folder(s). Default: <ProjectFolder>/.alpackages. |
-Analyzer | String[] | No | Analyzer assembly paths (CodeCop/AppSourceCop/etc.). |
-RuleSet | String | No | Ruleset file. |
-AssemblyProbingPath | String[] | No | Additional .NET assembly probing paths. |
-LogLevel | String | No | Compiler log level. Allowed values: ``, Error, Warning, Verbose, Normal. |
-BuildBy | String | No | Stamped into the compiled app's manifest as the tool that built it (alc /BuildBy). Default 'ALbuild'. Pass '' to omit. Default: 'ALbuild'. |
-BuildUrl | String | No | URL of the build that produced the app, stamped into the manifest (alc /BuildUrl). |
-SourceRepositoryUrl | String | No | Source repository URL stamped into the manifest (alc /SourceRepositoryUrl). |
-SourceCommit | String | No | Source commit hash stamped into the manifest (alc /SourceCommit). |
-DockerExecutable | String | No | (Container) The Docker executable to use (default 'docker'). Default: 'docker'. |
-NoDiagnosticOutput | switch | No | Do not print the compiler's diagnostic lines (warnings/errors/info) in the logged output; the caller renders them from the returned Diagnostics instead (e.g. as DevOps annotations). Context lines are still logged. Without this switch the full compiler output is logged. |
Output
PSCustomObject with Success, OutputFile, ExitCode, Output.
Examples
Example 1
Code
Invoke-BcContainerTest
Runs AL tests in a Business Central container and collects/parses the results.
ALbuild's built-in AL test runner. It drives the AL Test Tool page inside the container (no BcContainerHelper) and produces a JUnit/XUnit result file that is copied to the host, parsed into a summary, and optionally used to fail the build.
Test apps are taken from -ProjectFolder (every AL test app found is run) or from an explicit -ExtensionId list. For folder-based discovery the optional ALbuild 'pipeline.config' beside each app.json is honoured: its 'alTestRunnerId' selects the test-runner codeunit. The runner codeunit otherwise defaults to 130450 (test isolation) or, with -DisableIsolation, 130451 (isolation disabled); an explicit -TestRunnerCodeunitId overrides everything.
For advanced scenarios a custom in-container invocation can still be supplied via -TestExecution (a script block that writes the result file to $ResultPathInContainer); when given, ALbuild only collects and parses the result and does not use the built-in runner.
Syntax
Code
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
-Name | String | Yes | Container name. |
-ProjectFolder | String | No | Folder searched recursively for AL test apps to run. Mutually exclusive with -ExtensionId. |
-ExtensionId | String[] | Yes | One or more app ids to run tests for, instead of discovering them from a project folder. |
-TestExecution | ScriptBlock | Yes | Optional custom in-container script block (advanced). When supplied, the built-in runner is not used; the block must write the result file to $ResultPathInContainer. |
-Credential | PSCredential | No | Credentials of a SUPER user (NavUserPassword). If omitted, the containerUsername / containerPassword environment variables are used when present. |
-TestSuite | String | No | Test suite name. Default 'DEFAULT'. Default: 'DEFAULT'. |
-TestRunnerCodeunitId | Int32 | No | Explicit test-runner codeunit id, overriding pipeline.config and the isolation default. |
-DisableIsolation | switch | No | Use the isolation-disabled test runner (130451) as the default instead of 130450. |
-Tenant | String | No | Tenant to use. Default 'default'. Default: 'default'. |
-CompanyName | String | No | Company to run tests in. Default: the server's default company. |
-Culture | String | No | Culture for the test run. Default 'en-US' (Microsoft tests target en-US). Default: 'en-US'. |
-Auth | String | No | Client services credential type: NavUserPassword (default), Windows or AAD. Allowed values: NavUserPassword, Windows, AAD. Default: 'NavUserPassword'. |
-AzureDevOps | switch | No | Emit Azure DevOps warning log issues for failing tests. |
-ResultPath | String | No | Host path to write the JUnit result file to. Default: ./TestResults.xml. Default: (Join-Path (Get-Location) 'TestResults.xml'). |
-ResultPathInContainer | String | No | Container path the run writes results to. Default: C:\bcptest\TestResults.xml. Default: 'C:\run\my\TestResults.xml'. |
-FailOnTestFailure | switch | No | Throw if any test failed. |
-CodeCoverageTrackingType | String | No | Allowed values: Disabled, PerRun, PerCodeunit, PerTest. Default: 'Disabled'. |
-CodeCoverageMap | String | No | Allowed values: Disabled, PerCodeunit, PerTest. Default: 'Disabled'. |
-CodeCoveragePath | String | No | |
-DockerExecutable | String | No | The Docker executable to use (default 'docker'). Default: 'docker'. |
Output
PSCustomObject with Passed, Failed, Skipped, Total, Failures, Success, ResultPath.
Examples
Example 1
Code
Example 2
Code
Invoke-BcTranslationSync
Syncs a project's target-language XLFs from its generated .g.xlf and fills them from the translation memory (the orchestration behind albuild translation sync).
For each target language: locates the generated base file (<App>.g.xlf, from the AL compiler's TranslationFile feature) and the target XLF under the project's translations folder, runs Sync-BcTranslation (structural merge), then - unless -NoMemory - builds a prioritised translation memory (Import-BcTranslationMemory) from the configured sources and applies it (Merge-BcTranslationMemory). Deterministic and offline: only exact TM matches are filled; the rest stay needs-translation for a downstream consumer.
Sources (priority: self > sibling apps > BC base):
- self: the app's own *.<lang>.xlf (highest)
- xlf: a path/glob to other apps' XLFs (from albuild.json translation.memory.sources)
- bc-base: Microsoft Base/System Application <lang> XLFs, resolved from the BC artifact cache of the project's target application version (best-effort: skipped with a warning when not present in the cache - never triggers a download).
With -Check nothing is written: each language is synced into a temp copy and compared to the committed XLF; a difference is reported as drift (for the CI 'check' pipeline mode).
Syntax
Code
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
-ProjectFolder | String | Yes | The AL app folder (contains app.json and a Translations subfolder). |
-WorkspaceRoot | String | No | The repo root holding albuild.json (for translation config + memory sources). Defaults to ProjectFolder. |
-Language | String[] | No | Target language(s) (e.g. de-DE). Default: albuild.json translation.targetLanguages, else the languages of the existing *.??-??.xlf files. |
-BaseFile | String | No | Override the generated base .g.xlf (default: the single *.g.xlf under the translations folder). |
-DetectSourceChanges | Boolean | No | Passed to Sync-BcTranslation (mark changed sources needs-adaptation). Default: $true. Default: $true. |
-NoMemory | switch | No | Skip the translation-memory fill (structural sync only). |
-Check | switch | No | Do not write: report whether the committed XLF is out of sync with the .g.xlf (drift). |
Output
PSCustomObject { skipped?, translationsFolder, baseFile, languages: [ { language, targetFile, added, kept, adapted, tm { filled, skipped, byOrigin }, drift? } ] }.
Invoke-BcValidation
Validates an AL app by compiling it against one or more Business Central versions (licensed).
For each target Business Central artifact, creates a temporary container, compiles the app (optionally with analyzers/ruleset such as AppSourceCop for AppSource submissions), records the outcome, and removes the container. This catches version-compatibility and analyzer issues before submission. A valid ALbuild license is required.
Symbols are expected in the project's .alpackages (resolve them first with Resolve-BcDependencies). Analyzer assemblies must be passed by path via -Analyzer.
Syntax
Code
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
-ProjectFolder | String | Yes | The AL project folder. |
-ArtifactUrl | String[] | No | Explicit artifact URLs to validate against. If omitted, -Select determines them. |
-Country | String | No | Country for artifact resolution. Default 'w1'. Default: 'w1'. |
-Select | String[] | No | Artifact selectors to validate against when -ArtifactUrl is omitted (Current/NextMinor/NextMajor). Allowed values: Current, NextMinor, NextMajor. Default: @('Current'). |
-Credential | PSCredential | No | Container admin credential. |
-Analyzer | String[] | No | Analyzer assembly paths (e.g. AppSourceCop.dll). |
-RuleSet | String | No | Ruleset file. |
-DockerExecutable | String | No | The Docker executable to use (default 'docker'). Default: 'docker'. |
Output
PSCustomObject with Success and per-version Results.
Merge-BcCodeCoverage
Merges raw Business Central coverage (.dat) from several runs into one dataset (union, max hits per line).
Parallel/sharded test runs each emit their own coverage .dat files. This unions them by (Object, Line), keeping the highest hit count seen for each line, and writes a single merged .dat in BC's VariableText CSV shape (ObjectType,ObjectID,LineNo,Status,Hits) that Convert-BcCodeCoverage / Get-BcCodeCoverageSummary can consume. Status is written as 0 (Covered) because BC only ever exports executed lines.
Syntax
Code
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
-CoveragePath | String[] | Yes | One or more folders of *.dat files (or individual .dat files) to merge. |
-OutputPath | String | Yes | Destination .dat file (a folder is allowed; 'coverage_merged.dat' is written inside it). |
Output
PSCustomObject: OutputFile, ObjectCount, LineCount.
Merge-BcTranslationMemory
Fills untranslated units in a target XLIFF from a translation-memory index (deterministic, exact).
For each unit still in a needs-translation / needs-adaptation state (or with an empty target), looks up the index built by Import-BcTranslationMemory: first the context-sensitive "GenNote|source" key, then the plain "source" key. On an exact match it writes the <target>, sets state="translated", and records the origin in an auditable note (<note from-tool='albuild-tm'> origin=<self|app:...|bc-base></note>). Units without a match are left untouched (needs-translation) so a downstream consumer can translate the true new strings. No fuzzy matching, no LLM.
Syntax
Code
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
-Path | String | Yes | The target-language XLIFF file to fill (written in place unless -WhatIf). |
-Index | PSObject | Yes | The index object returned by Import-BcTranslationMemory. |
Output
PSCustomObject { filled, skipped, byOrigin (hashtable origin -> count), file }.
New-BcTranslationFile
Creates a new AL XLIFF target-language file from a generated base file.
Clones the generated base XLIFF (.g.xlf), sets the target language, and marks every unit needs-translation, producing a ready-to-translate target file.
Syntax
Code
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
-BaseFile | String | Yes | The generated base XLIFF file. |
-TargetLanguage | String | Yes | The target language code (e.g. de-DE). |
-OutputPath | String | No | Output path. Default: the base file with the language inserted (App.de-DE.xlf). |
Output
System.String - the created file path.
Examples
Example 1
Code
Publish-BcAppToDevEndpoint
POSTs an .app to a Business Central development service endpoint (the VS Code 'Publish' mechanism).
Uploads the .app as multipart/form-data to a '<devUrl>/dev/apps' endpoint with HTTP Basic auth, which publishes + synchronises + installs it as a development (ModernDev) extension - replaceable without a version bump. Mirrors ALbuild V1 / BcContainerHelper -useDevEndpoint. Kept as its own function so callers can resolve the URL however they like (e.g. a container's IP) and so it is mockable in tests.
Syntax
Code
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
-Url | String | Yes | The dev endpoint URL including query string, e.g. 'https://172.17.0.2:7049/BC/dev/apps?SchemaUpdateMode=synchronize'. |
-AppFile | String | Yes | Host path to the .app file to upload. |
-Credential | PSCredential | Yes | BC user credential for Basic authentication. |
-IgnoreSslErrors | switch | No | Accept the endpoint's (self-signed) TLS certificate. Uses the per-handler validator on PowerShell 7 (.NET) and the global ServicePointManager hook on Windows PowerShell 5.1 (.NET Framework). |
Publish-BcContainerApp
Publishes an AL app (.app) to a Business Central container, optionally syncing/installing.
Copies the .app into the container and publishes it with the BC server management cmdlets, then optionally synchronises and installs it. Requires Windows + Docker.
Syntax
Code
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
-Name | String | Yes | Container name. |
-AppFile | String | Yes | Path to the .app file on the host. |
-SkipVerification | switch | No | Publish without signature verification (for unsigned development apps). |
-Sync | switch | No | Synchronise the app after publishing. |
-Install | switch | No | Install the app after synchronising. |
-SyncMode | String | No | Schema sync mode: Add (default), Clean, Development or ForceSync. Allowed values: Add, Clean, Development, ForceSync. Default: 'Add'. |
-Scope | String | No | Global (default) or Tenant. Allowed values: Global, Tenant. Default: 'Global'. |
-ServerInstance | String | No | BC server instance. Default 'BC'. Default: 'BC'. |
-Tenant | String | No | Tenant. Default 'default'. Default: 'default'. |
-OperationTimeoutSeconds | Int32 | No | Maximum seconds to allow the publish/sync/install before abandoning it and throwing. Prevents a hung operation (e.g. a deadlocked schema sync) from freezing the build. Default 600. Default: 600. |
-DockerExecutable | String | No | The Docker executable to use (default 'docker'). Default: 'docker'. |
-Development | switch | No | |
-Credential | PSCredential | No |
Publish-BcTestinyResult
Publishes a JUnit test result file to Testiny via the Testiny importer CLI.
Uploads AL test results (a JUnit XML file, e.g. the one produced by Invoke-BcContainerTest) to Testiny using the official Testiny importer command-line tool. The importer is taken from -ImporterPath if supplied, otherwise downloaded and extracted from -ImporterUrl. Native replacement for the V1 PublishTestResultsTestiny task. For standard pipeline reporting use the built-in Azure DevOps PublishTestResults task instead; this is for teams that mirror results into Testiny.
Syntax
Code
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
-ResultsFile | String | Yes | Path to the JUnit results file to upload. |
-ApiKey | String | Yes | Testiny API key. |
-ProjectId | String | Yes | Testiny project id. |
-RunId | String | No | Optional Testiny test-run id to attach the results to. |
-Format | String | No | Result format passed to the importer. Default 'junit'. Allowed values: junit, xunit. Default: 'junit'. |
-ImporterUrl | String | No | URL of the importer download (a .zip). Used when -ImporterPath is not supplied. Default: 'https://app.testiny.io/download/latest/importer/testiny-importer-win.exe.zip'. |
-ImporterPath | String | No | Path to an already-available Testiny importer executable (skips the download). |
Output
PSCustomObject: ResultsFile, ProjectId, RunId.
Examples
Example 1
Code
Resolve-BcAnalyzerConfig
Determines the code analyzers and ruleset for a compile, layering the sources by precedence.
Precedence (highest first): an explicit value (the task input) > the project's albuild.json (Analyzers / RuleSet) > the project's .vscode/settings.json ('al.codeAnalyzers' / 'al.ruleSetPath'). Only the highest source that supplies a value is used (the sources do not merge), matching how an explicit pipeline input overrides committed config. Analyzer entries are returned as given (tokens / short names / DLL paths - Resolve-BcAnalyzer maps them at compile time); a relative ruleset path is resolved against the project folder.
Syntax
Code
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
-ProjectFolder | String | Yes | The AL project folder (holds app.json, optionally .vscode/settings.json and albuild.json). |
-WorkspaceRoot | String | No | Workspace root for albuild.json resolution (merged root + app). Default: the project folder. |
-InputAnalyzers | String | No | Explicit analyzers from the task input (comma/semicolon separated). Wins over config. |
-InputRuleSet | String | No | Explicit ruleset path from the task input. Wins over config. |
Output
PSCustomObject: Analyzers (string[]), RuleSet (string), AnalyzersSource, RuleSetSource.
Set-BcAppVersion
Sets the version of one or more Business Central apps by updating their app.json.
Updates the top-level "version" field of every app.json found under -Path (recursively, excluding symbol/package folders) - or a single app.json if -Path points directly at one. The new version is either an explicit -Version or computed from a token -Schema applied to each app's current version (see the schema tokens below). The version value is rewritten in place with a targeted text replacement so the rest of the file (ordering, indentation, comments-as-properties) is preserved; only the top-level version value changes.
Schema tokens (one per dotted position, case-insensitive): a number = literal; 'increment' = current component + 1; 'build-id' = the -BuildId value; 'no-of-commits' = the repository's git commit count; 'date' = today's date as yyyyMMdd; 'major'/'minor'/'build'/'revision'/ 'latest'/'keep' = keep the current component. Example: 'major.minor.increment.0' or the V1-style 'major.no-of-commits.build-id.date'.
The 'no-of-commits' token reads the git commit count from the repository, and 'date' reads the current date; both are computed once per call (stable across all apps stamped in that call). Apart from that (and the -OnlyUpdateOnChangedSource change check) this cmdlet only reads/writes app.json. Use Invoke-BcBuildVersionStamp for the pipeline-level "stamp + claim a build branch" flow.
Syntax
Code
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
-Path | String | No | A repository root to search recursively, an app folder, or a single app.json. Default: the current location. Default: (Get-Location).Path. |
-Schema | String | No | The token schema used to compute each new version from its current value. Default 'major.minor.increment.0'. Ignored when -Version is given. Default: 'major.minor.increment.0'. |
-Version | String | Yes | An explicit version applied to every matched app (overrides -Schema). |
-BaseVersion | Version | No | Apply the schema to this version instead of each app's own current version, so every app is computed from the same base (e.g. a release pipeline seeding the version from the latest build branch). Schema-only; ignored when -Version is given. |
-BuildId | String | No | Value substituted for the 'build-id' schema token. Defaults to the BUILD_BUILDID environment variable, or '0' when unset. |
-OnlyUpdateOnChangedSource | switch | No | Skip apps whose folder did not change in the most recent commit (git diff HEAD~1..HEAD). Requires a git working tree at -Path (or the app's repository). |
Output
PSCustomObject per app: AppJsonPath, AppFolder, PreviousVersion, NewVersion, Changed, Skipped.
Examples
Example 1
Code
Example 2
Code
Set-BcTranslationUnit
Sets the target text (and state) of a single translation unit in an AL XLIFF file.
The supported, auditable single-unit write path behind albuild translation set - no raw XML
editing. Selects the unit by id or by exact source text, writes the <target>, and sets its state:
'translated' (a completed translation) or 'needs-work' (mapped to the XLIFF 'needs-adaptation'
state). Namespace-agnostic (XLIFF 1.2/2.0) via the shared Get-BcXliffUnit reader.
Syntax
Code
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
-Path | String | Yes | The target-language XLIFF file to edit. |
-Id | String | No | The trans-unit id to set. Either -Id or -Source is required. |
-Source | String | No | The exact source text to match. Either -Id or -Source is required. |
-Target | String | Yes | The translated text to write into <target>. |
-State | String | No | 'translated' (default) or 'needs-work'. Allowed values: translated, needs-work. Default: 'translated'. |
Output
PSCustomObject { id, source, target, state, file }.
Start-BcContainerAppDataUpgrade
Runs the data upgrade for a published AL app version in a Business Central container.
When a tenant already holds data written by an EARLIER version of an app, installing the new version is refused - BC requires the app's upgrade codeunits to migrate that data first. That is Start-NAVAppDataUpgrade, and it is the step 'Install-NAVApp' tells you about only after failing: "an earlier version was already installed. Run Start-NAVAppDataUpgrade".
Publish and sync the new version first (Publish-BcContainerApp -Sync, without -Install), then call this. It replaces the install for that version: a successful data upgrade leaves the app installed at the new version.
Syntax
Code
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
-Name | String | Yes | Container name. |
-AppName | String | Yes | The app name. |
-AppVersion | String | No | The published version to upgrade to. Omit to let BC pick the newest published version. |
-ServerInstance | String | No | BC server instance. Default 'BC'. Default: 'BC'. |
-Tenant | String | No | Tenant. Default 'default'. Default: 'default'. |
-DockerExecutable | String | No | The Docker executable to use (default 'docker'). Default: 'docker'. |
Examples
Example 1
Code
Sync-BcContainerApp
Synchronises a published AL app's schema in a Business Central container.
Syntax
Code
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
-Name | String | Yes | Container name. |
-AppName | String | Yes | The app name. |
-AppVersion | String | No | Optional app version. |
-Mode | String | No | Schema sync mode: Add (default), Clean, Development or ForceSync. Allowed values: Add, Clean, Development, ForceSync. Default: 'Add'. |
-ServerInstance | String | No | BC server instance. Default 'BC'. Default: 'BC'. |
-Tenant | String | No | Tenant. Default 'default'. Default: 'default'. |
-DockerExecutable | String | No | The Docker executable to use (default 'docker'). Default: 'docker'. |
Sync-BcTranslation
Synchronises an AL XLIFF target file from a generated base file (.g.xlf).
Merges the translation units of the generated base file into the target file, preserving existing translations by matching units using a prioritised, multi-pass strategy:
- by id
- by Xliff-Generator note + source
- by Xliff-Generator note + Developer note
- by Xliff-Generator note
- by source + Developer note
- by source New units are added (untranslated); units removed from the base are dropped. When -DetectSourceChanges is set (default), a translation whose source text changed is marked needs-adaptation. The result is written back to the target file (XLIFF 1.2).
Syntax
Code
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
-BaseFile | String | Yes | The generated base XLIFF file (typically *.g.xlf). |
-TargetFile | String | Yes | The target-language XLIFF file to update (created if missing). |
-DetectSourceChanges | Boolean | No | Mark translations needs-adaptation when the source text changed. Default: $true. Default: $true. |
Examples
Example 1
Code
Test-BcAppBreakingChange
Checks an AL app for breaking changes against the baseline declared in its AppSourceCop.json.
AppSource breaking-change validation. If the project has an AppSourceCop.json with a "version" token, this:
- looks for the committed baseline app of that version in the repository (<publisher><name><version>.app);
- if the baseline is NOT committed, writes a warning and PROCEEDS without checking (Checked = $false) - you can't compare against a baseline you don't have;
- if it IS committed, compiles the app with the AppSourceCop analyzer against that baseline (the AL compiler emits AS-rule breaking-change diagnostics when the baseline app is present in the package cache and AppSourceCop.json carries the version) and reports them.
Symbols for the compile come from -PackageCachePath (default <ProjectFolder>/.alpackages); the baseline app is added to a temporary copy of that cache so the real .alpackages is untouched.
Syntax
Code
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
-ProjectFolder | String | Yes | The AL app project folder (contains app.json and AppSourceCop.json). |
-Version | String | No | Override the baseline version (default: the AppSourceCop.json "version" token). |
-SearchRoot | String | No | Where to look for the committed baseline .app. Default: the git repo root, else ProjectFolder. |
-PackageCachePath | String[] | No | Symbol folders for the compile. Default <ProjectFolder>/.alpackages. |
-Analyzer | String | No | AppSourceCop analyzer reference. Default the compiler token '${AppSourceCop}'. Default: '${AppSourceCop}'. |
-CompilerPath | String | No | AL Tool CLI (default 'alc'). |
-SkipCommittedCheck | switch | No | Treat a baseline .app present on disk but not git-tracked as committed (default: require tracked). |
Output
PSCustomObject: Checked, Version, BaselineCommitted, BaselineFile, Diagnostics, BreakingChanges, Success, Message.
Test-BcCodeCoverageThreshold
Gates a build on code-coverage thresholds -- overall and (optionally) per object.
Evaluates ALbuild coverage data (raw *.dat + workspace, or an existing coverage-summary.json) against a minimum overall line-coverage percentage and an optional per-object floor. Returns a verdict object ({ passed, lineCoverage, minLineCoverage, belowMinimum[], offenders[] }) and, with -ThrowOnFailure, throws so a pipeline step fails. Honest by construction: it uses the source-based denominator, so a suite that merely executes every covered line does not pass a real threshold.
Syntax
Code
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
-CoveragePath | String | Yes | |
-WorkspaceRoot | String | No | |
-DenominatorMode | String | No | Allowed values: Auto, Source, CoveredOnly. Default: 'Auto'. |
-SummaryPath | String | Yes | |
-MinLineCoverage | Double | Yes | Minimum overall line-coverage percent (0-100) required to pass. |
-MinObjectLineCoverage | Double | No | Optional per-object minimum; any workspace object below it is reported as an offender (and fails the gate). Default: 0. |
-ThrowOnFailure | switch | No | Throw a terminating error when the gate fails (for use as a pipeline gate). |
Output
PSCustomObject verdict.
Test-BcTranslation
Checks AL XLIFF translation files for missing and "needs-work" translations.
A CI gate for translations. For each XLIFF file it reports units with a missing translation (no/empty target, the configured missing placeholder, or a needs-translation/-adaptation state) and units that fail the technical needs-work rules (placeholder mismatch, option member count, consecutive spaces, source=target for same-language files). Use -FailOnIssue to fail the build when any issue is found.
Syntax
Code
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
-Path | String[] | Yes | One or more XLIFF files, folders or wildcards. The generated base file (*.g.xlf) is skipped. |
-MissingPlaceholder | String | No | Text that marks an untranslated target (e.g. '[NAB: NOT TRANSLATED]'). Default: none. |
-SkipNeedsWork | switch | No | Only check for missing translations, not the needs-work rules. |
-FailOnIssue | switch | No | Throw if any issue is found (for CI). |
Output
PSCustomObject per issue (File, UnitId, Type, Message).
Examples
Example 1
Code
Uninstall-BcContainerApp
Uninstalls an AL app in a Business Central container.
Syntax
Code
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
-Name | String | Yes | Container name. |
-AppName | String | Yes | The app name. |
-AppVersion | String | No | Optional app version. |
-ServerInstance | String | No | BC server instance. Default 'BC'. Default: 'BC'. |
-Tenant | String | No | Tenant. Default 'default'. Default: 'default'. |
-Force | switch | No | |
-DockerExecutable | String | No | The Docker executable to use (default 'docker'). Default: 'docker'. |
Unpublish-BcContainerApp
Unpublishes an AL app from a Business Central container.
Syntax
Code
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
-Name | String | Yes | Container name. |
-AppName | String | Yes | The app name. |
-AppVersion | String | No | Optional app version. |
-ServerInstance | String | No | BC server instance. Default 'BC'. Default: 'BC'. |
-DockerExecutable | String | No | The Docker executable to use (default 'docker'). Default: 'docker'. |
Update-BcAppManifest
Prepares an AL app manifest (app.json) for a target BC version: version features + preprocessor symbols.
Restores the pipeline's V1 "update manifest" behaviour for a compile against a specific BC version (a normal build against Latest, or a runtime package built for an older platform). Two adjustments, both keyed to -BcVersion:
-
Version features (port of Apply-BcVersionFeatures): set 'application' and 'platform' to '<major>.0.0.0' and 'runtime' to the target's AL runtime version. The runtime is '(major - 11).0' for BC >= 12 (17->6.0, 22->11.0, 28->17.0, ...), with the BC 18.1+ -> 7.1 special case; this keeps working for future majors (V1 stopped at 26/27). Skipped with -SkipVersionFeatures (then only the preprocessor symbols are written).
-
Preprocessor symbols: 'BC<min>'..'BC<target>', where 'min' is -MinMajor when given, otherwise the app's 'application' major read BEFORE the version-feature rewrite, plus any -PreprocessorSymbols. This lets version-conditional AL ('#if BC24 ... #endif') compile.
Any existing 'preprocessorSymbols' array is REPLACED, never read and never extended. The committed array belongs to the repository and may hold internal symbols (DEBUG, ONPREM) that must not reach a published app, so it is not treated as input - not even its BC entries. That also means the function cannot recover the original floor from it after it has stamped once: where a manifest may be stamped repeatedly, the caller remembers the baseline and passes -MinMajor.
Operates on a single app.json or every app.json under a folder (skipping .alpackages / output). Rewrites the file in place (build workspace); use before Invoke-BcCompiler.
Syntax
Code
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
-Path | String | Yes | An app.json file, or a folder searched recursively for app.json. |
-BcVersion | String | Yes | The target BC version - full ('28.3.52162.52455') or major ('28'); its major drives everything. |
-PreprocessorSymbols | String[] | No | Extra preprocessor symbols to add alongside the BC<n> range. The manifest's existing 'preprocessorSymbols' array is REPLACED, never extended - a repository may commit internal symbols such as DEBUG or ONPREM, and those must never travel into a published app. Everything the build needs beyond the BC range is passed here, deliberately and visibly. |
-MinMajor | Int32 | No | The floor of the BC<n> range, overriding the value derived from 'application'. Needed because this function OVERWRITES 'application'. A second stamp of the same file would otherwise read the previous target back as the floor and collapse the range - BC17..BC29 becomes BC29 - which turns every '#if BC24' false and silently compiles the '#else' branch. The floor is not recovered from the manifest's own symbols either (see -PreprocessorSymbols); the caller remembers it. The DevOps CompileApp task keeps it in a per-project pipeline variable and passes it here. |
-SkipVersionFeatures | switch | No | Only inject preprocessor symbols; leave application / runtime / platform unchanged. |
Output
PSCustomObject per app.json: AppJsonPath, MinMajor, TargetMajor, Runtime, Symbols.
Examples
Example 1
Code


