Skip to content

Commit

Permalink
Include core dump link
Browse files Browse the repository at this point in the history
Include the core dump link in the search-helix command

closes #4
  • Loading branch information
jaredpar committed May 4, 2020
1 parent 7826a33 commit 69ac18a
Show file tree
Hide file tree
Showing 11 changed files with 222 additions and 68 deletions.
10 changes: 8 additions & 2 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,15 @@
"preLaunchTask": "build",
"program": "${workspaceFolder}/runfo/bin/Debug/netcoreapp3.1/runfo.dll",
"args": [
"builds",
"search-helix",
"-before",
"2020/4/29"
"2020/4/29",
"-c",
"10",
"-d",
"runtime",
"-v",
"after 60000ms waiting for remote process"
],
"cwd": "${workspaceFolder}/runfo",
"console": "internalConsole",
Expand Down
50 changes: 43 additions & 7 deletions DevOps.Functions/Functions.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
#nullable enable

using System.IO;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
Expand All @@ -12,12 +13,16 @@
using DevOps.Util.Triage;
using Octokit;
using DevOps.Util;
using System;

namespace DevOps.Functions
{
public class BuildCompleteMessage
{
public string ProjectId { get; set; }
public string? ProjectId { get; set; }

public string? ProjectName { get; set; }

public int BuildNumber { get; set; }
}

Expand All @@ -42,8 +47,8 @@ public Functions(DevOpsServer server, GitHubClient gitHubClient, TriageContext c
[FunctionName("build")]
public async Task<IActionResult> OnBuild(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest req,
ILogger logger,
[Queue("build-complete", Connection = "AzureWebJobsStorage")] IAsyncCollector<string> queueCollector)
[Queue("build-complete", Connection = "AzureWebJobsStorage")] IAsyncCollector<string> queueCollector,
ILogger logger)
{
string requestBody = await new StreamReader(req.Body).ReadToEndAsync().ConfigureAwait(false);
logger.LogInformation(requestBody);
Expand All @@ -60,17 +65,48 @@ public Functions(DevOpsServer server, GitHubClient gitHubClient, TriageContext c
}

[FunctionName("triage-build")]
public async Task OnBuildComplete(
public async Task TriageBuildAsync(
[QueueTrigger("build-complete", Connection = "AzureWebJobsStorage")] string message,
ILogger logger)
{
var buildCompleteMessage = JsonConvert.DeserializeObject<BuildCompleteMessage>(message);
var projectName = await Server.ConvertProjectIdToNameAsync(buildCompleteMessage.ProjectId);
var projectName = buildCompleteMessage.ProjectName;
if (projectName is null)
{
var projectId = buildCompleteMessage.ProjectId;
if (projectId is null)
{
logger.LogError("Both project name and id are null");
return;
}

projectName = await Server.ConvertProjectIdToNameAsync(projectId);
}

logger.LogInformation($"Triaging build {projectName} {buildCompleteMessage.BuildNumber}");

var util = new AutoTriageUtil(Server, Context, logger);
await util.TriageAsync(projectName, buildCompleteMessage.BuildNumber);
await util.TriageBuildAsync(projectName, buildCompleteMessage.BuildNumber);
}

[FunctionName("triage-query")]
public async Task TriageQueryAsync(
[QueueTrigger("triage-query", Connection = "AzureWebJobsStorage")] string message,
[Queue("build-complete", Connection = "AzureWebJobsStorage")] IAsyncCollector<BuildCompleteMessage> triageQueue,
ILogger logger)
{
logger.LogInformation($"Triaging query: {message}");
var queryUtil = new DotNetQueryUtil(Server);
foreach (var build in await queryUtil.ListBuildsAsync(message))
{
var key = build.GetBuildKey();
var buildCompleteMessage = new BuildCompleteMessage()
{
ProjectName = key.Project,
BuildNumber = key.Number,
};
await triageQueue.AddAsync(buildCompleteMessage);
}
}

// [FunctionName("issues-update")]
Expand Down
4 changes: 2 additions & 2 deletions DevOps.Util.DotNet/HelixLogInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ namespace DevOps.Util.DotNet
{
public enum HelixLogKind
{
RunClientUri,
RunClient,

Console,

Expand Down Expand Up @@ -41,7 +41,7 @@ public sealed class HelixLogInfo

public string? GetUri(HelixLogKind kind) => kind switch
{
HelixLogKind.RunClientUri => RunClientUri,
HelixLogKind.RunClient => RunClientUri,
HelixLogKind.Console => ConsoleUri,
HelixLogKind.CoreDump => CoreDumpUri,
HelixLogKind.TestResults => TestResultsUri,
Expand Down
124 changes: 118 additions & 6 deletions DevOps.Util.DotNet/ReportBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,12 +56,11 @@ public sealed class ReportBuilder
builder.Append($"|[{definitionName}]({definitionUri})");
}

var kind = "Rolling";
if (buildInfo.PullRequestKey.HasValue)
{
kind = $"PR {buildInfo.PullRequestKey.Value.PullRequestUri}";
}
builder.AppendLine($"|[{buildInfo.Number}]({buildInfo.BuildUri})|{kind}|{result.JobName}|");
builder.Append("|");
AppendBuildLink(builder, buildInfo);
builder.Append("|");
AppendBuildKind(builder, buildInfo);
builder.AppendLine($"|{result.JobName}|");
}
else
{
Expand All @@ -84,5 +83,118 @@ public sealed class ReportBuilder

return builder.ToString();
}

public string BuildSearchHelix(
IEnumerable<(BuildInfo BuildInfo, HelixLogInfo HelixLogInfo)> results,
HelixLogKind[] kinds,
bool markdown,
string? footer = null)
{
var builder = new StringBuilder();
if (markdown)
{
builder.AppendLine(MarkdownReportStart);
builder.Append("|Build|Kind|");

var header = "|---|---|";
foreach (var kind in kinds)
{
var columnName = GetTitleName(kind);
builder.Append($"{columnName}|");
header += "---|";
}
builder.AppendLine();
builder.AppendLine(header);

foreach (var tuple in results)
{
var buildInfo = tuple.BuildInfo;
var helixLogInfo = tuple.HelixLogInfo;
builder.Append("|");
AppendBuildLink(builder, buildInfo);
builder.Append("|");
AppendBuildKind(builder, buildInfo);
builder.Append("|");
foreach (var kind in kinds)
{
var uri = helixLogInfo.GetUri(kind);
if (uri is null)
{
builder.Append("|");
continue;
}

var name = GetValueName(kind);
builder.Append($"[{name}]({uri})|");
}
builder.AppendLine();
}

AppendFooter();
builder.AppendLine(MarkdownReportEnd);
}
else
{
foreach (var tuple in results)
{
var buildInfo = tuple.BuildInfo;
var helixLogInfo = tuple.HelixLogInfo;

builder.AppendLine(buildInfo.BuildUri);
foreach (var kind in kinds)
{
var name = GetTitleName(kind);
var uri = helixLogInfo.GetUri(kind);
builder.AppendLine($" {name} - {uri}");
}
}
AppendFooter();
}

return builder.ToString();

void AppendFooter()
{
if (footer is object)
{
builder.AppendLine();
builder.AppendLine(footer);
}
}

static string GetTitleName(HelixLogKind kind) => kind switch
{
HelixLogKind.Console => "Console",
HelixLogKind.CoreDump => "Core Dump",
HelixLogKind.RunClient => "Run Client",
HelixLogKind.TestResults => "Test Results",
_ => throw new InvalidOperationException($"Invalid kind {kind}")
};

static string GetValueName(HelixLogKind kind) => kind switch
{
HelixLogKind.Console => "console.log",
HelixLogKind.CoreDump => "core dump",
HelixLogKind.RunClient => "runclient.py",
HelixLogKind.TestResults => "test results",
_ => throw new InvalidOperationException($"Invalid kind {kind}"),
};
}

private static void AppendBuildLink(StringBuilder builder, BuildInfo buildInfo)
{
builder.Append($"[{buildInfo.Number}]({buildInfo.BuildUri})");
}

private static void AppendBuildKind(StringBuilder builder, BuildInfo buildInfo)
{
var kind = "Rolling";
if (buildInfo.PullRequestKey is GitHubPullRequestKey prKey)
{
kind = $"[PR {prKey.Number}]({prKey.PullRequestUri})";
}

builder.Append(kind);
}
}
}
10 changes: 5 additions & 5 deletions DevOps.Util.Triage/AutoTriageUtil.cs
Original file line number Diff line number Diff line change
Expand Up @@ -94,23 +94,23 @@ public void EnsureTriageIssues()
};
}

public async Task TriageAsync(string projectName, int buildNumber)
public async Task TriageBuildAsync(string projectName, int buildNumber)
{
var build = await Server.GetBuildAsync(projectName, buildNumber).ConfigureAwait(false);
await TriageAsync(build).ConfigureAwait(false);
await TriageBuildAsync(build).ConfigureAwait(false);
}

public async Task TriageAsync(string buildQuery)
public async Task TriageQueryAsync(string buildQuery)
{
foreach (var build in await QueryUtil.ListBuildsAsync(buildQuery))
{
await TriageAsync(build).ConfigureAwait(false);
await TriageBuildAsync(build).ConfigureAwait(false);
}
}

// TODO: need overload that takes builds and groups up the issue and PR updates
// or maybe just make that a separate operation from triage
public async Task TriageAsync(Build build)
public async Task TriageBuildAsync(Build build)
{
var buildInfo = build.GetBuildInfo();
var modelBuild = TriageContextUtil.EnsureBuild(buildInfo);
Expand Down
2 changes: 1 addition & 1 deletion DevOps.Util.Triage/BuildTriageUtil.cs
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ internal async Task TriageAsync()
await DoSearchTimelineAsync(issue);
break;
case SearchKind.SearchHelixRunClient:
await DoSearchHelixAsync(issue, HelixLogKind.RunClientUri);
await DoSearchHelixAsync(issue, HelixLogKind.RunClient);
break;
case SearchKind.SearchHelixConsole:
await DoSearchHelixAsync(issue, HelixLogKind.Console);
Expand Down
13 changes: 12 additions & 1 deletion DevOps.Util/DevOpsServer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ public async Task<BuildArtifact> GetArtifactAsync(string project, int buildId, s
}

/// <summary>
/// The project in a server can be expressed as an IDE or a name. This method will convert the
/// The project in a server can be expressed as an ID or a name. This method will convert the
/// ID form, typically a GUID, into a friendly name.
/// </summary>
public async Task<string> ConvertProjectIdToNameAsync(string id)
Expand All @@ -225,6 +225,17 @@ public async Task<string> ConvertProjectIdToNameAsync(string id)
return definitions[0].Project.Name;
}

public async Task<string> ConvertProjectNameToIdAsync(string name)
{
var definitions = await ListDefinitionsAsync(name, top: 1);
if (definitions.Count == 0)
{
throw new InvalidOperationException();
}

return definitions[0].Project.Id;
}

public Task<MemoryStream> DownloadArtifactAsync(string project, int buildId, string artifactName) =>
WithMemoryStream(s => DownloadArtifactAsync(project, buildId, artifactName, s));

Expand Down
1 change: 1 addition & 0 deletions runfo/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ internal static async Task<int> Main(string[] args)
catch (Exception ex)
{
Console.WriteLine(ex.Message);
Console.WriteLine(ex.StackTrace);
return ExitFailure;
}

Expand Down
Loading

0 comments on commit 69ac18a

Please sign in to comment.