Continuous integration and delivery for an Azure Synapse Analytics workspace using DevOps - azure

I am using Azure DevOps for continuous integration and delivery for an Azure Synapse Analytics workspace where I have deploy the workspace to Development, Test, PreProduction and Production environments. The pipelines use parametrized LinkedServices, Datasets and Trigger. I am following these Microsoft documents document1, document2.
I need you to point me in right direction on how to pass variables from DevOps CI/CD to change the values according to the environment the Synpase workspace is deployed to?

Approach 1)
You can add Environment variable in the ARM template and use it for different environments in your pipeline like below:-
"connectionstring": {
"type": "string"
},
"environment": {
"type": "string"
}
},
"variables": {
"storageBlobDataContributorRoleID": "ba92f5b4-2d11-453d-a403-e96b0029c9fe",
"defaultDataLakeStorageAccountUrl": "[concat('https://', parameters('defaultDataLakeStorageAccountName'), '.dfs.core.windows.net')]",
"connectionString": "[if(equals(parameters('environment'), 'Production'), parameters('connectionStringProd'), parameters('connectionStringNonProd'))]"
Output:-
The above parameter checks, If the environment variable is set to Production, then it uses Production connection string or else other environment.
Approach 2)
You can also mention each production in the Azure DevOps Pipeline variables yaml script and use it in the Azure Pipelines like below:-
trigger:
- main
variables:
- name: DevEnvironment
value: "env-url"
- name: TestEnvironment
value: "env-url"
- name: PreProdEnvironment
value: "env-url"
- name: ProdEnvironment
value: "env-url"
stages:
- stage: Build
displayName: 'Build stage'
jobs:
- job: Build
displayName: 'Build job'
steps:
- script: echo 'Building the Synapse Analytics workspace...'
displayName: 'Build step'
- stage: DeployToDev
displayName: 'Deploy to Development'
dependsOn: Build
condition: eq(variables['Build.SourceBranch'], 'refs/heads/main')
jobs:
- job: Deploy
displayName: 'Deploy job'
steps:
- task: AzureResourceGroupDeployment#2
inputs:
deploymentScope: 'Resource Group'
azureResourceManagerConnection: 'MyAzureResourceManagerConnection'
subscriptionId: '<subscription-id>'
action: 'Create Or Update Resource Group'
resourceGroupName: '<resource-group-name>'
location: '<resource-group-location>'
templateLocation: 'Linked artifact'
csmFile: '<path-to-arm-template>'
csmParametersFile: '<path-to-arm-template-parameters>'
overrideParameters: '-environment $(DevEnvironment)'
- stage: DeployToTest
displayName: 'Deploy to Test'
dependsOn: Build
condition: and(eq(variables['Build.SourceBranch'], 'refs/heads/main'), eq(variables['Build.Reason'], 'Schedule'))
jobs:
- job: Deploy
displayName: 'Deploy job'
steps:
- task: AzureResourceGroupDeployment#2
inputs:
deploymentScope: 'Resource Group'
azureResourceManagerConnection: 'MyAzureResourceManagerConnection'
subscriptionId: '<subscription-id>'
action: 'Create Or Update Resource Group'
resourceGroupName: '<resource-group-name>'
location: '<resource-group-location>'
templateLocation: 'Linked artifact'
csmFile: '<path-to-arm-template>'
csmParametersFile: '<path-to-arm-template-parameters>'
overrideParameters: '-environment $(TestEnvironment)'
- stage: DeployToPreProd
displayName: 'Deploy to Pre-Production'
dependsOn: Build
condition: and(eq(variables['Build.SourceBranch'], 'refs/heads/main'), eq(variables['Build.Reason'], 'Manual'))
jobs:
- job: Deploy
displayName: 'Deploy job'
steps:
- task: AzureResourceGroupDeployment#2
inputs:
deploymentScope: 'Resource Group'
azureResourceManagerConnection: 'MyAzureResourceManagerConnection'
subscriptionId: '<subscription-id>'
action: 'Create Or Update Resource Group'
resourceGroupName: '<resource-group-name>'
location: '<resource-group-location>'
templateLocation: 'Linked artifact'
csmFile: '<path-to-arm-template>'
csmParametersFile: '<path-to-arm-template-parameters>'
overrideParameters: '-environment $(PreProdEnvironment)'
- stage: DeployToProd
displayName: 'Deploy to Production'
dependsOn: Build
condition: and(eq(variables['Build.SourceBranch'], 'refs/heads/main'), eq(variables['Build.Reason'], 'Manual'))
jobs:
- job: Deploy
displayName: 'Deploy job'
Approach 3)
Alternatively you can also configure different stages Dev, Test, Prod, Pre-Prod to deploy your Synapse workspace in specific environment like below:-

Related

Deploy to AzureDevOps - Error: Failed to get App service 'xxx' application settings

I want to deploy a Static Web App. Build and deploy stages are specified in azure-pipeline. The pipeline fails when it comes to AzureAppServiceSettings#1 task. That is what I got in log:
Got service connection details for Azure App Service:'xxx-dev-app'
Trying to update App Service Application settings. Data: {"testDb":"test"}
##[error]Error: Failed to get App service 'xxx-dev-app' application settings. Error: The Resource 'Microsoft.Web/sites/xxx-dev-app' under resource group 'xxx-dev-rg' was not found.
The task in azure-pipeline is:
- task: AzureAppServiceSettings#1
displayName: Azure App Service Settings
inputs:
azureSubscription: 'ServiceConnectionName'
appName: 'xxx-dev-app'
resourceGroupName: 'xxx-dev-rg'
appSettings: |
[
{
"name": "testDb",
"value": "test",
"slotSetting": false
}
]
DevOps has a Contributor access level both in the app and resource group.
Any suggestions what causes deployment failure?
I added a task for artifact downloading as it was proposed by #Daniel Mann, and it worked:
trigger:
- master
pool:
vmImage: ubuntu-latest
variables:
buildConfiguration: 'Release'
stages:
- stage: Build
jobs:
- job: Build
displayName: 'Build'
steps:
- task: DotNetCoreCLI#2
inputs:
command: 'build'
configuration: 'Release'
arguments: --output $(System.DefaultWorkingDirectory)/publish_output --configuration $(buildConfiguration)
- task: ArchiveFiles#2
displayName: 'Archive files'
inputs:
rootFolderOrFile: '$(System.DefaultWorkingDirectory)/publish_output'
includeRootFolder: false
archiveType: zip
archiveFile: $(Build.ArtifactStagingDirectory)/$(Build.BuildId).zip
replaceExistingArchive: true
- publish: $(Build.ArtifactStagingDirectory)/$(Build.BuildId).zip
artifact: drop
- stage: Test
dependsOn: Build
condition: succeeded()
jobs:
- job: Deploy
displayName: 'Deploy to Test'
steps:
- download: current
artifact: drop
- task: AzureWebApp#1
inputs:
azureSubscription: 'yyy'
appType: 'webApp'
appName: 'xxx'
package: '$(Pipeline.Workspace)/drop/*.zip'

YAML Parser error on Azure DevOps Pipeline

I'm getting the following error on my azure devop pipeline, it seems to relate towards parameters loop but despite writing the script multiple different ways I can't seem to get rid of it. YAML validators and my YAML linter don't detect an issue.
/azure-pipelines.yml (Line: 1, Col: 12): Unexpected value ''
Below is my code, it uses a template as well, which I will include beneath it.
azure-pipelines.yml
parameters:
steps:
- ${{ each project in parameters.projects }}:
- task: UsePythonVersion#0
displayName: 'Setting python version to 3.7'
inputs:
versionSpec: '3.7'
architecture: 'x64'
- script: |
pushd '$(System.DefaultWorkingDirectory)/${{ project }}'
pip install -r requirements.txt
displayName: 'Install prerequisites'
- task: ArchiveFiles#2
displayName: 'Archive files'
inputs:
rootFolderOrFile: '$(System.DefaultWorkingDirectory)/${{ project }}'
includeRootFolder: false
archiveFile: '$(System.DefaultWorkingDirectory)/${{ project }}.zip'
- task: PublishBuildArtifacts#1
inputs:
PathtoPublish: '$(System.DefaultWorkingDirectory)/${{ project }}.zip'
artifactName: 'drop'
- task: AzureResourceManagerTemplateDeployment#3
displayName: 'ARM Template deployment: Resource Group scope'
inputs:
azureResourceManagerConnection: $(serviceConnectionName)
subscriptionId: $(subscriptionId)
resourceGroupName: $(resourceGroupName)
location: $(resourceGroupLocation)
csmFile: 'deployment_template.json'
overrideParameters: '-appName ${{ project }} -storageAcctName $(storageAcctName) -hostingPlanName $(hostingPlanName)'
- task: AzureFunctionApp#1
inputs:
azureSubscription: $(serviceConnectionName)
appType: functionAppLinux
appName: ${{ project }}
package: '$(System.DefaultWorkingDirectory)/${{ project }}.zip'
Template - deploy-functions.yml
trigger:
- main
variables:
- group: 'AzFunctionsAppVariableGroup'
pool:
vmImage: ubuntu-18.04
steps:
- template: azure-pipelines.yml
parameters:
projects:
- ProjectName1
If I throw your azure-pipelines.yml into the pipeline editor in Azure DevOps, it marks the line ending of parameters: with the warning
"Incorrect type. Expected "array"."
I didn't work with templates on pipelines so far, but from the MS doc page, it seems that you need to specify the parameters that you are passing like so:
#azure-pipelines.yml
parameters:
- name: projects
type: object #object, since you are passing a list of strings
steps:
- ${{ each project in parameters.projects }}:
#...
It's suggested that you could enable the feature of YAML template editor with picture below and process the test.

AzureResourceManagerTemplateDeployment fails to find template using pattern when executed in Deployment Job

I have been experimenting with Azure Logic Apps and wanted to figure out a way to codify the deployment process so that I could setup a CI/CD pipeline with secrets and all the good stuff.
So I set out with a yml file with multiple ways to deploy the same Logic App.
Hardcoding the values of the input params to the task like Connected Service, Subscription, Resource Group etc. in a step inside a regular job.
Doing the same thing but inside a Deployment job.
Use Pipeline variables to extract these values and repeat as 1 and 2.
1 and 2 again but this time using Pipeline Variables that are marked as Secrets
so on and so forth.
However, everytime I run the AzureResourceManagerTemplateDeployment#3 inside a deployment job, it fails to find the ARM template file.
Why is the deployment job unable to find the ARM Template using the pattern that works when the it is not run as a deployment job?
Do deployment jobs not have access to the build directory?
How do I help the deployment job to find the file? Should I be giving it a link to the template file instead of a pattern?
Everytime I search for the AzureResourceManagerTemplateDeployment task docs, I get the docs page of AzureResourceGroupDeployment task which is very similar but not the same
https://learn.microsoft.com/en-us/azure/devops/pipelines/tasks/deploy/azure-resource-group-deployment?view=azure-devops#troubleshooting
As I was about to post this question, I did more searching online and came across the original docs of the AzureResourceManagerTemplateDeployment which states that if the file is part of a repository then one must specify the path to the ARM template using the help of system variables.
csmFile: "$(Build.Repository.LocalPath)/**/LogicApp.json"
csmParametersFile: "$(Build.Repository.LocalPath)/**/LogicApp.parameters.json"
I can confirm that this did not work either.
What could I be missing?
stages:
- stage: 'HardcodedJobStage'
displayName: 'HardcodedJobStage'
jobs:
- job: 'HardcodedJob'
displayName: HardcodedJob
pool:
vmImage: ubuntu-latest
workspace:
clean: all
steps:
- task: AzureResourceManagerTemplateDeployment#3
inputs:
deploymentScope: 'Resource Group'
ConnectedServiceName: 'Subscription (e6d1dg8c-bcd6-4713-b2f1-c9a0375d687d)'
subscriptionName: 'e6d1dg8c-bcd6-4713-b2f1-c9a0375d687d'
action: 'Create Or Update Resource Group'
resourceGroupName: 'AzureLogicApp'
location: 'UK South'
templateLocation: 'Linked artifact'
csmFile: '**/LogicApp.json'
csmParametersFile: '**/LogicApp.parameters.json'
deploymentMode: 'Incremental'
- stage: 'HardCodedDeployJobStage'
displayName: 'HardCodedDeployJobStage'
jobs:
- deployment: 'HardCodedDeployJob'
displayName: HardCodedDeployJob
pool:
vmImage: ubuntu-latest
workspace:
clean: all
environment: development
strategy:
runOnce:
deploy:
steps:
- task: AzureResourceManagerTemplateDeployment#3
inputs:
deploymentScope: 'Resource Group'
ConnectedServiceName: 'Subscription (e6d1dg8c-bcd6-4713-b2f1-c9a0375d687d)'
subscriptionName: 'e6d1dg8c-bcd6-4713-b2f1-c9a0375d687d'
action: 'Create Or Update Resource Group'
resourceGroupName: 'AzureLogicApp'
location: 'UK South'
templateLocation: 'Linked artifact'
csmFile: '**/LogicApp.json'
csmParametersFile: '**/LogicApp.parameters.json'
deploymentMode: 'Incremental'
The problem here was that I had to publish the templates as artifacts and share it between the stages.
So I copied the ARM template json files to a folder using CopyFiles task and then used the PublishPipelineArtifact task to publish the contents as a pipeline artifact. This can then be referenced later by the following stage by using the DownloadPipelineArtifact task.
Now my YAML looks something like:
stages:
- stage: 'HardcodedJobStage'
displayName: 'HardcodedJobStage'
jobs:
- job: 'HardcodedJob'
displayName: HardcodedJob
pool:
vmImage: ubuntu-latest
workspace:
clean: all
steps:
- task: AzureResourceManagerTemplateDeployment#3
inputs:
deploymentScope: 'Resource Group'
ConnectedServiceName: 'Subscription (e6d1dg8c-bcd6-4713-b2f1-c9a0375d687d)'
subscriptionName: 'e6d1dg8c-bcd6-4713-b2f1-c9a0375d687d'
action: 'Create Or Update Resource Group'
resourceGroupName: 'AzureLogicApp'
location: 'UK South'
templateLocation: 'Linked artifact'
csmFile: '**/LogicApp.json'
csmParametersFile: '**/LogicApp.parameters.json'
deploymentMode: 'Incremental'
- task: CopyFiles#2
inputs:
Contents: $(Build.SourcesDirectory)/AzureLogicApp/**/*.json
targetFolder: $(Build.ArtifactStagingDirectory)
- task: PublishPipelineArtifact#1
inputs:
targetPath: $(Build.ArtifactStagingDirectory)
artifactName: armtemplate
- stage: 'HardCodedDeployJobStage'
displayName: 'HardCodedDeployJobStage'
jobs:
- deployment: 'HardCodedDeployJob'
displayName: HardCodedDeployJob
pool:
vmImage: ubuntu-latest
workspace:
clean: all
environment: development
strategy:
runOnce:
deploy:
steps:
- task: DownloadPipelineArtifact#2
inputs:
artifact: armtemplate
- task: AzureResourceManagerTemplateDeployment#3
inputs:
deploymentScope: 'Resource Group'
ConnectedServiceName: 'Subscription (e6d1dg8c-bcd6-4713-b2f1-c9a0375d687d)'
subscriptionName: 'e6d1dg8c-bcd6-4713-b2f1-c9a0375d687d'
action: 'Create Or Update Resource Group'
resourceGroupName: 'AzureLogicApp'
location: 'UK South'
templateLocation: 'Linked artifact'
csmFile: $(Pipeline.Workspace)/armtemplate/**/LogicApp.json
csmParametersFile: $(Pipeline.Workspace)/armtemplate/**/LogicApp.parameters.json
deploymentMode: 'Incremental'
Assuming your yml pipeline is defined in the same git repository as the LogicApp json files, you could use csmFile as an absolute path with the 'root' being the git repo root folder. For example, if your logicapp files are in /app/logicapp/LogicApp.json, and your yml pipeline is in the same git repo but maybe in /pipelines/pipeline.yml, you could then set csmFile's value to app/logicapp/LogicApp.json (and same for csmParametersFile).

AzurePipeline error: Could not find any file matching the template file pattern

I have the following pipeline
variables:
azureSubscription: ...
stages:
- stage: Deploy
displayName: Deploy stage
dependsOn: Build
condition: succeeded()
jobs:
- deployment: Deploy
displayName: Deploy
environment: 'development'
strategy:
runOnce:
deploy:
steps:
- task: AzureResourceGroupDeployment#2
inputs:
action: 'Create Or Update Resource Group'
resourceGroupName: '...'
location: '...'
templateLocation: 'Linked artifact'
csmFile: '$(Pipeline.Workspace)/azure-deploy.json'
deploymentMode: 'Incremental'
The repo has the following files (at the root directory)
azure-pipelines.yaml
azure-deploy.json
and only a master branch.
I have tried:
azure-deploy.json
**azure-deploy.json
**/*azure-deploy.json
$(Build.SourcesDirectory)/azure-deploy.json
$(Pipeline.Workspace)/azure-deploy.json
$(System.DefaultWorkingDirectory)/azure-deploy.json
Having read:
Azure Pipeline Error: Could not find any file matching the template file pattern
VSTS Pipeline Deployment of ARM Error: Could not find any file matching the template file pattern
https://github.com/microsoft/azure-pipelines-tasks/issues/11520
to no avail. Any ideas?
Update: I have added a publish pipeline as suggested by #ShaykiAbramczyk
Now I get a Template file pattern matches a directory instead of a file: /home/vsts/work/1/azure-deploy.json
- stage: Build
displayName: Build stage
jobs:
- job: Build
displayName: Build
pool:
vmImage: $(vmImageName)
steps:
- task: PublishPipelineArtifact#1
inputs:
targetPath: '$(Pipeline.Workspace)'
artifact: 'azure-deploy.json'
publishLocation: 'pipeline'
"A deployment job doesn't automatically clone the source repo. You can checkout the source repo within your job with checkout: self."
Source: https://learn.microsoft.com/en-us/azure/devops/pipelines/process/deployment-jobs?view=azure-devops
Example from my setup, I put checkout: self as the first step and now my repository is cloned before before executing the Azure PowerShell:
strategy:
runOnce:
deploy:
steps:
- checkout: self
- task: AzurePowerShell#5
displayName: Setup Network
inputs:
It is a good strategy to go for the multi-stage pipelines for what you are doing.
Build is for composing your artifacts.
Deployment jobs is for the publishing part.
So you are on the right track.
If you need sources during the deployment jobs then use the checkout step to fetch the sources. ref. Repo Checkout docs.
Just my two cents
Because you use deployment job the sources from the master branch didn't download into the agent.
You need to publish the files in the build stage and consume them in the deployment - with pipeline artifacts.
Or, just run the AzureResourceGroupDeployment in a regular job, than the .json file will be in the agent.
My objective was to create a Blank and Starter Resource Group in Azure and nothing else. And this was repeatedly giving me the error
Template file pattern matches a directory instead of a file: /home/vsts/work/1/s
And thats what got me here.
I finally sorted that out with Stringfello's
- checkout self
step.
My full pipeline is as follows.
variables:
- name: finalBuildArtifactName
value: 'aspNetCoreDropFromYaml123'
- name: BuildParameters.RestoreBuildProjects
value: '**/*.csproj'
- name: BuildParameters.TestProjects
value: '**/*[Tt]ests/*.csproj'
- name: buildConfiguration
value: 'Release'
trigger:
- master
name: $(date:yyyyMMdd)$(rev:.r)
stages:
- stage: Build ##Basically prints out some vars and copies the template files.
jobs:
- job: buildWebApp
displayName: Build Stage for somepurpose
pool:
vmImage: ubuntu-latest
steps:
- script: |
echo build.artifactstagingdirectory and build.buildnumber are as follows.
echo $(build.artifactstagingdirectory) $(build.buildnumber)
echo $(projects)
echo $(BuildConfiguration)
echo Pipeline.Workspace is $(Pipeline.Workspace)
echo The current branch is - $(Build.SourceBranchName)!!.
echo $(finalBuildArtifactName)
echo "This is the build pipe line. This produces the necessary artifacts for subsequent release pipeline."
displayName: 'Command Line Script to write out some vars'
- powershell: |
# Write your PowerShell commands here.
Write-Host "This is from power shell command task"
Write-Host "This writes out the env vars"
get-childitem -path env:*
displayName: 'PowerShell script to write out env vars'
# The following task is needed. This copies the arm template files.
# Created these templates from Visual studio 2019 as follows.
# Right click your solution and Add -> New Project -> Azure Resource Group and gave the name Vivek_Aks_Rg
- task: CopyFiles#2
inputs:
SourceFolder: 'iac/ArmTemplates/Vivek_Aks_Rg/'
Contents: 'azuredeploy*.json'
TargetFolder: '$(build.artifactStagingDirectory)/ArmTemplates'
- task: PublishBuildArtifacts#1
displayName: Publish Artifact
condition: succeededOrFailed()
inputs:
PathtoPublish: '$(build.artifactstagingdirectory)'
ArtifactName: '$(finalBuildArtifactName)'
PublishLocation: 'Container'
- stage: DeployToDev
displayName: Deploy to Dev Env
jobs:
- deployment:
pool:
vmImage: ubuntu-latest
environment: Dev
strategy:
runOnce:
deploy:
steps:
- checkout: self
- task: AzureResourceManagerTemplateDeployment#3
displayName: 'Create Azure App Service in a Given Resource Group'
inputs:
deploymentScope: 'Subscription'
azureResourceManagerConnection: 'Pay-As-You-Go(123YourSubscriptionId)'
subscriptionId: '123YourSubscriptionId'
action: 'Create Or Update Resource Group'
resourceGroupName: 'YourResourceGroupName'
location: 'Central India'
csmFile: '$(Pipeline.Workspace)/$(finalBuildArtifactName)/ArmTemplates/azuredeploy.json'
csmParametersFile: '$(Pipeline.Workspace)/$(finalBuildArtifactName)/ArmTemplates/azuredeploy.parameters.json'
deploymentMode: 'Incremental'

Azure Devops YAML multi staged pipeline artifact issue

My Azure Devops YAML multi staged pipeline is giving me an error when doing an ARM deployment. The issue is downloading the artifact from the build. See the error here:
Error
It looks like the artifact is not being downloaded, in the jobs before they are being downloaded. The difference is that the production deployment needs to be approved and therefore it is inside a -deployment and not in a -job.
See the code here:
- stage: Deploy_Prod
dependsOn: Deploy_Acc
# Only deploy when build is from master
condition: and(succeeded(), eq(variables['build.sourceBranch'], 'refs/heads/master'))
jobs:
- deployment: 'Deploy_Prod'
pool:
vmImage: 'ubuntu-latest'
# Set envrironment for approval, see https://dev.azure.com/dept/DTNL%20-%20CBRE/_environments/5?view=resources
environment: cbre_prod
strategy:
runOnce:
deploy:
steps:
# Download build artifact
- download: current
artifact: Templates
# Deploy production infra
- task: AzureResourceManagerTemplateDeployment#3
displayName: 'Deploy production infrastructure'
inputs:
deploymentScope: 'Resource Group'
ConnectedServiceName: '***'
subscriptionName: '***'
action: 'Create Or Update Resource Group'
resourceGroupName: '***'
location: 'West Europe'
templateLocation: 'Linked artifact'
csmFile: 'azuredeploy.json'
csmParametersFile: 'azuredeploy-parameters-prod.json'
deploymentMode: 'incremental'
Does anybody know how I can download the artifact from a multi staged pipeline, while using -deployment instead of -job?
Working version with job, just for reference:
- stage: Deploy_Acc
dependsOn: Deploy_Test
# Only deploy when build is from master
condition: and(succeeded(), eq(variables['build.sourceBranch'], 'refs/heads/master'))
jobs:
- job: 'Deploy_Acc'
pool:
vmImage: 'ubuntu-latest'
steps:
# Download build artifact
- download: current
artifact: Templates
# Deploy acceptation infra
- task: AzureResourceManagerTemplateDeployment#3
displayName: 'Deploy acceptation infrastructure'
inputs:
deploymentScope: 'Resource Group'
ConnectedServiceName: '***'
subscriptionName: '***'
action: 'Create Or Update Resource Group'
resourceGroupName: '***-acc'
location: 'West Europe'
templateLocation: 'Linked artifact'
csmFile: 'azuredeploy.json'
csmParametersFile: 'azuredeploy-parameters-acc.json'
deploymentMode: 'incremental'
The documentation on deployment jobs suggests that you may not need to instruct it to download the artifact, that it happens automatically?
deploy: Used to run steps that deploy your application. Download artifact task will be auto injected only in the deploy hook for deployment jobs. To stop downloading artifacts, use - download: none or choose specific artifacts to download by specifying Download Pipeline Artifact task.
I don't see anything wrong with your code. In your artifact creation, have you used "Publish Pipeline Artifact"?

Resources