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

Add a field to the job summary to indicate if at least one bug was created #3611

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 5 additions & 7 deletions src/ApiService/ApiService/Functions/Jobs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -136,13 +136,11 @@ private async Task<HttpResponseData> Get(HttpRequestData req) {
static JobTaskInfo TaskToJobTaskInfo(Task t) => new(t.TaskId, t.Config.Task.Type, t.State);

var tasks = _context.TaskOperations.SearchStates(jobId);
if (search.WithTasks ?? false) {
var ts = await tasks.ToListAsync();
return await RequestHandling.Ok(req, JobResponse.ForJob(job, ts));
} else {
var taskInfo = await tasks.Select(TaskToJobTaskInfo).ToListAsync();
return await RequestHandling.Ok(req, JobResponse.ForJob(job, taskInfo));
}

IAsyncEnumerable<IJobTaskInfo> taskInfo = search.WithTasks ?? false ? tasks : tasks.Select(TaskToJobTaskInfo);

var crashReported = await _context.JobCrashReportedOperations.CrashReported(jobId);
return await RequestHandling.Ok(req, JobResponse.ForJob(job, taskInfo.ToEnumerable(), crashReported));
}

var jobs = await _context.JobOperations.SearchState(states: search.State ?? Enumerable.Empty<JobState>()).ToListAsync();
Expand Down
4 changes: 4 additions & 0 deletions src/ApiService/ApiService/Functions/QueueJobResult.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@ public async Async.Task Run([QueueTrigger("job-result", Connection = "AzureWebJo
var jobResultType = data.Type;
_log.LogInformation($"job result data type: {jobResultType}");

if (jobResultType == "CrashReported") {
var _result = await _context.JobCrashReportedOperations.ReportCrash(job.JobId, jr.TaskId);
}

Dictionary<string, double> value;
if (jr.Value.Count > 0) {
value = jr.Value;
Expand Down
7 changes: 5 additions & 2 deletions src/ApiService/ApiService/OneFuzzTypes/Model.cs
Original file line number Diff line number Diff line change
Expand Up @@ -968,9 +968,12 @@ public record Job(
StoredUserInfo? UserInfo,
string? Error = null,
DateTimeOffset? EndTime = null
) : StatefulEntityBase<JobState>(State) {
) : StatefulEntityBase<JobState>(State);

}
public record JobCrashReported(
[PartitionKey] Guid JobId,
[RowKey] Guid TaskId
) : EntityBase;

// This is like UserInfo but lacks the UPN:
public record StoredUserInfo(Guid? ApplicationId, Guid? ObjectId);
Expand Down
9 changes: 6 additions & 3 deletions src/ApiService/ApiService/OneFuzzTypes/Responses.cs
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ public record ContainerInfo(
Uri SasUrl
) : BaseResponse();


public record JobResponse(
Guid JobId,
JobState State,
Expand All @@ -101,10 +102,11 @@ public record JobResponse(
IEnumerable<IJobTaskInfo>? TaskInfo,
StoredUserInfo? UserInfo,
[property: JsonPropertyName("Timestamp")] // must retain capital T for backcompat
DateTimeOffset? Timestamp
DateTimeOffset? Timestamp,
bool CrashReported
// not including UserInfo from Job model
) : BaseResponse() {
public static JobResponse ForJob(Job j, IEnumerable<IJobTaskInfo>? taskInfo)
public static JobResponse ForJob(Job j, IEnumerable<IJobTaskInfo>? taskInfo, bool crashReported = false)
=> new(
JobId: j.JobId,
State: j.State,
Expand All @@ -113,7 +115,8 @@ public static JobResponse ForJob(Job j, IEnumerable<IJobTaskInfo>? taskInfo)
EndTime: j.EndTime,
TaskInfo: taskInfo,
UserInfo: j.UserInfo,
Timestamp: j.Timestamp
Timestamp: j.Timestamp,
CrashReported: crashReported
);
public DateTimeOffset? StartTime => EndTime is DateTimeOffset endTime ? endTime.Subtract(TimeSpan.FromHours(Config.Duration)) : null;
}
Expand Down
5 changes: 3 additions & 2 deletions src/ApiService/ApiService/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,11 @@ namespace Microsoft.OneFuzz.Service;
public class Program {

/// <summary>
///
///
/// </summary>
public class LoggingMiddleware : IFunctionsWorkerMiddleware {
/// <summary>
///
///
/// </summary>
/// <param name="context"></param>
/// <param name="next"></param>
Expand Down Expand Up @@ -198,6 +198,7 @@ public static async Async.Task Main() {
.AddScoped<INodeMessageOperations, NodeMessageOperations>()
.AddScoped<ISubnet, Subnet>()
.AddScoped<IAutoScaleOperations, AutoScaleOperations>()
.AddScoped<IJobCrashReportedOperations, JobCrashReportedOperations>()
.AddSingleton<GraphServiceClient>(new GraphServiceClient(new DefaultAzureCredential()))
.AddSingleton<DependencyTrackingTelemetryModule>()
.AddSingleton<ICreds, Creds>()
Expand Down
28 changes: 28 additions & 0 deletions src/ApiService/ApiService/onefuzzlib/JobCrashReported.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
using System.Threading.Tasks;
using ApiService.OneFuzzLib.Orm;
using Microsoft.Extensions.Logging;
namespace Microsoft.OneFuzz.Service;

public interface IJobCrashReportedOperations : IOrm<JobCrashReported> {
public Task<bool> CrashReported(Guid jobId);
public Task<OneFuzzResultVoid> ReportCrash(Guid jobId, Guid taskId);
}

public class JobCrashReportedOperations : Orm<JobCrashReported>, IJobCrashReportedOperations {
public JobCrashReportedOperations(ILogger<JobCrashReportedOperations> logTracer, IOnefuzzContext context) : base(logTracer, context) {
}

public async Task<bool> CrashReported(Guid jobId) {
return await QueryAsync(Query.PartitionKey(jobId.ToString())).AnyAsync();
}

public async Task<OneFuzzResultVoid> ReportCrash(Guid jobId, Guid taskId) {

var result = await Update(new JobCrashReported(jobId, taskId));
if (!result.IsOk) {
return OneFuzzResultVoid.Error(ErrorCode.UNABLE_TO_UPDATE, "Failed to update job crash reported");
}

return OneFuzzResultVoid.Ok;
}
}
3 changes: 2 additions & 1 deletion src/ApiService/ApiService/onefuzzlib/OnefuzzContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public interface IOnefuzzContext {
ITeams Teams { get; }
IGithubIssues GithubIssues { get; }
IAdo Ado { get; }

IJobCrashReportedOperations JobCrashReportedOperations { get; }
IFeatureManagerSnapshot FeatureManagerSnapshot { get; }
IConfigurationRefresher ConfigurationRefresher { get; }
}
Expand Down Expand Up @@ -101,6 +101,7 @@ public OnefuzzContext(IServiceProvider serviceProvider) {
public ITeams Teams => _serviceProvider.GetRequiredService<ITeams>();
public IGithubIssues GithubIssues => _serviceProvider.GetRequiredService<IGithubIssues>();
public IAdo Ado => _serviceProvider.GetRequiredService<IAdo>();
public IJobCrashReportedOperations JobCrashReportedOperations => _serviceProvider.GetRequiredService<IJobCrashReportedOperations>();

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

Expand Down
25 changes: 25 additions & 0 deletions src/ApiService/IntegrationTests/Fakes/TestContext.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using Microsoft.Extensions.Caching.Memory;
Expand Down Expand Up @@ -42,6 +43,7 @@ public TestContext(IHttpClientFactory httpClientFactory, OneFuzzLoggerProvider p
ReproOperations = new ReproOperations(provider.CreateLogger<ReproOperations>(), this);
Reports = new Reports(provider.CreateLogger<Reports>(), Containers);
NotificationOperations = new NotificationOperations(provider.CreateLogger<NotificationOperations>(), this);
JobCrashReportedOperations = new JobCrashReportedOperations(provider.CreateLogger<JobCrashReportedOperations>(), this);

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

public Async.Task InsertAll(IEnumerable<EntityBase> objs)
=> Async.Task.WhenAll(
objs.Select(x => x switch {
Task t => TaskOperations.Insert(t),
Node n => NodeOperations.Insert(n),
Pool p => PoolOperations.Insert(p),
Job j => JobOperations.Insert(j),
JobResult jr => JobResultOperations.Insert(jr),
Repro r => ReproOperations.Insert(r),
Scaleset ss => ScalesetOperations.Insert(ss),
NodeTasks nt => NodeTasksOperations.Insert(nt),
InstanceConfig ic => ConfigOperations.Insert(ic),
Notification n => NotificationOperations.Insert(n),
Webhook w => WebhookOperations.Insert(w),
JobCrashReported crashReported => JobCrashReportedOperations.Insert(crashReported),
_ => throw new NotSupportedException($"You will need to add an TestContext.InsertAll case for {x.GetType()} entities"),
}));

// Implementations:

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

public IWebhookMessageLogOperations WebhookMessageLogOperations { get; }

public IJobCrashReportedOperations JobCrashReportedOperations { get; }

// -- Remainder not implemented --

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

public IConfigurationRefresher ConfigurationRefresher => throw new NotImplementedException();


}
21 changes: 21 additions & 0 deletions src/ApiService/IntegrationTests/JobsTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -226,4 +226,25 @@ await Context.InsertAll(
Assert.Equal(task.Config.Task.Type, returnedTasks[0].Type);

}

[Fact]
public async Async.Task Get_CanFindSpecificJobWithBugs() {
var taskConfig = new TaskConfig(_jobId, new List<Guid>(), new TaskDetails(TaskType.Coverage, 60));
await Context.InsertAll(
new Job(_jobId, JobState.Stopped, _config, null),
new Task(_jobId, Guid.NewGuid(), TaskState.Running, Os.Windows, taskConfig),
new JobCrashReported(_jobId, Guid.NewGuid())
);

var func = new Jobs(Context, LoggerProvider.CreateLogger<Jobs>());

var ctx = new TestFunctionContext();
var result = await func.Run(TestHttpRequestData.FromJson("GET", new JobSearch(JobId: _jobId)), ctx);
Assert.Equal(HttpStatusCode.OK, result.StatusCode);

var response = BodyAs<JobResponse>(result);
Assert.Equal(_jobId, response.JobId);
Assert.NotNull(response.TaskInfo);
Assert.True(response.CrashReported);
}
}
1 change: 1 addition & 0 deletions src/pytypes/onefuzztypes/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -761,6 +761,7 @@ class Job(BaseModel):
task_info: Optional[List[Union[Task, JobTaskInfo]]]
user_info: Optional[UserInfo]
start_time: Optional[datetime] = None
crash_reported: Optional[bool] = None


class NetworkConfig(BaseModel):
Expand Down
Loading