2

I would like to have the following pipeline implemented in Azure DevOps:

  • One Build stage that builds the main artifact
  • 3 deployment stages for Dev Preprod and Prod that would deploy the artifact built in the previous stage to their respective environments

I can do that using Azure DevOps Multistage Pipelines and conditions on the branch name. However, when I push first to dev branch and it builds successfully, and then I push to say preprod branch as a Fast-forward, I would expect the pipeline to reuse the already built artifacts from the Build stage run in the dev branch, because those are the same commits.

What I observe in DevOps is that the Build stage is rerun even for the same commit, when I push to each different branch. Is it possible to achieve what I am trying to do using YAML-based pipelines?

Edit

The whole point of this workflow is not branching but rather staged deployment, from continuous deployment of latest and greatest dev commits down to rolling-out production-ready software for our 500+ internal users. What I am trying to achieve is something called build promotion where one and the same build artifact gets promoted to an increasingly large circle of users. I would be happy to achieve this without fiddling with git branches.

Krzysztof Madej
  • 32,704
  • 10
  • 78
  • 107
insitu
  • 4,488
  • 3
  • 25
  • 42
  • 2
    Branch-per-environment is an anti-pattern. Consider adopting a modern branching pattern such as GitFlow. – Daniel Mann May 05 '20 at 14:53
  • 1
    Use deployment jobs with environments and approval gates defined on the environments to put approvals between the jobs. Then you can freely promote a single build between environments with no need to mess around with branches. – Daniel Mann May 05 '20 at 16:34
  • That was my first attempt and the one I reverted to once I realised builds were not "naturally" promoted when one updated another branch. Hence my question as I may have missed something obvious. – insitu May 05 '20 at 16:43
  • @LeoLiu-MSFT It resolved the question if it did not answer it. The point is: Both provided answers are equivalent as to the provided "resolution", e.g it's not possible to do what I want with Azure pipelines. Not sure which one to accept... – insitu May 07 '20 at 21:45
  • Not sure if this is helpful, but there is a 'download pipeline artifacts' task. [Article](https://learn.microsoft.com/en-us/azure/devops/pipelines/tasks/utility/download-pipeline-artifact?view=azure-devops) date is december 2020, so it maybe newer than your question. – Michael Oct 12 '21 at 08:27

2 Answers2

1

This should be rather a comment (since it is more idea, than a real working solution) than answer but I'm afraid that I will extend limit.

In my opinion this is impossible but let me explain this in details. Becuase what you actually need is a pipeline controller by commit flow. What you need is gate/approval based on appearance of commit in certain branch. This kind of approval is possible.

Imagine you made a commit to Dev branch. Your pipeline starts, deployment to Dev envrionment finishes and not is time for Preprod but before this an approval with call to Azure Function is made. You will pass this headers

{
"Content-Type":"application/json", 
"PlanUrl": "$(system.CollectionUri)", 
"ProjectId": "$(system.TeamProjectId)", 
"HubName": "$(system.HostType)", 
"PlanId": "$(system.PlanId)", 
"JobId": "$(system.JobId)", 
"TimelineId": "$(system.TimelineId)", 
"TaskInstanceId": "$(system.TaskInstanceId)", 
"AuthToken": "$(system.AccessToken)",
"BuildId":"$(Build.BuildId)",
"StageName":"$(System.StageName)"
}

In Azure Function you will get build id and stage name. With build id you can call REST API to get changes and check if they already in stageName branch (in this case it is Preprod. Since they are not there, stage will fail.

Once you move this commit to PreProd branch you should trigger previously failed build to check condition again and pick up already created artifact. You need to probably do with some kind of web hook and what is worse this is not possible at the moment. You cannot trigger a specific stage (please check documentation). You may try to get build with failing stage and queue them again, but in this case you will deploy again to Dev.

So you see this is extremly difficult to achieve this. But maybe someone will get with a better idea.

Krzysztof Madej
  • 32,704
  • 10
  • 78
  • 107
  • Thanks Krzysztof for the suggestion. Indeed, this seems pretty involved. I am disappointed but I guess you are right, what I want to achieve is pretty close to being impossible with Azure DevOps as the tool is not flexible enough and not thought with that goal in mind. I guess I will have to find another way... – insitu May 06 '20 at 05:57
0

Is it possible to achieve what I am trying to do using YAML-based pipelines?

Agree with Krzysztof Madej, I do not think it is impossible to achieve your request by using YAML-based pipelines.

To achieve it, we must ensure that every commit on the Preprod branch is the same as every commit on the dev branch before we can use conditions on the branch name to skip build stage

stages:
-stage: Build
   displayName: Build
   and(succeeded(), eq(variables['CommitBranchName'], 'refs/heads/dev'))

Then we could get the CommitBranchName by the git command git branch --contains .

However, we cannot guarantee that each branch is the same as the dev commit, and azure devops cannot determine whether the two commits are the same. The event that triggered the build is commit, not content of commit.

Hope this helps.

Leo Liu
  • 71,098
  • 10
  • 114
  • 135