Skip to content

Commit 5b6214c

Browse files
authored
Merge pull request Azure#69 from Azure/ci-cd-azdo
feat: CI/CD For Infra using Azure Devops Pipeline
2 parents 4e9e7a9 + 0081582 commit 5b6214c

File tree

10 files changed

+317
-26
lines changed

10 files changed

+317
-26
lines changed

.ado/infra-deploy.yml

Lines changed: 193 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
1+
name: Build and deploy infrastructure as code to Azure
2+
3+
trigger:
4+
branches:
5+
include:
6+
- master
7+
paths:
8+
include:
9+
- bicep/**
10+
- '.ado/infra-deploy.yml'
11+
12+
parameters:
13+
- name: teardown
14+
displayName: Should teardown infrastructure?
15+
type: boolean
16+
default: false
17+
18+
pool:
19+
vmImage: 'ubuntu-latest'
20+
21+
variables:
22+
- name: REGISTRY
23+
value: ghcr.io
24+
- name: BACKEND_API_IMAGE_NAME
25+
value: azure/tasksmanager-backend-api
26+
- name: FRONTEND_APP_IMAGE_NAME
27+
value: azure/tasksmanager-frontend-webapp
28+
- name: BACKEND_PROCESSOR_IMAGE_NAME
29+
value: azure/tasksmanager-backend-processor
30+
- group: 'AcaApp'
31+
32+
33+
stages:
34+
- stage: Lint
35+
condition: eq('${{ parameters.teardown }}', false)
36+
jobs:
37+
- job: Lint
38+
displayName: Lint bicep files
39+
steps:
40+
- checkout: self
41+
- task: Bash@3
42+
displayName: Perform linting
43+
inputs:
44+
targetType: 'inline'
45+
script: |
46+
set -e
47+
echo "Linting bicep files"
48+
az bicep build --f bicep/main.bicep
49+
50+
- stage: Validate
51+
condition: and(succeeded(), eq('${{ parameters.teardown }}', false))
52+
dependsOn: Lint
53+
jobs:
54+
- job: Validate
55+
displayName: Create RG and Validate bicep template
56+
steps:
57+
- checkout: self
58+
- task: AzureCLI@2
59+
displayName: Create resource group
60+
inputs:
61+
azureSubscription: $(AZURE_SUBSCRIPTION)
62+
scriptType: 'bash'
63+
scriptLocation: 'inlineScript'
64+
inlineScript: |
65+
set -e
66+
echo "Creating resource group"
67+
if [[ $(az group exists -n $(RESOURCE_GROUP)) == true ]]
68+
then
69+
echo "Resource group already exists in the subscription"
70+
else
71+
az group create --name $(RESOURCE_GROUP) --location $(LOCATION)
72+
echo "Resource group created"
73+
fi
74+
75+
- task: AzureResourceManagerTemplateDeployment@3
76+
inputs:
77+
deploymentScope: 'Resource Group'
78+
azureResourceManagerConnection: $(AZURE_SUBSCRIPTION)
79+
action: 'Create Or Update Resource Group'
80+
resourceGroupName: $(RESOURCE_GROUP)
81+
location: $(LOCATION)
82+
templateLocation: 'Linked artifact'
83+
csmFile: 'bicep/main.bicep'
84+
csmParametersFile: 'bicep/main.parameters.json'
85+
deploymentMode: 'Validation'
86+
87+
- stage: Deploy
88+
displayName: Deploy infrastructure using GHCR image
89+
dependsOn: Validate
90+
condition: and(succeeded() , eq(variables.CONTAINER_REGISTRY_NAME, ''))
91+
jobs:
92+
- job: Deploy
93+
displayName: Deploy infrastructure using GHCR image
94+
steps:
95+
- checkout: self
96+
- task: AzureResourceManagerTemplateDeployment@3
97+
inputs:
98+
deploymentScope: 'Resource Group'
99+
azureResourceManagerConnection: $(AZURE_SUBSCRIPTION)
100+
action: 'Create Or Update Resource Group'
101+
resourceGroupName: $(RESOURCE_GROUP)
102+
location: '$(LOCATION)'
103+
templateLocation: 'Linked artifact'
104+
csmFile: 'bicep/main.bicep'
105+
csmParametersFile: 'bicep/main.parameters.json'
106+
overrideParameters: '-containerRegistryName -backendProcessorServiceImage $(REGISTRY)/$(BACKEND_PROCESSOR_IMAGE_NAME):latest -backendApiServiceImage $(REGISTRY)/$(BACKEND_API_IMAGE_NAME):latest -frontendWebAppServiceImage $(REGISTRY)/$(FRONTEND_APP_IMAGE_NAME):latest'
107+
deploymentMode: 'Incremental'
108+
deploymentName: 'azdo-deploy-$(Build.BuildId)'
109+
110+
- stage: Create_Import_ACR
111+
displayName: Create Azure Container Registry if needed
112+
dependsOn: Validate
113+
condition: and(succeeded(), ne(variables.CONTAINER_REGISTRY_NAME, ''), eq('${{ parameters.teardown }}', false))
114+
jobs:
115+
- job: Create_ACR
116+
displayName: Create Azure Container Registry if needed
117+
steps:
118+
- task: AzureCLI@2
119+
displayName: Create Azure Container Registry if needed
120+
inputs:
121+
azureSubscription: $(AZURE_SUBSCRIPTION)
122+
scriptType: 'bash'
123+
scriptLocation: 'inlineScript'
124+
inlineScript: |
125+
set -e
126+
echo "Creating Azure Container Registry if needed"
127+
if [[ $(az acr check-name -n $(CONTAINER_REGISTRY_NAME) -o tsv --query "nameAvailable") == false ]]
128+
then
129+
echo "ACR already exists."
130+
if [[ $(az acr list -g $(RESOURCE_GROUP) -o tsv --query "[?name=='$(CONTAINER_REGISTRY_NAME)']") == "" ]]
131+
then
132+
echo "ACR exists but not in the resource group $(RESOURCE_GROUP). Please select a different name for the ACR and update in repository variable."
133+
exit 1
134+
fi
135+
else
136+
az acr create --name $(CONTAINER_REGISTRY_NAME) --resource-group $(RESOURCE_GROUP) --sku Basic --location $(LOCATION)
137+
echo "ACR created"
138+
fi
139+
- job: Import_Image
140+
displayName: Import image to ACR from GHCR
141+
dependsOn: Create_ACR
142+
condition: succeeded()
143+
steps:
144+
- task: AzureCLI@2
145+
displayName: Import images from GitHub Container Registry
146+
inputs:
147+
azureSubscription: $(AZURE_SUBSCRIPTION)
148+
scriptType: 'bash'
149+
scriptLocation: 'inlineScript'
150+
inlineScript: |
151+
set -e
152+
echo "Import images from GitHub Container Registry"
153+
az acr import --name $(CONTAINER_REGISTRY_NAME) --source $(REGISTRY)/$(BACKEND_PROCESSOR_IMAGE_NAME):latest --image tasksmanager/tasksmanager-backend-processor --force
154+
az acr import --name $(CONTAINER_REGISTRY_NAME) --source $(REGISTRY)/$(BACKEND_API_IMAGE_NAME):latest --image tasksmanager/tasksmanager-backend-api --force
155+
az acr import --name $(CONTAINER_REGISTRY_NAME) --source $(REGISTRY)/$(FRONTEND_APP_IMAGE_NAME):latest --image tasksmanager/tasksmanager-frontend-webapp --force
156+
157+
- stage: Deploy_With_ACR
158+
displayName: Deploy infrastructure using ACR image
159+
dependsOn: Create_Import_ACR
160+
condition: and(succeeded(), ne(variables.CONTAINER_REGISTRY_NAME, ''), eq('${{ parameters.teardown }}', false))
161+
jobs:
162+
- job: Deploy
163+
displayName: Deploy infrastructure using ACR image
164+
steps:
165+
- checkout: self
166+
- task: AzureResourceManagerTemplateDeployment@3
167+
inputs:
168+
deploymentScope: 'Resource Group'
169+
azureResourceManagerConnection: $(AZURE_SUBSCRIPTION)
170+
action: 'Create Or Update Resource Group'
171+
resourceGroupName: $(RESOURCE_GROUP)
172+
location: $(LOCATION)
173+
templateLocation: 'Linked artifact'
174+
csmFile: 'bicep/main.bicep'
175+
csmParametersFile: 'bicep/main.parameters.json'
176+
overrideParameters: '-containerRegistryName $(CONTAINER_REGISTRY_NAME) -backendProcessorServiceImage $(CONTAINER_REGISTRY_NAME).azurecr.io/tasksmanager/tasksmanager-backend-processor:latest -backendApiServiceImage $(CONTAINER_REGISTRY_NAME).azurecr.io/tasksmanager/tasksmanager-backend-api:latest -frontendWebAppServiceImage $(CONTAINER_REGISTRY_NAME).azurecr.io/tasksmanager/tasksmanager-frontend-webapp:latest'
177+
deploymentMode: 'Incremental'
178+
deploymentName: 'azdo-deploy-$(Build.BuildId)'
179+
180+
- stage: Teardown
181+
displayName: Teardown infrastructure
182+
dependsOn: []
183+
condition: eq('${{ parameters.teardown }}', true)
184+
jobs:
185+
- job: Teardown
186+
displayName: Teardown infrastructure
187+
steps:
188+
- task: AzureResourceManagerTemplateDeployment@3
189+
inputs:
190+
deploymentScope: 'Resource Group'
191+
azureResourceManagerConnection: $(AZURE_SUBSCRIPTION)
192+
action: 'DeleteRG'
193+
resourceGroupName: $(RESOURCE_GROUP)

.github/workflows/infra-deploy.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ jobs:
137137
az acr import --name ${{ vars.CONTAINER_REGISTRY_NAME }} --source ${{ env.REGISTRY }}/${{ env.BACKEND_API_IMAGE_NAME }}:latest --image tasksmanager/tasksmanager-backend-api --force
138138
az acr import --name ${{ vars.CONTAINER_REGISTRY_NAME }} --source ${{ env.REGISTRY }}/${{ env.FRONTEND_APP_IMAGE_NAME }}:latest --image tasksmanager/tasksmanager-frontend-webapp --force
139139
140-
# This job deploys the bicep template to Azure subscription either using ACR images
140+
# This job deploys the bicep template to Azure subscription using ACR images
141141
deploy-with-acr-images:
142142
runs-on: ubuntu-latest
143143
if : ${{ github.event.inputs.teardown != 'true' }}
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
2+
# Deploy Infrastructure Using Azure DevOps
3+
4+
!!! info "Module Duration"
5+
30 minutes
6+
7+
In the [previous section](../../aca/10-aca-iac-bicep/iac-bicep.md), we demonstrated how Bicep scripts can be used to automate the deployment of infrastructure components. However, creating the container registry and deploying the Bicep scripts using the Azure CLI still required manual effort. For a more efficient and streamlined process, it's preferable to use automation. Azure DevOps is a great solution for automating workflows, and in this section, we'll explain how to create a Azure DevOps pipeline for deploying the infrastructure components of our application.
8+
9+
The workshop repository contains a Azure Devops Pipeline yaml file that will be used to deploy the infrastructure components of our application. Follow the steps below to create a devops pipeline to deploy the infrastructure components of our application.
10+
11+
!!! note
12+
The following instructions assume that you will utilize the forked Github repository both as the host for your YAML pipeline and the source code. However, it is possible to host the same assets in your Azure DevOps repository instead, if that is your preference. It is important to remember that if you choose to store your assets in your Azure DevOps repository, you will have to direct your Azure DevOps pipeline towards the Azure DevOps repository instead of the Github repository.
13+
14+
### Fork the GitHub repository
15+
16+
Start by forking the workshop repository to your GitHub account. Follow the steps below to fork the workshop:
17+
18+
1. Navigate to the workshop repository at [:material-github: Azure/aca-dotnet-workshop](https://github.com/Azure/aca-dotnet-workshop){target=_blank}
19+
2. Click the **Fork** button in the top-right corner of the page.
20+
3. Select your GitHub account to fork the repository to.
21+
4. Wait for the repository to be forked.
22+
23+
### Configure a Service Connection for GitHub and Azure Subscription
24+
25+
Before we start with creating pipeline, we need to configure service connection for GitHub and Azure Subscription. You can do this in either existing or new project.
26+
27+
#### Create a Service Connection for GitHub
28+
29+
Provide access to the repository forked above by creating a service connection to GitHub. You create a new pipeline by first selecting a GitHub repository and then a YAML file in repository at path [.ado/infra-deploy.yml](https://raw.githubusercontent.com/Azure/aca-dotnet-workshop/main/.ado/infra-deploy.yml){target=_blank}.
30+
31+
The repository in which the YAML file is present is called self repository. By default, this is the repository that your pipeline builds.
32+
33+
There are three authentication types for granting Azure Pipelines access to your GitHub repositories while creating
34+
a pipeline. Follow guide at [this link](https://learn.microsoft.com/en-us/azure/devops/pipelines/repos/github?view=azure-devops&tabs=yaml#access-to-github-repositories){target=_blank}
35+
to create service connection for GitHub.
36+
37+
38+
![AZDO GitHub Connection](../../assets/gifs/azdo-github-connection.gif)
39+
40+
#### Create Service Connection for Azure Subscription
41+
42+
Create a new service connection to your azure subscription by following the steps at [this link](https://docs.microsoft.com/en-us/azure/devops/pipelines/library/service-endpoints?view=azure-devops&tabs=yaml#create-a-service-connection){target=_blank}.
43+
44+
!!! note
45+
Update the created service connection role to have **[User Access Administrator](https://learn.microsoft.com/en-us/azure/role-based-access-control/built-in-roles#user-access-administrator)** role. This is required for pipeline to be able to perform role assignments in the infrastructure components deployed. To update the role of a service connection in Azure DevOps to have the User Access Administrator role, you can follow these steps:
46+
47+
- Navigate to the Azure portal and select the subscription where the service connection is created.
48+
49+
- Click on **Access control (IAM)** in the left-hand menu.
50+
51+
- Click on **Add role assignment**.
52+
53+
- For the **Assignment type** choose **Privileged administrator roles**.
54+
55+
- In the **Role** section choose **User Access Administrator**.
56+
57+
- In the **Members** section, search for the name of the service connection that you want to update and select it.
58+
59+
- Click **Save** to apply the changes.
60+
61+
### Configure Variable Group under Azure DevOps Library Section
62+
63+
Create a variable group named **AcaApp** under Library in your Azure Devops project. Make sure the pipeline has permissions to access the created variable group under **Pipeline permissions**.
64+
65+
This variable group will be used to store below details:
66+
67+
```bash
68+
# AZURE_SUBSCRIPTION: Name of the service connection created for Azure Subscription
69+
AZURE_SUBSCRIPTION=<service connection name>
70+
71+
# LOCATION: Azure region where resources will be deployed
72+
LOCATION=<location>
73+
74+
# RESOURCE_GROUP: Name of the resource group which will be created and where the resources will be deployed
75+
RESOURCE_GROUP=<resource group name>
76+
77+
# (OPTIONAL)CONTAINER_REGISTRY_NAME: Unique name of the container registry which will be created and where images will be imported
78+
CONTAINER_REGISTRY_NAME=<container registry name>
79+
```
80+
81+
!!! note
82+
83+
Repository variable `CONTAINER_REGISTRY_NAME` is only needed by pipeline if you intend to deploy images from a private Azure Container Registry (ACR). You may chose to skip defining this variable and the pipeline will use the [public github container registry images](https://github.com/orgs/Azure/packages?repo_name=aca-dotnet-workshop) to deploy the images.
84+
85+
### Trigger Azure Devops Pipeline
86+
87+
With these steps completed, you are now ready to trigger the Pipeline.
88+
89+
!!! success
90+
91+
Your Pipeline should be triggered and the infrastructure components of our application should be deployed successfully.
92+
93+
![GitHub Actions Workflow](../../assets/gifs/azdo-trigger.gif)
94+
95+
96+
??? info "Want to delete the resources deployed by the pipeline?"
97+
98+
Trigger the pipeline again select **checkbox** option named **Should teardown infrastructure?**.
99+
100+
![GitHub Actions Workflow](../../assets/gifs/azdo-delete.gif)

docs/aca/10-aca-iac-bicep/ci-cd-git-action.md

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,12 @@
11

2-
# Deploy infrastructure using GitHub Actions
2+
# Deploy Infrastructure Using GitHub Actions
33

44
!!! info "Module Duration"
55
30 minutes
66

7-
GitHub Actions is a great way to automate your workflow. In this section, we will create a GitHub Action workflow to
8-
deploy the infrastructure components of our application.
7+
In the [previous section](../../aca/10-aca-iac-bicep/iac-bicep.md), we demonstrated how Bicep scripts can be used to automate the deployment of infrastructure components. However, creating the container registry and deploying the Bicep scripts using the Azure CLI still required manual effort. For a more efficient and streamlined process, it's preferable to use automation. GitHub Actions is a great solution for automating workflows, and in this section, we'll explain how to create a GitHub Action workflow for deploying the infrastructure components of our application.
98

10-
The workshop repository contains a GitHub Action workflow file that will be used to deploy the infrastructure
11-
components of our application. Follow the steps below to create a GitHub Action workflow to deploy the
12-
infrastructure components of our application.
9+
The workshop repository contains a GitHub Action workflow file that will be used to deploy the infrastructure components of our application. Follow the steps below to create a GitHub Action workflow to deploy the infrastructure components of our application.
1310

1411
### Fork the GitHub repository
1512

@@ -109,8 +106,7 @@ locally, follow the steps below to configure the repository for OIDC authenticat
109106

110107
### Configure GitHub Repository Secrets
111108

112-
Configure secrets details in GitHub repo as described here in [create GitHub secrets](https://learn.microsoft.com/en-us/azure/developer/github/connect-from-azure?tabs=azure-cli%2Clinux#create-github-secrets).
113-
Use below values mapped to relevant secrets in GitHub.
109+
Configure secrets details in GitHub repo as described here in [create GitHub secrets](https://learn.microsoft.com/en-us/azure/developer/github/connect-from-azure?tabs=azure-cli%2Clinux#create-github-secrets). Use below values mapped to relevant secrets in GitHub.
114110

115111
```bash
116112
# AZURE_SUBSCRIPTION_ID
@@ -123,11 +119,11 @@ echo $APP_ID
123119

124120
### Configure GitHub Repository Variables
125121

126-
Configure repository variables as shown below:
122+
Configure repository variables in GitHub repo as described here in [create GitHub variables](https://docs.github.com/en/actions/learn-github-actions/variables). Use below values mapped to relevant variables in GitHub.
127123

128124
```bash
129125
# LOCATION: Azure region where resources will be deployed
130-
LOCATION=<location>
126+
LOCATION=<location. e.g. eastus>
131127

132128
# RESOURCE_GROUP: Name of the resource group which will be created and resources will be deployed
133129
RESOURCE_GROUP=<resource group name>
@@ -144,9 +140,7 @@ CONTAINER_REGISTRY_NAME=<container registry name>
144140

145141
### Trigger GitHub Actions Workflow
146142

147-
With these steps completed, you are now ready to trigger the GitHub Actions workflow name **Build and deploy
148-
infrastructure as code to Azure** using **workflow dispatch** to deploy the infrastructure components of our
149-
application.
143+
With these steps completed, you are now ready to trigger the GitHub Actions workflow named **Build and deploy infrastructure as code to Azure** using **workflow dispatch** to deploy the infrastructure components of the application.
150144

151145
!!! success
152146

0 commit comments

Comments
 (0)