From 6816d8c5c196679868bd4a6cf30b696f61eb35c6 Mon Sep 17 00:00:00 2001 From: Adam Chance <6444703+drakon64@users.noreply.github.com> Date: Mon, 23 Dec 2024 21:21:10 +0000 Subject: [PATCH] Delete queued tasks if their parent job is cancelled --- Ktisis.Common/Clients/GoogleClient.cs | 21 +++++++++++++ .../GitHubWebhookEventProcessor.cs | 31 +++++++++++-------- tofu/ktisis/cloud_tasks.tf | 7 ++++- 3 files changed, 45 insertions(+), 14 deletions(-) diff --git a/Ktisis.Common/Clients/GoogleClient.cs b/Ktisis.Common/Clients/GoogleClient.cs index ecd75a9..54b37c2 100644 --- a/Ktisis.Common/Clients/GoogleClient.cs +++ b/Ktisis.Common/Clients/GoogleClient.cs @@ -78,6 +78,27 @@ public static async Task CreateTask(CreateCloudTask task) await Console.Out.WriteLineAsync(await request.Content.ReadAsStringAsync()); } + public static async Task DeleteTask(string task) + { + var accessToken = await GetAccessToken(); + + var request = await Ktisis.HttpClient.SendAsync( + new HttpRequestMessage + { + Method = HttpMethod.Delete, + Headers = + { + { "Authorization", $"{accessToken.TokenType} {accessToken.AccessToken}" }, + }, + RequestUri = new Uri( + $"https://cloudtasks.googleapis.com/v2/projects/{Project}/locations/{Region}/queues/{Queue}/tasks/{task}" + ), + } + ); + + await Console.Out.WriteLineAsync(await request.Content.ReadAsStringAsync()); + } + public static async Task CreateInstance(CreateInstance instance, string zone) { var accessToken = await GetAccessToken(); diff --git a/Ktisis.Receiver/EventProcessors/GitHubWebhookEventProcessor.cs b/Ktisis.Receiver/EventProcessors/GitHubWebhookEventProcessor.cs index 0ad08a1..6e70a52 100644 --- a/Ktisis.Receiver/EventProcessors/GitHubWebhookEventProcessor.cs +++ b/Ktisis.Receiver/EventProcessors/GitHubWebhookEventProcessor.cs @@ -10,6 +10,7 @@ using Octokit.Webhooks; using Octokit.Webhooks.Events; using Octokit.Webhooks.Events.WorkflowJob; +using Octokit.Webhooks.Models.WorkflowJobEvent; namespace Ktisis.Receiver.EventProcessors; @@ -42,6 +43,9 @@ await Console.Out.WriteLineAsync( return; } + var instanceName = + $"{workflowJobEvent.Repository!.FullName.Replace('/', '-')}-{workflowJobEvent.WorkflowJob.RunId}-{workflowJobEvent.WorkflowJob.Id}"; + switch (workflowJobEvent.Action) { case "queued": @@ -96,16 +100,13 @@ await Console.Out.WriteLineAsync( } } - var name = - $"{workflowJobEvent.Repository!.FullName.Replace('/', '-')}-{workflowJobEvent.WorkflowJob.RunId}-{workflowJobEvent.WorkflowJob.Id}"; - await GoogleClient.CreateTask( new CreateCloudTask { Task = new CloudTask { Name = - $"projects/{Program.Project}/locations/{Program.Region}/queues/{Program.Queue}/tasks/{Convert.ToHexString(SHA256.HashData(Encoding.UTF8.GetBytes(name)))}", + $"projects/{Program.Project}/locations/{Program.Region}/queues/{Program.Queue}/tasks/{Convert.ToHexString(SHA256.HashData(Encoding.UTF8.GetBytes(instanceName)))}", HttpRequest = new CloudTaskHttpRequest { Url = Program.TaskServiceUrl, @@ -117,7 +118,7 @@ await GoogleClient.CreateTask( Zone = zone, Instance = new CreateInstance { - Name = name, + Name = instanceName, MachineType = $"projects/{GoogleClient.Project}/zones/{zone}/machineTypes/{machineType}", NetworkInterfaces = @@ -223,14 +224,18 @@ rm actions-runner-linux-{runnerArchitecture}-2.321.0.tar.gz } case "completed": { - // TODO: Get the instance zone rather than brute-forcing - foreach (var zone in Program.Zones) - { - await GoogleClient.DeleteInstance( - workflowJobEvent.WorkflowJob.RunnerName!, - zone - ); - } + if ( + workflowJobEvent.WorkflowJob.Conclusion!.Value + == WorkflowJobConclusion.Cancelled + ) + await GoogleClient.DeleteTask(instanceName); + else + // TODO: Get the instance zone rather than brute-forcing + foreach (var zone in Program.Zones) + await GoogleClient.DeleteInstance( + workflowJobEvent.WorkflowJob.RunnerName!, + zone + ); break; } diff --git a/tofu/ktisis/cloud_tasks.tf b/tofu/ktisis/cloud_tasks.tf index 36aed0f..2d4fa75 100644 --- a/tofu/ktisis/cloud_tasks.tf +++ b/tofu/ktisis/cloud_tasks.tf @@ -24,7 +24,12 @@ resource "google_cloud_tasks_queue" "cloud_tasks" { } resource "google_cloud_tasks_queue_iam_member" "ktisis" { + for_each = toset([ + "enqueuer", + "taskDeleter", + ]) + member = google_service_account.ktisis_receiver.member name = google_cloud_tasks_queue.cloud_tasks.name - role = "roles/cloudtasks.enqueuer" + role = "roles/cloudtasks.${each.value}" }