TFS 2017 How to rollback a release - ucd

Has anyone has a robust way to rollback if a release fails? The methods mentioned in this article doesn't sound very practical: https://blogs.msdn.microsoft.com/devops/2016/03/28/implement-rollback-with-release-management-for-tfs-2015/
IBM UrbanCode Deploy can choose to redeploy the previous successful deployment w/o any user intervention: https://developer.ibm.com/urbancode/videos/rollback-scenarios-in-ibm-urbancode-deploy/
Can we have that in TFS?

Once you install the Release Management Utility Tasks extension in your account, you’ll see a task called “Rollback powershell” in the task catalog. For rollback, you just need to add this task to the release definition and mark it “always run”.
An example to access the task execution information is as follows.
try
{
$jsonobject = ConvertFrom-Json $env:Release_Tasks
}
catch
{
Write-Verbose -Verbose “Error parsing Release_Tasks environment variable”
Write-Verbose -Verbose $Error
}
foreach ($task in $jsonobject | Get-Member -MemberType NoteProperty)
{
$taskproperty = $jsonobject.$($task.Name) | ConvertFrom-Json
Write-Verbose -Verbose “Task $($taskproperty.Name) with rank $($task.Name) has status $($taskproperty.Status)”
// Perform rollback action required in case $task.Name has status failed
}
Please notice, you may need to update the api version. Check the case below:
https://social.msdn.microsoft.com/Forums/expression/en-US/aacab4c3-b25b-4348-90b1-4d5661d9d148/release-management-utility-tasks-rollback-task-is-not-working-in-tfs-2017-update-1?forum=tfsbuild

Related

How to stop a Storage Event Trigger of Azure Data Factory using Powershell when there is a Delete lock on the Resource group?

I want to stop a Storage Event Trigger that is on my data factory before I make modifications to the factory using ARM deployment/Azure DevOps. There is a Delete lock on my resource group which is causing the below error when I try to stop the trigger using powershell (Stop-AzDataFactoryV2Trigger) :
Error Code: BadRequest
Error Message: The scope '/subscriptions/XXX/resourceGroups/XXX/providers/Microsoft.Storage/storageAccounts/XXX/providers/Microsoft.EventGrid/eventSubscriptions/XXX'
cannot perform delete operation because following scope(s) are locked: '/subscriptions/XXX/resourceGroups/XXX'. Please remove the lock and try again.
Is there any way to do my ADF deployments without having to remove this Delete lock?
After a bit of research and digging around, I found out that the direct answer to this question is that it's not possible to Start/Stop a Storage Event Trigger on a Data Factory when there is a Delete lock on the entire Resource Group. This is because whenever a Storage Event Trigger is started or stopped, an Event Subscription (which is a resource) is created and deleted in the Resource Group but with a Delete lock in place, this deletion cannot happen.
However, there are few workarounds to address this requirement :
Have a Delete lock at the Resource level and not at the Resource
Group level.
Move the Data Factory and the Storage Account to a different Resource Group
which doesn't have a Delete lock.
Delete the "Delete lock" before the deployment of the ADF and recreate it after
the deployment. For this, the Service Principal being used to do the deployments
should have the permission needed to update/delete locks.
If anyone has a direct solution to this problem, I'm happy to accept that as the answer. Thanks.
The following sample script can be used to stop triggers before deployment.
if ($predeployment -eq $true) {
#Stop all triggers
Write-Host "Stopping deployed triggers`n"
$triggersToStop | ForEach-Object {
if ($_.TriggerType -eq "BlobEventsTrigger" -or $_.TriggerType -eq "CustomEventsTrigger") {
Write-Host "Unsubscribing" $_.Name "from events"
$status = Remove-AzDataFactoryV2TriggerSubscription -ResourceGroupName $ResourceGroupName -DataFactoryName $DataFactoryName -Name $_.Name
while ($status.Status -ne "Disabled"){
Start-Sleep -s 15
$status = Get-AzDataFactoryV2TriggerSubscriptionStatus -ResourceGroupName $ResourceGroupName -DataFactoryName $DataFactoryName -Name $_.Name
}
}
Write-Host "Stopping trigger" $_.Name
Stop-AzDataFactoryV2Trigger -ResourceGroupName $ResourceGroupName -DataFactoryName $DataFactoryName -Name $_.Name -Force
}
For more information follow this Pre- and Post-deployment script given in official documentation.

How to destroy a branch in TFVC using the REST API?

I am looking to delete and then destroy a branch in TFVC (in Azure Devops) using the REST API and Powershell, but after checking the documentation I have to ask: is this possible using the API?
Using the GET documentation as a guide I could take a guess at it and run something similar to the following:
DELETE https://dev.azure.com/{organization}/{project}/_apis/tfvc/branches?path={path}&api-version=6.0
but given the destructive nature of these calls I am reluctant to guess. And there is no obvious way to invoke the destroy functionality.
Alternatively, is there a way to trace the API call that must (probably?) be executed if I was to run the command line tf vc destroy "$/MyBranch/Path"? Or am I going to have to resort to using a Powershell snapin for this?
Why not use tf vc destroy from powershell? Most of TFVC is handled by the old SOAP API and doesn't have a REST equivalent. The investment in more REST APIs for TFVC is unlikely. You can invoke tf vc from powershell assuming you have Team Explorer installed on the machine.
Alternatively, you can load the Client Object Model into PowerShell directly and invoke the destroy calls from it. The call is pretty straightforward. That way the Client Object Model will do all the API wrestling. You can get the assemblies from NuGet without installing Team Explorer to a machine.
To get an instance of the VersionControlServer class you can look at my TFVC tasks. The code below is untested, but should get you really close:
[System.Reflection.Assembly]::LoadFrom("Newtonsoft.Json.dll")
[System.Reflection.Assembly]::LoadFrom("Microsoft.TeamFoundation.Client")
[System.Reflection.Assembly]::LoadFrom("Microsoft.TeamFoundation.Common")
[System.Reflection.Assembly]::LoadFrom("Microsoft.TeamFoundation.VersionControl.Client")
[System.Reflection.Assembly]::LoadFrom("Microsoft.TeamFoundation.WorkItemTracking.Client")
[System.Reflection.Assembly]::LoadFrom("Microsoft.TeamFoundation.Diff")
$OnNonFatalError = [Microsoft.TeamFoundation.VersionControl.Client.ExceptionEventHandler] {
param($sender, $e)
if ($e.Exception -ne $null -and $e.Exception.Message -ne $null)
{
Write-Message -Type Warning $e.Exception.Message
}
if ($e.Failure -ne $null -and $e.Failure.Message -ne $null)
{
Write-Message -Type Warning $e.Failure.Message
if ($e.Failure.Warnings -ne $null -and $e.Failure.Warnings.Length -gt 0)
{
foreach ($warning in $e.Failure.Warnings)
{
Write-Message -Type Warning $warning.ParentOrChildTask
}
}
}
}
function Get-TfsVersionControlServer()
{
[cmdletbinding()]
param(
[string] $ProjectCollectionUri
)
$collection = New-Object Microsoft.TeamFoundation.Client.TfsTeamProjectCollection(
$ProjectCollectionUri)
$collection.EnsureAuthenticated()
$versionControlServer =
$provider.TfsTeamProjectCollection.GetService([Microsoft.TeamFoundation.VersionControl.Client.VersionControlServer])
$versionControlServer.add_NonFatalError($OnNonFatalError)
return $versionControlServer
}
Get-TfsVersionControlServer().Destroy(...)
Then call the destroy function from there.
I looked at the API documentation as well. In my experience, Azure keeps their API documents up to date pretty well. The absence of the DELETE operation in their documentation indicates that the DELETE operation is not yet supported. Even if it 'worked', I wouldn't use it until it was supported in their API - especially with something dealing with version control.

Skip a stage if the previous one has errors in Azure Pipeline Release

I've got a very simple Azure Pipeline Release, I just want to skip a stage if there are any errors in the previous one. I've already checked https://learn.microsoft.com/en-us/azure/devops/pipelines/process/conditions?view=azure-devops&tabs=classic
Setting the Test job to run "Only when all previous jobs have succeeded" doesn't help
My main goal is to skip the test stage whenever there's a particular condition in the previous one, and passing variables between stages doesn't seem to be possible, nor using the gates, so I've got to idea to deliberately raise an error in the stage. The stages run some PS scripts, and I can't make the whole stage fail from that either
Screen shot
The stages run some PS scripts, and I can't make the whole stage fail
from that either
Are you using PowerShell task or similar tasks? Try editing the task and enabling the Fail on Standard Error option:
After that task will fail if there's any error is written to the error pipeline. Also in pre-deployment conditions of your Test stage, make sure the trigger when ... checkbox is unchecked:
From what I understood you need sth like this feature. So as you see this is not supported out of the box.
You can use REST API to get state of running release and analyze response to verify it there is any issue with issueType = Error. Then in this script you need to call exit 1. This is not ideal, but it works.
$uri = "https://vsrm.dev.azure.com/thecodemanual/Devops manual/_apis/release/releases/$(Release.ReleaseId)?api-version=5.1"
Write-Host $(Release.ReleaseId)
Write-Host $uri
# Invoke the REST call
$result = Invoke-RestMethod -Uri $uri -Method Get -Headers #{Authorization = "Bearer $env:SYSTEM_ACCESSTOKEN"}
$errors = #()
$result.environments |
ForEach-Object { $_.deploySteps |
ForEach-Object { $_.releaseDeployPhases |
ForEach-Object { $_.deploymentJobs |
ForEach-Object { $_.tasks |
ForEach-Object { $errors += $_.issues | Where-Object { $_.issueType -eq "Error" } }}}}}
Write-Host $errors.Count
if($errors.Count -gt 0) {
Write-Host Error
exit 1
}
Without step above I got this:
And with this step this:

How to read the logs from TFS Build/Release and change the task status accordingly?

I am using TFS(on premises 2015)automated build and release for one of my project. In release definition, I have an ALM task and I can see the TFS release log returning "completed successfully: Y (or N) " in the log based on the task completion status in ALM and the ALM task always shows a success. Is there any way that I can read the this "completed successfully: N" from the logs and fail the ALM release task itself as an indication of failure?
Thanks in advance for any help!
Well you're not giving much help here. With or having a better idea of what your script does... But you could do something like
(At the end of your command)
Command -errorvariable fail
If ($fail -ne $null){
$success = $fail
} Else {
$success = $true
}
You could also pipe the error variable into the file at the next line if it's a txt log.
Command -ev fail
$fail | out-file log.txt -append
Or
Command -ev fail
If ($fail -ne $null) {
Write-output "the command failed at $variable" | out-file log.txt -append
}
$variable would be the variable used for your loop or whatever to identify the current task.

How do you get powershell script output in the deployment log for a vNext Release Template?

This blog post is the only thing I have found that comes close to the problem but it doesn't explain how to configure the Deploy Using PS/DSC to run with the verbose option:
http://nakedalm.com/create-log-entries-release-management/
I can get this Agent-based Release Template to run the script:
Write-Debug "debug"
Write-Output "output"
Write-Verbose "verbose"
Write-Warning "warning"
The drilling down into deployment log for this release provides a log with the lines:
output
WARNING: warning
If I add -verbose to the Arguments field I also get a "VERBOSE: verbose" line in the log.
This is great, but I need the access to the System Variables ($Stage, $BuildNumber, etc). When I create a vNext template to run the same script (instructions are here: http://www.visualstudio.com/en-us/get-started/deploy-no-agents-vs.aspx), the log reports:
Copying recursively from \\vsalm\Drops2\TestBuild\TestBuild_20130710.3 to c:\Windows\DtlDownloads\my vnext component succeeded.
It is nice that this copying operation succeeded and all, but I'd like my script's output to be in this log as well. Does anyone have any idea about configuring a "Deploy Using PS/DSC" action so that the powershell script output is captured by Release Management?
For a vNext Release Template, try Write-Verbose with a -verbose switch if you want to see the powershell script output in the logs.
Eg. Write-Verbose "Some text" -verbose
Allow me to shamelessly plug my own blog article about this subject, because I found that it's not easy to get a script that does everything right.
The following script skeleton ensures that stdout output is logged without empty lines, and that processing is halted on the first error, in which case both the error details and the stdout output upto that point are visible in MSRM:
function Deploy()
{
$ErrorActionPreference = "Stop"
try
{
#
# Deployment actions go here.
#
}
catch
{
# Powershell tracks all Exceptions that occured so far in $Error
Write-Output "$Error"
# Signal failure to MSRM:
$ErrorActionPreference = "Continue"
Write-Error "Error: $Error"
}
}
pushd $Global:ApplicationPath
Deploy | Out-String | Write-Verbose -Verbose
popd
This is just the final result, the explanation behind it can be found here.