The surprise,
At my team we have been happily using Azure DevOps (formerly known as VSTS, Visual Studio Online) building and releasing our projects into Azure. Yesterday, out of the blue, one of our releases broke. Azure DevOps AzureFileCopy Error. InvalidContentLink, unable to download deployment content from ‘https://…..’
Huh?
the analysis…
After some inspection this turned out to be a combination of the power of a Software as a Service like Azure Devops, combined with our desire of using the latest and greatest of these applications. We are using V2 of this task, which is in Preview and thus bound to change. In many cases these changes are adding or simplifying features for us developers, but in this case something broke.
In our release pipeline we are using a task called Azure File Copy V2. This task is using azcopy to copy some deployment related stuff into a blob container, in this case a linked ARM template.
The main template, let’s call it azuredeploy.json, is using a path to a linked ARM template. This path is created on the fly using an output parameter of the Azure File Copy task, the outputStorageURI. To this location, a subfolder is added for our linked temlate:
"templateLink": { "uri": "[concat(parameters('storageURI'),'/Microsoft.Storage/Project.StorageAccount.json', parameters('storageURISasToken'))]" }
On October 4th a change was done in this task: a trailing slash was added for compatibility with uri function (link to github)
Now, since the release pipeline in Azure DevOps is not as insensitive to duplicate slashes as an OS like Windows, problems rise when this output parameter is combined with our own second part of the template path. The leading slash, which was previously required for the template to work, was now causing a problem…
… and a solution
Luckily I found a workaround quickly because of the open source nature of these Azure pipeline tasks. I introduced a new variable that checks the existence of the trailing slash and adjusts the parameter to get something working again. After that I replaced parameters(‘storageURI) with variables(‘newStorageURI’) in the template. Linked templates don’t have to be updated, they will get the correct URI passed to them by azuredeploy.json.
"variables": {
"newStoragrURI": "[if(endsWith(parameters('storageURI'), '/'), take(parameters('storageURI'),add(length(parameters('storageUr')),-1)),parameters('_artifactsLocation'))]"
}
Another solution would of course have been to remove our own ‘extra’ leading slash from our templates, but I considered this solution more backwards- and forwards compatible:)