Trim System.Title if length is > 128 (#3284)

* Trim System.Title if length is > 128

* Format Ado.cs

* Add System.Title to Repro Steps if it needs to be trimmed

* Use Convert.ToHexString() instead of an Aggregate

* Add the full length System.Title to the Scriban template instead of inserting it into repro steps

* Upgrade transient dependency for component governance
This commit is contained in:
Kanan B
2023-07-14 18:37:45 -07:00
committed by GitHub
parent 930bb3f0b7
commit f958cb7916
10 changed files with 64 additions and 34 deletions

View File

@ -55,6 +55,7 @@
<PackageReference Include="Polly.Extensions.Http" Version="3.0.0" />
<PackageReference Include="OpenTelemetry.Api" Version="1.5.0-rc.1" />
<PackageReference Include="System.Diagnostics.DiagnosticSource" Version="8.0.0-preview.4.23259.5" />
<PackageReference Include="Grpc.Net.Client" Version="2.52.0" />
</ItemGroup>
<ItemGroup>
<None Update="host.json">

View File

@ -1108,6 +1108,7 @@ public record TemplateRenderContext(
Uri TargetUrl,
Container ReportContainer,
string ReportFilename,
string IssueTitle,
string ReproCmd
);

View File

@ -1,4 +1,5 @@
using System.Net.Http;
using System.Text;
using System.Text.Json;
using Microsoft.Extensions.Logging;
using Microsoft.TeamFoundation.WorkItemTracking.WebApi;
@ -168,6 +169,9 @@ public class Ado : NotificationsBase, IAdo {
}
public sealed class AdoConnector {
// https://github.com/MicrosoftDocs/azure-devops-docs/issues/5890#issuecomment-539632059
private const int MAX_SYSTEM_TITLE_LENGTH = 128;
private readonly AdoTemplate _config;
private readonly Renderer _renderer;
private readonly string _project;
@ -175,7 +179,10 @@ public class Ado : NotificationsBase, IAdo {
private readonly Uri _instanceUrl;
private readonly ILogger _logTracer;
public static async Async.Task<AdoConnector> AdoConnectorCreator(IOnefuzzContext context, Container container, string filename, AdoTemplate config, Report report, ILogger logTracer, Renderer? renderer = null) {
renderer ??= await Renderer.ConstructRenderer(context, container, filename, report, logTracer);
if (!config.AdoFields.TryGetValue("System.Title", out var issueTitle)) {
issueTitle = "example title";
}
renderer ??= await Renderer.ConstructRenderer(context, container, filename, issueTitle, report, logTracer);
var instanceUrl = context.Creds.GetInstanceUrl();
var project = renderer.Render(config.Project, instanceUrl);
@ -391,6 +398,14 @@ public class Ado : NotificationsBase, IAdo {
});
}
if (_config.AdoFields.TryGetValue("System.Title", out var systemTitle) && systemTitle.Length > MAX_SYSTEM_TITLE_LENGTH) {
var systemTitleHashString = Convert.ToHexString(
System.Security.Cryptography.SHA256.HashData(Encoding.UTF8.GetBytes(systemTitle))
);
// try to avoid naming collisions caused by the trim by appending the first 8 characters of the title's hash at the end
_config.AdoFields["System.Title"] = $"{systemTitle[..(MAX_SYSTEM_TITLE_LENGTH - 14)]}... [{systemTitleHashString[..8]}]";
}
foreach (var field in _config.AdoFields.Keys) {
var value = Render(_config.AdoFields[field]);

View File

@ -22,7 +22,7 @@ public class GithubIssues : NotificationsBase, IGithubIssues {
var report = (Report)reportable;
try {
await Process(config, container, filename, report);
await Process(config, container, filename, config.Title, report);
} catch (ApiException e) {
await LogFailedNotification(report, e, notificationId);
}
@ -63,8 +63,8 @@ public class GithubIssues : NotificationsBase, IGithubIssues {
};
}
private async Async.Task Process(GithubIssuesTemplate config, Container container, string filename, Report report) {
var renderer = await Renderer.ConstructRenderer(_context, container, filename, report, _logTracer);
private async Async.Task Process(GithubIssuesTemplate config, Container container, string filename, string issueTitle, Report report) {
var renderer = await Renderer.ConstructRenderer(_context, container, filename, issueTitle, report, _logTracer);
var handler = await GithubConnnector.GithubConnnectorCreator(config, renderer, _context.Creds.GetInstanceUrl(), _context, _logTracer);
await handler.Process();
}

View File

@ -88,6 +88,7 @@ public class JinjaTemplateAdapter {
var minimizedStackFunctionLinesSha = "abc123";
var reportContainer = templateRenderContext?.ReportContainer ?? Container.Parse("example-container-name");
var reportFileName = templateRenderContext?.ReportFilename ?? "example file name";
var issueTitle = templateRenderContext?.IssueTitle ?? "example title";
var reproCmd = templateRenderContext?.ReproCmd ?? "onefuzz command to create a repro";
var toolName = "tool name";
var toolVersion = "tool version";
@ -216,6 +217,7 @@ public class JinjaTemplateAdapter {
context,
reportContainer,
reportFileName,
issueTitle,
report,
log,
task,
@ -235,6 +237,7 @@ public class JinjaTemplateAdapter {
targetUrl,
reportContainer,
reportFileName,
issueTitle,
reproCmd
);

View File

@ -37,6 +37,7 @@ public abstract class NotificationsBase {
private readonly Report _report;
private readonly Container _container;
private readonly string _filename;
private readonly string _issueTitle;
private readonly TaskConfig _taskConfig;
private readonly JobConfig _jobConfig;
private readonly Uri _targetUrl;
@ -48,6 +49,7 @@ public abstract class NotificationsBase {
IOnefuzzContext context,
Container container,
string filename,
string issueTitle,
Report report,
ILogger log,
Task? task = null,
@ -85,6 +87,7 @@ public abstract class NotificationsBase {
return new Renderer(
container,
filename,
issueTitle,
report,
checkedTask,
checkedJob,
@ -96,6 +99,7 @@ public abstract class NotificationsBase {
public Renderer(
Container container,
string filename,
string issueTitle,
Report report,
Task task,
Job job,
@ -106,6 +110,7 @@ public abstract class NotificationsBase {
_report = report;
_container = container;
_filename = filename;
_issueTitle = issueTitle;
_taskConfig = task.Config;
_jobConfig = job.Config;
_reportUrl = reportUrl;
@ -132,6 +137,7 @@ public abstract class NotificationsBase {
_targetUrl,
_container,
_filename,
_issueTitle,
$"onefuzz --endpoint {instanceUrl} repro create_and_connect {_container} {_filename}"
));

View File

@ -142,6 +142,16 @@
"resolved": "0.12.2",
"contentHash": "JgMAGj8ekeAzKkagubXqf1UqgfHq89GyA1UQYWbkAe441uRr2Rh2rktkx5Z0LPwmD/aOqu9cxjekD2GZjP8rbw=="
},
"Grpc.Net.Client": {
"type": "Direct",
"requested": "[2.52.0, )",
"resolved": "2.52.0",
"contentHash": "hWVH9g/Nnjz40ni//2S8UIOyEmhueQREoZIkD0zKHEPqLxXcNlbp4eebXIOicZtkwDSx0TFz9NpkbecEDn6rBw==",
"dependencies": {
"Grpc.Net.Common": "2.52.0",
"Microsoft.Extensions.Logging.Abstractions": "3.0.3"
}
},
"Microsoft.Azure.AppConfiguration.Functions.Worker": {
"type": "Direct",
"requested": "[6.0.0, )",
@ -475,21 +485,12 @@
},
"Grpc.Core.Api": {
"type": "Transitive",
"resolved": "2.49.0",
"contentHash": "6OTcSQ8iML+xzmELhH4anUZlNM3dHDKPFBsMLSdiT80LJaaZKxwZml/K9ZdfLIjSR/EzdMZzzU2Avbedz4N7BA==",
"resolved": "2.52.0",
"contentHash": "SQiPyBczG4vKPmI6Fd+O58GcxxDSFr6nfRAJuBDUNj+PgdokhjWJvZE/La1c09AkL2FVm/jrDloG89nkzmVF7A==",
"dependencies": {
"System.Memory": "4.5.3"
}
},
"Grpc.Net.Client": {
"type": "Transitive",
"resolved": "2.49.0",
"contentHash": "mLXxEJzqnRHseVzRCzSQznA7y8pcSStVbstLTUuQRulN7kREovh82ctNkGpkfwONi/DHoWscX9mJLiAmh0gjOQ==",
"dependencies": {
"Grpc.Net.Common": "2.49.0",
"Microsoft.Extensions.Logging.Abstractions": "3.0.3"
}
},
"Grpc.Net.ClientFactory": {
"type": "Transitive",
"resolved": "2.49.0",
@ -501,10 +502,10 @@
},
"Grpc.Net.Common": {
"type": "Transitive",
"resolved": "2.49.0",
"contentHash": "G0TVTS8fjCk8b7td/E7C8/ssJPm3JnGVBKsveoj/89PIwIee72qkXG+tVn5c1gwTanEFPdyPoydna/bmU/NAaw==",
"resolved": "2.52.0",
"contentHash": "di9qzpdx525IxumZdYmu6sG2y/gXJyYeZ1ruFUzB9BJ1nj4kU1/dTAioNCMt1VLRvNVDqh8S8B1oBdKhHJ4xRg==",
"dependencies": {
"Grpc.Core.Api": "2.49.0"
"Grpc.Core.Api": "2.52.0"
}
},
"Microsoft.ApplicationInsights": {

View File

@ -58,6 +58,7 @@ public abstract class AdoTestBase : FunctionTestBase {
new Ado.Renderer(
Container.Parse("abc"),
string.Empty,
string.Empty,
new Report(null, null, string.Empty, string.Empty, string.Empty, new(), string.Empty, string.Empty, null, Guid.Empty, Guid.Empty, null, null, null, null, null, null, null, null, null, null, null, null),
new Task(Guid.Empty, Guid.Empty, TaskState.Init, Os.Windows, new TaskConfig(Guid.Empty, null, new TaskDetails(TaskType.LibfuzzerFuzz, 1))),
new Job(Guid.Empty, JobState.Init, new JobConfig(string.Empty, string.Empty, string.Empty, 1, null)),

View File

@ -284,18 +284,18 @@
},
"Grpc.Core.Api": {
"type": "Transitive",
"resolved": "2.49.0",
"contentHash": "6OTcSQ8iML+xzmELhH4anUZlNM3dHDKPFBsMLSdiT80LJaaZKxwZml/K9ZdfLIjSR/EzdMZzzU2Avbedz4N7BA==",
"resolved": "2.52.0",
"contentHash": "SQiPyBczG4vKPmI6Fd+O58GcxxDSFr6nfRAJuBDUNj+PgdokhjWJvZE/La1c09AkL2FVm/jrDloG89nkzmVF7A==",
"dependencies": {
"System.Memory": "4.5.3"
}
},
"Grpc.Net.Client": {
"type": "Transitive",
"resolved": "2.49.0",
"contentHash": "mLXxEJzqnRHseVzRCzSQznA7y8pcSStVbstLTUuQRulN7kREovh82ctNkGpkfwONi/DHoWscX9mJLiAmh0gjOQ==",
"resolved": "2.52.0",
"contentHash": "hWVH9g/Nnjz40ni//2S8UIOyEmhueQREoZIkD0zKHEPqLxXcNlbp4eebXIOicZtkwDSx0TFz9NpkbecEDn6rBw==",
"dependencies": {
"Grpc.Net.Common": "2.49.0",
"Grpc.Net.Common": "2.52.0",
"Microsoft.Extensions.Logging.Abstractions": "3.0.3"
}
},
@ -310,10 +310,10 @@
},
"Grpc.Net.Common": {
"type": "Transitive",
"resolved": "2.49.0",
"contentHash": "G0TVTS8fjCk8b7td/E7C8/ssJPm3JnGVBKsveoj/89PIwIee72qkXG+tVn5c1gwTanEFPdyPoydna/bmU/NAaw==",
"resolved": "2.52.0",
"contentHash": "di9qzpdx525IxumZdYmu6sG2y/gXJyYeZ1ruFUzB9BJ1nj4kU1/dTAioNCMt1VLRvNVDqh8S8B1oBdKhHJ4xRg==",
"dependencies": {
"Grpc.Core.Api": "2.49.0"
"Grpc.Core.Api": "2.52.0"
}
},
"Microsoft.ApplicationInsights": {
@ -2514,6 +2514,7 @@
"Azure.Storage.Blobs": "[12.13.0, )",
"Azure.Storage.Queues": "[12.11.0, )",
"Faithlife.Utility": "[0.12.2, )",
"Grpc.Net.Client": "[2.52.0, )",
"Microsoft.Azure.AppConfiguration.Functions.Worker": "[6.0.0, )",
"Microsoft.Azure.Functions.Extensions": "[1.1.0, )",
"Microsoft.Azure.Functions.Worker": "[1.14.1, )",

View File

@ -286,18 +286,18 @@
},
"Grpc.Core.Api": {
"type": "Transitive",
"resolved": "2.49.0",
"contentHash": "6OTcSQ8iML+xzmELhH4anUZlNM3dHDKPFBsMLSdiT80LJaaZKxwZml/K9ZdfLIjSR/EzdMZzzU2Avbedz4N7BA==",
"resolved": "2.52.0",
"contentHash": "SQiPyBczG4vKPmI6Fd+O58GcxxDSFr6nfRAJuBDUNj+PgdokhjWJvZE/La1c09AkL2FVm/jrDloG89nkzmVF7A==",
"dependencies": {
"System.Memory": "4.5.3"
}
},
"Grpc.Net.Client": {
"type": "Transitive",
"resolved": "2.49.0",
"contentHash": "mLXxEJzqnRHseVzRCzSQznA7y8pcSStVbstLTUuQRulN7kREovh82ctNkGpkfwONi/DHoWscX9mJLiAmh0gjOQ==",
"resolved": "2.52.0",
"contentHash": "hWVH9g/Nnjz40ni//2S8UIOyEmhueQREoZIkD0zKHEPqLxXcNlbp4eebXIOicZtkwDSx0TFz9NpkbecEDn6rBw==",
"dependencies": {
"Grpc.Net.Common": "2.49.0",
"Grpc.Net.Common": "2.52.0",
"Microsoft.Extensions.Logging.Abstractions": "3.0.3"
}
},
@ -312,10 +312,10 @@
},
"Grpc.Net.Common": {
"type": "Transitive",
"resolved": "2.49.0",
"contentHash": "G0TVTS8fjCk8b7td/E7C8/ssJPm3JnGVBKsveoj/89PIwIee72qkXG+tVn5c1gwTanEFPdyPoydna/bmU/NAaw==",
"resolved": "2.52.0",
"contentHash": "di9qzpdx525IxumZdYmu6sG2y/gXJyYeZ1ruFUzB9BJ1nj4kU1/dTAioNCMt1VLRvNVDqh8S8B1oBdKhHJ4xRg==",
"dependencies": {
"Grpc.Core.Api": "2.49.0"
"Grpc.Core.Api": "2.52.0"
}
},
"Microsoft.ApplicationInsights": {
@ -2516,6 +2516,7 @@
"Azure.Storage.Blobs": "[12.13.0, )",
"Azure.Storage.Queues": "[12.11.0, )",
"Faithlife.Utility": "[0.12.2, )",
"Grpc.Net.Client": "[2.52.0, )",
"Microsoft.Azure.AppConfiguration.Functions.Worker": "[6.0.0, )",
"Microsoft.Azure.Functions.Extensions": "[1.1.0, )",
"Microsoft.Azure.Functions.Worker": "[1.14.1, )",