Created
March 12, 2018 02:15
-
-
Save anonymous/bba1ad640ab2d4b14988e8add9ce0444 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Concurrent; | |
using System.Linq; | |
using System.Net; | |
using System.Threading.Tasks; | |
using Microsoft.AspNetCore; | |
using Microsoft.AspNetCore.Builder; | |
using Microsoft.AspNetCore.Hosting; | |
using Microsoft.AspNetCore.Mvc; | |
using Microsoft.Extensions.Caching.Memory; | |
using Microsoft.Extensions.Configuration; | |
using Microsoft.Extensions.DependencyInjection; | |
using Newtonsoft.Json; | |
using Newtonsoft.Json.Linq; | |
using Octopus.Client; | |
using Octopus.Client.Model; | |
namespace ManualWebhook | |
{ | |
class Program | |
{ | |
static void Main(string[] args) | |
{ | |
Console.WriteLine("Hello World!"); | |
BuildWebHost(args).Run(); | |
} | |
public static IWebHost BuildWebHost(string[] args) => | |
WebHost.CreateDefaultBuilder(args) | |
.UseStartup<Startup>() | |
.UseKestrel(options => | |
{ | |
options.Listen(IPAddress.Any, 5000); | |
}) | |
.Build(); | |
} | |
public class Startup | |
{ | |
public Startup(IHostingEnvironment env, IConfiguration config) | |
{ | |
HostingEnvironment = env; | |
Configuration = config; | |
} | |
public IHostingEnvironment HostingEnvironment { get; } | |
public IConfiguration Configuration { get; } | |
public void ConfigureServices(IServiceCollection services) | |
{ | |
services.AddTransient<IOctopusAsyncRepository>((sp) => | |
{ | |
// API client used to query the Octopus server | |
var client = new OctopusClientFactory().CreateAsyncClient(new OctopusServerEndpoint("http://localhost:8080", "API-COYG6KD4TKTPYIWCOQ3W5ZI19HO")); | |
return client.Result.Repository; | |
}); | |
services.AddMvc(); | |
} | |
public void Configure(IApplicationBuilder app) | |
{ | |
app.UseMvc(); | |
} | |
} | |
[Route("octopus-webhook")] | |
public class OctopusWebhookController : Controller | |
{ | |
readonly IOctopusAsyncRepository _repository; | |
public OctopusWebhookController(IOctopusAsyncRepository repository) | |
{ | |
_repository = repository; | |
} | |
// This is called by the Octopus web hook. The payload it receives looks like: | |
// | |
// { | |
// "Payload": { | |
// "Event": { | |
// "Category": "ManualInterventionInterruptionRaised", | |
// "RelatedDocumentIds": [ | |
// "Deployments-123", <-- This tells us the deployment ID | |
// ... | |
// | |
[HttpPost("manual-intervention")] | |
public async Task<ActionResult> ManualInterventionRequested([FromBody] JObject o) | |
{ | |
var octopusEvent = o.Value<JObject>("Payload").Value<JObject>("Event"); | |
var eventCategory = octopusEvent.Value<string>("Category"); | |
// Validate that we got the event type we expected | |
if (eventCategory != "ManualInterventionInterruptionRaised") | |
return BadRequest("Unknown event category: " + eventCategory); | |
var relatedDocuments = octopusEvent.Value<JArray>("RelatedDocumentIds").Values<string>(); | |
var deploymentId = relatedDocuments.First(documentId => documentId.StartsWith("Deployments-")); | |
var deployment = await _repository.Deployments.Get(deploymentId); | |
var task = await _repository.Deployments.GetTask(deployment); | |
if (task.State != TaskState.Queued) | |
{ | |
// A deployment should be marked as queued when a manual intervention is encountered (it is queued because it is | |
// waiting until someone submits it). | |
return BadRequest("Task completed already"); | |
} | |
await SubmitInterruption(deploymentId); | |
return Content("OK"); | |
} | |
async Task SubmitInterruption(string deploymentId) | |
{ | |
// Find the "interruption" object that corresponds with this deployment | |
var interruptions = await _repository.Interruptions.List(regardingDocumentId: deploymentId); | |
var interruption = interruptions.Items.First(); | |
// The current user must first take responsibility for the interruption (so multiple people don't submit it at once) | |
await _repository.Interruptions.TakeResponsibility(interruption); | |
// Set the result | |
interruption.Form.Values["Result"] = "Proceed"; // Or, "Abort" to cancel | |
interruption.Form.Values["Notes"] = "Any other information here"; | |
// Submit the interruption | |
await _repository.Interruptions.Submit(interruption); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment