Skip to main content
FOSSA Logo

Azure DevOps Pipelines – Setup and CI/CD Guide for .NET and AKS

Technical guide to setting up Azure DevOps Pipelines for .NET applications and container deployments to AKS, with Azure Repos, Azure Container Registry integration, and FOSSA for compliance scanning.

Contents

Azure DevOps Pipelines – Setup & CI/CD Tutorial

About Azure Pipelines

Azure Pipelines is a cloud service for automating builds, tests, and deployments of code projects as part of Continuous Integration and Continuous Delivery (CI/CD). It's a core service of Azure DevOps that supports many languages and platforms (e.g. .NET, Node, Python) and integrates natively with Azure services. Key points include:

  • CI/CD Workflow: Developers push code changes to a repository (Azure Repos Git or GitHub), triggering pipeline runs that build, test, and deploy the application.
  • YAML Pipeline-as-Code: Pipeline definitions are typically stored as azure-pipelines.yml in your repo, enabling version-controlled, code-reviewed build/deployment processes.
  • Azure Integration: Out-of-the-box integration with Azure Repos for source control, Azure Container Registry (ACR) for container images, and Azure Kubernetes Service (AKS) for deployments.
  • Hosted Agents: Microsoft-hosted build agents on Windows, Linux, and macOS run your pipeline tasks. You specify an agent VM image (like ubuntu-latest) in the pipeline config.
  • Common Workloads: Frequently used with .NET applications and containerized workloads. For example, you can compile and test a .NET project, build a Docker image, push it to ACR, and deploy to AKS – all in one pipeline.

Azure Pipelines Setup Guide – Azure DevOps CI/CD Tutorial

Follow this guide to set up Azure Pipelines from initial project creation to your first successful CI/CD pipeline execution. We'll focus on a typical use case: building a .NET application, containerizing it, and deploying to Azure Kubernetes Service, using Azure Repos for source code and ACR for the container image.

Prerequisites: You should have an Azure DevOps organization and project (sign up free if needed), and an Azure subscription for deploying resources. Also ensure you have an Azure Container Registry and an AKS cluster created (for example, via Azure CLI commands).

Steps:

  1. Create or Select an Azure DevOps Project – Sign in to Azure DevOps and create a new project or use an existing one. Projects are logical containers for your code repos and pipelines.

  2. Import Code into Azure Repos – Push or import your application's code into an Azure Repos Git repository within the project. You can do this via Git commands or the Azure DevOps web interface (e.g. initialize a repo and upload files in the Repos section).

  3. Create a New Pipeline – In Azure DevOps, go to Pipelines > Pipelines and click New Pipeline. The pipeline creation wizard will prompt you to select your source code repository and pipeline type:

    • Choose Azure Repos Git and select your repository (if asked to select a source).
    • For pipeline configuration, select a template. For example, choose "Deploy to Azure Kubernetes Service" if you want a full CI/CD pipeline for AKS. Alternatively, you can start with ".NET Desktop/ASP.NET Core" templates for simpler build/test pipelines.
    • If using the AKS template, you'll be prompted to select your Azure Subscription, AKS cluster, ACR, etc. Provide the requested info (cluster name, namespace, registry, image name, etc.). Azure Pipelines will automatically create a service connection for ACR and AKS if needed.
  4. Review the Generated Pipeline YAML – Azure DevOps will analyze your selections and generate an azure-pipelines.yml in your repo. This YAML defines your CI/CD pipeline:

    • It typically includes a trigger on your main branch (so pushes trigger CI builds).
    • It defines stages for Build (CI) and Deploy (CD).
    • In the Build stage, you'll see steps to build and possibly test your application. For containerized .NET apps, the build might be done via a Docker task. If using a pure .NET template, you'd see tasks like DotNetCoreCLI@2 to restore, build, and test the project.
    • For example, the pipeline uses the Docker@2 task to build and push a Docker image to ACR:
      # ... (within Build stage job steps)
      - task: Docker@2
        displayName: Build and push Docker image to ACR
        inputs:
          command: buildAndPush
          repository: <your ACR name>.azurecr.io/${{ variables.imageName }}
          dockerfile: ${{ variables.dockerfilePath }}
          containerRegistry: ${{ variables.dockerRegistryServiceConnection }}
          tags: |
            $(Build.BuildId)
      The above YAML uses Azure Container Registry service connection to authenticate and push the built image.
    • In the Deploy stage, the YAML will use Kubernetes deployment tasks to release the app to AKS. For example, Azure Pipelines can apply the Kubernetes manifest files:
      # ... (within Deploy stage job steps)
      - task: KubernetesManifest@1
        displayName: Deploy to AKS
        inputs:
          action: deploy
          kubernetesServiceConnection: <your AKS service connection>
          manifests: |
            manifests/deployment.yml
            manifests/service.yml
          containers: $(ACR_LOGIN_SERVER)/${{ variables.imageName }}:$(Build.BuildId)
      This uses the Kubernetes manifest task to deploy the Kubernetes deployment.yml and service.yml (which reference the image built in the previous stage) to your AKS cluster.

    Note: The pipeline YAML may create an imagePullSecret for ACR and use a predefined Kubernetes service connection for AKS. Azure DevOps handles these details when you use the AKS deployment template, so you don't have to manually write authentication steps.

  5. Save and Run the Pipeline – Commit the YAML file to your repo (the wizard usually does this with a commit message like "Add pipeline to our repository" when you click Save and run). This triggers the first pipeline run. You can follow the pipeline's progress in the Azure DevOps Pipelines UI:

    • The pipeline will queue on a hosted agent. In real-time, you can see logs for each step (e.g. restoring packages, building the app, running tests, building the Docker image, pushing to ACR, deploying to AKS).
    • The Build stage should complete (green check mark), then the Deploy stage will execute. Azure Pipelines shows each stage and job transitioning from running (blue) to successful (green).
    • If anything fails (red X), examine the log output in that step to diagnose (common issues include missing Azure service connections or misconfigured YAML). Fix the YAML or environment and commit again to re-run.
  6. Verify Deployment – Once the pipeline finishes, verify that your application is deployed:

    • In Azure DevOps, go to the Environments or the pipeline run summary to find the deployment details (for AKS deployments, Azure Pipelines registers an environment that you can view under Environments tab, showing the Kubernetes cluster and namespace).
    • For our example, you can check the AKS cluster to see if the application pods are running. Use kubectl get pods (if you have Kubeconfig access) or navigate to Azure Portal > AKS > Workloads.
    • If a service with a LoadBalancer was deployed, get its external IP and try to access the app (e.g. via web browser for a web app). For instance, hitting <EXTERNAL-IP>:8080 should show "Hello world" for the sample app.

At this point, you have a functioning CI/CD pipeline: a code push to Azure Repos triggers an automated build of the .NET application, containerization of the app, and deployment of the container to AKS. The entire process is repeatable and managed via Azure DevOps Pipelines.

For more details on Azure DevOps Pipelines and AKS integration, see the official Microsoft documentation on deploying to AKS with Azure Pipelines.

flowchart LR
    commit[Code Commit (Azure Repos)] --> buildCI[CI: Build & Push Image];
    buildCI --> acr[(Azure Container Registry)];
    acr --> deployCD[CD: Deploy to AKS];
    deployCD --> aks[(AKS Cluster)];

Ongoing Usage and Best Practices

Once your pipeline is set up and running, here are ongoing usage tips and best practices:

  • Pipeline Triggers & Branches: Adjust triggers as needed. By default, trigger: - main runs CI on each push to main. You can add triggers for other branches or pull request validation (PR pipelines). Consider protecting main by requiring PR validation pipelines before merge.

  • Infrastructure as Code: Keep pipeline definitions in code (YAML) and use Azure DevOps to manage them. Edit the azure-pipelines.yml in your repo to update the pipeline. Azure Pipelines' web editor with IntelliSense and task assistant can help you add/edit tasks easily.

  • Variable Management: Use Azure Pipeline variables for configuration (e.g. image names, paths, connection names). Sensitive info (like API keys or passwords) should be stored as secret variables or in Azure Key Vault. You can also use Variable Groups or Azure DevOps Library for sharing common variables (e.g. across pipelines or stages).

  • Multi-Stage & Environments: Leverage multiple stages (Dev, Staging, Prod) in YAML to promote builds through environments. You can set conditions so that, for example, a Deploy-to-Prod stage only runs after a manual approval. Azure Pipelines allows setting environment approvals and checks for controlled deployments (e.g. require a human review before production deployment).

  • Monitoring: Track pipeline run history in Azure DevOps (each run has logs and history). Set up alerts or use Azure Monitor for CI/CD telemetry. Azure Pipelines integrates with Azure Application Insights and other monitoring tools to surface deployment health metrics.

For a comprehensive overview of Azure Pipelines architecture and best practices, refer to the Azure Pipelines baseline architecture documentation.

Using Azure Pipelines with FOSSA for Compliance

Integrating FOSSA into your Azure DevOps Pipeline adds automated open source license compliance and vulnerability scanning to your CI/CD process. FOSSA is a tool that scans your code and its dependencies for license violations and known security vulnerabilities. By using FOSSA in your pipeline, you can catch compliance or security issues early, on every build.

How to integrate FOSSA:

  • Set up FOSSA CLI: FOSSA provides a CLI client (fossa-cli) for scanning projects. Install this in your pipeline before analysis. For example, add a step in your YAML to download the latest FOSSA CLI:

    - script: |
        curl -H "Cache-Control: no-cache" https://raw.githubusercontent.com/fossas/fossa-cli/master/install-latest.sh | bash
      displayName: Install FOSSA CLI

    This command fetches and installs the fossa CLI tool on the build agent.

  • Configure FOSSA API Key: In FOSSA, generate an API token (go to your FOSSA account Integration Settings to get an API Key). In Azure Pipelines, add this token as a secret pipeline variable, e.g. FOSSA_API_KEY. This key authenticates the CLI to upload scan results to your FOSSA project.

  • Add FOSSA Analysis Step: After your build (and ideally after any package installation or build output is ready), add a step to run FOSSA analysis:

    - script: fossa analyze
      env:
        FOSSA_API_KEY: $(FOSSA_API_KEY)
      displayName: Run FOSSA Scan

    This command scans the project's dependencies and uploads a report to FOSSA. Ensure the environment variable is passed so the CLI can authenticate.

  • Review FOSSA results: FOSSA will evaluate licenses and vulnerabilities against your policies. If there are issues (e.g. a disallowed license), FOSSA can fail the build or mark the pipeline run with an alert depending on how you configure policy enforcement. You can view detailed reports in the FOSSA dashboard, which will show exactly which dependencies or licenses triggered the alerts.

By incorporating FOSSA into Azure Pipelines, teams gain an additional CI/CD quality gate: every build is not only compiling and testing code, but also continuously checking open-source compliance and security. This proactive scanning helps catch license issues (like GPL or AGPL code that might be inadvertently included) and known CVEs in libraries early in the development lifecycle, before they make it to production.

Tip: Maintain a .fossa.yml configuration in your repository if you need to customize what FOSSA scans or ignore certain paths. FOSSA will automatically pick up this config during the fossa analyze run.

For more information on integrating FOSSA with CI systems, check out the FOSSA Generic CI documentation.

With Azure DevOps Pipelines and FOSSA, your CI/CD process is both robust and compliant – building and deploying your .NET and container-based applications to Azure, while enforcing open source license policies and monitoring security vulnerabilities continuously.