Adding tooling to maintain snapshot dependencies
This commit is contained in:
parent
84c2e7cffe
commit
1d5b5f4f62
|
|
@ -136,6 +136,15 @@ var repos='${new Dictionary<string,string> {
|
||||||
Exec("build.cmd", "install", repo.Key);
|
Exec("build.cmd", "install", repo.Key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#run-snapshot-manager
|
||||||
|
@{
|
||||||
|
Exec(@".nuget\nuget.exe", @"restore -out packages tools\TCDependencyManager\packages.config", "");
|
||||||
|
var programFiles = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86);
|
||||||
|
var msbuildPath = Path.Combine(programFiles, "MSBuild", "12.0", "Bin", "MsBuild.exe");
|
||||||
|
Exec(msbuildPath, "TCDependencyManager.csproj", @"tools\TCDependencyManager");
|
||||||
|
Exec(@"tools\TCDependencyManager\bin\Debug\TCDependencyManager.exe", "", "");
|
||||||
|
}
|
||||||
|
|
||||||
macro name='GitPull' gitUri='string' gitBranch='string' gitFolder='string'
|
macro name='GitPull' gitUri='string' gitBranch='string' gitFolder='string'
|
||||||
git-pull
|
git-pull
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
<configuration>
|
||||||
|
|
||||||
|
</configuration>
|
||||||
|
|
@ -0,0 +1,97 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Net.Http.Headers;
|
||||||
|
using System.Text;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
|
||||||
|
namespace TCDependencyManager
|
||||||
|
{
|
||||||
|
public class GitHubAPI
|
||||||
|
{
|
||||||
|
private const string BaseUrl = "https://api.github.com/";
|
||||||
|
private readonly string _oauthToken;
|
||||||
|
|
||||||
|
public GitHubAPI(string oauthToken)
|
||||||
|
{
|
||||||
|
_oauthToken = oauthToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Repository> GetRepos()
|
||||||
|
{
|
||||||
|
using (var client = GetClient())
|
||||||
|
{
|
||||||
|
var response = client.GetAsync("orgs/aspnet/repos?page=1&per_page=100").Result;
|
||||||
|
return response.EnsureSuccessStatusCode()
|
||||||
|
.Content
|
||||||
|
.ReadAsAsync<List<Repository>>().Result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Project> GetProjects(Repository repo)
|
||||||
|
{
|
||||||
|
IEnumerable<string> projectNames = null;
|
||||||
|
using (var client = GetClient())
|
||||||
|
{
|
||||||
|
string path = string.Format("/repos/aspnet/{0}/contents/src?ref=dev", repo.Name);
|
||||||
|
var response = client.GetAsync(path).Result;
|
||||||
|
if (response.IsSuccessStatusCode)
|
||||||
|
{
|
||||||
|
var result = response.Content.ReadAsAsync<JArray>().Result;
|
||||||
|
projectNames = result.Select(r => r["name"].Value<string>());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
projectNames = Enumerable.Empty<string>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return projectNames
|
||||||
|
.AsParallel()
|
||||||
|
.Select(p => new Project
|
||||||
|
{
|
||||||
|
Repo = repo,
|
||||||
|
ProjectName = p,
|
||||||
|
Dependencies = ReadDependencies(repo, p)
|
||||||
|
})
|
||||||
|
.ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<string> ReadDependencies(Repository repo, string project)
|
||||||
|
{
|
||||||
|
using (var client = GetClient())
|
||||||
|
{
|
||||||
|
string path = string.Format("/repos/aspnet/{0}/contents/src/{1}/project.json?ref=dev", repo.Name, project);
|
||||||
|
var response = client.GetAsync(path).Result;
|
||||||
|
if (response.IsSuccessStatusCode)
|
||||||
|
{
|
||||||
|
var result = response.Content.ReadAsAsync<JObject>().Result;
|
||||||
|
var content = JsonConvert.DeserializeObject<JObject>(
|
||||||
|
Encoding.UTF8.GetString(
|
||||||
|
Convert.FromBase64String(result["content"].Value<string>())));
|
||||||
|
var dependencies = (JObject)content["dependencies"];
|
||||||
|
if (dependencies != null)
|
||||||
|
{
|
||||||
|
return dependencies.Cast<JProperty>()
|
||||||
|
.Where(prop => !String.IsNullOrEmpty(prop.Value.Value<string>()))
|
||||||
|
.Select(prop => prop.Name)
|
||||||
|
.ToList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new List<string>(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private HttpClient GetClient()
|
||||||
|
{
|
||||||
|
var client = new HttpClient
|
||||||
|
{
|
||||||
|
BaseAddress = new Uri(BaseUrl)
|
||||||
|
};
|
||||||
|
client.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue("AspNet-CI", "1.0"));
|
||||||
|
client.DefaultRequestHeaders.Add("Authorization", "token " + _oauthToken);
|
||||||
|
return client;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace TCDependencyManager
|
||||||
|
{
|
||||||
|
public class Project
|
||||||
|
{
|
||||||
|
public Repository Repo { get; set; }
|
||||||
|
|
||||||
|
public string ProjectName { get; set; }
|
||||||
|
|
||||||
|
public List<string> Dependencies { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace TCDependencyManager
|
||||||
|
{
|
||||||
|
public class Repository
|
||||||
|
{
|
||||||
|
private readonly HashSet<Repository> _dependencies = new HashSet<Repository>();
|
||||||
|
|
||||||
|
public string Id { get; set; }
|
||||||
|
|
||||||
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
public HashSet<Repository> Dependencies { get { return _dependencies; } }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,54 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace TCDependencyManager
|
||||||
|
{
|
||||||
|
public class SnapshotDependencies
|
||||||
|
{
|
||||||
|
public int Count { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("snapshot-dependency")]
|
||||||
|
public List<SnapshotDepedency> Dependencies { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class SnapshotDepedency
|
||||||
|
{
|
||||||
|
public string Id { get; set; }
|
||||||
|
|
||||||
|
public string Type { get; set; }
|
||||||
|
|
||||||
|
public Properties Properties { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("source-buildType")]
|
||||||
|
public BuildType BuildType { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Properties
|
||||||
|
{
|
||||||
|
public List<NameValuePair> Property { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class BuildType
|
||||||
|
{
|
||||||
|
public string Id { get; set; }
|
||||||
|
|
||||||
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
public string ProjectId { get; set; }
|
||||||
|
|
||||||
|
public string ProjectName { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class NameValuePair
|
||||||
|
{
|
||||||
|
public NameValuePair(string name, string value)
|
||||||
|
{
|
||||||
|
Name = name;
|
||||||
|
Value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
public string Value { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,77 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics.Contracts;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net;
|
||||||
|
|
||||||
|
namespace TCDependencyManager
|
||||||
|
{
|
||||||
|
class Program
|
||||||
|
{
|
||||||
|
private static readonly string[] _excludedRepos = new[] { "xunit", "kruntime", "coreclr", "universe" };
|
||||||
|
|
||||||
|
static int Main(string[] args)
|
||||||
|
{
|
||||||
|
var teamCityUrl = GetEnv("TEAMCITY_SERVERURL");
|
||||||
|
var teamCityUser = GetEnv("TEAMCITY_USER");
|
||||||
|
var teamCityPass = GetEnv("TEAMCITY_PASSWORD");
|
||||||
|
var githubCreds = GetEnv("GITHUB_CREDS");
|
||||||
|
|
||||||
|
var teamCity = new TeamCityAPI(teamCityUrl,
|
||||||
|
new NetworkCredential(teamCityUser, teamCityPass));
|
||||||
|
|
||||||
|
var gitHub = new GitHubAPI(githubCreds);
|
||||||
|
|
||||||
|
Console.WriteLine("Listing GitHub repos");
|
||||||
|
var repos = gitHub.GetRepos()
|
||||||
|
.Where(repo => !_excludedRepos.Contains(repo.Name, StringComparer.OrdinalIgnoreCase))
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
Console.WriteLine("Listing projects under repos");
|
||||||
|
var projects = repos.AsParallel()
|
||||||
|
.SelectMany(repo => gitHub.GetProjects(repo))
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
|
||||||
|
Console.WriteLine("Creating dependency tree");
|
||||||
|
MapRepoDependencies(projects);
|
||||||
|
|
||||||
|
Console.WriteLine("Ensuring depndencies are consistent on TeamCity");
|
||||||
|
foreach (var repo in repos.Where(p => p.Dependencies.Any()))
|
||||||
|
{
|
||||||
|
teamCity.EnsureDependencies(repo.Name, repo.Dependencies.Select(r => r.Name));
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void MapRepoDependencies(List<Project> projects)
|
||||||
|
{
|
||||||
|
var projectLookup = projects.ToDictionary(project => project.ProjectName, StringComparer.OrdinalIgnoreCase);
|
||||||
|
|
||||||
|
foreach (var project in projects)
|
||||||
|
{
|
||||||
|
foreach (var dependency in project.Dependencies)
|
||||||
|
{
|
||||||
|
Project dependencyProject;
|
||||||
|
if (projectLookup.TryGetValue(dependency, out dependencyProject) &&
|
||||||
|
project.Repo != dependencyProject.Repo)
|
||||||
|
{
|
||||||
|
project.Repo.Dependencies.Add(dependencyProject.Repo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string GetEnv(string key)
|
||||||
|
{
|
||||||
|
var envValue = Environment.GetEnvironmentVariable(key);
|
||||||
|
if (String.IsNullOrEmpty(envValue))
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(key);
|
||||||
|
}
|
||||||
|
return envValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,36 @@
|
||||||
|
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("TCDependencyManager")]
|
||||||
|
[assembly: AssemblyDescription("")]
|
||||||
|
[assembly: AssemblyConfiguration("")]
|
||||||
|
[assembly: AssemblyCompany("")]
|
||||||
|
[assembly: AssemblyProduct("TCDependencyManager")]
|
||||||
|
[assembly: AssemblyCopyright("Copyright © 2014")]
|
||||||
|
[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("9645f4a8-75b5-46ad-8539-7d9c5f61c4c9")]
|
||||||
|
|
||||||
|
// 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")]
|
||||||
|
|
@ -0,0 +1,73 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="12.0" DefaultTargets="Build" 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>{72C96182-352E-44EC-B157-AFEBDC7A74DD}</ProjectGuid>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||||
|
<RootNamespace>TCDependencyManager</RootNamespace>
|
||||||
|
<AssemblyName>TCDependencyManager</AssemblyName>
|
||||||
|
<TargetFrameworkVersion>v4.5.1</TargetFrameworkVersion>
|
||||||
|
<FileAlignment>512</FileAlignment>
|
||||||
|
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||||
|
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||||
|
<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' ">
|
||||||
|
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||||
|
<DebugType>pdbonly</DebugType>
|
||||||
|
<Optimize>true</Optimize>
|
||||||
|
<OutputPath>bin\Release\</OutputPath>
|
||||||
|
<DefineConstants>TRACE</DefineConstants>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="Newtonsoft.Json">
|
||||||
|
<HintPath>..\..\packages\Newtonsoft.Json.4.5.11\lib\net40\Newtonsoft.Json.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="System" />
|
||||||
|
<Reference Include="System.Core" />
|
||||||
|
<Reference Include="System.Net.Http" />
|
||||||
|
<Reference Include="System.Net.Http.Formatting, Version=5.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||||
|
<SpecificVersion>False</SpecificVersion>
|
||||||
|
<HintPath>..\..\packages\Microsoft.AspNet.WebApi.Client.5.1.1\lib\net45\System.Net.Http.Formatting.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="System.Xml.Linq" />
|
||||||
|
<Reference Include="System.Data.DataSetExtensions" />
|
||||||
|
<Reference Include="Microsoft.CSharp" />
|
||||||
|
<Reference Include="System.Data" />
|
||||||
|
<Reference Include="System.Xml" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Include="TeamCityAPI.cs" />
|
||||||
|
<Compile Include="GitHubAPI.cs" />
|
||||||
|
<Compile Include="Program.cs" />
|
||||||
|
<Compile Include="Models\Projects.cs" />
|
||||||
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
|
<Compile Include="Models\Repository.cs" />
|
||||||
|
<Compile Include="Models\SnapshotDependency.cs" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="App.config" />
|
||||||
|
<None Include="packages.config" />
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
|
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||||
|
Other similar extension points exist, see Microsoft.Common.targets.
|
||||||
|
<Target Name="BeforeBuild">
|
||||||
|
</Target>
|
||||||
|
<Target Name="AfterBuild">
|
||||||
|
</Target>
|
||||||
|
-->
|
||||||
|
</Project>
|
||||||
|
|
@ -0,0 +1,118 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Net.Http.Headers;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Serialization;
|
||||||
|
|
||||||
|
namespace TCDependencyManager
|
||||||
|
{
|
||||||
|
public class TeamCityAPI
|
||||||
|
{
|
||||||
|
private readonly string _teamCityUrl;
|
||||||
|
private readonly ICredentials _creds;
|
||||||
|
|
||||||
|
public TeamCityAPI(string teamCityUrl, ICredentials creds)
|
||||||
|
{
|
||||||
|
_teamCityUrl = teamCityUrl;
|
||||||
|
_creds = creds;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool TryGetDependencies(string configId, out List<string> dependencies)
|
||||||
|
{
|
||||||
|
string url = String.Format("httpAuth/app/rest/buildTypes/{0}/snapshot-dependencies", configId);
|
||||||
|
var client = GetClient();
|
||||||
|
var response = client.GetAsync(url).Result;
|
||||||
|
if (response.StatusCode == HttpStatusCode.NotFound)
|
||||||
|
{
|
||||||
|
// We don't have the config setup on the CI. That is ok.
|
||||||
|
dependencies = null;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
dependencies = response.EnsureSuccessStatusCode()
|
||||||
|
.Content.ReadAsAsync<SnapshotDependencies>()
|
||||||
|
.Result
|
||||||
|
.Dependencies.Select(f => f.Id)
|
||||||
|
.ToList();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetDependencies(string configId, IEnumerable<string> dependencies)
|
||||||
|
{
|
||||||
|
foreach (var dependencyId in dependencies)
|
||||||
|
{
|
||||||
|
Console.WriteLine("For {0} adding: {1}", configId, dependencyId);
|
||||||
|
|
||||||
|
string url = String.Format("httpAuth/app/rest/buildTypes/{0}/snapshot-dependencies", configId);
|
||||||
|
var client = GetClient();
|
||||||
|
var props = new Properties
|
||||||
|
{
|
||||||
|
Property = new List<NameValuePair>
|
||||||
|
{
|
||||||
|
new NameValuePair("run-build-if-dependency-failed", "true"),
|
||||||
|
new NameValuePair("take-successful-builds-only", "true"),
|
||||||
|
new NameValuePair("take-started-build-with-same-revisions", "true")
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var snapshotDependency = new SnapshotDepedency
|
||||||
|
{
|
||||||
|
Id = dependencyId,
|
||||||
|
Type = "snapshot_dependency",
|
||||||
|
Properties = props,
|
||||||
|
BuildType = new BuildType
|
||||||
|
{
|
||||||
|
Id = dependencyId,
|
||||||
|
Name = dependencyId,
|
||||||
|
ProjectId = "AspNet",
|
||||||
|
ProjectName = "AspNet"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var serialized = JsonConvert.SerializeObject(snapshotDependency, new JsonSerializerSettings { ContractResolver = new CamelCasePropertyNamesContractResolver() });
|
||||||
|
var content = new StringContent(serialized);
|
||||||
|
content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
|
||||||
|
var response = client.PostAsync(url, content).Result;
|
||||||
|
response.EnsureSuccessStatusCode();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string NormalizeId(string dependencyId)
|
||||||
|
{
|
||||||
|
return dependencyId.Replace(".", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void EnsureDependencies(string configId, IEnumerable<string> dependencies)
|
||||||
|
{
|
||||||
|
List<string> currentDepenencies;
|
||||||
|
if (TryGetDependencies(configId, out currentDepenencies))
|
||||||
|
{
|
||||||
|
var dependenciesToAdd = dependencies.Select(NormalizeId)
|
||||||
|
.Except(currentDepenencies, StringComparer.OrdinalIgnoreCase);
|
||||||
|
|
||||||
|
SetDependencies(configId, dependenciesToAdd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private HttpClient GetClient()
|
||||||
|
{
|
||||||
|
var handler = new HttpClientHandler
|
||||||
|
{
|
||||||
|
PreAuthenticate = true,
|
||||||
|
Credentials = _creds
|
||||||
|
};
|
||||||
|
|
||||||
|
var client = new HttpClient(handler)
|
||||||
|
{
|
||||||
|
BaseAddress = new Uri(_teamCityUrl)
|
||||||
|
};
|
||||||
|
client.DefaultRequestHeaders.Accept.Clear();
|
||||||
|
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
|
||||||
|
|
||||||
|
return client;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<packages>
|
||||||
|
<package id="Microsoft.AspNet.WebApi.Client" version="5.1.1" targetFramework="net451" />
|
||||||
|
<package id="Newtonsoft.Json" version="4.5.11" targetFramework="net451" />
|
||||||
|
</packages>
|
||||||
Loading…
Reference in New Issue