The Hello World CI/CD sample

Update 2021/2/10: BcContainerHelper has replaced NavContainerHelper. This blog post still reference NavContainerHelper, which is outdated.

Quite a few partners have build their CI/CD pipelines based on the HelloWorld CI/CD sample repository here: https://dev.azure.com/businesscentralapps/HelloWorld (the one used in the Hands On Lab – http://aka.ms/cicdhol).

I have just finished the upgrade of this repository to use artifacts instead of docker images. This blog post describes the changes done.

Settings.json

https://dev.azure.com/businesscentralapps/HelloWorld/_git/HelloWorld?path=%2Fscripts%2Fsettings.json

Settings.json was changed to include artifacts instead of container images. Also I have removed the alwaysPull setting, which is really designed to indicate whether or not to check if there is a newer image available – that is not needed anymore.

Create-Container.ps1

https://dev.azure.com/businesscentralapps/HelloWorld/_git/HelloWorld?path=%2Fscripts%2FCreate-Container.ps1

Create-Contailer was changed to look at the artifact setting instead of the ContainerImage setting. Furthermore, if the imagename is set in settings, it transfers this to the container to pre-build a specific image for subsequent usages.

Read-Settings.ps1

https://dev.azure.com/businesscentralapps/HelloWorld/_git/HelloWorld?path=%2Fscripts%2FRead-Settings.ps1

Read-Settings.ps1 was changed to use the new settings and set devops variables accordingly.

CI.yaml

https://dev.azure.com/businesscentralapps/HelloWorld/_git/HelloWorld?path=%2Fscripts%2FCI.yml

In the pipeline, I removed the task, which performs the insider docker login and I changes the pool to use azure hosted agents.

Local-Build and AzureVM-Build

https://dev.azure.com/businesscentralapps/HelloWorld/_git/HelloWorld?path=%2Fscripts%2FLocal-Build.ps1 and https://dev.azure.com/businesscentralapps/HelloWorld/_git/HelloWorld?path=%2Fscripts%2FAzureVM-Build.ps1

These functions are used to simulate/run a pipeline locally or in an Azure VM. The functions have been changed to use the new settings (and cache docker images if imageName was specified)

Local-Sandbox and AzureVM-Sandbox

https://dev.azure.com/businesscentralapps/HelloWorld/_git/HelloWorld?path=%2Fscripts%2FLocal-Sandbox.ps1 and https://dev.azure.com/businesscentralapps/HelloWorld/_git/HelloWorld?path=%2Fscripts%2FAzureVM-Sandbox.ps1

These functions are used to create a sandbox container for the project locally or in an Azure VM. The functions have been changed to use the new settings (and cache docker images if imageName was specified)

Initialize.ps1

https://dev.azure.com/businesscentralapps/HelloWorld/_git/HelloWorld?path=%2Fscripts%2FInitialize.ps1

Initialize is used by the functions which locally or in Azure VMs creates sandboxes or runs build pipelines to read settings and initialize values. Kind of the local version of Read-Settings.

Adopt the changes

I updated the scripts for all three versions (hybrid, 14.x and 16.x). If you haven’t modified the PowerShell scripts, you can probably just download new versions and override the old. The settings and yaml file you will have to change by hand.

The hands on lab will also be updated to adopt the changes to artifacts.

Hope this helps

Enjoy

Freddy Kristiansen
Technical Evangelist

18 thoughts on “The Hello World CI/CD sample

  1. Hello and thanks for the great bunch of post about CI/CD, however could you explain how do you declare a license file stored in the repos, in the pipelines variable? Hands on Lab is using a local agent if i’m not mistaken so license store locally.

    Like

  2. Hi! I do have a question here regarding dependencies. I have been trying to figure out why my builds are failing to compile. After some time i found that this example of yours increases the app build version for each run. So for the first run everything is on 1.0.0.0 and works. For second run the version of “base” will be 1.0.1.0, and this will cause the compilation of the extension “app” to fail because it depends on “base” 1.0.0.0 still. Note you will only get this out if you remove “base” 1.0.0.0 from the build symbols folder.

    So for this example you have, should we not also increase the dependency automatically? If we have a multiple extensions that is not the same version i under stand the current code. However if we would like to increase all extensions versions to the same we should also increase the dependency version. Or am i maybe thinking about this in the wrong way?

    Like

  3. Hey Freddy, I am currently on my first attempts go get your sample up and running and I think I figured it out now. I also see that you just recently adjusted the whole sample scripts to switch from images to artifacts. We curate our own registry to speed up access to the containers on our development machines since the artifact way takes longer and the pipelines could run on different VMs. Pulling the images from our central registry is much faster and I wonder if it is still possible to use images instead of artifacts in the latest versions by manipulating some variables (the -imagename parameter in the Create-Container.ps1 maybe)?

    Like

      • Wow, that sounds awesome! Thank you so much for sharing your hard work with us 🙂
        I´m really looking forward to the new version. In the meantime I will have time to gain some experience with the current version and the processes involved to set up proper ci/cd pipelines 🙂

        Like

      • Hello, is there some kind of access to a preview version of your scripts where I could test the usage of images instead of artifacts? Or am I asking too early? 🙂

        Like

    • Sorry no. The HOL is complete with artifacts and it is basically just transferring an imagename to run-alpipeline instead of artifactUrl and imagename – and then read that from settings.
      Note that you would have to build these images yourself, we don’t ship images anymore.

      Like

      • I am not sure I am interpreting your answer correctly. The no sounds like it is not possible, The rest of your answer creates hope 😉

        I would suppose if it works, I should add another “version” in the settings.json file, leave the $version.artifact parameter empty and define the $version.imageName parameter. But the latter one does not seem to be valid for the settings.json. I don´t see how else it could be implemented. Altering the call of Run-ALPipeline in the DevOps-Pipeline.ps1 could do, but I think I am altering a Script in a spot that will break anything else. And as far as my current test is running it seems I am right 🙂
        Do you have a hint for me how to alter the settings.json(?) so an empty artifact parameter is created and I can still fill the imagename parameter for the Run-AlPipeline cmdlet when it is called later in the process?

        As for the images, that´s fine. We build images on the fly for the sandbox environments, where you need to pull the latest artifacts all the time anyway. But for the stable versions and on-prem releases, we build the images based on the artifacts for our own registry so we can re-use them very quickly. Downloading images from there is multiple times faster than downloading artifacts and building the images on the fly. So this saves a lot of time for build runs. That is why I am investing time to also be able to use images in the pipelines where it helps us and using artifacts where it makes no sense to pre-build images for our registry.

        Like

  4. Thanks for putting this together.
    In the Run Pipeline, after the
    Removing C:\ProgramData\BcContainerHelper\Extensions\hostedagent-helloworld-ci

    I’m receiving the following error?
    ##[error]Download-File : Exception calling “DownloadFile” with “2” argument(s): “The remote server returned an error: (403) Forbidden.”

    Like

  5. Hello Freddy, I am following the lab, but get an error when running Local-DevEnv.ps1: ‘No app folders found’. See output below. Any idea?

    PS C:\Users\MaartenGerritsenMagi\Documents\AL\CICD\CICD\scripts> .\Local-DevEnv.ps1
    Set artifact = //17.3.20469.21555/us
    Set pipelineName = HelloWorld.AppSource-ci
    Set containerName = helloworld-appsource-ci
    Set installApps = ”
    Set previousApps = ‘https://businesscentralapps.azureedge.net/githubhelloworld-appsource/latest/apps.zip’
    Set appSourceCopMandatoryAffixes = ‘hw_’
    Set appSourceCopSupportedCountries = ‘us,dk,gb’
    Set appFolders = ‘app,base’
    Set testFolders = ‘test’
    Set memoryLimit = ‘6G’
    Set additionalCountries = ”
    Set genericImageName = ”
    Set vaultNameForLocal = ‘IgoBuildVariables’
    Set bcContainerHelperVersion = ‘preview’
    Set installTestRunner = True
    Set installTestFramework = False
    Set installTestLibraries = False
    Set installPerformanceToolkit = False
    Set enableCodeCop = False
    Set enableAppSourceCop = True
    Set enablePerTenantExtensionCop = False
    Set useDefaultAppSourceRuleSet = True
    Set doNotSignApps = True
    Set doNotRunTests = False
    Set cacheImage = True
    Set CreateRuntimePackages = True
    BcContainerHelper version 2.0.9
    Get Secret buildpasswordSecret
    Get Secret insidersastokenSecret
    Get Secret licensefileSecret
    No app folders found
    At C:\Program Files\WindowsPowerShell\Modules\BcContainerHelper\2.0.9\AppHandling\Run-AlPipeline.ps1:333 char:5
    + throw “No app folders found”
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : OperationStopped: (No app folders found:String) [], RuntimeException
    + FullyQualifiedErrorId : No app folders found

    Like

Leave a comment