Skip to content

Commit

Permalink
Use controllers for update_jobs/{id}/*
Browse files Browse the repository at this point in the history
  • Loading branch information
mburumaxwell committed Sep 19, 2023
1 parent ebe2745 commit b93ecb2
Show file tree
Hide file tree
Showing 4 changed files with 130 additions and 96 deletions.
117 changes: 117 additions & 0 deletions server/Tingle.Dependabot/Controllers/UpdateJobsController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using System.ComponentModel.DataAnnotations;
using System.Text.Json;
using System.Text.Json.Nodes;
using Tingle.Dependabot.Events;
using Tingle.Dependabot.Models;
using Tingle.Dependabot.Models.Dependabot;
using Tingle.Dependabot.Models.Management;
using Tingle.EventBus;

namespace Tingle.Dependabot.Controllers;

[ApiController]
[Route("/update_jobs")]
[Authorize(AuthConstants.PolicyNameUpdater)]
public class UpdateJobsController : ControllerBase // TODO: unit and integration test this
{
private readonly MainDbContext dbContext;
private readonly IEventPublisher publisher;
private readonly ILogger logger;

public UpdateJobsController(MainDbContext dbContext, IEventPublisher publisher, ILogger<UpdateJobsController> logger)
{
this.dbContext = dbContext ?? throw new ArgumentNullException(nameof(dbContext));
this.publisher = publisher ?? throw new ArgumentNullException(nameof(publisher));
this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
}

// TODO: implement logic for *pull_request endpoints

[HttpPost("{id}/create_pull_request")]
public async Task<IActionResult> CreatePullRequestAsync([FromRoute, Required] string id, [FromBody] PayloadWithData<DependabotCreatePullRequestModel> model)
{
var job = await dbContext.UpdateJobs.SingleAsync(p => p.Id == id);
logger.LogInformation("Received request to create a pull request from job {JobId} but we did nothing.\r\n{ModelJson}", id, JsonSerializer.Serialize(model));
return Ok();
}

[HttpPost("{id}/update_pull_request")]
public async Task<IActionResult> UpdatePullRequestAsync([FromRoute, Required] string id, [FromBody] PayloadWithData<DependabotUpdatePullRequestModel> model)
{
var job = await dbContext.UpdateJobs.SingleAsync(p => p.Id == id);
logger.LogInformation("Received request to update a pull request from job {JobId} but we did nothing.\r\n{ModelJson}", id, JsonSerializer.Serialize(model));
return Ok();
}

[HttpPost("{id}/close_pull_request")]
public async Task<IActionResult> ClosePullRequestAsync([FromRoute, Required] string id, [FromBody] PayloadWithData<DependabotClosePullRequestModel> model)
{
var job = await dbContext.UpdateJobs.SingleAsync(p => p.Id == id);
logger.LogInformation("Received request to close a pull request from job {JobId} but we did nothing.\r\n{ModelJson}", id, JsonSerializer.Serialize(model));
return Ok();
}

[HttpPost("{id}/record_update_job_error")]
public async Task<IActionResult> RecordErrorAsync([FromRoute, Required] string id, [FromBody] PayloadWithData<DependabotRecordUpdateJobErrorModel> model)
{
var job = await dbContext.UpdateJobs.SingleAsync(p => p.Id == id);

job.Error = new UpdateJobError
{
Type = model.Data!.ErrorType,
Detail = model.Data.ErrorDetail,
};

await dbContext.SaveChangesAsync();

return Ok();
}

[HttpPatch("{id}/mark_as_processed")]
public async Task<IActionResult> MarkAsProcessedAsync([FromRoute, Required] string id, [FromBody] PayloadWithData<DependabotMarkAsProcessedModel> model)
{
var job = await dbContext.UpdateJobs.SingleAsync(p => p.Id == id);

// publish event that will run update the job and collect logs
var evt = new UpdateJobCheckStateEvent { JobId = id, };
await publisher.PublishAsync(evt);

return Ok();
}

[HttpPost("{id}/update_dependency_list")]
public async Task<IActionResult> UpdateDependencyListAsync([FromRoute, Required] string id, [FromBody] PayloadWithData<DependabotUpdateDependencyListModel> model)
{
var job = await dbContext.UpdateJobs.SingleAsync(p => p.Id == id);
var repository = await dbContext.Repositories.SingleAsync(r => r.Id == job.RepositoryId);

// update the database
var update = repository.Updates.SingleOrDefault(u => u.PackageEcosystem == job.PackageEcosystem && u.Directory == job.Directory);
if (update is not null)
{
update.Files = model.Data?.DependencyFiles ?? new();
}
await dbContext.SaveChangesAsync();

return Ok();
}

[HttpPost("{id}/record_ecosystem_versions")]
public async Task<IActionResult> RecordEcosystemVersionsAsync([FromRoute, Required] string id, [FromBody] JsonNode model)
{
var job = await dbContext.UpdateJobs.SingleAsync(p => p.Id == id);
logger.LogInformation("Received request to record ecosystem version from job {JobId} but we did nothing.\r\n{ModelJson}", id, model.ToJsonString());
return Ok();
}

[HttpPost("{id}/increment_metric")]
public async Task<IActionResult> IncrementMetricAsync([FromRoute, Required] string id, [FromBody] JsonNode model)
{
var job = await dbContext.UpdateJobs.SingleAsync(p => p.Id == id);
logger.LogInformation("Received metrics from job {JobId} but we did nothing with them.\r\n{ModelJson}", id, model.ToJsonString());
return Ok();
}
}
2 changes: 1 addition & 1 deletion server/Tingle.Dependabot/Controllers/WebhooksController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ namespace Tingle.Dependabot.Controllers;
[ApiController]
[Route("/webhooks")]
[Authorize(AuthConstants.PolicyNameServiceHooks)]
public class WebhooksController : ControllerBase
public class WebhooksController : ControllerBase // TODO: unit test this
{
private readonly IEventPublisher publisher;
private readonly ILogger logger;
Expand Down
12 changes: 12 additions & 0 deletions server/Tingle.Dependabot/Models/PayloadWithData.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using System.ComponentModel.DataAnnotations;

namespace Tingle.Dependabot.Models;

public class PayloadWithData<T> where T : new()
{
[Required]
public T? Data { get; set; }

[System.Text.Json.Serialization.JsonExtensionData]
public Dictionary<string, object>? Extensions { get; set; }
}
95 changes: 0 additions & 95 deletions server/Tingle.Dependabot/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,6 @@
app.MapHealthChecks("/liveness", new HealthCheckOptions { Predicate = _ => false, });
app.MapControllers();
app.MapManagementApi();
app.MapUpdateJobsApi();

// setup the application environment
await AppSetup.SetupAsync(app);
Expand Down Expand Up @@ -227,98 +226,4 @@ public static IEndpointRouteBuilder MapManagementApi(this IEndpointRouteBuilder

return builder;
}

public static IEndpointRouteBuilder MapUpdateJobsApi(this IEndpointRouteBuilder builder)
{
var logger = builder.ServiceProvider.GetRequiredService<ILoggerFactory>().CreateLogger("UpdateJobsApi");

// endpoints accessed by the updater during execution

var group = builder.MapGroup("update_jobs");
group.RequireAuthorization(AuthConstants.PolicyNameUpdater);

// TODO: implement logic for *pull_request endpoints
group.MapPost("/{id}/create_pull_request", async (MainDbContext dbContext, [FromRoute, Required] string id, [FromBody] PayloadWithData<DependabotCreatePullRequestModel> model) =>
{
var job = await dbContext.UpdateJobs.SingleAsync(p => p.Id == id);
logger.LogInformation("Received request to create a pull request from job {JobId} but we did nothing.\r\n{ModelJson}", id, JsonSerializer.Serialize(model));
return Results.Ok();
});
group.MapPost("/{id}/update_pull_request", async (MainDbContext dbContext, [FromRoute, Required] string id, [FromBody] PayloadWithData<DependabotUpdatePullRequestModel> model) =>
{
var job = await dbContext.UpdateJobs.SingleAsync(p => p.Id == id);
logger.LogInformation("Received request to update a pull request from job {JobId} but we did nothing.\r\n{ModelJson}", id, JsonSerializer.Serialize(model));
return Results.Ok();
});
group.MapPost("/{id}/close_pull_request", async (MainDbContext dbContext, [FromRoute, Required] string id, [FromBody] PayloadWithData<DependabotClosePullRequestModel> model) =>
{
var job = await dbContext.UpdateJobs.SingleAsync(p => p.Id == id);
logger.LogInformation("Received request to close a pull request from job {JobId} but we did nothing.\r\n{ModelJson}", id, JsonSerializer.Serialize(model));
return Results.Ok();
});

group.MapPost("/{id}/record_update_job_error", async (MainDbContext dbContext, [FromRoute, Required] string id, [FromBody] PayloadWithData<DependabotRecordUpdateJobErrorModel> model) =>
{
var job = await dbContext.UpdateJobs.SingleAsync(p => p.Id == id);

job.Error = new UpdateJobError
{
Type = model.Data!.ErrorType,
Detail = model.Data.ErrorDetail,
};

await dbContext.SaveChangesAsync();

return Results.Ok();
});
group.MapPatch("/{id}/mark_as_processed", async (IEventPublisher publisher, MainDbContext dbContext, [FromRoute, Required] string id, [FromBody] PayloadWithData<DependabotMarkAsProcessedModel> model) =>
{
var job = await dbContext.UpdateJobs.SingleAsync(p => p.Id == id);

// publish event that will run update the job and collect logs
var evt = new UpdateJobCheckStateEvent { JobId = id, };
await publisher.PublishAsync(evt);

return Results.Ok();
});
group.MapPost("/{id}/update_dependency_list", async (MainDbContext dbContext, [FromRoute, Required] string id, [FromBody] PayloadWithData<DependabotUpdateDependencyListModel> model) =>
{
var job = await dbContext.UpdateJobs.SingleAsync(p => p.Id == id);
var repository = await dbContext.Repositories.SingleAsync(r => r.Id == job.RepositoryId);

// update the database
var update = repository.Updates.SingleOrDefault(u => u.PackageEcosystem == job.PackageEcosystem && u.Directory == job.Directory);
if (update is not null)
{
update.Files = model.Data?.DependencyFiles ?? new();
}
await dbContext.SaveChangesAsync();

return Results.Ok();
});

group.MapPost("/{id}/record_ecosystem_versions", async (MainDbContext dbContext, [FromRoute, Required] string id, [FromBody] JsonNode model) =>
{
var job = await dbContext.UpdateJobs.SingleAsync(p => p.Id == id);
logger.LogInformation("Received request to record ecosystem version from job {JobId} but we did nothing.\r\n{ModelJson}", id, model.ToJsonString());
return Results.Ok();
});
group.MapPost("/{id}/increment_metric", async (MainDbContext dbContext, [FromRoute, Required] string id, [FromBody] JsonNode model) =>
{
var job = await dbContext.UpdateJobs.SingleAsync(p => p.Id == id);
logger.LogInformation("Received metrics from job {JobId} but we did nothing with them.\r\n{ModelJson}", id, model.ToJsonString());
return Results.Ok();
});

return builder;
}

public class PayloadWithData<T> where T : new()
{
[Required]
public T? Data { get; set; }

[System.Text.Json.Serialization.JsonExtensionData]
public Dictionary<string, object>? Extensions { get; set; }
}
}

0 comments on commit b93ecb2

Please sign in to comment.