Business Central AL Development
From VS Code to Sandbox — A Pipeline Walkthrough
A Step-by-Step Guide for Developers New to Azure DevOps
Introduction
If you are an AL developer who has been writing code in Visual Studio Code but deploying manually, this guide is for you. We will walk through the entire journey — from setting up your AL project, pushing it to Azure DevOps, writing a build pipeline, and finally automatically deploying your extension to a Business Central Sandbox environment.
No previous DevOps experience is needed. We will explain every step clearly and keep the language simple.
What You Will Need
Before we begin, make sure the following are ready:
• Visual Studio Code (VS Code) installed on your machine
• AL Language extension installed in VS Code (from Microsoft)
• Access to a Business Central Sandbox environment (cloud or on-premise)
• An Azure DevOps account (free at dev.azure.com)
• Git installed on your machine
Reference: Download VS Code from https://code.visualstudio.com
Reference: AL Language Extension on Marketplace: https://marketplace.visualstudio.com/items?itemName=ms-dynamics-smb.al
You can Write a Simple AL Extension
File 1: TableExtension — CustomerExt.al
tableextension 50100 "Customer Extension" extends Customer
{
fields
{
field(50100; "Loyalty Points"; Integer)
{
Caption = 'Loyalty Points';
DataClassification = CustomerContent;
}
}
}
File 2: PageExtension — CustomerCardExt.al
pageextension 50101 "Customer Card Extension" extends "Customer Card"
{
layout
{
addlast(General)
{
field("Loyalty Points"; Rec."Loyalty Points")
{
ApplicationArea = All;
ToolTip = 'Shows the loyalty points earned by this customer.';
}
}
}
}
Setting Up Azure DevOps Repository
Create an Azure DevOps Account and Project
If you do not already have one, go to dev.azure.com and sign in with your Microsoft account. Click "New Project", give it a name (for example "BC-Extensions"), set visibility to Private, and click Create.
Reference: Azure DevOps getting started guide: https://learn.microsoft.com/en-us/azure/devops/user-guide/sign-up-invite-teammates
Initialize the Git Repository
Once the project is created, click on "Repos" in the left menu. You will see an empty repository. Azure DevOps will show you the commands to push an existing repository.
Open a terminal in your VS Code project folder and run these commands:
git init
git add .
git commit -m "Initial commit - AL extension"
git branch -M main
git remote add origin https://dev.azure.com/YourOrg/BC-Extensions/_git/BC-Extensions
git push -u origin main
💡 Tip: Create a .gitignore file in your project root so you do not accidentally push the .alpackages folder or the .app output file. These are large and can be regenerated by the pipeline.
Recommended .gitignore for AL Projects
.alpackages/
*.app
.vscode/
rad.json
Create a Service Connection (for Sandbox Deployment)
We need to tell Azure DevOps how to connect to Business Central. This is done via a Service Connection.
In Azure DevOps go to: Project Settings (bottom-left gear icon) → Service Connections → New Service Connection.
For Business Central SaaS, we will use a Bearer Token or OAuth approach. The most common approach for automated pipelines is to create a Service Principal (App Registration) in Azure AD and use it with a client secret.
Reference: How to set up Azure AD App Registration for BC API access: https://learn.microsoft.com/en-us/dynamics365/business-central/dev-itpro/administration/automation-apis-using-s2s-authentication
Writing the Azure DevOps Pipeline (YAML)
What is a YAML Pipeline?
A YAML pipeline is simply a text file that tells Azure DevOps what to do: which tools to use, which commands to run, and in what order. It lives inside your repository so it is version-controlled just like your AL code.
The pipeline file is typically named azure-pipelines.yml and placed at the root of your repository.
|
Key Concepts: Trigger: when the pipeline runs. Pool: the machine it runs on. Steps: the individual tasks to perform. Variables: reusable values like your environment name or app version. |
Create azure-pipelines.yml
In your VS Code project, create a new file at the root called azure-pipelines.yml. Here is a complete, working pipeline for building and deploying your AL extension:
# azure-pipelines.yml
# Builds the AL extension and deploys to BC Sandbox
trigger:
branches:
include:
- main
pool:
vmImage: "windows-latest"
variables:
bcVersion: "23.0"
appPublisher: "Your Company Name"
appName: "My First Extension"
sandboxName: "MySandbox"
tenantId: "$(BC_TENANT_ID)" # stored as pipeline secret
clientId: "$(BC_CLIENT_ID)" # stored as pipeline secret
clientSecret: "$(BC_CLIENT_SECRET)" # stored as pipeline secret
steps:
# Step 1: Install BcContainerHelper PowerShell module
- task: PowerShell@2
displayName: "Install BcContainerHelper"
inputs:
targetType: "inline"
script: |
Install-Module BcContainerHelper -Force -AllowClobber
# Step 2: Compile the AL project into a .app file
- task: PowerShell@2
displayName: "Compile AL Extension"
inputs:
targetType: "inline"
script: |
$alePackagesFolder = "$(Build.SourcesDirectory)\.alpackages"
$appProjectFolder = "$(Build.SourcesDirectory)"
$appOutputFolder = "$(Build.ArtifactStagingDirectory)"
Compile-AppInBcContainer `
-containerName "bcserver" `
-appProjectFolder $appProjectFolder `
-appOutputFolder $appOutputFolder `
-credential (New-Object PSCredential("admin", (ConvertTo-SecureString "P@ssword1" -AsPlainText -Force)))
# Step 3: Publish the .app file to BC Sandbox via API
- task: PowerShell@2
displayName: "Publish to Business Central Sandbox"
inputs:
targetType: "inline"
script: |
$appFile = Get-ChildItem "$(Build.ArtifactStagingDirectory)" -Filter "*.app" | Select-Object -First 1
$authContext = New-BcAuthContext `
-tenantID "$(tenantId)" `
-clientID "$(clientId)" `
-clientSecret "$(clientSecret)"
Publish-BcContainerApp `
-bcAuthContext $authContext `
-environment "$(sandboxName)" `
-appFile $appFile.FullName `
-useDevEndpoint
# Step 4: Publish the .app as a pipeline artifact for audit trail
- task: PublishBuildArtifacts@1
displayName: "Save .app as Build Artifact"
inputs:
pathToPublish: "$(Build.ArtifactStagingDirectory)"
artifactName: "BCExtension"
Reference: BcContainerHelper module documentation: https://github.com/microsoft/navcontainerhelper
Store Secrets as Pipeline Variables
You never hardcode passwords or client secrets in your YAML file. Azure DevOps lets you store them as secret variables.
In Azure DevOps, go to your Pipeline → Edit → Variables (top right corner). Add the following variables and mark them as Secret:
• BC_TENANT_ID — your Azure AD tenant ID
• BC_CLIENT_ID — the App Registration client ID
• BC_CLIENT_SECRET — the App Registration client secret
💡 Tip: Secret variables are masked in all logs. Even if someone accidentally prints them, they appear as ***. Always use secret variables for credentials.
Running the Pipeline and Deploying to Sandbox
Push Your Code and Trigger the Pipeline
Now commit and push the azure-pipelines.yml file to the main branch:
git add azure-pipelines.yml
git commit -m "Add Azure DevOps pipeline for BC extension"
git push origin main
When the push lands on the main branch, Azure DevOps will automatically detect the YAML file (if you have already created the pipeline definition) and trigger a new run.
Create the Pipeline Definition in Azure DevOps
If this is your first time, you need to tell Azure DevOps where your YAML file lives:
Watch the Pipeline Run
Once triggered, click on the running pipeline to see real-time logs. You will see each step execute:
• Install BcContainerHelper — downloads the PowerShell module
• Compile AL Extension — builds the .app file from your code
• Publish to Business Central Sandbox — uploads the app to your sandbox
• Save .app as Build Artifact — stores the file for audit or rollback
1. In Azure DevOps, click on Pipelines in the left sidebar
2. Click New Pipeline
3. Select Azure Repos Git as the code source
4. Select your BC-Extensions repository
5. Choose "Existing Azure Pipelines YAML file"
6. Select /azure-pipelines.yml from the main branch
7. Click Continue and then Save and Run
Verify in Business Central Sandbox
After the pipeline succeeds, log in to your Business Central Sandbox environment. Go to:
Settings → Extension Management
You should see your extension "My First Extension" listed and installed. Open the Customer Card — the new "Loyalty Points" field should be visible on the General tab.
Tips and Best Practices
• Always use branches — never push code directly to main in a team environment. Use feature branches and Pull Requests.
• Version your app.json carefully. Each deployment should increment the version number (e.g., 1.0.0.0 → 1.0.1.0).
• Use pipeline stages if you have multiple environments (Sandbox → UAT → Production). Each stage can require manual approval.
• Store all secrets in Azure DevOps Variable Groups — this lets you reuse them across multiple pipelines.
• Enable pipeline notifications so your team gets an email or Teams message when a build fails.
Reference: AL development best practices: https://learn.microsoft.com/en-us/dynamics365/business-central/dev-itpro/developer/devenv-dev-overview
Reference: Azure DevOps Pipelines documentation: https://learn.microsoft.com/en-us/azure/devops/pipelines/get-started/what-is-azure-pipelines
Reference: BcContainerHelper GitHub (AL build tools): https://github.com/microsoft/navcontainerhelper
You have now walked through the full lifecycle of a Business Central AL extension — from writing code in VS Code, pushing it to Azure DevOps, building it through a YAML pipeline, and deploying it automatically to your Sandbox.
This setup may feel like extra work at first, but once it is in place, every code change you push to main will be built and deployed automatically. No more manual uploads. No more "which version is in sandbox?" questions.
As you grow more comfortable, you can extend this pipeline to include automated tests using AL Test Runner, deploy to multiple environments with approval gates, and integrate with Teams notifications.
Happy Coding!



