Implementing CI/CD with Azure DevOps: Azure Artifacts and Release Pipelines

Implementing CI/CD with Azure DevOps: Azure Artifacts and Release Pipelines

Image

Overview

This document provides a step-by-step guide on setting up a CI/CD pipeline using Azure Artifacts and Azure DevOps. The project involves deploying a sample Nike landing page using Tailwind CSS.

Key Points

  1. Introduction to Azure Artifacts:

    • Azure Artifacts is a central repository for storing and consuming packages.

    • Benefits include maintaining history, auditing, and consuming packages across multiple pipelines and projects.

  2. Setting Up the Project:

    • Create a new Azure DevOps project.

    • Import the sample project repository from GitHub.

  3. Creating Azure Resources:

    • Create an Azure Web App service.

    • Configure application settings to refresh the cache after deployments.

  4. CI Pipeline Configuration:

    • Create a CI pipeline in YAML.

    • Install dependencies and build the project using Tailwind CSS.

    • Publish the package to Azure Artifacts.

  5. Managing Permissions:

    • Ensure the build service account has contributor access to the Azure Artifacts feed.
  6. Creating a Release Pipeline:

    • Set up a release pipeline to deploy the package from Azure Artifacts to the Azure Web App.

    • Enable triggers for package promotion.

  7. Deployment and Verification:

    • Deploy the application and verify the deployment by accessing the web app.

    • Use Azure portal tools for troubleshooting and log analysis.

Tools and Technologies Used

  • Azure DevOps: For CI/CD pipeline setup and project management.

  • Azure Artifacts: For package management and storage.

  • Azure Web App: For hosting the deployed application.

  • Tailwind CSS: For building the project.

  • GitHub: For source code repository.

  • Kudu Console: For interacting with the web app's underlying host operating system.

Prerequisites

Before diving into this project, here are some skills and tools you should be familiar with:

Need to create a Personal Access Token (PAT)-

  • [x] Terraform code

    Note: Replace resource names and variables as per your requirement in terraform code

    • Update terraform.tfvars.
  • [x] App Repo (Nike App)

  • [x] Azure Account: You’ll need an Azure account to create resources like virtual Machine, and AKS clusters, and manage pipelines.

  • [x] Terraform Knowledge: Familiarity with Terraform in provisioning, managing, and cleaning up infrastructure.

  • [x] GitHub: Experience with GitHub for version control and managing repositories.

  • [x] Command-Line Tools: Basic comfort with using the command line for managing infrastructure and services.

  • [x] Basic CI/CD Knowledge: Some understanding of Continuous Integration and Deployment is recommended.

  • [x] Linux VM: Docker must be installed on a Linux virtual machine to run containers.

Setting Up Infrastructure

I have created a Terraform code to set up the entire infrastructure, including the installation of required applications and tools.

  • ⇒ Virtual machines will be created named as "devopsdemovm"

  • ⇒ Docker Install

  • ⇒ Azure Cli Install

Virtual Machine creation

First, we'll create the necessary virtual machines using terraform code.

Below is a terraform Code:

Once you clone repo and run the terraform command.

$ ls -l
-rw-r--r-- 1 bsingh 1049089   261 Feb 10 11:10 azure_artifact.tf 
-rw-r--r-- 1 bsingh 1049089   437 Feb 10 10:48 DevOps_UI.tf      
-rw-r--r-- 1 bsingh 1049089   920 Feb 10 10:52 output.tf
-rw-r--r-- 1 bsingh 1049089   528 Jan  8 15:25 provider.tf       
drwxr-xr-x 1 bsingh 1049089     0 Feb  7 18:08 scripts/
-rw-r--r-- 1 bsingh 1049089  6261 Feb 10 09:45 Selfthost-Agent.tf
-rw-r--r-- 1 bsingh 1049089   274 Jan  8 13:28 ssh_key.tf
-rw-r--r-- 1 bsingh 1049089  1871 Feb 10 11:06 terraform.tfvars
-rw-r--r-- 1 bsingh 1049089  2847 Feb 10 10:52 variable.tf
-rw-r--r-- 1 bsingh 1049089   682 Feb 10 09:34 web-app.tf

You need to run the following terraform command.

terraform init
terraform fmt
terraform validate
terraform plan
terraform apply 
# Optional <terraform apply --auto-approve>
  • Terraform Output:

Image

Once you run the terraform command, then we will verify the following things to make sure everything is setup via a terraform.

Inspect the Cloud-Init logs:

Once connected to VM then you can check the status of the user_data script by inspecting the log files

# Primary log file for cloud-init
sudo tail -f /var/log/cloud-init-output.log
                    or 
sudo cat /var/log/cloud-init-output.log | more
  • If the user_data script runs successfully, you will see output logs and any errors encountered during execution.

  • If there’s an error, this log will provide clues about what failed.

Verify software Installation

  • [x] Docker version
azureuser@devopsdemovm:~$  docker --version
Docker version 24.0.7, build 24.0.7-0ubuntu4.1

docker ps -a
azureuser@devopsdemovm:~$ docker ps

azureuser@devopsdemovm:~$ docker image ls
REPOSITORY                                       TAG       IMAGE ID       CREATED       SIZE
mc1arke/sonarqube-with-community-branch-plugin   latest    307499b84ff2   13 days ago   1.13GB

azureuser@devopsdemovm:~$ docker container ls
CONTAINER ID   IMAGE                                            COMMAND                  CREATED          STATUS          PORTS                                       NAMES
973939f2cdc7   mc1arke/sonarqube-with-community-branch-plugin   "/opt/sonarqube/dock…"   41 minutes ago   Up 41 minutes   0.0.0.0:9000->9000/tcp, :::9000->9000/tcp   sonar
  • [x] Azure CLI version
azureuser@devopsdemovm:~$ az version
{
  "azure-cli": "2.67.0",
  "azure-cli-core": "2.67.0",
  "azure-cli-telemetry": "1.1.0",
  "extensions": {}
}
  • [x] Java Version
azureuser@devopsdemovm:~$ java --version
openjdk 17.0.13 2024-10-15
OpenJDK Runtime Environment (build 17.0.13+11-Ubuntu-2ubuntu122.04)
OpenJDK 64-Bit Server VM (build 17.0.13+11-Ubuntu-2ubuntu122.04, mixed mode, sharing)
  • [x] Trivy Version
azureuser@devopsdemovm:~$ trivy --version
Version: 0.58.1
  • [x] Maven Version
azureuser@devopsdemovm:~$ mvn -version
Apache Maven 3.6.3
Maven home: /usr/share/maven
Java version: 17.0.13, vendor: Ubuntu, runtime: /usr/lib/jvm/java-17-openjdk-amd64
Default locale: en, platform encoding: UTF-8
OS name: "linux", version: "6.5.0-1025-azure", arch: "amd64", family: "unix"
azureuser@devopsdemovm:~$

Step-by-Step Process:

Verify application accessibility

  • Configure Web App

    • I tried to open in the browser and got the below page it is because of by default azure cache is enabled and we have to disable it.

    • Go to Web App and add the following settings.

      Name: WEBSITE_DYNAMIC_CACHE
      Value: 0

      Name: WEBSITE_ENABLE_SYNC_UPDATE_SITE
      Value: never

      Name: WEBSITE_LOCAL_CACHE_OPTION
      Value: never

Image

  • Restart the webapp application.

  • Verify default Application accessible or not.

  • Image

  • Default App is accessible.

  • Image

Verify Project Status

  • Select the Organization> verify project is created or not.

    Image

Verify Repo Status

  • select the project and verify repo is imported or not.

    Image

Configure Service Connection

  • First create Service Connection in Azure Devops.

  • Once you create a connection then note it down the connection Name, because that name would be used in pipeline.

  • On agent machine, make sure login with azure login and connection is active, if not then login with following.

      az login --use-device-code
    
  • Create Service Principal via Azure CLI

  • Need to Create a service Connection in pipeline first.

    • Pipeline> Service Connections>Create Service Connection> select "Azure Service Connection"

      Image

      Image

      Image

      Image

      Image

      Image

Configure Self-hosted Linux Agent.

  • Need to configure Self-hosted Linux agents/integrate to Azure DevOps

  • Take a putty session of the virtual machine and follow the below procedure to configure the self-hosted agent in the pipeline.

cd myagent
azureuser@devopsdemovm:~/myagent$ ls -l
total 144072
drwxrwxr-x 26 azureuser azureuser     20480 Nov 13 10:54 bin
-rwxrwxr-x  1 azureuser azureuser      3173 Nov 13 10:45 config.sh
-rwxrwxr-x  1 azureuser azureuser       726 Nov 13 10:45 env.sh
drwxrwxr-x  7 azureuser azureuser      4096 Nov 13 10:46 externals
-rw-rw-r--  1 azureuser azureuser      9465 Nov 13 10:45 license.html
-rw-rw-r--  1 azureuser azureuser      3170 Nov 13 10:45 reauth.sh
-rw-rw-r--  1 azureuser azureuser      2753 Nov 13 10:45 run-docker.sh
-rwxrwxr-x  1 azureuser azureuser      2014 Nov 13 10:45 run.sh
-rw-r--r--  1 root      root      147471638 Nov 13 12:22 vsts-agent-linux-x64-4.248.0.tar.gz

Update the ./config.sh Command:

  **project: Nike-Website**: Specifies the project name for scoping.
  **pool: nike-website-pool**: Links the agent to the specific project-level pool.
# Configuration of the self-hosted agent
cd myagent
./config.sh --unattended --url https://dev.azure.com/<OrganizationName> --auth pat --token <Tocken_value> --pool <nike-website-pool> --agent aksagent --acceptTeeEula
# Start the agent service
sudo ./svc.sh install
sudo ./svc.sh start

Image

  • Steps to Configure the Agent for Project Context:

    • Log in to the Azure DevOps portal.

    • Agent Pool is already create at the Project Level:

    • Navigate to your organization (https://dev.azure.com/<Organization_name>).

    • Open the Nike-Website project.

    • Go to Project Settings > Agent Pools.

    • Image

    • Pool to link existing one.

      Image

  • Verify the Agent Registration in DevOps Portal:

    • After running the command, the agent should be registered in the nike-website-pool.

    • Select the Organization> Organization setting> Pipeline> Agent Pools

      Image

    • Go to Nike-Website > Project Settings > Agent Pools to confirm the agent is listed and active.

      Image

Set Permission for Azure Artifact.

  • To add the permission

  • Image

  • Add the following permission to make it a working pipeline.

  • Image

    Image

Configure CI Pipeline.

  • Configure Build pipeline.

Image

Image

Image

Build and install npm

Image

stages:
  - stage: Build
    jobs:
    - job: Build
      steps:
      - task: Npm@1
        inputs:
          command: 'custom'
          customCommand: 'install -D tailwindcss postcss autoprefixer'
      - task: Npm@1
        inputs:
          command: 'custom'
          customCommand: 'run build'

To add a stage to publish the artifact.

Image

- task: Npm@1
        inputs:
          command: 'publish'
          workingDir: './dist'
          publishRegistry: 'useFeed'
          publishFeed: 'c420a86b-fd1f-4e29-90eb-17d488d300b6/d00f33c5-ab18-4698-8ce1-39601d6af518'

Configure CD Pipeline.

  • Release Pipeline

    Image

  • Rename the stage

    Image

  • Add the artifact

    Image

    Image

  • Configure stage for Deployment

    • Add service principal in deployment

      Image

      Image

      Image

    • Select the custom agent pool name

      Image

    • Configure application in pipeline.

      • location for Package or folder

        Image

      • Runtime stack & Deployment Script | Inline Script:

        Image

          cp -rf /home/site/wwwroot/package/* /home/site/wwwroot/
        

        click save.

    • Enable the trigger for auto-deployment

      Image

      Image

CD Pipeline Status.

Image

Application Accessibility

Congratulations :-) the application is working and accessible.🔥

Image

  • if you face any issues then go to the web app and check the logs.

Environment Cleanup:

  • As we are using Terraform, we will use the following command to delete

    run the terraform command.

      Terraform destroy --auto-approve
    

    Image

Conclusion

This guide shows how to set up a CI/CD pipeline using Azure DevOps and Azure Artifacts. By following these steps, you can effectively manage and deploy applications with better control over package management and deployment processes. Remember to clean up resources after deployment to avoid extra charges..

Ref Link: