This repository was archived by the owner on Feb 23, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 25
Expand file tree
/
Copy pathRetreiveBuildContainerInformation.cs
More file actions
340 lines (311 loc) · 14.5 KB
/
RetreiveBuildContainerInformation.cs
File metadata and controls
340 lines (311 loc) · 14.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Net.Http;
using System.Text;
using System.Text.RegularExpressions;
namespace stress.codegen
{
public class RetreiveBuildContainerInformation : Task
{
private BuildMaps buildMap;
private bool SeparateTestStep;
[Required]
public string BuildPAT { get; set; }
[Required]
public string HelixAPIKey { get; set; }
[Required]
public string Repo { get; set; }
[Required]
public string Branch { get; set; }
[Required]
public string OperatingSystem{ get; set; }
public string ConfigurationGroup { get; set; }
public string Platform { get; set; }
public string SubType { get; set; }
public string BuildNumber{ get; set; }
public string TestStorageAccountKey { get; set; }
[Output]
public string TestPattern { get; set; }
[Output]
public string ProductContainerName { get; set; }
[Output]
public string ProductStorageAccount { get; set; }
[Output]
public string TestStorageAccount { get; set; }
[Output]
public string TestContainerName { get; set; }
const string containerRegex = @"Creating container named '(.*?)' in storage account (.*?)\.";
const string buildDefnUrlRegex = @"https:\/\/(.*?)\.visualstudio\.com\/DefaultCollection\/(.*?)\/_build\?_a=summary&buildId=(.*)";
public override bool Execute()
{
Debugger.Launch();
buildMap = new BuildMaps();
GetLatestBuilds();
return !Log.HasLoggedErrors;
}
private void GetLatestBuilds()
{
if (string.IsNullOrEmpty(BuildNumber))
{
GetLatestBuildNumber();
buildMap.BuildNumber = BuildNumber;
}
//Product build
string dotnetMCUrl = $"https://helix.dot.net/api/2017-01-20/aggregate/analysisdetail?analysisName=Visual+Studio+Build+Information&analysisType=external&build={ BuildNumber }&groupBy=job.properties.operatingSystem&groupBy=job.properties.subType&groupBy=job.properties.configurationGroup&groupBy=job.properties.platform&source=official%2F{Repo}%2F{Branch}%2F&type=build%2Fproduct%2F&workitem=Orchestration";
try
{
string value = string.Empty;
using (HttpClient client = new HttpClient())
{
client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Add("Authentication", string.Format("{0} {1}", "token", HelixAPIKey));
using (HttpResponseMessage response = client.GetAsync(dotnetMCUrl).Result)
{
response.EnsureSuccessStatusCode();
value = response.Content.ReadAsStringAsync().Result;
}
}
JArray buildDefintionsArray = (JArray)JsonConvert.DeserializeObject(value);
string type = string.Empty;
foreach (var buildDefinition in buildDefintionsArray)
{
//https://devdiv.visualstudio.com/DefaultCollection/DevDiv/_build?_a=summary&buildId=570846
string url = buildDefinition["Analysis"]["Uri"].ToString();
string operatingSystem = buildDefinition["Key"]["job.properties.operatingSystem"].ToString().Replace(" ", string.Empty);
string configurationGroup = buildDefinition["Key"]["job.properties.configurationGroup"].ToString();
string platform = buildDefinition["Key"]["job.properties.platform"].ToString();
string subType = buildDefinition["Key"]["job.properties.subType"].ToString();
//coreclr has a testBuild type
type =string.Join("-", operatingSystem, configurationGroup, platform, subType);
Match m = Regex.Match(url, buildDefnUrlRegex);
if (m.Groups == null)
{
continue;
}
//hack until coreclr labels it's builds correctly
if (buildMap.buildmap.ContainsKey(type))
{
continue;
}
BuildContainerInformation bContainerInformation = new BuildContainerInformation();
VSOBuild build = new VSOBuild(m.Groups[1].Value, m.Groups[2].Value, m.Groups[3].Value);
bContainerInformation.ProductBuild = build;
//coreclr
if (subType == "testBuild")
{
SeparateTestStep = true;
GetTestContainer(bContainerInformation);
}
else
{
GetProductContainer(bContainerInformation);
}
buildMap.buildmap.Add(type, bContainerInformation);
}
}
catch (Exception ex)
{
Log.LogError(ex.ToString());
}
//Grab Test zips for OperatingSystem
List<string> potentialTestZips = new List<string>();
BuildContainerInformation bc;
BuildContainerInformation bcProduct;
//coreclr
if (SeparateTestStep)
{
bcProduct = buildMap.buildmap[string.Join("-", OperatingSystem, ConfigurationGroup, Platform, "testBuild")];
bc = buildMap.buildmap[string.Join("-", OperatingSystem, ConfigurationGroup, Platform, "testBuild")];
potentialTestZips = RetreiveBlobNames.GetBlobs(bc.TestDropStorageAccount, TestStorageAccountKey, bc.TestDropContainer);
}
else
{
bcProduct = null;
bc = buildMap.buildmap[string.Join("-", OperatingSystem, ConfigurationGroup, Platform, SubType)];
potentialTestZips = RetreiveBlobNames.GetBlobs(bc.TestDropStorageAccount, TestStorageAccountKey, bc.TestDropContainer);
}
string testPattern = string.Empty;
//Get path selection for stress
if (potentialTestZips.Count > 0) {
for (int counter = 0; counter < potentialTestZips.Count; counter++)
{
int lastIndexOf = potentialTestZips[counter].LastIndexOf('/');
if (lastIndexOf > 0)
{
testPattern = potentialTestZips[counter].Substring(0, lastIndexOf);
Log.LogMessage("Test zip pattern: {0}", testPattern);
break;
}
}
}
//Setup output parameters
TestPattern = testPattern;
ProductStorageAccount = bc.ProductDropStorageAccount == null ? bcProduct.TestDropStorageAccount : bc.TestDropStorageAccount;
ProductContainerName = bc.ProductDropContainer == null ? bcProduct.TestDropStorageAccount : bc.TestDropStorageAccount;
TestStorageAccount = bc.TestDropStorageAccount==null ? string.Empty : bc.TestDropStorageAccount;
TestContainerName = bc.TestDropContainer==null ? string.Empty : bc.TestDropContainer;
}
private void GetLatestBuildNumber()
{
string GetBuildNumberUrl = $"https://helix.dot.net/api/2016-08-25/aggregate/jobs?groupBy=job.build&maxResultSets=6&source=official%2F{ Repo }%2F{ Branch }%2F&type=build%2Fproduct%2F";
try
{
string value = string.Empty;
using (HttpClient client = new HttpClient())
{
client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Add("Authentication", string.Format("{0} {1}", "token", HelixAPIKey));
using (HttpResponseMessage response = client.GetAsync(GetBuildNumberUrl).Result)
{
response.EnsureSuccessStatusCode();
value = response.Content.ReadAsStringAsync().Result;
}
JArray buildapiObject = (JArray)JsonConvert.DeserializeObject(value);
//Grab latest one
//TODO: Grab latest passing one?
BuildNumber = buildapiObject[0]["Key"]["job.build"].ToString();
}
}
catch (Exception ex)
{
Log.LogMessage(ex.ToString());
}
}
private void GetProductContainer(BuildContainerInformation b)
{
string logData = GetBuildLog(b.ProductBuild);
int i = 0;
MatchCollection mCollection = Regex.Matches(logData, containerRegex, RegexOptions.None);
if (mCollection.Count == 3)
{
foreach (Match m in mCollection)
{
if (i == 0)
{
b.TestDropContainer = m.Groups[1].Value;
b.TestDropStorageAccount = m.Groups[2].Value;
}
//Assumption that SendToHelix api order printed out doesn't change.
if (i == 1)
{
b.TestResultsContainer = m.Groups[1].Value;
b.TestResultsStorageAccount = m.Groups[2].Value;
}
if (i == 2)
{
b.ProductDropContainer = m.Groups[1].Value;
b.ProductDropStorageAccount = m.Groups[2].Value;
}
i++;
}
}
else
{
//hack until order for each repo is sorted out.
foreach (Match m in mCollection)
{
if (i == 0)
{
b.ProductDropContainer = m.Groups[1].Value;
b.ProductDropStorageAccount = m.Groups[2].Value;
}
i++;
}
}
}
//In case you would like to get TestContainer for a repo like coreclr where the test build is in a separate step
private void GetTestContainer(BuildContainerInformation b)
{
string logData = GetBuildLog(b.ProductBuild);
int i = 0;
MatchCollection mCollection = Regex.Matches(logData, containerRegex, RegexOptions.None);
foreach (Match m in mCollection)
{
if (i == 0)
{
b.TestDropContainer = m.Groups[1].Value;
b.TestDropStorageAccount = m.Groups[2].Value;
}
//Assumption that SendToHelix api order printed out doesn't change.
if (i == 1)
{
b.TestResultsContainer = m.Groups[1].Value;
b.TestResultsStorageAccount = m.Groups[2].Value;
}
i++;
}
}
private string GetBuildLog(VSOBuild build)
{
string logData = string.Empty;
string stepNumber = string.Empty;
string LogApiUrl = $"https://{build.VSOProjectNamespace}.visualstudio.com/DefaultCollection/{build.DefaultCollection}/_apis/build/builds/{build.VSOBuildId}/logs";
try
{
using (HttpClient client = new HttpClient())
{
client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(string.Format("{0}:{1}", "", BuildPAT))));
using (HttpResponseMessage response = client.GetAsync(LogApiUrl).Result)
{
response.EnsureSuccessStatusCode();
logData = response.Content.ReadAsStringAsync().Result;
JObject logCountObject = (JObject)JsonConvert.DeserializeObject(logData);
string count = logCountObject["count"].ToString();
int stepNumber1 = int.Parse(count) - 1;
stepNumber = stepNumber1.ToString();
}
string LogCountApiUrl = $"https://{build.VSOProjectNamespace}.visualstudio.com/DefaultCollection/{build.DefaultCollection}/_apis/build/builds/{build.VSOBuildId}/logs/{stepNumber}";
using (HttpResponseMessage response = client.GetAsync(LogCountApiUrl).Result)
{
response.EnsureSuccessStatusCode();
logData = response.Content.ReadAsStringAsync().Result;
}
}
}
catch (Exception ex)
{
Log.LogMessage(ex.ToString());
}
return logData;
}
}
}
internal class BuildMaps
{
public Dictionary<string, BuildContainerInformation> buildmap;
public string BuildNumber;
public BuildMaps()
{
buildmap = new Dictionary<string, BuildContainerInformation>();
}
}
internal class VSOBuild
{
public string DefaultCollection { get; set; }
public string VSOProjectNamespace { get; set; }
public string VSOBuildId { get; set; }
public string ProductStepContainingContainer { get; set; }
public string TestStepContainingContainer { get; set; }
public VSOBuild(string project, string collection, string buildid)
{
VSOProjectNamespace = project;
DefaultCollection = collection;
VSOBuildId = buildid;
}
}
internal class BuildContainerInformation
{
public VSOBuild ProductBuild { get; set; }
public string TestDropStorageAccount { get; set; }
public string TestDropContainer { get; set; }
public string ProductDropStorageAccount { get; set; }
public string ProductDropContainer { get; set; }
public string TestResultsContainer { get; set; }
public string TestResultsStorageAccount { get; set; }
}