Skip to content
This repository has been archived by the owner on Mar 29, 2024. It is now read-only.

Latest commit

 

History

History

azure-pipelines

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Opinionated CI/CD Pipelines

The pipelines in this repository follow opinionated best practices. They are documented here for reference and easier debugging.

Video Walkthrough

And there's a ca. 20 minute video walkthrough explaining the pipelines and why I organize them this way:
youtube.com/watch?v=e0bF1LlclEs

YouTube Video

File Structure

The main pipelines sit in this azure-pipelines directory and use subfolders for templating.

├── README.md
├── production.yaml
├── dev.yaml
├── jobs
│   ├── app-service.yaml
│   ├── asset-pipeline.yaml
│   ├── docker.yaml
│   └── tests.yaml
├── steps
│   └── debug-vars.yaml
└── vars
    ├── dev.yaml
    ├── global.yaml
    └── prod.yaml

Templates and Variables

Local Templates

The jobs and steps are intended for local use only and thus do not require parameters: definitions at each job scope. Therefore any varable referenced in a job, e.g. variables.isProduction can be found at a higher scope.

Global Variables

Due to the sheer amount of variables set, the conditionals and global defaults are set in vars/global.yaml.

# Global scope
trigger:
  - main
variables:
  - template: vars/global.yaml

Environment Specific Variables

Note: this is no longer used since switching to environment specific pipelines, but kept here for reference.

Some parameters, e.g. app name are dependent on the deployment target environment. Using conditionals at stages: scope, the defaults are overwritten.

- stage: StageName
  variables:
  - ${{ if eq(variables.isMain, 'True') }}:
    - template: vars/dev.yaml
  - ${{ if eq(variables.isProduction, 'True') }}:
    - template: vars/prod.yaml

Important: Environment specific variables must be set in a non-root, e.g. downstream scope.

Triggers and Deployments

Please also see Docker Images section, which describes the git tag trigger.

Pipeline Branch Triggers Pull Request Triggers Deployment
dev.yaml main
feat/*
fix/*
main Dev
production.yaml production (none) Production

Zero Trust Principle

Pull Requests only runs tests and does not build any images. The YAML pedanticly excludes forks, pull requests and scheduled runs. In this manner only git merge events, which requires human intervention will trigger deployments. This is configured using branch production configurations.

See vars/global.yaml for details:

# Excerpt
variables:
  isFork:       ${{ eq(variables['System.PullRequest.IsFork'], 'True') }}
  isPR:         ${{ eq(variables['Build.Reason'], 'PullRequest') }}
  isScheduled:  ${{ eq(variables['Build.Reason'], 'Schedule') }}
  isTrustedCI:  ${{ and( eq(variables.isFork,'False'), eq(variables.isPR,'False'), eq(variables.isScheduled,'False') ) }}

Docker Images

Tag Definitions

  • Image Tag
    Refers to version of particular image, e.g. 0.1.0 or latest

  • Docker Tag
    Refers to full image name that includes private registry hostname, for example:
    nodejsdemo.azurecr.io/azure-nodejs-demo:0.1.0

Build Triggers & Tags

  • Docker Images are only built in the dev.yaml CI pipeline.
  • Production-ready images are locked (Azure Container Registry specific feature) and thus immutable.
Triggers Image Tag Immutable
main branch dev-$(git rev-parse --short HEAD) -
v* tag e.g. 0.1.0 True

Deployment

Deployment pipeline only deploys existing images, which have passed previous stages and are thus assumed valid and secure.

Branch Image Tag
main dev
production Version per package.json