# Apps module

**Module:** `businessdev.ALbuild.Apps` &nbsp;•&nbsp; **Tier:** Free &nbsp;•&nbsp; **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`](#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`](#get-bccodecoveragedelta) | Computes "patch coverage" -- how well the lines you changed (vs a git baseline) are covered by tests. |
| [`Get-BcCodeCoverageSummary`](#get-bccodecoveragesummary) | Returns the ALbuild code-coverage summary (and per-object lines) without writing report files. |
| [`Get-BcContainerAppDiagnostic`](#get-bccontainerappdiagnostic) | Explains why publishing, installing or synchronising an app in a container fails. |
| [`Get-BcTestQuality`](#get-bctestquality) | Heuristically assesses the QUALITY of AL tests (assertions, arrange/act/assert) -- not their coverage. |
| [`Get-BcTranslationUnit`](#get-bctranslationunit) | Lists the translation units of an AL XLIFF file as structured objects (the read surface behind `albuild translation list`). |
| [`Get-BcVersionComponents`](#get-bcversioncomponents) | Splits a Business Central version into its components plus a 3-part SemVer form. |
| [`Import-BcTranslationMemory`](#import-bctranslationmemory) | Builds (and caches) a deterministic translation-memory index from prioritised reference XLIFFs. |
| [`Install-Bc365App`](#install-bc365app) | Installs one or more 365 business development apps into a Business Central container. |
| [`Install-BcAlTool`](#install-bcaltool) | Ensures the cross-platform AL Tool CLI is installed (as a .NET global tool) and on PATH. |
| [`Install-BcAzureSignTool`](#install-bcazuresigntool) |  |
| [`Install-BcContainerApp`](#install-bccontainerapp) | Installs a published AL app in a Business Central container. |
| [`Install-BcContainerDependency`](#install-bccontainerdependency) | Publishes and installs an AL project's resolved dependency apps into a container, in dependency order. |
| [`Invoke-BcAppSigning`](#invoke-bcappsigning) | Signs one or more AL .app files using AzureSignTool and an Azure Key Vault certificate. |
| [`Invoke-BcCompiler`](#invoke-bccompiler) | Compiles an AL project into an .app package. |
| [`Invoke-BcContainerTest`](#invoke-bccontainertest) | Runs AL tests in a Business Central container and collects/parses the results. |
| [`Invoke-BcTranslationSync`](#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`](#invoke-bcvalidation) | Validates an AL app by compiling it against one or more Business Central versions (licensed). |
| [`Merge-BcCodeCoverage`](#merge-bccodecoverage) | Merges raw Business Central coverage (.dat) from several runs into one dataset (union, max hits per line). |
| [`Merge-BcTranslationMemory`](#merge-bctranslationmemory) | Fills untranslated units in a target XLIFF from a translation-memory index (deterministic, exact). |
| [`New-BcTranslationFile`](#new-bctranslationfile) | Creates a new AL XLIFF target-language file from a generated base file. |
| [`Publish-BcAppToDevEndpoint`](#publish-bcapptodevendpoint) | POSTs an .app to a Business Central development service endpoint (the VS Code 'Publish' mechanism). |
| [`Publish-BcContainerApp`](#publish-bccontainerapp) | Publishes an AL app (.app) to a Business Central container, optionally syncing/installing. |
| [`Publish-BcTestinyResult`](#publish-bctestinyresult) | Publishes a JUnit test result file to Testiny via the Testiny importer CLI. |
| [`Resolve-BcAnalyzerConfig`](#resolve-bcanalyzerconfig) | Determines the code analyzers and ruleset for a compile, layering the sources by precedence. |
| [`Set-BcAppVersion`](#set-bcappversion) | Sets the version of one or more Business Central apps by updating their app.json. |
| [`Set-BcTranslationUnit`](#set-bctranslationunit) | Sets the target text (and state) of a single translation unit in an AL XLIFF file. |
| [`Start-BcContainerAppDataUpgrade`](#start-bccontainerappdataupgrade) | Runs the data upgrade for a published AL app version in a Business Central container. |
| [`Sync-BcContainerApp`](#sync-bccontainerapp) | Synchronises a published AL app's schema in a Business Central container. |
| [`Sync-BcTranslation`](#sync-bctranslation) | Synchronises an AL XLIFF target file from a generated base file (.g.xlf). |
| [`Test-BcAppBreakingChange`](#test-bcappbreakingchange) | Checks an AL app for breaking changes against the baseline declared in its AppSourceCop.json. |
| [`Test-BcCodeCoverageThreshold`](#test-bccodecoveragethreshold) | Gates a build on code-coverage thresholds -- overall and (optionally) per object. |
| [`Test-BcTranslation`](#test-bctranslation) | Checks AL XLIFF translation files for missing and "needs-work" translations. |
| [`Uninstall-BcContainerApp`](#uninstall-bccontainerapp) | Uninstalls an AL app in a Business Central container. |
| [`Unpublish-BcContainerApp`](#unpublish-bccontainerapp) | Unpublishes an AL app from a Business Central container. |
| [`Update-BcAppManifest`](#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

```powershell
Convert-BcCodeCoverage
    -CoveragePath <String>
    [-WorkspaceRoot <String>]
    [-Format <String[]>]
    [-DenominatorMode <String>]
    [-OutputFolder <String>]
    [-TestQuality <Object>]
    [-ExcludeNeverExecutedObjects]
    [-ExcludeProjects <String[]>]
```

### 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 '&lt;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

```powershell
Get-BcCodeCoverageDelta
    -BaselineRef <String>
    [-HeadRef <String>]
    -WorkspaceRoot <String>
    -CoveragePath <String>
    -SummaryPath <String>
```

### 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 &#123; 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
&#123; lineCoverage, coveredLines, totalExecutableLines, objectCount, denominatorMode } summary plus the
per-object breakdown, so agents and scripts can inspect coverage without re-emitting Cobertura/Markdown.

### Syntax

```powershell
Get-BcCodeCoverageSummary
    -CoveragePath <String>
    [-WorkspaceRoot <String>]
    [-DenominatorMode <String>]
    -SummaryPath <String>
```

### 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

```powershell
Get-BcContainerAppDiagnostic
    -Name <String>
    [-AppName <String>]
    [-ServerInstance <String>]
    [-Tenant <String>]
    [-EventLogEntries <Int32>]
    [-DockerExecutable <String>]
```

### 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**

```powershell
Get-BcContainerAppDiagnostic -Name albmcp01480a -AppName '365 business Banking'

Reports the published versions, the tenant data version and the blockers preventing a publish.
```

---

## 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

```powershell
Get-BcTestQuality
    -WorkspaceRoot <String>
    -Path <String>
```

### 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 &#123; 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

```powershell
Get-BcTranslationUnit
    -Path <String>
    [-OnlyMissing]
    [-State <String>]
```

### 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: &#123; 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

```powershell
Get-BcVersionComponents
    -Version <Version>
```

### 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

```powershell
Import-BcTranslationMemory
    -Reference <Object[]>
    [-ContextAware <Boolean>]
    [-CacheDir <String>]
    [-NoCache]
```

### Parameters

| Parameter | Type | Required | Description |
| --- | --- | :---: | --- |
| `-Reference` | Object[] | Yes | Ordered reference descriptors (highest priority first is NOT required - Priority decides). Each: [pscustomobject]@&#123; Files = &lt;string[] paths or globs>; Origin = '&lt;self\|app:Name\|bc-base>'; Priority = &lt;int> } |
| `-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 &#123; ContextAware, Count, Entries (hashtable key -> &#123; 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

```powershell
Install-Bc365App
    -Name <String>
    -AppId <String[]>
    [-InstallerUrl <String>]
    [-DockerExecutable <String>]
```

### 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**

```powershell
Install-Bc365App -Name bld -AppId '0f94d4ef-5c3a-4002-93f2-2a2be05219c0'
```

---

## 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

```powershell
Install-BcAlTool
    [-PackageId <String>]
    [-Version <String>]
    [-BcVersion <String>]
    [-RuntimeVersion <String>]
    [-Prerelease <String>]
    [-ToolPath <String>]
    [-Global]
    [-Force]
    [-Source <String>]
    [-DotNetExecutable <String>]
```

### 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**

```powershell
Install-BcAlTool
```

**Example 2**

```powershell
Install-BcAlTool -BcVersion '29.0.53586.0'
# BC29 -> AL runtime 18 -> the newest 18.x AL Tool (a '-beta' while BC29 is in preview),
# installed side by side under <base>\altool\<version>.
```

---

## Install-BcAzureSignTool

### Syntax

```powershell
Install-BcAzureSignTool
    [-PackageId <String>]
    [-Version <String>]
    [-Force]
    [-Source <String>]
    [-DotNetExecutable <String>]
```

### 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

```powershell
Install-BcContainerApp
    -Name <String>
    -AppName <String>
    [-AppVersion <String>]
    [-ServerInstance <String>]
    [-Tenant <String>]
    [-DockerExecutable <String>]
```

### 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

```powershell
Install-BcContainerDependency
    -Name <String>
    [-PackageFolder <String[]>]
    [-PackageFile <String[]>]
    [-ServerInstance <String>]
    [-SkipVerification <Boolean>]
    [-OperationTimeoutSeconds <Int32>]
    [-DockerExecutable <String>]
```

### 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

```powershell
Invoke-BcAppSigning
    -Path <String[]>
    -KeyVaultUrl <String>
    -TenantId <String>
    -ClientId <String>
    -ClientSecret <String>
    -CertificateName <String>
    [-TimestampUrl <String>]
    [-SignToolPath <String>]
    [-SkipAutoInstall]
```

### 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**

```powershell
Invoke-BcAppSigning -Path .\out\*.app -KeyVaultUrl $url -TenantId $t -ClientId $c -ClientSecret $s -CertificateName $name
```

---

## 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 "&lt;publisher>_&lt;name>_&lt;version>.app", derived
from app.json.

### Syntax

```powershell
Invoke-BcCompiler
    -ProjectFolder <String>
    [-OutputFolder <String>]
    [-Engine <String>]
    [-CompilerPath <String>]
    [-ContainerName <String>]
    [-ContainerCompilerPath <String>]
    [-PackageCachePath <String[]>]
    [-Analyzer <String[]>]
    [-RuleSet <String>]
    [-AssemblyProbingPath <String[]>]
    [-LogLevel <String>]
    [-BuildBy <String>]
    [-BuildUrl <String>]
    [-SourceRepositoryUrl <String>]
    [-SourceCommit <String>]
    [-DockerExecutable <String>]
    [-NoDiagnosticOutput]
```

### 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: &lt;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: &lt;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**

```powershell
Invoke-BcCompiler -ProjectFolder ./app
```

---

## 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

```powershell
Invoke-BcContainerTest
    -Name <String>
    [-ProjectFolder <String>]
    -ExtensionId <String[]>
    -TestExecution <ScriptBlock>
    [-Credential <PSCredential>]
    [-TestSuite <String>]
    [-TestRunnerCodeunitId <Int32>]
    [-DisableIsolation]
    [-Tenant <String>]
    [-CompanyName <String>]
    [-Culture <String>]
    [-Auth <String>]
    [-AzureDevOps]
    [-ResultPath <String>]
    [-ResultPathInContainer <String>]
    [-FailOnTestFailure]
    [-CodeCoverageTrackingType <String>]
    [-CodeCoverageMap <String>]
    [-CodeCoveragePath <String>]
    [-DockerExecutable <String>]
```

### 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**

```powershell
Invoke-BcContainerTest -Name bld -ProjectFolder $env:BUILD_REPOSITORY_LOCALPATH -FailOnTestFailure
```

**Example 2**

```powershell
Invoke-BcContainerTest -Name bld -ExtensionId '5e8c2f...' -Credential $cred -AzureDevOps
```

---

## 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 (&lt;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 *.&lt;lang>.xlf (highest)
 - xlf: a path/glob to other apps' XLFs (from albuild.json translation.memory.sources)
 - bc-base: Microsoft Base/System Application &lt;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

```powershell
Invoke-BcTranslationSync
    -ProjectFolder <String>
    [-WorkspaceRoot <String>]
    [-Language <String[]>]
    [-BaseFile <String>]
    [-DetectSourceChanges <Boolean>]
    [-NoMemory]
    [-Check]
```

### 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 &#123; skipped?, translationsFolder, baseFile, languages: [ &#123; language, targetFile, added, kept, adapted, tm &#123; 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

```powershell
Invoke-BcValidation
    -ProjectFolder <String>
    [-ArtifactUrl <String[]>]
    [-Country <String>]
    [-Select <String[]>]
    [-Credential <PSCredential>]
    [-Analyzer <String[]>]
    [-RuleSet <String>]
    [-DockerExecutable <String>]
```

### 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

```powershell
Merge-BcCodeCoverage
    -CoveragePath <String[]>
    -OutputPath <String>
```

### 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 &lt;target>, sets
state="translated", and records the origin in an auditable note (&lt;note from-tool='albuild-tm'>
origin=&lt;self|app:...|bc-base>&lt;/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

```powershell
Merge-BcTranslationMemory
    -Path <String>
    -Index <PSObject>
```

### 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 &#123; 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

```powershell
New-BcTranslationFile
    -BaseFile <String>
    -TargetLanguage <String>
    [-OutputPath <String>]
```

### 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**

```powershell
New-BcTranslationFile -BaseFile .\App.g.xlf -TargetLanguage de-DE
```

---

## 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 '&lt;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

```powershell
Publish-BcAppToDevEndpoint
    -Url <String>
    -AppFile <String>
    -Credential <PSCredential>
    [-IgnoreSslErrors]
```

### 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

```powershell
Publish-BcContainerApp
    -Name <String>
    -AppFile <String>
    [-SkipVerification]
    [-Sync]
    [-Install]
    [-SyncMode <String>]
    [-Scope <String>]
    [-ServerInstance <String>]
    [-Tenant <String>]
    [-OperationTimeoutSeconds <Int32>]
    [-DockerExecutable <String>]
    [-Development]
    [-Credential <PSCredential>]
```

### 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

```powershell
Publish-BcTestinyResult
    -ResultsFile <String>
    -ApiKey <String>
    -ProjectId <String>
    [-RunId <String>]
    [-Format <String>]
    [-ImporterUrl <String>]
    [-ImporterPath <String>]
```

### 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**

```powershell
Publish-BcTestinyResult -ResultsFile .\TestResults.xml -ApiKey $key -ProjectId '42'
```

---

## 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

```powershell
Resolve-BcAnalyzerConfig
    -ProjectFolder <String>
    [-WorkspaceRoot <String>]
    [-InputAnalyzers <String>]
    [-InputRuleSet <String>]
```

### 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

```powershell
Set-BcAppVersion
    [-Path <String>]
    [-Schema <String>]
    -Version <String>
    [-BaseVersion <Version>]
    [-BuildId <String>]
    [-OnlyUpdateOnChangedSource]
```

### 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**

```powershell
Set-BcAppVersion -Path . -Schema 'major.minor.build-id.0' -BuildId $env:BUILD_BUILDID
```

**Example 2**

```powershell
Set-BcAppVersion -Path .\app -Version '2.3.0.0'
```

---

## 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 &lt;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

```powershell
Set-BcTranslationUnit
    -Path <String>
    [-Id <String>]
    [-Source <String>]
    -Target <String>
    [-State <String>]
```

### 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 &lt;target>. |
| `-State` | String | No | 'translated' (default) or 'needs-work'. **Allowed values:** `translated`, `needs-work`. **Default:** `'translated'`. |

### Output

PSCustomObject &#123; 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

```powershell
Start-BcContainerAppDataUpgrade
    -Name <String>
    -AppName <String>
    [-AppVersion <String>]
    [-ServerInstance <String>]
    [-Tenant <String>]
    [-DockerExecutable <String>]
```

### 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**

```powershell
Start-BcContainerAppDataUpgrade -Name albmcp01480a -AppName '365 business Banking' -AppVersion 18.4.0.0
```

---

## Sync-BcContainerApp

Synchronises a published AL app's schema in a Business Central container.

### Syntax

```powershell
Sync-BcContainerApp
    -Name <String>
    -AppName <String>
    [-AppVersion <String>]
    [-Mode <String>]
    [-ServerInstance <String>]
    [-Tenant <String>]
    [-DockerExecutable <String>]
```

### 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:
 1. by id
 2. by Xliff-Generator note + source
 3. by Xliff-Generator note + Developer note
 4. by Xliff-Generator note
 5. by source + Developer note
 6. 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

```powershell
Sync-BcTranslation
    -BaseFile <String>
    -TargetFile <String>
    [-DetectSourceChanges <Boolean>]
```

### 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**

```powershell
Sync-BcTranslation -BaseFile .\App.g.xlf -TargetFile .\App.de-DE.xlf
```

---

## 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:
 1. looks for the committed baseline app of that version in the repository
 (&lt;publisher>_&lt;name>_&lt;version>.app);
 2. 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;
 3. 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 &lt;ProjectFolder>/.alpackages); the
baseline app is added to a temporary copy of that cache so the real .alpackages is untouched.

### Syntax

```powershell
Test-BcAppBreakingChange
    -ProjectFolder <String>
    [-Version <String>]
    [-SearchRoot <String>]
    [-PackageCachePath <String[]>]
    [-Analyzer <String>]
    [-CompilerPath <String>]
    [-SkipCommittedCheck]
```

### 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 &lt;ProjectFolder>/.alpackages. |
| `-Analyzer` | String | No | AppSourceCop analyzer reference. Default the compiler token '$&#123;AppSourceCop}'. **Default:** `'$&#123;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
(&#123; 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

```powershell
Test-BcCodeCoverageThreshold
    -CoveragePath <String>
    [-WorkspaceRoot <String>]
    [-DenominatorMode <String>]
    -SummaryPath <String>
    -MinLineCoverage <Double>
    [-MinObjectLineCoverage <Double>]
    [-ThrowOnFailure]
```

### 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

```powershell
Test-BcTranslation
    -Path <String[]>
    [-MissingPlaceholder <String>]
    [-SkipNeedsWork]
    [-FailOnIssue]
```

### 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**

```powershell
Test-BcTranslation -Path ./app/Translations -FailOnIssue
```

---

## Uninstall-BcContainerApp

Uninstalls an AL app in a Business Central container.

### Syntax

```powershell
Uninstall-BcContainerApp
    -Name <String>
    -AppName <String>
    [-AppVersion <String>]
    [-ServerInstance <String>]
    [-Tenant <String>]
    [-Force]
    [-DockerExecutable <String>]
```

### 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

```powershell
Unpublish-BcContainerApp
    -Name <String>
    -AppName <String>
    [-AppVersion <String>]
    [-ServerInstance <String>]
    [-DockerExecutable <String>]
```

### 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
 '&lt;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&lt;min>'..'BC&lt;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

```powershell
Update-BcAppManifest
    -Path <String>
    -BcVersion <String>
    [-PreprocessorSymbols <String[]>]
    [-MinMajor <Int32>]
    [-SkipVersionFeatures]
```

### 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&lt;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&lt;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**

```powershell
Update-BcAppManifest -Path .\app -BcVersion '28.3.52162.52455'
```

---
