Compatibility
ALWasp provides two separate compatibility workflows. Neither one is part of a normal build command.
| Command | Inputs | Compiler required | Purpose |
|---|---|---|---|
alwasp compare |
Previous .app + current .app |
No | Informational public-symbol change log |
alwasp validate compatibility |
Previous .app + current AL source |
Yes | Microsoft’s AppSourceCop baseline validation |
These checks do not prove that an extension upgrade is runtime-safe. Publish/sync/upgrade testing, data migration, upgrade code, permissions, and changed business behavior still require an appropriate Business Central environment and test suite.
Compare compiled packages
alwasp compare previous/MyApp.app output/MyApp.app
alwasp compare previous/MyApp.app output/MyApp.app --json output/compare.json
The console output is titled ALWasp compare report and groups public-symbol changes by
namespace into REMOVED, CHANGED, and ADDED. The reader uses each package’s manifest and
SymbolReference.json; it does not require AL compiler tools, a container, or a sandbox.
compare is an informational package change log, not a compatibility gate: it does not classify
changes as breaking, and it does not fail because changes were found. A completed comparison
always exits 0; unreadable packages, mismatched app IDs, invalid arguments, or a report-write
failure exit 1. There is no --fail-on option and no ruleset applies to compare — use
validate compatibility when current source must be checked against Microsoft’s AppSourceCop
baseline rules.
Validate one source project
alwasp validate compatibility \
--project ./src/Core \
--baseline ./previous/Core.app \
--ruleset ./rulesets/AppSourceCop.ruleset.json
This command restores current dependencies plus Application, Platform, and explicit dependencies recorded in the historical baseline package’s NavxManifest.xml, obtains alc, enables AppSourceCop, and recompiles the current source against the baseline package. App identity is matched by app ID; name and publisher changes are reported but allowed, and the version is expected to differ. If an old Microsoft Application major is no longer published, ALWasp uses the lowest available compatible symbols package.
ALWasp temporarily supplies AppSourceCop’s baseline identity and cache properties. Existing user settings in AppSourceCop.json are honored, and the original file is restored byte-for-byte afterward. Current restored packages and historical .app files beside the baseline are staged so AppSourceCop can resolve referenced types instead of reporting false MissingTypeSymbol changes.
--ruleset is resolved from the current directory and overrides configured rulesets. In direct mode, omitting it auto-detects ruleset.json, then the first *.ruleset.json in the project directory.
Validate a dynamic multi-app repository
alwasp validate compatibility `
--project-root .\src `
--baseline-directory .\latest `
--ruleset .\dyce.ruleset.json
Directory mode:
- discovers
app.jsonprojects and baseline.apppackages recursively; - matches projects to baselines by app ID, never by filename;
- rejects duplicate project IDs and multiple baselines matching the same project;
- validates matched projects in dependency order;
- reports unmatched projects as new and skips them unless a matched app depends on them;
- compiles required new local dependency apps first without AppSourceCop;
- after a matched app fails AppSourceCop, compiles it once without AppSourceCop and stages the package for downstream validations while preserving the original failure;
- makes every package under
--baseline-directoryavailable as a historical dependency; - excludes
.git,.alpackages,.alwasp,.output,bin,obj, andnode_modulesfrom project discovery.
The isolated validation cache is seeded from <project-root>/.alpackages. If the shared cache is elsewhere, pass it explicitly:
alwasp validate compatibility `
--project-root .\src `
--baseline-directory .\latest `
--packages .\.alpackages `
--ruleset .\dyce.ruleset.json
The final summary separates validation results, prepared local dependencies, skipped new apps, failures, and total processing time.
Config-driven validation
Put the baseline on the corresponding app entry in alwasp.json:
{
"apps": [
{
"id": "core",
"path": "src/Core",
"compatibility": {
"baseline": "previous/Core.app"
}
}
]
}
Then validate the same target/profile selection model used by build:
alwasp validate compatibility release
alwasp validate compatibility --profile appsource
Compatibility validation always enables AppSourceCop for this command. By default it remains separate from alwasp build, so running both stages intentionally compiles the source twice — unless the profile opts into build-integrated validation, below.
validate compatibility temporarily applies the effective build-time applicationInsights
setting to each selected project’s app.json before compiling, and restores the original file
afterward. This matches the app.json state the following build will produce, so AppSourceCop
does not raise a false AS0092 warning about a connection string or instrumentation key that is
intentionally injected by the build.
Profile-bound baseline validation
A profile can fold compatibility validation directly into its normal alwasp build, so the build
output is the compatibility-validated artifact instead of a separate, duplicate compile:
{
"apps": [
{
"id": "Broker",
"path": "./Broker",
"compatibility": { "baseline": "./previous/Broker.app" }
}
],
"profiles": {
"release": {
"include": "apps",
"outFolder": "output/release",
"compatibility": { "enabled": true }
}
}
}
alwasp build release
With compatibility.enabled: true, apps in the profile’s selection that declare
compatibility.baseline are compiled once with AppSourceCop bound to that baseline, and the
successful package is collected through the profile’s ordinary outFolder/outputSuffix flow —
eliminating the validate compatibility followed by build loop. Selected apps without a
baseline are compiled normally, not skipped. Compatibility is scoped to the profile: other
profiles keep their configured appSourceCop setting and are never implicitly baseline-checked.
Historical dependencies use an isolated temporary cache, and a user-owned AppSourceCop.json is
restored byte-for-byte after every compile group.
Use the standalone alwasp validate compatibility [targetOrProfile] command instead when
compatibility must be checked independently of — or more often than — the build itself.
Microsoft symbol cache safety
When a symbols feed lags behind a preview or artifact-provided Business Central version, ALWasp may resolve an older fallback package from the feed. A newer compatible Microsoft .app already staged in the package cache is retained; the older feed fallback cannot downgrade it. Equal or genuinely newer resolved packages can still replace cached entries when canonical/localized package selection requires it.
If a direct dependency allows an older package but a transitive dependency requires a newer one, ALWasp resolves the package again at the stricter minimum. Repeated AppIds are skipped only when the version already restored satisfies the later requirement.