Photo by JJ Ying

Dynamically create default pipeline using Terraform inside Azure DevOps

Setup the build definitions

Posted by Damien Aicheh on 10/27/2022 · 5 mins

In this tutorial we will configure the default pipeline for each repository that we previously created associated with our Azure DevOps project using Terraform!

This tutorial is part of a full series of tutorials on configuring Azure DevOps using Terraform. You can download the project from the previous part and follow along.

Usecase

The idea is to prepare the project so that the team start with the minimum of configuration to add a continuous integration and delivery process (CI/CD). So to encourage them to do it as the really begining of the project you can directly create a first pipeline to build the project using Terraform.

So we will create two things:

  • The build definition that target the azure-pipelines.yml we previously added to the repositories
  • A variables group to store their potential secrets

In this way you setup the naming conventions to follow, so the teams will have example to base on.

Defining the variable group

Let’s create a new file called variables_group.tf, by default we want to store the domain and the application name in it. After that, the team have enough rights for adding their own variables and secrets in the dedicated group.

resource "azuredevops_variable_group" "this" {
  count        = length(var.repositories)
  project_id   = azuredevops_project.this.id
  name         = "${var.repositories[count.index].domain}.${var.repositories[count.index].application}.shared"
  description  = "The Variable Group for ${title(var.repositories[count.index].domain)} ${title(var.repositories[count.index].application)}"
  allow_access = true

  variable {
    name  = "Domain"
    value = var.repositories[count.index].domain
  }

  variable {
    name  = "Application"
    value = var.repositories[count.index].application
  }
}

To be more flexible we add the shared prefix at the end of the group name so the teams can then add other group with other prefix if needed, such as dev, stagging, prod, etc.. You can find the definitions of secrets in the Terraform documentation.

Add a build definition

In the previously tutorial we added a default azure_pipeline.yml file in each repository. It’s time to use it!

Add a new file called build_definition.tf, and for each repository, you can create the build definition associated with it.

resource "azuredevops_build_definition" "build_definitions" {
  count      = length(var.repositories)
  project_id = azuredevops_project.this.id
  name       = "${var.repositories[count.index].domain}_${var.repositories[count.index].type}_${var.repositories[count.index].application}"

  repository {
    repo_type   = "TfsGit"
    branch_name = "refs/heads/develop"
    repo_id     = azuredevops_git_repository.this[count.index].id
    yml_path    = "azure_pipelines.yml"
  }

  ci_trigger {
    use_yaml = true
  }
}

With that done, the team will just need to update the azure_pipeline.yml to match their needs without having to ask the administrator right to create this first pipeline.

You can find all the properties available in the Terraform documentation.

Run Terraform

Let’s run a new Terraform plan command and apply it:

terraform plan -var-file=env.tfvars --out=plan.out

Then:

terraform apply plan.out

As result you should see in Azure DevOps, your build definitions inside the Pipelines section and in the Library section, the variables group!

Final touch

The build definitions with their associated variables group was generated inside Azure DevOps using Terraform. You will find full source code in this Github repository.

What’s next?

In the next tutorial of this series we will focus on adding policies to each repositories!

Do not hesitate to follow me on to not miss my next tutorial!