With Dynamics 365 for Finance and Operations Azure DevOps Tasks you can easily setup Continuous integration pipelines. Build – Release (upload to LCS Asset Library and deploy). Everything works like a charm, until you install new Service update to your environment (build). If you run build-release pipelines after update, task “Dynamics Lifecycle Services (LCS) Asset Upload” in Release pipeline ends with an error like:
Leaf path not found: 'd:\a\r1\a\_Unified Operations platform - Build Main\Packages\AXDeployableRuntime_7.0.5286.35426_2019.7.9.1.zip'
This is because task for LCS upload has hardcoded AOS service version number in package filename at “File to upload”. This number changes after Service update.
To fix the problem you have to update package filename with actual AOS service version number.
But, when you update (and you have to every month, right?) build environment again, version changes and you must go and manually edit Upload step to new version number again. As we do not like manual work, especially periodic manual work, how to fix this once for all?
Long story short: Get actual build AOS service version number, save it to variable and then replace hardcoded number in Upload step by variable value.
Problem #1 How to get AOS service number into variable
I believe that there are more ways how to achieve this, but I used Powershell task together with great and powerful d365fo.tools.
EDIT: You may have Build server in Microsoft subscription. Therefore no Admin rights on station, so you are not able to install d365fo.tools for all users. I edited get-d365installedservice cmdlet and took just part getting AOS service number. It loses logic for getting paths from registry, but works fine.
Problem #2 – Save & Load variable
There are few limitations in Azure DevOps when working with variables: by design you cannot share variables between Build and Release pipelines, you cannot share custom edited variables between jobs and you cannot query AOS version in same job as you do upload to Asset Library (different agents pool types).
So, what we will do? How about to save variables from Build pipeline “somewhere” and load them during Release pipeline? Fortunately there is an Azure DevOps extension which solve this for us: “Variable Tools for Azure DevOps Services”.
OK, let’s go through process step by step:
Prepare
- In build and release pipelines create variable for storing AOS service number ( AOS_ServiceVersion_Build ). You can leave it blank (I put value “empty”for debugging reason).
- On your build VM install d365fo.tools.
- Install “Variable tools for Azure DevOps Services” extensions into you Azure DevOps environment.
Build Pipeline
- Create Powershell task for saving AOS service number into variable.
- Type: Inline Script
- Inline Script:
$AOSServiceVersion = (get-d365installedservice | Where-Object {$_.ServiceName -eq 'AOSService'} ).version
Write-Host $AOSServiceVersion
Write-Host "##vso[task.setvariable variable=AOS_ServiceVersion_Build]$AOSServiceVersion"
EDIT: If you can’t or don’t want to install d365fo.tools on build server use this, more specific script. Result and other steps will be same:
$AOSServicePath = "C:\DynamicsAX\InstallationRecords\ServiceModelInstallationRecords"
$AOSServiceFile = Get-ChildItem -Path $AOSServicePath -Filter "AOSService_Current.xml"
$AOSServiceVersion = (Select-Xml -XPath "/ServiceModelInstallationInfo/Version" -Path
$AOSServiceFile.fullname).Node."#Text"
Write-Host "##vso[task.setvariable variable=AOS_ServiceVersion_Build]$AOSServiceVersion"
2. Use “Variable Save Task” to save variable. This task will save all variables with prefix AOS into meta-aos.json file
- Prefixes: AOS
- Output Path : “$(Build.ArtifactStagingDirectory)\AOSMetadata”
3.Last step in build pipeline is Publishing Artifact.
- Path to publish: $(Build.ArtifactStagingDirectory)\AOSMetadata
- ArtifactName: AOSMetadata
- Artifact publish location: Azure Pipelines
Release pipeline
1. To load json file with AOS variable add “Variable Load Task” to your Upload job. Select path where artifact meta-aos.json has been saved by Build pipeline. You should be able to browse it. In our case:
$(System.DefaultWorkingDirectory)/_Unified Operations platform - Build
Main/AOSMetadata/meta-aos.json
After this step you will have variable $AOS_Service_Version_Build set and ready for use.
2.Update LCS Asset Upload task. Replace hardcoded service version with variable:
- File to upload:
$(System.DefaultWorkingDirectory)/_Unified Operations platform - Build Main/Packages/AXDeployableRuntime_$(AOS_SERVICEVERSION_BUILD)_$(Build.BuildNumber).zip
That’s it. Now you can install Service Updates without re-configuring you release pipelines anymore. I’ve tested this setup when updating from App1003PU27 to App1004PU28 and it worked without any issue.