Terraform-provider-azuredevops: Pipelines in the same Bitbucket repo is triggered multiple times

Created on 2 Dec 2020  路  8Comments  路  Source: microsoft/terraform-provider-azuredevops

Community Note

  • Please vote on this issue by adding a 馃憤 reaction to the original issue to help the community and maintainers prioritize this request
  • Please do not leave "+1" or "me too" comments, they generate extra noise for issue followers and do not help prioritize the request
  • If you are interested in working on this issue or have submitted a pull request, please leave a comment

Terraform (and Azure DevOps Provider) Version

Terraform 0.13.5, azuredevsop provider 0.1.0

Affected Resource(s)

  • azuredevops_build_definition

Terraform Configuration Files

data "azuredevops_project" "project" {
  name = "MyProject"
}

resource "azuredevops_build_definition" "build_infra" {
  project_id = data.azuredevops_project.project.id
  name       = "infra-build"

  ci_trigger {
    use_yaml = true
  }

  pull_request_trigger {
    use_yaml = true
    forks {
      enabled       = false
      share_secrets = false
    }
  }

  repository {
    repo_type             = "Bitbucket"
    service_connection_id = var.BitbucketConnectionID
    repo_id               = "MyOrg/MyRepo"
    yml_path              = "infra/azure-pipelines.yml"
  }

  variable {
    name  = "system.debug"
    value = "false"
  }
}

resource "azuredevops_build_definition" "build_code" {
  project_id = data.azuredevops_project.project.id
  name       = "code-build"

  ci_trigger {
    use_yaml = true
  }

  pull_request_trigger {
    use_yaml = true
    forks {
      enabled       = false
      share_secrets = false
    }
  }

  repository {
    repo_type             = "Bitbucket"
    service_connection_id = var.BitbucketConnectionID
    repo_id               = "MyOrg/MyRepo"
    yml_path              = "src/azure-pipelines.yml"
  }

  variable {
    name  = "system.debug"
    value = "false"
  }
}

Debug Output

Panic Output

Expected Behavior

  • Two build definitions for the same repo are created
  • A change in the infra folder triggers the infra-build pipeline triggers once
  • A change in the src folder triggers the code-build pipeline triggers once

Actual Behavior

  • Two build definitions for the same repo are created
  • A change in the infra folder somehow triggers the infra-build build twice
  • A change in the src folder somehow triggers the src-build build twice
  • After a couple more changes there is an error starting the build:
Could not retrieve file content for /infra/azure-pipelines.yml from repository self hosted on Bitbucket using commit <Guid>. Bitbucket reported the error, "Too Many Requests"

Steps to Reproduce

  1. terraform apply with the the sample code above
  2. Setup a repo with two folders infra and src, with two different azure-pipelines.yml files inside, each one triggering the pipeline only when the corresponding infra or src folder change
  3. Make a changer under the infra folder and push
  4. Make a change聽under the src folder and push

Important Factoids

If I create the same build definitions "organically" using the Azure DevOps UI there's only one trigger as expected.
I started getting this behavior when I removed all my build definitions and recreated them from scratch with this provider.

The var.BitbucketConnectionID value is the guid corresponding to the Bitbucket Connection from the Azure DevOps portal

I tried removing the code-build definition, and keeping only the infra-build one, and I still got 4 triggered builds from one repo change. It's almost like the build definition subscribes 4 times to the Bitbucket webhook.

References

  • #0000

Most helpful comment

I understand @xuzhang3

Now the issue I described originally happens when:

  • Set use_yaml = true in the TF module
  • Two different build configurations point to the same Bitbucket repo

I think there's still a bug there

Now, for my use case I took a step back and realized that NOT setting use_yaml at all and manage the triggers in TF is actually better:

  • I don't need to copy-paste the ci trigger and pr trigger sections in all the .ymls
  • I can centralize the default values for those triggers in a TF module on top of the ADO provider
  • Each repo now has a pipelines folder, with a TF module to setup the build definition(s). That's where the ci and pr triggers can be overridden if the default is not good enough.

I think this is cleaner. Having the triggers defined in the .yml is odd to me.

All 8 comments

@oscarmorasu In your configuration, you set the configure: use_yaml = true which means the trigger is managed in your pipeline.xml, ADO provider cannot control the build triggers, you can find some configure example at: https://docs.microsoft.com/en-us/azure/devops/pipelines/repos/bitbucket?view=azure-devops&tabs=yaml#ci-triggers

Thanks for the information @xuzhang3

So if I use a Bitbucket as the connection and use_yaml = true with multiple build definition is an invalid setup?

This is how I came up with that configuration:

  • Both pipelines already existed in ADO. They were created using the Web UI
  • I ran terraform import on each build definition
  • Ran terraform plan and look at the differences
  • Tweak the terraform to match the differences. That included the use_yaml = true flag
  • Ran terraform plan again and now there are no differences

I am still trying to understand why this setup works ok using the Web UI, but doesn't when using the ADO Provider

Hi @oscarmorasu Pipeline triggers can be set from UI or yaml configuration. Here you use use_yaml = true which means pipeline trigger is controlled by your pipeline.xml.
If you set user_yaml=false, an example UI configuration would look like:
image

I understand @xuzhang3

Now the issue I described originally happens when:

  • Set use_yaml = true in the TF module
  • Two different build configurations point to the same Bitbucket repo

I think there's still a bug there

Now, for my use case I took a step back and realized that NOT setting use_yaml at all and manage the triggers in TF is actually better:

  • I don't need to copy-paste the ci trigger and pr trigger sections in all the .ymls
  • I can centralize the default values for those triggers in a TF module on top of the ADO provider
  • Each repo now has a pipelines folder, with a TF module to setup the build definition(s). That's where the ci and pr triggers can be overridden if the default is not good enough.

I think this is cleaner. Having the triggers defined in the .yml is odd to me.

hi @oscarmorasu Have you set different path filter for different pipeline.xml configure?

BTW, good job with the ADO provider @xuzhang3

It boils down to this:

resource "azuredevops_build_definition" "code_build" {
  project_id = data.azuredevops_project.project.id
  name       = var.src_name
  path       = "\\${var.path}"
  agent_pool_name = var.agent_pool_name
  variable_groups = local.group_ids
  ci_trigger {
    override {
      batch = false

      branch_filter {
        include = ["master"]
      }
      path_filter {
        include = ["src"]
      }
    }
  }

  pull_request_trigger {
    forks {
      enabled       = false
      share_secrets = false
    }
    override {
      auto_cancel = true
      branch_filter {
        include = ["master"]
      }
      path_filter {
         include = ["src"]
      }
    }
  }
}

resource "azuredevops_build_definition" "infra_build" {
  project_id = data.azuredevops_project.project.id
  name       = var.infra_name
  path       = "\\${var.path}"
  agent_pool_name = var.agent_pool_name
  variable_groups = local.group_ids
  ci_trigger {
    override {
      batch = false

      branch_filter {
        include = ["master"]
      }
      path_filter {
        include = ["infra"]
      }
    }
  }

  pull_request_trigger {
    forks {
      enabled       = false
      share_secrets = false
    }
    override {
      auto_cancel = true
      branch_filter {
        include = ["master"]
      }
      path_filter {
         include = ["infra"]
      }
    }
  }
}

Some more notes:

  • I actually have multiple infra and multiple src folders (mono-repo pattern), so I am encapsulating the azuredevops_build_definition in a module and generate multiple definitions at the same time using TF count. I suggest adding a section in the documentation about mono-repos, where multiple build definitions map to the same repo, and the path_filter maps to different folders in the mono-repo
  • With this provider I pulled agent_pool_name and variable_groups to be part of the TF module, which allows me to keep the azure-pipelines.yml much cleaner (DRY).

@oscarmorasu Good suggestions, add example documents for different scenario 馃槃

Close this issue, feel free to reopen it if you have questions.

Was this page helpful?
0 / 5 - 0 ratings