1

I am wondering if Azure DevOps has the ability to do conditional flow as part of a release definition.

My use case: I have a PowerShell script that deploys a SQL Server DACPAC to create or update a database. Sometimes this deployment will fail because a change was made that could potentially cause data loss. Instead of absolutely failing the deployment, I would like to trigger a manual intervention for a DBA to review the changes. If they resume, I would like to attempt the deployment again, but this time with a flag that will ignore potential data loss issues.

Finally, if that second db deployment attempt is successful, I would like the flow to continue back to the rest of the deployment tasks.

Here is a general flow diagram:

Azure DevOps Manual Intervention flow diagram

Other requirements:

  • If the db deployment fails, but the manual intervention resumes and succeeds, I want the entire deployment to be marked as succeeded.
  • I want the flow after resuming an intervention to merge back into existing tasks that would be run on db deployment success. Corollary: I do not want to maintain dual flows with identical tasks.

I am using the Designer (Web UI) and not YAML for all my current builds/releases, but I am also interested if YAML has a solution for this.

Azure DevOps has a section for Conditions, but I did not find that particularly helpful. The number of conditions seems limited. It also looks like variables can be set on jobs, but this appears to be only available with YAML.

Is there a way to set up the conditionals at the end of phases/jobs or tasks to achieve this branching behavior?

  • I actually think you can handle this without the hacky step. Let me see if I can set it up. – Sumo May 2 at 21:53
1

Maybe is not a full resolution for you, but you can start with this:

After the "Critical Task" add an "Agentless job"

enter image description here

Add a "Manual Intervention" task

enter image description here

In the "Additional options" in the job specify "Run this job - Only when a previous job has failed"

enter image description here

1

@Shayki's answer was a large portion of what I was looking for (thanks!), but I was eventually able to figure out a solution that met all of my requirements. It involves a less than ideal use of the Release Description to propagate state between jobs.

The updated flow diagram looks like this:

conditional flow solution

I was originally thinking of the conditional flow as an if else statement, but it is really more of multiple if statements where the condition is the same. If flag is set, do X; if flag is set, do Y; etc.

Details

Instead of running the agentless job when a previous condition fails (which would result in the entire deployment failing, a violation of one of my requirements), I created a custom condition that the agentless job runs as:

custom condition with variable expressions

If all the previous tasks have succeeded, and if the Release.ReleaseDescription variable contains the string defined in the _dbDeployErrors variable, then this job will execute (and the manual intervention task inside of it).

The _dbDeployErrors variable isn't too important, I set it to ;DB_DEPLOY_ERRORS_$EnvironmentName. The main idea is that, at least with the Web Designer, there is no way to pass information from an agent job to an agentless job. So I wrote a powershell script which uses the Get Release and Update Release Azure DevOps REST API to update the Release Description parameter on the release. This allows me to pass information to the next job in the deployment.

The basic steps for setting this flag are:

  1. Run the db deployment
  2. If the deployment has errors, do not fail task, but instead set an agent variable
  3. Next task determines if the variable is set, and if so calls the Update Release API to append the flag to the release description
  4. Future jobs and tasks can now analyze the state of the release description variable

Note: I set an agent variable instead of making the API call from the db-deploy script so that I can keep my deploy script clean and maintainable. I move the responsibility of calling the API to a dedicated script instead.

If the Manual Intervention is resumed, then the third job executes as an agent job. It will attempt to deploy the db again, but this time it sets a -Force flag on the script to ignore possible data loss (it was approved by the one who performed the intervention). If this deployment succeeds, then a quick cleanup is run to call the Update Release API and clear the flag from the release description. Finally, the other tasks can resume as normal.

Here is what the tasks in my final release definition looks like:

full release definition

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.