private void ExecuteWorkItem(HelixJobListEntry currentWorkItem) { Log.LogMessage($"Executing {currentWorkItem.WorkItemId}"); Log.LogMessage($"Command: '{currentWorkItem.Command}'\nTimeout: {currentWorkItem.TimeoutInSeconds} seconds. "); Dictionary <string, string> environment = GenerateHelixEnvironmentVariables(currentWorkItem.WorkItemId); string generatedLogRoot = environment["HELIX_LOG_ROOT"]; Directory.CreateDirectory(generatedLogRoot); string runnerScript = GenerateRunnerScript(environment, currentWorkItem.Command, Path.Combine(ExecutionFolder, "runnerscripts", currentWorkItem.WorkItemId)); ProcessStartInfo pStartInfo = new ProcessStartInfo() { FileName = runnerScript, CreateNoWindow = false, RedirectStandardOutput = true, WorkingDirectory = Path.Combine(ExecutionFolder, "work", CorrelationId, currentWorkItem.WorkItemId), UseShellExecute = false }; DateTime startTime = DateTime.Now; Process workItem = Process.Start(pStartInfo); string output = workItem.StandardOutput.ReadToEnd(); workItem.Refresh(); if (workItem.WaitForExit((int)TimeSpan.FromSeconds(currentWorkItem.TimeoutInSeconds).TotalMilliseconds)) { Log.LogMessage($"Executed for {(workItem.ExitTime - startTime).Seconds}.{(workItem.ExitTime - startTime).Milliseconds} seconds. (Exit code: {workItem.ExitCode})"); Log.LogMessage(MessageImportance.Low, $"Log:\n{output}"); } // Timed out else { Log.LogError($"Timed out during execution."); TryKillProcess(workItem); } // Crashed, errors, or failed tests if (workItem.ExitCode != 0) { Log.LogError($"Non-0 exit code, please review logs."); } if (!string.IsNullOrEmpty(output)) { string logPath = Path.Combine(generatedLogRoot, "stdout.log"); File.WriteAllText(logPath, output); } Log.LogMessage(MessageImportance.Low, $"Logs for execution stored in {generatedLogRoot}"); // HELIX_LOG_ROOT is customized per-workitem here, so we can associate it specially with the run. foreach (string file in Directory.GetFiles(generatedLogRoot)) { TaskItem loggedFile = new TaskItem(file); loggedFile.SetMetadata("WorkItemFriendlyName", currentWorkItem.WorkItemId); loggedFile.SetMetadata("LogDirectory", generatedLogRoot); logs.Add(loggedFile); } }
private void UnpackPayloads(HelixJobListEntry currentWorkItem) { foreach (string correlationPayloadFile in currentWorkItem.CorrelationPayloadUris) { string resolvedPayload = correlationPayloadFile; // We're handling the job list that has HTTP Uris, so need to download these first // We could eventually just use the local files but this would involve producing a // separate, and not-real-for-Helix Job list JSON. if (correlationPayloadFile.StartsWith("http", StringComparison.OrdinalIgnoreCase)) { string fileName = correlationPayloadFile.Substring(correlationPayloadFile.LastIndexOf('/') + 1); fileName = fileName.Substring(0, fileName.IndexOf('?')); resolvedPayload = Path.Combine(ExecutionFolder, fileName); if (!File.Exists(resolvedPayload)) { DownloadTo(correlationPayloadFile, resolvedPayload); } } if (File.Exists(resolvedPayload)) { Unzip(resolvedPayload, correlationReproFolder, false); } else { Log.LogError($"Could not find payload at {correlationPayloadFile}"); } } string workitemPayload = currentWorkItem.PayloadUri; if (!string.IsNullOrEmpty(workitemPayload)) { if (workitemPayload.StartsWith("http", StringComparison.OrdinalIgnoreCase)) { string fileName = workitemPayload.Substring(workitemPayload.LastIndexOf('/') + 1); if (fileName.IndexOf('?') > 0) { fileName = fileName.Substring(0, fileName.IndexOf('?')); } workitemPayload = Path.Combine(ExecutionFolder, fileName); if (!File.Exists(workitemPayload)) { DownloadTo(currentWorkItem.PayloadUri, workitemPayload); } } if (File.Exists(workitemPayload)) { Unzip(workitemPayload, Path.Combine(ExecutionFolder, "work", CorrelationId, currentWorkItem.WorkItemId), true); } else { Log.LogWarning($"Could not obtain work item payload specified by {currentWorkItem.PayloadUri}. This will likely break execution."); } } }