NavWithNav

The premier knowledge-sharing hub for Microsoft Dynamics 365 Business Central developers, architects, and ERP professionals.

Back to Series
Business Central

A Beginner's Guide to Business Central AL Development with Azure DevOps Pipelines

New to Azure DevOps? This step-by-step guide walks you through everything — setting up an AL project in VS Code, pushing your code to Azure DevOps, writing a YAML pipeline, and automatically deploying your Business Central extension to a Sandbox environment. No DevOps experience needed.

Nitin VermaMarch 14, 2026 15 min read
Business CentralOAuthAPIAuthentication
A Beginner's Guide to Business Central AL Development with Azure DevOps Pipelines

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!

0
0

Discussion (0)

Leave a comment

No comments yet. Be the first to share your thoughts!

Newsletter

Stay updated with the latest Business Central development tips.

Nitin Verma

Nitin Verma

Solution Architect

Extensive experience specializing in Microsoft Dynamics NAV, Business Central, Power Platform, and ERP Architecture.

Read full bio

Search Articles

Monthly Archive

Loading...

Visitor Stats