feat(manager): support Business Central AL app.json dependencies, application, and platform #43504
Replies: 4 comments 1 reply
|
small update: One of the main reasons why this is pretty complicated to do with custom managers is that nuget normalizes out 0 revisions (storing 28.0.0.0 as 28.0.0), but Business Central needs the full version in its dependencies. |
|
Sounds good. I am attaching the new package manager details form. Check the details requested in the form, and add it to you discussion descripiton incase you missed something, I'll take a look once you confirm and create an issue. Thanks! |
|
Hi there, You're asking us to support a new package manager. We need to know some basic information about this package manager first. Please copy/paste the new package manager questionnaire, and fill it out in full. Once the questionnaire is filled out we'll decide if we want to support this new manager. Good luck, The Renovate team |
New package manager questionnaireDid you read our documentation on adding a package manager?
BasicsWhat's the name of the package manager?Business Central AL extension manager. Suggested manager ID: What language(s) does this package manager support?The package file is JSON — specifically, the Business Central How popular is this package manager?Business Central is used by hundreds of thousands of organizations globally as a cloud and on-premises ERP platform. The AL extension ecosystem includes many thousands of ISVs and in-house development teams, all of whom maintain Does this language have other (competing?) package managers?
AL-Go for GitHub is a CI/CD framework that downloads BC symbol packages at build time, but it does not manage dependency versions or open PRs for updates — it is not a package manager in the Renovate sense. BcContainerHelper manages Docker-based BC development environments but also does not track or update package versions. There is no general-purpose package manager for AL extensions today. Dependency version updates are maintained manually. What are the big selling points for this package manager?
Detecting package filesWhat kind of package files, and names, does this package manager use?
Which
|
| Feed | URL | Used for |
|---|---|---|
| MSSymbolsV2 | https://pkgs.dev.azure.com/dynamicssmb2/DynamicsBCPublicFeeds/_packaging/MSSymbolsV2/nuget/v3/index.json |
publisher == "Microsoft" |
| AppSourceSymbols | https://pkgs.dev.azure.com/dynamicssmb2/DynamicsBCPublicFeeds/_packaging/AppSourceSymbols/nuget/v3/index.json |
all other publishers |
Users who publish private extensions to their own Azure Artifacts NuGet feeds will need to configure a third registry and authenticate via hostRules. The registry URL is not present in app.json; it must be provided in Renovate config.
Where can Renovate find the custom host/registry?
- User needs to configure Renovate where to find the information, provide details.
The two public feeds above are known constants and can be hardcoded as defaults in the manager. Private feed URLs are not discoverable from app.json and must be user-configured.
Are there any constraints in the package files that Renovate should use in the lookup procedure?
- No constraints.
The application version sets the BC wave the extension targets, which creates an implicit compatibility constraint (dependencies should generally be at the same or higher BC wave). However, this does not need to affect the lookup procedure — Renovate should simply report the latest available version. It is up to the developer to decide whether to accept a cross-wave update.
Will users need the ability to configure language or other constraints using Renovate config?
- No.
Artifacts
Does the package manager use a lock file or checksum file?
- No lock file or checksum.
BC's AL compiler downloads symbol packages at build time directly from the configured feeds. There is no lockfile concept in the AL ecosystem.
Is the locksum or checksum mandatory?
- Package manager does not use locksums or checksums.
If lockfiles or checksums are used: what tool and exact commands should Renovate use to update one (or more) package versions in a dependency file?
N/A.
Package manager cache
Does the package manager use a cache?
- No.
If the package manager uses a cache, how can Renovate control the cache?
- Package manager does not use a cache.
Should Renovate keep a cache?
- No.
Generating a lockfile from scratch
Can the package manager generate a lockfile from scratch?
- No, the package manager does not use lockfiles.
Other
What else should we know about this package manager?
1. NuGet versioner is incompatible — must use a custom versioner
This is the most important implementation detail. The built-in nuget versioner treats any bare version string as a minimum-version range (>=version). For BC, currentValue: "25.0.0.0" is resolved to the latest version satisfying >=25.0.0.0 — which is always the latest version on the feed. This makes currentVersion == latestVersion, and Renovate produces no update and no PR.
The manager must use a regex-based versioner that treats versions as exact comparable values:
^(?<major>\d+)\.(?<minor>\d+)\.(?<patch>\d+)(\.(?<build>\d+))?$
The optional 4th group handles both 3-part feed versions (28.0.0) and 4-part app.json versions (28.0.0.0) without special-casing.
2. 4-part version write-back
NuGet normalizes trailing-zero revisions at the feed level. A version stored in app.json as 28.0.0.0 may be retrieved from the feed as 28.0.0 (3-part). The BC compiler rejects 3-part versions — it requires major.minor.patch.revision. The manager must append .0 when writing a 3-part version back to app.json.
Conversely, versions with non-zero 4th parts (e.g., 28.1.49838.50198 for the Application package) must be written as-is, since the 4th part carries meaningful build information.
3. NuGet package name construction
For dependencies array entries, the NuGet package name is constructed as:
<PublisherNoSpaces>.<NameNoSpaces>.symbols.<id>
where spaces are stripped from both publisher and name, and id is the GUID from the dependencies entry.
Two packages are exceptions (no GUID suffix): Microsoft.Application.symbols and Microsoft.Platform.symbols. These correspond to the top-level application and platform fields respectively.
4. Workaround using the current JSONata custom manager
As a reference implementation, we have a working workaround using Renovate's JSONata custom manager. The repository axiansinfoma/al-example-renovate demonstrates this approach, including the regex versioner override and a postUpgradeTasks sed command for 4-part write-back normalization. The postUpgradeTasks requirement is a key limitation of the custom manager approach, as it requires self-hosted Renovate. A native manager would handle version normalization natively without requiring postUpgradeTasks.
5. app.json false-positive disambiguation
The filename app.json is shared with Office Add-in manifests. The presence of application (a version string), platform (a version string), and/or a dependencies array with GUID id fields uniquely identifies a BC app.json. The manager should validate at least one of these fields before processing.
Uh oh!
There was an error while loading. Please reload this page.
Tell us more.
Summary
I'd like to suggest support for Microsoft Dynamics 365 Business Central extension dependencies declared in
app.json.Business Central AL projects define extension metadata and dependencies in
app.json, and Renovate support for this file would make it possible to keep extension dependencies, as well asapplicationandplatform, up to date automatically.Reference documentation:
Use case
In Business Central AL projects,
app.jsoncontains:applicationplatformdependenciesarray describing dependent extensionsThe dependencies include fields such as:
idpublishernameversionToday these values typically need to be maintained manually.
It would be very useful if Renovate could:
app.jsondependenciesarrayapplicationandplatformProposed manager
A new built-in manager for Business Central / AL extensions.
Suggested details:
business-centraloral-extensionapp.json/(^|\/)app\.json$/Example
app.json{ "id": "11111111-2222-3333-4444-555555555555", "name": "My BC Extension", "publisher": "Contoso", "version": "1.0.0.0", "platform": "24.0.0.0", "application": "24.0.0.0", "dependencies": [ { "id": "437dbf0e-84ff-417a-965d-ed2bb9650972", "publisher": "Microsoft", "name": "Base Application", "version": "24.0.0.0" }, { "id": "63ca2fa4-4f03-4f2b-a480-172fef340d3f", "publisher": "Microsoft", "name": "System Application", "version": "24.0.0.0" }, { "id": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee", "publisher": "MyVendor", "name": "Shared Library", "version": "2.3.0.0" } ] }Extraction model
Renovate would ideally extract:
dependenciesarrayapplicationfieldplatformfieldFor dependency identity, the
idfield should be the primary identifier inapp.json.The
publisherandnamefields are useful metadata, but dependency resolution in the package feed can be derived from the Business Central package identity convention described below.Datasource / lookup
If a datasource is required, NuGet is the primary datasource.
There are two primary public NuGet feeds that can be used:
https://dynamicssmb2.visualstudio.com/DynamicsBCPublicFeeds/_artifacts/feed/AppSourceSymbolsfor all extensions not published by Microsofthttps://dynamicssmb2.visualstudio.com/DynamicsBCPublicFeeds/_artifacts/feed/MSSymbolsV2for extensions published by MicrosoftFor extension dependencies in
app.json, the corresponding NuGet package id is generally:<publisher>.<name>.symbols.<id>This means Renovate could extract:
publishernameidversionand then construct the package id for lookup.
Special cases
There are two important exceptions in the MS Symbols feed:
Microsoft.Application.symbolsMicrosoft.Platform.symbolsThese can be used to renovate the top-level fields in
app.json:applicationplatformSo in addition to
dependencies, this manager could also update:"application": "24.0.0.0"viaMicrosoft.Application.symbols"platform": "24.0.0.0"viaMicrosoft.Platform.symbolsPossible lookup strategy
A possible implementation strategy would be:
Dependencies
app.jsonpublisher,name,id, andversion<publisher>.<name>.symbols.<id>MSSymbolsV2whenpublisher == "Microsoft"AppSourceSymbolsotherwiseTop-level fields
applicationtoMicrosoft.Application.symbolsplatformtoMicrosoft.Platform.symbolsWhy this would help
This would help teams:
applicationandplatformupdatesThanks for considering this idea.
All reactions