cleanup from adding test project (#3)

* initial commit of Tapas.CICD.ReleaseHelper v0.5.3

* added Tapas.CICD.ReleaseHelper.Test

* cleanup from adding test project
This commit is contained in:
Leo Leong 2018-11-21 17:49:00 -08:00 коммит произвёл GitHub
Родитель 406e98cc6c
Коммит 73ea0ac6dd
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
9 изменённых файлов: 0 добавлений и 940 удалений

Просмотреть файл

@ -1,36 +0,0 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Tapas.CICD.ReleaseHelper")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Tapas.CICD.ReleaseHelper")]
[assembly: AssemblyCopyright("Copyright © 2018")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("1c4ade56-13e8-4da8-93f0-ba62b3d5288c")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

Просмотреть файл

@ -1,139 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{1C4ADE56-13E8-4DA8-93F0-BA62B3D5288C}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Tapas.CICD.ReleaseHelper</RootNamespace>
<AssemblyName>Tapas.CICD.ReleaseHelper</AssemblyName>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<Deterministic>true</Deterministic>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.IdentityModel.Clients.ActiveDirectory, Version=3.17.2.31801, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>packages\Microsoft.IdentityModel.Clients.ActiveDirectory.3.17.2\lib\net45\Microsoft.IdentityModel.Clients.ActiveDirectory.dll</HintPath>
</Reference>
<Reference Include="Microsoft.IdentityModel.Clients.ActiveDirectory.Platform, Version=3.17.2.31801, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>packages\Microsoft.IdentityModel.Clients.ActiveDirectory.3.17.2\lib\net45\Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.dll</HintPath>
</Reference>
<Reference Include="Microsoft.IdentityModel.Logging, Version=5.2.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>packages\Microsoft.IdentityModel.Logging.5.2.1\lib\net451\Microsoft.IdentityModel.Logging.dll</HintPath>
</Reference>
<Reference Include="Microsoft.IdentityModel.Tokens, Version=5.2.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>packages\Microsoft.IdentityModel.Tokens.5.2.1\lib\net451\Microsoft.IdentityModel.Tokens.dll</HintPath>
</Reference>
<Reference Include="Microsoft.TeamFoundation.Build2.WebApi, Version=16.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>packages\Microsoft.TeamFoundationServer.Client.16.140.0-preview\lib\net45\Microsoft.TeamFoundation.Build2.WebApi.dll</HintPath>
</Reference>
<Reference Include="Microsoft.TeamFoundation.Common, Version=16.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>packages\Microsoft.VisualStudio.Services.Client.16.140.0-preview\lib\net45\Microsoft.TeamFoundation.Common.dll</HintPath>
</Reference>
<Reference Include="Microsoft.TeamFoundation.Core.WebApi, Version=16.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>packages\Microsoft.TeamFoundationServer.Client.16.140.0-preview\lib\net45\Microsoft.TeamFoundation.Core.WebApi.dll</HintPath>
</Reference>
<Reference Include="Microsoft.TeamFoundation.Dashboards.WebApi, Version=16.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>packages\Microsoft.TeamFoundationServer.Client.16.140.0-preview\lib\net45\Microsoft.TeamFoundation.Dashboards.WebApi.dll</HintPath>
</Reference>
<Reference Include="Microsoft.TeamFoundation.DistributedTask.Common.Contracts, Version=16.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>packages\Microsoft.TeamFoundation.DistributedTask.Common.Contracts.16.140.0-preview\lib\net45\Microsoft.TeamFoundation.DistributedTask.Common.Contracts.dll</HintPath>
</Reference>
<Reference Include="Microsoft.TeamFoundation.Policy.WebApi, Version=16.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>packages\Microsoft.TeamFoundationServer.Client.16.140.0-preview\lib\net45\Microsoft.TeamFoundation.Policy.WebApi.dll</HintPath>
</Reference>
<Reference Include="Microsoft.TeamFoundation.SourceControl.WebApi, Version=16.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>packages\Microsoft.TeamFoundationServer.Client.16.140.0-preview\lib\net45\Microsoft.TeamFoundation.SourceControl.WebApi.dll</HintPath>
</Reference>
<Reference Include="Microsoft.TeamFoundation.Test.WebApi, Version=16.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>packages\Microsoft.TeamFoundationServer.Client.16.140.0-preview\lib\net45\Microsoft.TeamFoundation.Test.WebApi.dll</HintPath>
</Reference>
<Reference Include="Microsoft.TeamFoundation.TestManagement.WebApi, Version=16.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>packages\Microsoft.TeamFoundationServer.Client.16.140.0-preview\lib\net45\Microsoft.TeamFoundation.TestManagement.WebApi.dll</HintPath>
</Reference>
<Reference Include="Microsoft.TeamFoundation.Wiki.WebApi, Version=16.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>packages\Microsoft.TeamFoundationServer.Client.16.140.0-preview\lib\net45\Microsoft.TeamFoundation.Wiki.WebApi.dll</HintPath>
</Reference>
<Reference Include="Microsoft.TeamFoundation.Work.WebApi, Version=16.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>packages\Microsoft.TeamFoundationServer.Client.16.140.0-preview\lib\net45\Microsoft.TeamFoundation.Work.WebApi.dll</HintPath>
</Reference>
<Reference Include="Microsoft.TeamFoundation.WorkItemTracking.Process.WebApi, Version=16.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>packages\Microsoft.TeamFoundationServer.Client.16.140.0-preview\lib\net45\Microsoft.TeamFoundation.WorkItemTracking.Process.WebApi.dll</HintPath>
</Reference>
<Reference Include="Microsoft.TeamFoundation.WorkItemTracking.WebApi, Version=16.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>packages\Microsoft.TeamFoundationServer.Client.16.140.0-preview\lib\net45\Microsoft.TeamFoundation.WorkItemTracking.WebApi.dll</HintPath>
</Reference>
<Reference Include="Microsoft.VisualStudio.Services.Client.Interactive, Version=16.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>packages\Microsoft.VisualStudio.Services.InteractiveClient.16.140.0-preview\lib\net45\Microsoft.VisualStudio.Services.Client.Interactive.dll</HintPath>
</Reference>
<Reference Include="Microsoft.VisualStudio.Services.Common, Version=16.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>packages\Microsoft.VisualStudio.Services.Client.16.140.0-preview\lib\net45\Microsoft.VisualStudio.Services.Common.dll</HintPath>
</Reference>
<Reference Include="Microsoft.VisualStudio.Services.ReleaseManagement.WebApi, Version=17.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>packages\Microsoft.VisualStudio.Services.Release.Client.16.140.0-preview\lib\net45\Microsoft.VisualStudio.Services.ReleaseManagement.WebApi.dll</HintPath>
</Reference>
<Reference Include="Microsoft.VisualStudio.Services.TestManagement.TestPlanning.WebApi, Version=16.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>packages\Microsoft.TeamFoundationServer.Client.16.140.0-preview\lib\net45\Microsoft.VisualStudio.Services.TestManagement.TestPlanning.WebApi.dll</HintPath>
</Reference>
<Reference Include="Microsoft.VisualStudio.Services.TestResults.WebApi, Version=16.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>packages\Microsoft.TeamFoundationServer.Client.16.140.0-preview\lib\net45\Microsoft.VisualStudio.Services.TestResults.WebApi.dll</HintPath>
</Reference>
<Reference Include="Microsoft.VisualStudio.Services.WebApi, Version=16.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>packages\Microsoft.VisualStudio.Services.Client.16.140.0-preview\lib\net45\Microsoft.VisualStudio.Services.WebApi.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json, Version=11.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>packages\Newtonsoft.Json.11.0.2\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.IdentityModel.Tokens.Jwt, Version=5.2.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>packages\System.IdentityModel.Tokens.Jwt.5.2.1\lib\net451\System.IdentityModel.Tokens.Jwt.dll</HintPath>
</Reference>
<Reference Include="System.Net.Http.Formatting, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>packages\Microsoft.AspNet.WebApi.Client.5.2.3\lib\net45\System.Net.Http.Formatting.dll</HintPath>
</Reference>
<Reference Include="System.Runtime.Serialization" />
<Reference Include="System.Web.Http, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>packages\Microsoft.AspNet.WebApi.Core.5.2.3\lib\net45\System.Web.Http.dll</HintPath>
</Reference>
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="TfsRelease.CloneReleaseEnvironment.cs" />
<Compile Include="TfsRelease.cs" />
<Compile Include="TfsRelease.GetDeploymentErrors.cs" />
<Compile Include="TfsRelease.GetTfsReleaseEnvironmentNames.cs" />
</ItemGroup>
<ItemGroup>
<None Include="app.config" />
<None Include="packages.config" />
<None Include="README.md" />
<None Include="Tapas.CICD.ReleaseHelper.nuspec" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

Просмотреть файл

@ -1,18 +0,0 @@
<?xml version="1.0"?>
<package >
<metadata>
<id>$id$</id>
<version>$version$</version>
<title>$title$</title>
<authors>$author$</authors>
<owners>$author$</owners>
<licenseUrl>https://github.com/Microsoft/release-helper</licenseUrl>
<projectUrl>https://github.com/Microsoft/release-helper</projectUrl>
<iconUrl>http://icon_url_here_or_delete_this_line/</iconUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>$description$</description>
<releaseNotes>Alpha version of release helper library</releaseNotes>
<copyright>Copyright 2018</copyright>
<tags>azuredevops tfs release</tags>
</metadata>
</package>

Просмотреть файл

@ -1,251 +0,0 @@
using Microsoft.VisualStudio.Services.ReleaseManagement.WebApi;
using Microsoft.VisualStudio.Services.ReleaseManagement.WebApi.Contracts;
using Newtonsoft.Json;
using System.Collections.Generic;
using System.Linq;
namespace Tapas.CICD.ReleaseHelper
{
public partial class TfsRelease
{
public string CloneReleaseEnvironment(string SourceEnvName, string TargetEnvName)
{
string result = "";
var definitions = relclient.GetReleaseDefinitionsAsync(TfsEnvInfo.ProjectName, TfsEnvInfo.ReleaseDefinitionName, ReleaseDefinitionExpands.Environments, isExactNameMatch: true).Result;
if (definitions.Count() > 0)
{
//This call is to get the project GUID
var project = projclient.GetProject(TfsEnvInfo.ProjectName).Result;
//This returns everything in a definition including properties such as Owner in an Environment
var def = relclient.GetReleaseDefinitionAsync(project.Id, definitions.First().Id).Result;
var envcount = def.Environments.Count;
var defenvlist = def.Environments.Where(e => e.Name == SourceEnvName);
if (defenvlist.Count() > 0)
{
var source = defenvlist.First();
var newrank = def.Environments.Select(e => e.Rank).ToList().Max() + 1;
if (def.Environments.Where(e => e.Name == TargetEnvName).Count() == 0)
{
//Environment must have a minimum RetentionPolicy, Rank, Owner,
//PreDeployApprovals, PostDeployApprovals and DeployPhases
var target = new ReleaseDefinitionEnvironment()
{
Name = TargetEnvName,
RetentionPolicy = source.RetentionPolicy,
Rank = newrank,
Owner = source.Owner,
PreDeployApprovals = source.PreDeployApprovals,
PostDeployApprovals = source.PostDeployApprovals,
DeployPhases = source.DeployPhases
};
def.Environments.Add(target);
var newdef = relclient.UpdateReleaseDefinitionAsync(def, project.Id).Result;
var envinfo = new TfsCloneReleaseEnvInfo()
{
ReleaseName = newdef.Name,
EnvironmentName = target.Name,
CloneFrom = SourceEnvName,
RetentionPolicy = target.RetentionPolicy.ToString(),
Rank = target.Rank,
Owner = target.Owner.DisplayName,
PreDeployApprovals = target.PreDeployApprovals.Approvals.Where(e => e.Approver != null).OrderBy(e => e.Approver.DisplayName).Select(e => e.Approver.DisplayName).ToArray(),
PostDeployApprovals = target.PostDeployApprovals.Approvals.Where(e => e.Approver != null).OrderBy(e => e.Approver.DisplayName).Select(e => e.Approver.DisplayName).ToArray(),
DeployPhases = target.DeployPhases.OrderBy(e => e.Name).Select(e => e.Name).ToArray(),
success = (newdef.Environments.Count > envcount) ? true : false //Basic detection if environment was added
};
result = JsonConvert.SerializeObject(envinfo, Formatting.Indented);
}
else { result = $"**Warning** An Env with name \"{TargetEnvName}\" already exists"; }
}
else { result = $"**Warning** Failed to find Env with name \"{SourceEnvName}\""; }
}
else { result = $"**Warning** Failed to find Release Definition with name \"{TfsEnvInfo.ReleaseDefinitionName}\""; }
return result;
}
public string CloneReleaseEnvironment(string SourceEnvName, string TargetEnvName, int DeployGroupId)
{
string result = "";
var definitions = relclient.GetReleaseDefinitionsAsync(TfsEnvInfo.ProjectName, TfsEnvInfo.ReleaseDefinitionName, ReleaseDefinitionExpands.Environments, isExactNameMatch: true).Result;
if (definitions.Count() > 0)
{
//This call is to get the project GUID
var project = projclient.GetProject(TfsEnvInfo.ProjectName).Result;
//This returns everything in a definition including properties such as Owner in an Environment
var def = relclient.GetReleaseDefinitionAsync(project.Id, definitions.First().Id).Result;
var envcount = def.Environments.Count;
var defenvlist = def.Environments.Where(e => e.Name == SourceEnvName);
if (defenvlist.Count() > 0)
{
var source = defenvlist.First();
var newrank = def.Environments.Select(e => e.Rank).ToList().Max() + 1;
if (def.Environments.Where(e => e.Name == TargetEnvName).Count() == 0)
{
//Environment must have a minimum RetentionPolicy, Rank, Owner,
//PreDeployApprovals, PostDeployApprovals and DeployPhases
var target = new ReleaseDefinitionEnvironment()
{
Name = TargetEnvName + " - Clone from " + SourceEnvName,
RetentionPolicy = source.RetentionPolicy,
Rank = newrank,
Owner = source.Owner,
PreDeployApprovals = source.PreDeployApprovals,
PostDeployApprovals = source.PostDeployApprovals
};
//Clone phases and tasks
var newphases = source.DeployPhases.ToList();
//Update deployment group name in phases
foreach (var p in newphases)
{
if (p.PhaseType == DeployPhaseTypes.MachineGroupBasedDeployment)
{
var m = ((MachineGroupBasedDeployPhase)p);
var inputs = m.GetDeploymentInput();
var newinputs = (MachineGroupDeploymentInput)inputs.Clone();
newinputs.QueueId = DeployGroupId;
m.DeploymentInput = newinputs;
}
}
target.DeployPhases = newphases;
def.Environments.Add(target);
var newdef = relclient.UpdateReleaseDefinitionAsync(def, project.Id).Result;
var envinfo = new TfsCloneReleaseEnvInfo()
{
ReleaseName = newdef.Name,
EnvironmentName = target.Name,
CloneFrom = SourceEnvName,
RetentionPolicy = target.RetentionPolicy.ToString(),
Rank = target.Rank,
Owner = target.Owner.DisplayName,
PreDeployApprovals = target.PreDeployApprovals.Approvals.Where(e => e.Approver != null).OrderBy(e => e.Approver.DisplayName).Select(e => e.Approver.DisplayName).ToArray(),
PostDeployApprovals = target.PostDeployApprovals.Approvals.Where(e => e.Approver != null).OrderBy(e => e.Approver.DisplayName).Select(e => e.Approver.DisplayName).ToArray(),
DeployPhases = target.DeployPhases.OrderBy(e => e.Name).Select(e => e.Name).ToArray(),
success = (newdef.Environments.Count > envcount) ? true : false //Basic detection if environment was added
};
result = JsonConvert.SerializeObject(envinfo, Formatting.Indented);
}
else { result = $"**Warning** An Env with name \"{TargetEnvName}\" already exists"; }
}
else { result = $"**Warning** Failed to find Env with name \"{SourceEnvName}\""; }
}
else { result = $"**Warning** Failed to find Release Definition with name \"{TfsEnvInfo.ReleaseDefinitionName}\""; }
return result;
}
/*
public bool CloneReleaseEnvironment(string SourceEnvName, string TargetEnvName)
{
bool success = false;
var definitions = relclient.GetReleaseDefinitionsAsync(TfsEnvInfo.ProjectName, TfsEnvInfo.ReleaseDefinitionName, ReleaseDefinitionExpands.Environments, isExactNameMatch: true).Result;
//This call is to get the project GUID
var project = projclient.GetProject(TfsEnvInfo.ProjectName).Result;
//This returns everything in a definition including properties such as Owner in an Environment
var def = relclient.GetReleaseDefinitionAsync(project.Id, definitions.First().Id).Result;
var envcount = def.Environments.Count;
var source = def.Environments.Where(e => e.Name == SourceEnvName).First();
//Environment must have a minimum RetentionPolicy, Rank, Owner,
//PreDeployApprovals, PostDeployApprovals and DeployPhases
var target = new ReleaseDefinitionEnvironment()
{
Name = TargetEnvName,
RetentionPolicy = source.RetentionPolicy,
Rank = source.Rank++,
Owner = source.Owner,
PreDeployApprovals = source.PreDeployApprovals,
PostDeployApprovals = source.PostDeployApprovals,
DeployPhases = source.DeployPhases
};
def.Environments.Add(target);
var newdef = relclient.UpdateReleaseDefinitionAsync(def, project.Id).Result;
//Basic detection if environment was added
if (newdef.Environments.Count > envcount)
success = true;
return success;
}
*/
/*
public bool CloneReleaseEnvironment(string SourceEnvName, string TargetEnvName, int DeployGroupId)
{
bool success = false;
//This call is to get the project GUID
var project = projclient.GetProject(TfsEnvInfo.ProjectName).Result;
//This returns everything in a definition including properties such as Owner in an Environment
var def = relclient.GetReleaseDefinitionAsync(project.Id, TfsEnvInfo.ReleaseDefinitionID).Result;
var envcount = def.Environments.Count;
var source = def.Environments.Where(e => e.Name == SourceEnvName).First();
var newrank = def.Environments.Select(e => e.Rank).ToList().Max() + 1;
//Environment must have a minimum RetentionPolicy, Rank, Owner,
//PreDeployApprovals, PostDeployApprovals and DeployPhases
var target = new ReleaseDefinitionEnvironment()
{
Name = TargetEnvName + " - Clone from " + SourceEnvName,
RetentionPolicy = source.RetentionPolicy,
Rank = newrank,
Owner = source.Owner,
PreDeployApprovals = source.PreDeployApprovals,
PostDeployApprovals = source.PostDeployApprovals
};
//Clone phases and tasks
var newphases = source.DeployPhases.ToList();
//Update deployment group name in phases
foreach (var p in newphases)
{
if (p.PhaseType == DeployPhaseTypes.MachineGroupBasedDeployment)
{
var m = ((MachineGroupBasedDeployPhase)p);
var inputs = m.GetDeploymentInput();
var newinputs = (MachineGroupDeploymentInput)inputs.Clone();
newinputs.QueueId = DeployGroupId;
m.DeploymentInput = newinputs;
}
}
target.DeployPhases = newphases;
def.Environments.Add(target);
var newdef = relclient.UpdateReleaseDefinitionAsync(def, project.Id).Result;
//Basic detection if environment was added
if (newdef.Environments.Count > envcount)
success = true;
return success;
}
*/
}
}

Просмотреть файл

@ -1,254 +0,0 @@
using Microsoft.VisualStudio.Services.ReleaseManagement.WebApi.Contracts;
using Microsoft.VisualStudio.Services.ReleaseManagement.WebApi;
using Newtonsoft.Json;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.IO;
using System;
namespace Tapas.CICD.ReleaseHelper
{
public partial class TfsRelease
{
public string GetDeploymentErrors(int PastInstances)
{
string result = "";
List<TfsReleaseError> errorlist = new List<TfsReleaseError>();
Dictionary<string, string> inputs = new Dictionary<string, string>();
var def = relclient.GetReleaseDefinitionsAsync(TfsEnvInfo.ProjectName, TfsEnvInfo.ReleaseDefinitionName, isExactNameMatch: true).Result;
if (def.Count() > 0)
{
var id = def.First().Id;
var runs = relclient.GetDeploymentsAsync(project: TfsEnvInfo.ProjectName, definitionId: id, deploymentStatus: DeploymentStatus.Failed, operationStatus: DeploymentOperationStatus.PhaseFailed, queryOrder: ReleaseQueryOrder.Descending, top: PastInstances).Result;
foreach (var run in runs)
{
var rel = relclient.GetReleaseAsync(TfsEnvInfo.ProjectName, run.Release.Id).Result;
var env = rel.Environments.First(e => e.Id == run.ReleaseEnvironmentReference.Id);
var attempt = env.DeploySteps.First(s => s.Attempt == run.Attempt);
var phase = attempt.ReleaseDeployPhases.First(p => p.Status == DeployPhaseStatus.Failed);
//assumption here is each phase has only one job that failed
var job = phase.DeploymentJobs.First(j => j.Job.Status == Microsoft.VisualStudio.Services.ReleaseManagement.WebApi.TaskStatus.Failed);
var failedtask = job.Tasks.Where(t => t.Status == Microsoft.VisualStudio.Services.ReleaseManagement.WebApi.TaskStatus.Failed).First();
var error = new TfsReleaseError()
{
ReleaseName = rel.Name,
EnvironmentName = env.Name,
Attempt = attempt.Attempt,
PhaseType = phase.PhaseType.ToString(),
AgentName = failedtask.AgentName,
TaskName = failedtask.Name,
StartTime = failedtask.StartTime,
FinishTime = failedtask.FinishTime,
ErrorMessages = failedtask.Issues.Where(i => i.Message != "").Select(i => i.Message).ToArray()
};
var snapshot = env.DeployPhasesSnapshot.First(dps => dps.Rank == phase.Rank);
if (failedtask.Task != null) //failing at download artifacts
{
inputs = snapshot.WorkflowTasks.First(w => w.TaskId == failedtask.Task.Id).Inputs;
}
error.TaskInputs = inputs;
List<TfsArtifact> artifacts = new List<TfsArtifact>();
foreach (var a in rel.Artifacts)
{
var build = a.DefinitionReference.Where(d => d.Key == "version").Select(v => v.Value.Name).First();
var buildurl = a.DefinitionReference.Where(d => d.Key == "artifactSourceVersionUrl").Select(v => v.Value.Id).First();
artifacts.Add(new TfsArtifact()
{
Build = build,
BuildUrl = buildurl
});
}
error.Artifacts = artifacts.ToArray();
errorlist.Add(error);
}
//To download all logs for a given release
//docs: https://docs.microsoft.com/en-us/rest/api/vsts/release/releases/get%20logs?view=vsts-rest-4.1
//GET https://{accountName}.vsrm.visualstudio.com/{project}/_apis/release/releases/{releaseId}/logs?api-version=4.1-preview.2
//client.DownloadFile(rel.LogsContainerUrl, rel.Name + ".zip");
//The return data seems to have bad encoding; looks like a bug
//var logs = tfsclient.GetLogsAsync(tfsinfo.ProjectName, id).Result;
//Handle case when no errors are found
if (errorlist.Count > 0)
{
result = JsonConvert.SerializeObject(errorlist, Formatting.Indented);
}
else { result = $"**Warning** No errors found"; }
}
else { result = $"**Warning** Failed to find Release Definition with name \"{TfsEnvInfo.ReleaseDefinitionName}\""; }
return result;
}
public string GetLatestError()
{
string result = "";
List<TfsReleaseError> errorlist = new List<TfsReleaseError>();
var deflist = relclient.GetReleaseDefinitionsAsync(TfsEnvInfo.ProjectName, TfsEnvInfo.ReleaseDefinitionName, isExactNameMatch: true, expand: ReleaseDefinitionExpands.Environments).Result;
if (deflist.Count() > 0)
{
var def = deflist.First();
var defenvlist = def.Environments.Where(e => e.Name == TfsEnvInfo.EnvironmentName);
if (defenvlist.Count() > 0)
{
var defenv = defenvlist.First();
var rellist = relclient.GetReleasesAsync(def.Id, defenv.Id).Result;
if (rellist.Count() > 0)
{
var rel = rellist.Where(r => r.Name == TfsEnvInfo.ReleaseName);
if (rel.Count() > 0)
{
var relid = rel.First().Id;
var reldetails = relclient.GetReleaseAsync(TfsEnvInfo.ProjectName, relid).Result;
var env = reldetails.Environments.Where(e => e.Name == TfsEnvInfo.EnvironmentName).First();
var steplist = env.DeploySteps.Where(s => s.Status == DeploymentStatus.Failed);
foreach (var step in steplist)
{
//assuming only one phase that fails in any one deployment
var phase = step.ReleaseDeployPhases.Where(p => p.Status == DeployPhaseStatus.Failed).First();
//assumption here is each phase has only one job that failed
var job = phase.DeploymentJobs.First(j => j.Job.Status == TaskStatus.Failed);
var failedtask = job.Tasks.Where(t => t.Status == TaskStatus.Failed).First();
var error = new TfsReleaseError()
{
ReleaseName = reldetails.Name,
EnvironmentName = env.Name,
Attempt = step.Attempt,
PhaseType = phase.PhaseType.ToString(),
AgentName = failedtask.AgentName,
TaskName = failedtask.Name,
StartTime = failedtask.StartTime,
FinishTime = failedtask.FinishTime,
ErrorMessages = failedtask.Issues.Where(i => i.Message != "").Select(i => i.Message).ToArray()
};
var logstream = relclient.GetTaskLogAsync(TfsEnvInfo.ProjectName, reldetails.Id, env.Id, phase.Id, failedtask.Id).Result;
var reader = new StreamReader(logstream);
var logstring = reader.ReadToEnd();
var lines = logstring.Replace("\n", "").Split('\r');
var errorindex = Array.FindIndex(lines, l => l.Contains(error.ErrorMessages.First()));
string logsample = "";
var samplelength = 10;
int begin = (errorindex - samplelength) > 0 ? (errorindex - samplelength) : 0;
int end = (errorindex + samplelength) < lines.Length ? (errorindex + samplelength) : lines.Length;
for (int i = begin; i < end; i++)
{
logsample += lines[i];
}
error.ErrorLog = logstring;
errorlist.Add(error);
}
//Handle case when no errors are found
if (errorlist.Count > 0)
{
result = JsonConvert.SerializeObject(errorlist, Formatting.Indented);
}
else { result = $"**Warning** No errors found"; }
}
else { result = $"**Warning** Failed to find Release Details with name \"{TfsEnvInfo.ReleaseName}\""; }
}
else { result = $"**Warning** Failed to find Release with name \"{TfsEnvInfo.ReleaseName}\""; }
}
else { result = $"**Warning** Failed to find Env with name \"{TfsEnvInfo.EnvironmentName}\""; }
}
else { result = $"**Warning** Failed to find Release Definition with name \"{TfsEnvInfo.ReleaseDefinitionName}\""; }
return result;
}
public string GetDeploymentErrors(DateTime mindate, DateTime maxdate)
{
string result = "";
List<TfsReleaseError> errorlist = new List<TfsReleaseError>();
Dictionary<string, string> inputs = new Dictionary<string, string>();
var runs = relclient.GetDeploymentsAsync(project: TfsEnvInfo.ProjectName, minStartedTime: mindate, maxStartedTime: maxdate, deploymentStatus: DeploymentStatus.Failed, operationStatus: DeploymentOperationStatus.PhaseFailed, queryOrder: ReleaseQueryOrder.Descending).Result;
foreach (var run in runs)
{
var rel = relclient.GetReleaseAsync(TfsEnvInfo.ProjectName, run.Release.Id).Result;
var env = rel.Environments.First(e => e.Id == run.ReleaseEnvironmentReference.Id);
var attempt = env.DeploySteps.First(s => s.Attempt == run.Attempt);
var phase = attempt.ReleaseDeployPhases.First(p => p.Status == DeployPhaseStatus.Failed);
//assumption here is each phase has only one job that failed
var job = phase.DeploymentJobs.First(j => j.Job.Status == TaskStatus.Failed);
var failedtask = job.Tasks.Where(t => t.Status == TaskStatus.Failed).First();
//GetDeploymentsAsync return top 50 regardless of minStartedTime or maxStartedTime
//looks like a bug
if (failedtask.StartTime >= mindate && failedtask.StartTime <= maxdate)
{
var error = new TfsReleaseError()
{
ReleaseName = rel.Name,
EnvironmentName = env.Name,
Attempt = attempt.Attempt,
PhaseType = phase.PhaseType.ToString(),
AgentName = failedtask.AgentName,
TaskName = failedtask.Name,
StartTime = failedtask.StartTime,
FinishTime = failedtask.FinishTime,
ErrorMessages = failedtask.Issues.Where(i => i.Message != "").Select(i => i.Message).ToArray()
};
var snapshot = env.DeployPhasesSnapshot.First(dps => dps.Rank == phase.Rank);
if (failedtask.Task != null) //failing at download artifacts
{
inputs = snapshot.WorkflowTasks.First(w => w.TaskId == failedtask.Task.Id).Inputs;
}
error.TaskInputs = inputs;
List<TfsArtifact> artifacts = new List<TfsArtifact>();
foreach (var a in rel.Artifacts)
{
var build = a.DefinitionReference.Where(d => d.Key == "version").Select(v => v.Value.Name).First();
var q = a.DefinitionReference.Where(d => d.Key == "artifactSourceVersionUrl").Select(v => v.Value.Id);
var buildurl = (q.Count() > 0) ? q.First() : "";
artifacts.Add(new TfsArtifact()
{
Build = build,
BuildUrl = buildurl
});
}
error.Artifacts = artifacts.ToArray();
errorlist.Add(error);
}
}
//Handle case when no errors are found
if (errorlist.Count > 0)
{
result = JsonConvert.SerializeObject(errorlist, Formatting.Indented);
}
else { result = $"**Warning** No errors found"; }
return result;
}
}
}

Просмотреть файл

@ -1,40 +0,0 @@
using Microsoft.VisualStudio.Services.ReleaseManagement.WebApi.Contracts;
using Newtonsoft.Json;
using System.Collections.Generic;
using System.Linq;
namespace Tapas.CICD.ReleaseHelper
{
public partial class TfsRelease
{
public string GetTfsReleaseEnvironmentNames()
{
string result = "";
var definitions = relclient.GetReleaseDefinitionsAsync(TfsEnvInfo.ProjectName, TfsEnvInfo.ReleaseDefinitionName, ReleaseDefinitionExpands.Environments, isExactNameMatch: true).Result;
if (definitions.Count() > 0)
{
var def = definitions.First();
var releaseinfo = new TfsReleaseInfo()
{
ReleaseName = def.Name,
ReleaseNameFormat = def.Name,
Comment = def.Comment,
IsDeleted = def.IsDeleted,
ModifiedOn = def.ModifiedOn,
ModifiedBy = def.ModifiedBy.DisplayName,
CreatedOn = def.CreatedOn,
CreatedBy = def.CreatedBy.DisplayName,
Description = def.Description,
Revision = def.Revision,
EnvironmentNames = def.Environments.OrderBy(e => e.Name).Select(e => e.Name).ToArray()
};
result = JsonConvert.SerializeObject(releaseinfo, Formatting.Indented);
}
else { result = $"**Warning** Failed to find Release Definition with name \"{TfsEnvInfo.ReleaseDefinitionName}\""; }
return result;
}
}
}

Просмотреть файл

@ -1,176 +0,0 @@
using Microsoft.TeamFoundation.Core.WebApi;
using Microsoft.VisualStudio.Services.Client;
using Microsoft.VisualStudio.Services.Common;
using Microsoft.VisualStudio.Services.ReleaseManagement.WebApi.Clients;
using Microsoft.VisualStudio.Services.WebApi;
using System;
using System.Collections.Generic;
using System.Net;
namespace Tapas.CICD.ReleaseHelper
{
//Sample output
//release name: Release_20181017.1
//phase type: PhaseDeployment
//attempt #: 1
//agent name: BUILD_Agent1
//task name: Build Solution
//task starttime: 10/17/2018 10:22:20 PM
//task endtime: 10/17/2018 10:22:32 PM
//errors messages:
// Issues[0].Message
// Issues[1].Message
// Issues[2].Message
public struct TfsReleaseError
{
public string ReleaseName;
public string EnvironmentName;
public string PhaseType;
public int Attempt;
public string AgentName;
public string TaskName;
public DateTime? StartTime;
public DateTime? FinishTime;
public string[] ErrorMessages;
public string ErrorLog;
public Dictionary<string, string> TaskInputs;
public TfsArtifact[] Artifacts;
}
public struct TfsArtifact
{
public string Build;
public string BuildUrl;
}
public struct TfsInfo
{
public string ProjectCollectionUrl;
public string ProjectName;
public string ReleaseDefinitionName;
public int ReleaseDefinitionID;
public string ReleaseName;
public string EnvironmentName;
}
public struct TfsCloneReleaseEnvInfo
{
public string ReleaseName;
public string EnvironmentName;
public string CloneFrom;
public string RetentionPolicy;
public int Rank;
public string Owner;
public string[] PreDeployApprovals;
public string[] PostDeployApprovals;
public string[] DeployPhases;
public bool success;
}
public struct TfsReleaseInfo
{
public string ReleaseName;
public string Comment;
public string ReleaseNameFormat;
public bool IsDeleted;
public DateTime ModifiedOn;
public string ModifiedBy;
public DateTime CreatedOn;
public string CreatedBy;
public string Description;
public int Revision;
public string[] EnvironmentNames;
}
public partial class TfsRelease : IDisposable
{
// Dispose pattern. Refer https://msdn.microsoft.com/en-us/library/system.idisposable(v=vs.110).aspx
// Track whether Dispose has been called.
private bool disposed = false;
private WebClient client;
private ReleaseHttpClient relclient;
private ProjectHttpClient projclient;
public TfsInfo TfsEnvInfo { get; internal set; }
public TfsRelease(TfsInfo TfsEnvInfo)
{
this.TfsEnvInfo = TfsEnvInfo;
// Interactively ask the user for credentials, caching them so the user isn't constantly prompted
VssCredentials credentials = new VssClientCredentials();
credentials.Storage = new VssClientCredentialStorage();
VssConnection connection = new VssConnection(new Uri(this.TfsEnvInfo.ProjectCollectionUrl), credentials);
relclient = connection.GetClient<ReleaseHttpClient>();
projclient = connection.GetClient<ProjectHttpClient>();
client = new WebClient();
client.Credentials = credentials.Windows.Credentials;
}
public TfsRelease(TfsInfo TfsEnvInfo, string pat)
{
this.TfsEnvInfo = TfsEnvInfo;
// Use PAT in order to perform rest calls
VssConnection connection = new VssConnection(new Uri(this.TfsEnvInfo.ProjectCollectionUrl), new VssBasicCredential(string.Empty, pat));
relclient = connection.GetClient<ReleaseHttpClient>();
projclient = connection.GetClient<ProjectHttpClient>();
}
// Implement IDisposable.
// Do not make this method virtual.
// A derived class should not be able to override this method.
public void Dispose()
{
Dispose(true);
// This object will be cleaned up by the Dispose method.
// Therefore, you should call GC.SupressFinalize to
// take this object off the finalization queue
// and prevent finalization code for this object
// from executing a second time.
GC.SuppressFinalize(this);
}
// Dispose(bool disposing) executes in two distinct scenarios.
// If disposing equals true, the method has been called directly
// or indirectly by a user's code. Managed and unmanaged resources
// can be disposed.
// If disposing equals false, the method has been called by the
// runtime from inside the finalizer and you should not reference
// other objects. Only unmanaged resources can be disposed.
protected virtual void Dispose(bool disposing)
{
// Check to see if Dispose has already been called.
if (!this.disposed)
{
// If disposing equals true, dispose all managed
// and unmanaged resources.
if (disposing)
{
// Dispose resources.
}
// Note disposing has been done.
disposed = true;
}
}
// Use C# destructor syntax for finalization code.
// This destructor will run only if the Dispose method
// does not get called.
// It gives your base class the opportunity to finalize.
// Do not provide destructors in types derived from this class.
~TfsRelease()
{
// Do not re-create Dispose clean-up code here.
// Calling Dispose(false) is optimal in terms of
// readability and maintainability.
Dispose(false);
}
}
}

Просмотреть файл

@ -1,11 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-11.0.0.0" newVersion="11.0.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

Просмотреть файл

@ -1,15 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.AspNet.WebApi.Client" version="5.2.3" targetFramework="net461" />
<package id="Microsoft.AspNet.WebApi.Core" version="5.2.3" targetFramework="net461" />
<package id="Microsoft.IdentityModel.Clients.ActiveDirectory" version="3.17.2" targetFramework="net461" />
<package id="Microsoft.IdentityModel.Logging" version="5.2.1" targetFramework="net461" />
<package id="Microsoft.IdentityModel.Tokens" version="5.2.1" targetFramework="net461" />
<package id="Microsoft.TeamFoundation.DistributedTask.Common.Contracts" version="16.140.0-preview" targetFramework="net461" />
<package id="Microsoft.TeamFoundationServer.Client" version="16.140.0-preview" targetFramework="net461" />
<package id="Microsoft.VisualStudio.Services.Client" version="16.140.0-preview" targetFramework="net461" />
<package id="Microsoft.VisualStudio.Services.InteractiveClient" version="16.140.0-preview" targetFramework="net461" />
<package id="Microsoft.VisualStudio.Services.Release.Client" version="16.140.0-preview" targetFramework="net461" />
<package id="Newtonsoft.Json" version="11.0.2" targetFramework="net461" />
<package id="System.IdentityModel.Tokens.Jwt" version="5.2.1" targetFramework="net461" />
</packages>