AL Pipeline: Business Central Builds for Azure Devops (Without Going Nuts)
James

James @crazycga

Location:
Calgary, Alberta, Canada
Joined:
Oct 31, 2023

AL Pipeline: Business Central Builds for Azure Devops (Without Going Nuts)

Publish Date: Jun 4
0 0

Are you tired of the confusing of manual downloads, half-baked scripts, and undocumented requirements every time you need to build a Business Central AL extension? Same.

That’s why I built BCBuildTasks — a clean, pipeline-native Azure DevOps extension that does the hard stuff for you.

  • AL compiler? Downloaded.
  • Dependencies? Handled.
  • Build .app? Wrapped.
  • Documentation? Actually exists and is up to date!

Let me show you how it works — and how to use it.


What Is BCBuildTasks?

BCBuildTasks is an Azure DevOps extension for building AL projects for Dynamics 365 Business Central.

It:

  • Uses PowerShell under the hood (because it actually works)
  • Uses some Javascript under the hood (because Microsoft, for some reason)
  • Integrates with pipeline variables and Azure secrets
  • Authenticates with Business Central via Microsoft Entra
  • Compiles your extension using the latest AL compiler (by default) or a selected compiler version

Note: It’s Windows-agent only. That’s Microsoft’s fault, not mine. For now, at least...


Tasks Included

Here’s what you get:

Get AL Compiler

Downloads the latest (or a specific version) AL VSIX, unpacks it, and sets up your build agent with alc.exe.

Get AL Dependencies

Authenticates to your BC sandbox and downloads all .app dependencies defined in app.json.

Build AL Package

Wraps alc.exe with all the folder and versioning logic you shouldn’t have to think about.

Get List of Companies

Gets a list of the companies in the Business Central tenant.

Get List of Modules

Gets a list of modules installed on the Business Central tenant, with the ability to exclude Microsoft modules.

Publish (experimental)

Actually publishes the module on the target Business Central tenant (for PTEs.) Note this is currently experimental because this is a really finicky routine...


Authentication: You Need Entra

To use this extension, you need to register an app in Microsoft Entra (formerly Azure AD). Why? Because the BC APIs won’t talk to your pipeline without it.

You’ll need:

  • TenantId
  • ClientId
  • ClientSecret
  • Permissions to API.ReadWrite.All on Business Central (to compile)
  • Permissions to API.Automation.All on Business Central (to deploy)
  • Admin consent (yes, that button that always gets skipped)

Full image walkthrough here →


Sample Pipeline

- task: EGGetALCompiler@0
  displayName: "Get AL compiler"
  inputs:
   DownloadDirectory: $(Build.SourcesDirectory)\compiler
   Version: 'latest'
   ExpansionDirectory: 'expanded'

- task: EGGetALDependencies@0
  displayName: "Get AL dependencies"
  inputs:
   ClientId: "<your client id>"
   ClientSecret: "<your client secret>"
   EnvironmentName: '<your environment name>'
   PathToAppJson: $(Build.SourcesDirectory)\CodeModule
   PathToPackagesDirectory: $(Build.SourcesDirectory)\.alpackages
   TenantId: "<your tenant id>"

- task: EGBuildALPackage@0
  displayName: "Compile AL package"
  inputs:
    ALEXEPathFolder: $(Build.SourcesDirectory)/compiler/expanded/extension/bin/win32/alc.exe
    EntireAppName: "TestApp.1.1.1.app"
    OutAppFolder: $(Build.ArtifactStagingDirectory)
    PackageCachePath: $(Build.SourcesDirectory)\.alpackages
    ProjectPath: $(Build.SourcesDirectory)\CodeModule

- task: PublishBuildArtifacts@1
  displayName: "Publish artifact"
  inputs:
    ArtifactName: "drop"
    PathtoPublish: $(Build.ArtifactStagingDirectory)

- task: EGDeployBCModule@0
  displayName: "Deploy module to Business Central"
  inputs:
    TenantId: "<target tenant id>"
    EnvironmentName: "<target environment name>"
    ClientId: "<target-capable client id>"
    ClientSecret: "<target-capable client secret>"
    CompanyId: "<company id>"
    AppFilePath: "$(Build.ArtifactStagingDirectory)\\TestApp.1.1.1.app"

- task: EGGetBCCompanies@0
  displayName: "Getting list of companies"
  inputs:
    TenantId: "<target tenant id>"
    EnvironmentName: "<target environment name>"
    ClientId: "<target-capable client id>"
    ClientSecret: "<target-capable client secret>"

- task: EGGetBCModules@0
  displayName: "Getting list of modules installed"
  inputs:
    TenantId: "<target tenant id>"
    EnvironmentName: "<target environment name>"
    ClientId: "<target-capable client id>"
    ClientSecret: "<target-capable client secret>"
    CompanyId: "<company id>"
Enter fullscreen mode Exit fullscreen mode

Pro Tips (for Dummies)

  • Store secrets in Azure Pipelines Library → Variable Groups
  • To that end, you can even integrate Azure Key Vault onto your variable groups, but that's beyond scope of this document
  • Use a dedicated Entra app per environment
  • Don’t check secrets into appsettings.json — seriously
  • Pin the AL compiler version if you don’t trust Microsoft’s “latest”

Full Docs

The github repo is at: GitHub repo

Included are:

  • Screenshots of the entire required Entra and Business Central configuration
  • Detailed task input/output reference
  • License and support info

Problems?

I'd say best bet is open a GitHub issue. This is an ongoing side project so I intend to keep it up to date for a bit...

Wanna Know How it Was Done?

Feel free to ask, again using a GitHub issue.

Comments 0 total

    Add comment