Another post about Business Central development and Git. Maybe the last one. Who knows?
Whatever your precise circumstances, if you are developing apps for Business Central you have to be mindful of the differences between BC versions and how it affects your app. If you are only developing for SaaS you might only care about the current and next version.
If you are developing and maintaining apps for the on-prem/PaaS market then likely you need to concern yourself with a wider range of BC versions. Even a we-only-support-Business-Central-and-not-NAV stance means we are now supporting four major versions – 13, 14, 15 and 16. I refuse to call the versions “Business Central <Year> <Spring Release/Fall Release/Wave One/Wave Two> – a number makes much more sense to me. Also, I’m British – “fall” is an accident, not a season.
Nomenclature aside, all of this does present us with a challenge. How do we maintain the source code for our apps, for different Business Central versions, in an efficient manner?
Changes Between Versions
For the uninitiated, what sorts of changes are we talking about between platform versions? There are various things to think about:
- Runtime differences e.g. new mandatory properties in app.json
- target – using “Cloud” instead of “Extension”
- dependencies – using “id” instead of “appId”
- depending on the “System Application” and “Base Application” apps rather than using the application property
- Standard fields that have recently been converted to enums
- Standard functionality that has been moved, methods that have new signatures
And of course, many of you will have experienced the pain of the BC14 -> BC15 upgrade. TempBlob, Base64, Languages, Tenant Mgt. / Environment Info, Calendar Management – all breaking changes. Microsoft were criticised, rightly so, for breaking BC14 compatible apps so badly in BC15.
To their credit, however, Microsoft said that they would minimise future breaking changes, instead marking code as becoming obsolete for at least 12 months until it is removed. That has been borne out with the release of BC16. All but one of our BC15 apps works without any changes in BC16. The exception was an app that was using the Sorting Method on Warehouse Activity Header which has been converted from an option to an enum and now has different values. Microsoft sent me an email with the details of the compilation error.
How to manage this then? When we first switched from developing AL apps on NAV2018 (don’t – it’s more trouble than it’s worth) to BC13 we created a new Git repo for each app. It became obvious that we don’t want to keep doing that. We don’t want as many repos as number of apps * number of supported BC versions. We need something smarter than that.
We’ve settled on something like this instead:
- the master branch has the stable code for the current release of BC (as of this week, BC16), app.json has a platform value to match the latest version (18.104.22.168) and is built against the current Docker image (mcr.microsoft.com/businesscentral/sandbox)
- new development is done against the current BC (worldwide) version in release, bug, and feature branches (as described here)
- the code for each version of BC that we are supporting is in a BC13, BC14 or BC15 branch – this branch has an appropriate platform value in app.json and is built against a sandbox Docker image of that version
Imagine a repo like this:
* 3b6ba3c (HEAD -> BC14) Env. Info changes for BC14 * 5e3fda6 TempBlob changes for BC14 * 0f85829 Update Docker image for BC14 * e4fe665 app.json for BC14 | * 517615b (BC15) Update Docker image for BC15 | * e893e39 app.json for BC15 |/ * 60fe758 (tag: 1.1.0, master) Some changes for v1.1.0 * 8bd6f26 (tag: 1.0.0) Initial version
The current version of our app is 1.1.0 and we are supporting the current version of BC (BC16, in the master branch) and BC15 and BC14 in their respective branches. Revisiting an earlier idea, I like to think of these branches as telling a story, answering the question – “what changes do you have to make to the current version of the code to make it compatible with this version of BC?” For BC15 the answer is “not much” – just change app.json and the Docker image. For BC14 the answer is likely to be somewhat longer.
Now we are going to work on the next version of our app, v1.2.0. These changes would go through feature branches, pull requests, a release branch and eventually into master. I’ll skip all that and just show a new commit in the master branch.
* cd7b2ff (HEAD -> master, tag: 1.2.0) Changes for v1.2.0 | * 3b6ba3c (BC14) Env. Info changes for BC14 | * 5e3fda6 TempBlob changes for BC14 | * 0f85829 Update Docker image for BC14 | * e4fe665 app.json for BC14 |/ | * 517615b (BC15) Update Docker image for BC15 | * e893e39 app.json for BC15 |/ * 60fe758 (tag: 1.1.0) Some changes for v1.1.0 * 8bd6f26 (tag: 1.0.0) Initial version
Pushing those changes to the master branch triggers a build against BC16. Now, we want to include the 1.2.0 changes in the BC15 and BC14 versions of our app. We can simply rebase the BC15 and BC14 branches back on top of the master branch.
* f4a7d9b (HEAD -> BC14) Env. Info changes for BC14 * dd072ea TempBlob changes for BC14 * ad8905b Update Docker image for BC14 * 184001e app.json for BC14 | * 71140f4 (BC15) Update Docker image for BC15 | * 2981c4d app.json for BC15 |/ * cd7b2ff (tag: 1.2.0, master) Changes for v1.2.0 * 60fe758 (tag: 1.1.0) Some changes for v1.1.0 * 8bd6f26 (tag: 1.0.0) Initial version
(Force) Pushing the changes to the BC15 and BC14 branches will trigger new builds of the app against their respective Docker images.
Depending on what the v1.2.0 changes actually were, we may need to do some more work in the BC14 branch to make the new code compatible e.g. if the new code included some use of the TempBlob codeunit.
* ff1455b (HEAD -> BC14) More TempBlob changes * f4a7d9b Env. Info changes for BC14 * dd072ea TempBlob changes for BC14 * ad8905b Update Docker image for BC14 * 184001e app.json for BC14 | * 71140f4 (BC15) Update Docker image for BC15 | * 2981c4d app.json for BC15 |/ * cd7b2ff (tag: 1.2.0, master) Changes for v1.2.0 * 60fe758 (tag: 1.1.0) Some changes for v1.1.0 * 8bd6f26 (tag: 1.0.0) Initial version
Going back to the idea of the BC14 branch telling a coherent story of making the app compatible with BC14, does it make much sense to have two commits of TempBlob changes? No. It doesn’t add anything for a developer looking at the repo in the future. We can sort that with an interactive rebase: git rebase -i master
pick 184001e app.json for BC14 pick ad8905b Update Docker image for BC14 pick dd072ea TempBlob changes for BC14 pick f4a7d9b Env. Info changes for BC14 pick ff1455b More TempBlob changes
Change the rebase script to tell Git to “fixup” the second TempBlob change into the first.
pick 184001e app.json for BC14 pick ad8905b Update Docker image for BC14 pick dd072ea TempBlob changes for BC14 fixup ff1455b More TempBlob changes pick f4a7d9b Env. Info changes for BC14
Those changes will be melded together and keep the history of the repo neat and readable.