From b437ccd2428267ccba4d5a5d5b4cf3fa94d94a47 Mon Sep 17 00:00:00 2001 From: Nazar Mokrynskyi Date: Sat, 5 Sep 2026 07:54:00 +0300 Subject: [PATCH] Avoid truncating event.json while other steps read it --- src/Runner.Worker/ExecutionContext.cs | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/src/Runner.Worker/ExecutionContext.cs b/src/Runner.Worker/ExecutionContext.cs index 0f9410821c6..0547ad3dce8 100644 --- a/src/Runner.Worker/ExecutionContext.cs +++ b/src/Runner.Worker/ExecutionContext.cs @@ -1330,11 +1330,36 @@ public void WriteWebhookPayload() { var workflowFile = Path.Combine(workflowDirectory, "event.json"); Trace.Info($"Write event payload to {workflowFile}"); - File.WriteAllText(workflowFile, gitHubEvent, new UTF8Encoding(false)); + WriteWebhookPayloadFile(workflowFile, gitHubEvent); SetGitHubContext("event_path", workflowFile); } } + // Every step writes the very same webhook payload to the very same file before it runs, and + // steps can run concurrently (parallel/background steps). This implements an atomic write + // that avoids file corruption. + private static void WriteWebhookPayloadFile(string workflowFile, string gitHubEvent) + { + if (File.Exists(workflowFile)) + { + return; + } + + var tempFile = $"{workflowFile}.{Guid.NewGuid():N}.tmp"; + File.WriteAllText(tempFile, gitHubEvent, new UTF8Encoding(false)); + try + { + File.Move(tempFile, workflowFile); + } + catch (IOException) when (File.Exists(workflowFile)) + { + } + finally + { + File.Delete(tempFile); + } + } + private void InitializeTimelineRecord(Guid timelineId, Guid timelineRecordId, Guid? parentTimelineRecordId, string recordType, string displayName, string refName, int? order, bool embedded = false) { _mainTimelineId = timelineId;