Skip to content
This repository was archived by the owner on Nov 1, 2023. It is now read-only.

Commit 88b2cb5

Browse files
committed
Add a field to the job summary to indicate if at least one bug was created
1 parent d50fd48 commit 88b2cb5

File tree

11 files changed

+101
-16
lines changed

11 files changed

+101
-16
lines changed

src/ApiService/ApiService/Functions/Jobs.cs

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -136,13 +136,11 @@ private async Task<HttpResponseData> Get(HttpRequestData req) {
136136
static JobTaskInfo TaskToJobTaskInfo(Task t) => new(t.TaskId, t.Config.Task.Type, t.State);
137137

138138
var tasks = _context.TaskOperations.SearchStates(jobId);
139-
if (search.WithTasks ?? false) {
140-
var ts = await tasks.ToListAsync();
141-
return await RequestHandling.Ok(req, JobResponse.ForJob(job, ts));
142-
} else {
143-
var taskInfo = await tasks.Select(TaskToJobTaskInfo).ToListAsync();
144-
return await RequestHandling.Ok(req, JobResponse.ForJob(job, taskInfo));
145-
}
139+
140+
IAsyncEnumerable<IJobTaskInfo> taskInfo = search.WithTasks ?? false ? tasks : tasks.Select(TaskToJobTaskInfo);
141+
142+
var crashReported = await _context.JobCrashReportedOperations.CrashReported(jobId);
143+
return await RequestHandling.Ok(req, JobResponse.ForJob(job, taskInfo.ToEnumerable(), crashReported));
146144
}
147145

148146
var jobs = await _context.JobOperations.SearchState(states: search.State ?? Enumerable.Empty<JobState>()).ToListAsync();

src/ApiService/ApiService/Functions/QueueJobResult.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,10 @@ public async Async.Task Run([QueueTrigger("job-result", Connection = "AzureWebJo
4949
var jobResultType = data.Type;
5050
_log.LogInformation($"job result data type: {jobResultType}");
5151

52+
if (jobResultType == "CrashReported") {
53+
var _result = await _context.JobCrashReportedOperations.ReportCrash(job.JobId, jr.TaskId);
54+
}
55+
5256
Dictionary<string, double> value;
5357
if (jr.Value.Count > 0) {
5458
value = jr.Value;

src/ApiService/ApiService/OneFuzzTypes/Model.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -968,9 +968,12 @@ public record Job(
968968
StoredUserInfo? UserInfo,
969969
string? Error = null,
970970
DateTimeOffset? EndTime = null
971-
) : StatefulEntityBase<JobState>(State) {
971+
) : StatefulEntityBase<JobState>(State);
972972

973-
}
973+
public record JobCrashReported(
974+
[PartitionKey] Guid JobId,
975+
[RowKey] Guid TaskId
976+
) : EntityBase;
974977

975978
// This is like UserInfo but lacks the UPN:
976979
public record StoredUserInfo(Guid? ApplicationId, Guid? ObjectId);

src/ApiService/ApiService/OneFuzzTypes/Responses.cs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ public record ContainerInfo(
9292
Uri SasUrl
9393
) : BaseResponse();
9494

95+
9596
public record JobResponse(
9697
Guid JobId,
9798
JobState State,
@@ -101,10 +102,11 @@ public record JobResponse(
101102
IEnumerable<IJobTaskInfo>? TaskInfo,
102103
StoredUserInfo? UserInfo,
103104
[property: JsonPropertyName("Timestamp")] // must retain capital T for backcompat
104-
DateTimeOffset? Timestamp
105+
DateTimeOffset? Timestamp,
106+
bool CrashReported
105107
// not including UserInfo from Job model
106108
) : BaseResponse() {
107-
public static JobResponse ForJob(Job j, IEnumerable<IJobTaskInfo>? taskInfo)
109+
public static JobResponse ForJob(Job j, IEnumerable<IJobTaskInfo>? taskInfo, bool crashReported = false)
108110
=> new(
109111
JobId: j.JobId,
110112
State: j.State,
@@ -113,7 +115,8 @@ public static JobResponse ForJob(Job j, IEnumerable<IJobTaskInfo>? taskInfo)
113115
EndTime: j.EndTime,
114116
TaskInfo: taskInfo,
115117
UserInfo: j.UserInfo,
116-
Timestamp: j.Timestamp
118+
Timestamp: j.Timestamp,
119+
CrashReported: crashReported
117120
);
118121
public DateTimeOffset? StartTime => EndTime is DateTimeOffset endTime ? endTime.Subtract(TimeSpan.FromHours(Config.Duration)) : null;
119122
}

src/ApiService/ApiService/Program.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,11 @@ namespace Microsoft.OneFuzz.Service;
2424
public class Program {
2525

2626
/// <summary>
27-
///
27+
///
2828
/// </summary>
2929
public class LoggingMiddleware : IFunctionsWorkerMiddleware {
3030
/// <summary>
31-
///
31+
///
3232
/// </summary>
3333
/// <param name="context"></param>
3434
/// <param name="next"></param>
@@ -198,6 +198,7 @@ public static async Async.Task Main() {
198198
.AddScoped<INodeMessageOperations, NodeMessageOperations>()
199199
.AddScoped<ISubnet, Subnet>()
200200
.AddScoped<IAutoScaleOperations, AutoScaleOperations>()
201+
.AddScoped<IJobCrashReportedOperations, JobCrashReportedOperations>()
201202
.AddSingleton<GraphServiceClient>(new GraphServiceClient(new DefaultAzureCredential()))
202203
.AddSingleton<DependencyTrackingTelemetryModule>()
203204
.AddSingleton<ICreds, Creds>()
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
using System.Threading.Tasks;
2+
using ApiService.OneFuzzLib.Orm;
3+
using Microsoft.Extensions.Logging;
4+
namespace Microsoft.OneFuzz.Service;
5+
6+
public interface IJobCrashReportedOperations : IOrm<JobCrashReported> {
7+
public Task<bool> CrashReported(Guid jobId);
8+
public Task<OneFuzzResultVoid> ReportCrash(Guid jobId, Guid taskId);
9+
}
10+
11+
public class JobCrashReportedOperations : Orm<JobCrashReported>, IJobCrashReportedOperations {
12+
public JobCrashReportedOperations(ILogger<JobCrashReportedOperations> logTracer, IOnefuzzContext context) : base(logTracer, context) {
13+
}
14+
15+
public async Task<bool> CrashReported(Guid jobId) {
16+
return await QueryAsync(Query.RowKey(jobId.ToString())).AnyAsync();
17+
}
18+
19+
public async Task<OneFuzzResultVoid> ReportCrash(Guid jobId, Guid taskId) {
20+
21+
var result = await Update(new JobCrashReported(jobId, taskId));
22+
if (!result.IsOk) {
23+
return OneFuzzResultVoid.Error(ErrorCode.UNABLE_TO_UPDATE, "Failed to update job crash reported");
24+
}
25+
26+
return OneFuzzResultVoid.Ok;
27+
}
28+
}

src/ApiService/ApiService/onefuzzlib/OnefuzzContext.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ public interface IOnefuzzContext {
4949
ITeams Teams { get; }
5050
IGithubIssues GithubIssues { get; }
5151
IAdo Ado { get; }
52-
52+
IJobCrashReportedOperations JobCrashReportedOperations { get; }
5353
IFeatureManagerSnapshot FeatureManagerSnapshot { get; }
5454
IConfigurationRefresher ConfigurationRefresher { get; }
5555
}
@@ -101,6 +101,7 @@ public OnefuzzContext(IServiceProvider serviceProvider) {
101101
public ITeams Teams => _serviceProvider.GetRequiredService<ITeams>();
102102
public IGithubIssues GithubIssues => _serviceProvider.GetRequiredService<IGithubIssues>();
103103
public IAdo Ado => _serviceProvider.GetRequiredService<IAdo>();
104+
public IJobCrashReportedOperations JobCrashReportedOperations => _serviceProvider.GetRequiredService<IJobCrashReportedOperations>();
104105

105106
public IFeatureManagerSnapshot FeatureManagerSnapshot => _serviceProvider.GetRequiredService<IFeatureManagerSnapshot>();
106107

src/ApiService/ApiService/onefuzzlib/notifications/Ado.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -663,8 +663,8 @@ public async Async.Task Process(IList<(string, string)> notificationInfo, bool i
663663
_logTracer.AddTags(notificationInfo);
664664
_logTracer.AddTag("WorkItemId", entry.Id.HasValue ? entry.Id.Value.ToString() : "");
665665
_logTracer.LogEvent(adoEventType);
666-
}
667666
}
667+
}
668668

669669
private static bool IsADODuplicateWorkItem(WorkItem wi, Dictionary<string, string>? duplicateFields) {
670670
// A work item could have System.State == Resolve && System.Reason == Duplicate

src/ApiService/IntegrationTests/Fakes/TestContext.cs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.Collections.Generic;
23
using System.Linq;
34
using System.Net.Http;
45
using Microsoft.Extensions.Caching.Memory;
@@ -42,6 +43,7 @@ public TestContext(IHttpClientFactory httpClientFactory, OneFuzzLoggerProvider p
4243
ReproOperations = new ReproOperations(provider.CreateLogger<ReproOperations>(), this);
4344
Reports = new Reports(provider.CreateLogger<Reports>(), Containers);
4445
NotificationOperations = new NotificationOperations(provider.CreateLogger<NotificationOperations>(), this);
46+
JobCrashReportedOperations = new JobCrashReportedOperations(provider.CreateLogger<JobCrashReportedOperations>(), this);
4547

4648
FeatureManagerSnapshot = new TestFeatureManagerSnapshot();
4749
WebhookOperations = new TestWebhookOperations(httpClientFactory, provider.CreateLogger<WebhookOperations>(), this);
@@ -65,9 +67,28 @@ public Async.Task InsertAll(params EntityBase[] objs)
6567
InstanceConfig ic => ConfigOperations.Insert(ic),
6668
Notification n => NotificationOperations.Insert(n),
6769
Webhook w => WebhookOperations.Insert(w),
70+
JobCrashReported crashReported => JobCrashReportedOperations.Insert(crashReported),
6871
_ => throw new NotSupportedException($"You will need to add an TestContext.InsertAll case for {x.GetType()} entities"),
6972
}));
7073

74+
public Async.Task InsertAll(IEnumerable<EntityBase> objs)
75+
=> Async.Task.WhenAll(
76+
objs.Select(x => x switch {
77+
Task t => TaskOperations.Insert(t),
78+
Node n => NodeOperations.Insert(n),
79+
Pool p => PoolOperations.Insert(p),
80+
Job j => JobOperations.Insert(j),
81+
JobResult jr => JobResultOperations.Insert(jr),
82+
Repro r => ReproOperations.Insert(r),
83+
Scaleset ss => ScalesetOperations.Insert(ss),
84+
NodeTasks nt => NodeTasksOperations.Insert(nt),
85+
InstanceConfig ic => ConfigOperations.Insert(ic),
86+
Notification n => NotificationOperations.Insert(n),
87+
Webhook w => WebhookOperations.Insert(w),
88+
JobCrashReported crashReported => JobCrashReportedOperations.Insert(crashReported),
89+
_ => throw new NotSupportedException($"You will need to add an TestContext.InsertAll case for {x.GetType()} entities"),
90+
}));
91+
7192
// Implementations:
7293

7394
public IMemoryCache Cache { get; }
@@ -109,6 +130,8 @@ public Async.Task InsertAll(params EntityBase[] objs)
109130

110131
public IWebhookMessageLogOperations WebhookMessageLogOperations { get; }
111132

133+
public IJobCrashReportedOperations JobCrashReportedOperations {get;}
134+
112135
// -- Remainder not implemented --
113136

114137
public IConfig Config => throw new System.NotImplementedException();
@@ -143,4 +166,6 @@ public Async.Task InsertAll(params EntityBase[] objs)
143166
public IAdo Ado => throw new NotImplementedException();
144167

145168
public IConfigurationRefresher ConfigurationRefresher => throw new NotImplementedException();
169+
170+
146171
}

src/ApiService/IntegrationTests/JobsTests.cs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,4 +226,25 @@ await Context.InsertAll(
226226
Assert.Equal(task.Config.Task.Type, returnedTasks[0].Type);
227227

228228
}
229+
230+
[Fact]
231+
public async Async.Task Get_CanFindSpecificJobWithBugs() {
232+
var taskConfig = new TaskConfig(_jobId, new List<Guid>(), new TaskDetails(TaskType.Coverage, 60));
233+
await Context.InsertAll(
234+
new Job(_jobId, JobState.Stopped, _config, null),
235+
new Task(_jobId, Guid.NewGuid(), TaskState.Running, Os.Windows, taskConfig),
236+
new JobCrashReported(_jobId, Guid.NewGuid())
237+
);
238+
239+
var func = new Jobs(Context, LoggerProvider.CreateLogger<Jobs>());
240+
241+
var ctx = new TestFunctionContext();
242+
var result = await func.Run(TestHttpRequestData.FromJson("GET", new JobSearch(JobId: _jobId)), ctx);
243+
Assert.Equal(HttpStatusCode.OK, result.StatusCode);
244+
245+
var response = BodyAs<JobResponse>(result);
246+
Assert.Equal(_jobId, response.JobId);
247+
Assert.NotNull(response.TaskInfo);
248+
Assert.True(response.CrashReported);
249+
}
229250
}

src/pytypes/onefuzztypes/models.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -761,6 +761,7 @@ class Job(BaseModel):
761761
task_info: Optional[List[Union[Task, JobTaskInfo]]]
762762
user_info: Optional[UserInfo]
763763
start_time: Optional[datetime] = None
764+
crash_reported: Optional[bool] = None
764765

765766

766767
class NetworkConfig(BaseModel):

0 commit comments

Comments
 (0)