public void Initialise() { Task.Run(async() => { while (true) { RunBuild currentBuild = null; currentBuild = await GetCurrentBuild(); IQueueBuilder queueBuilder = new RabbitBuilder(); using (ISender statusMessageSender = queueBuilder.ConfigureTransport(_queueServer, _queueVhost, _queueUsername, _queuePassword) .ISendTo(QueueNames.Status(currentBuild.Build)) .Build()) { try { Action <(string status, string warning, string error)> notify = ((string status, string warning, string error)state) => { if (!string.IsNullOrEmpty(state.status)) { Console.WriteLine($"INFO: {state.status}"); } if (!string.IsNullOrEmpty(state.warning)) { Console.WriteLine($"WARNING: {state.warning}"); } if (!string.IsNullOrEmpty(state.error)) { Console.WriteLine($"ERROR: {state.error}"); } statusMessageSender.Send(StatusReport(state)); }; await RunProcess(currentBuild, notify); } catch (Exception ex) { statusMessageSender.Send(StatusReport((null, null, SerialiseError(ex)))); // TODO : Log the exception // Rethrowing the exception from this point would kill the thread which we don't want to do } finally { RemoveBuild(currentBuild); } } } }, _cancellationToken); }
private string EnhanceYaml(RunBuild instruction) { ComposeFileParser parser = new ComposeFileParser(instruction.Yaml); if (instruction.EnvironmentVariables == null) { instruction.EnvironmentVariables = new Dictionary <string, string>(); } instruction.EnvironmentVariables.Add("TESTER_INSTANCE", _instanceName); parser.AddEnvironmentVariables(instruction.EnvironmentVariables); return(parser.Save()); }
public Task RunBuild(RunBuild build) { Builds.Add(build); return(Task.Run(async() => { while (true) { if (!Builds.Contains(build)) { return Task.CompletedTask; } await Task.Delay(1000); } }, _cancellationToken)); }
private Task <RunBuild> GetCurrentBuild() { return(Task.Run(async() => { RunBuild currentBuild = null; while (currentBuild == null) { currentBuild = Builds.FirstOrDefault(); if (currentBuild == null) { await Task.Delay(1000); } } return currentBuild; }, _cancellationToken)); }
public static void RunBuild(RunBuild build) { IQueueBuilder queueBuilder = new RabbitBuilder(); List <Task> tasks = new List <Task>(); using (ISender statusMessageSender = queueBuilder.ConfigureTransport(_queueServer, _queueVhost, _queueUsername, _queuePassword) .ISendTo(QueueNames.Status(build.Build)) .Build()) { SendStatusMessage(statusMessageSender, $"Starting build {build.Build}"); } foreach (var proc in processes) { tasks.Add(proc.RunBuild(build)); } // Wait for at least one task to complete this build before moving onto the next build Task.WaitAny(tasks.ToArray()); // Don't send anymore messages to the status queue after this point as it might have been removed already // and we don't want to re-create it }
private RunBuild CreateBuildInstruction(BuildRunRequest request) { ComposeFileParser composeFileParser = new ComposeFileParser(request.Yaml); RunBuild runBuild = new RunBuild { Yaml = request.Yaml, Build = request.Build, Image = composeFileParser.GetTesterImageName(), Command = composeFileParser.GetTesterLocation(), EnvironmentVariables = new Dictionary <string, string> { { "TESTER_SERVER", _host }, { "TESTER_VHOST", _vHost }, { "TESTER_USERNAME", _username }, { "TESTER_PASSWORD", _password }, { "TESTER_REQUEST_QUEUE", $"{request.Build}_request" }, { "TESTER_RESPONSE_QUEUE", $"{request.Build}_response" } } }; return(runBuild); }
public async Task StartBuild(BuildRunRequest request) { try { ReportStatus($"[{request.Build}] Staring"); RunBuild buildInstruction = CreateBuildInstruction(request); string testOutput; using (DockerWrapper docker = new DockerWrapper()) { CancellationTokenSource cancellationTokenSource = new CancellationTokenSource(); //cancellationTokenSource.CancelAfter(TimeSpan.FromSeconds(60)); Dictionary <string, string> environmentVariable = new Dictionary <string, string> { { "TESTER_LISTTESTS", "true" } }; testOutput = await docker.Run(buildInstruction.Image, environmentVariables : environmentVariable, command : buildInstruction.Command, cancellationToken : cancellationTokenSource.Token); } List <RunTest> tests = new List <RunTest>(); string[] testNames = testOutput.Split('\n'); foreach (string testName in testNames) { if (!string.IsNullOrEmpty(testName)) { RunTest item = new RunTest { Build = request.Build, FullName = testName.Trim() }; tests.Add(item); } } AddTestsToDictionary(_expectedTests, tests); // Configure receivers statusMessageReceiver = ConfigureReceiver(QueueNames.Status(request.Build)); testResultReceiver = ConfigureReceiver(QueueNames.TestResponse(request.Build)); // Add all the tests to the queue ReportStatus($"[{request.Build}] Sending Test Instructions ..."); testInstructionSender = ConfigureSender(QueueNames.TestRequest(request.Build)); SendTestInstructions(testInstructionSender, tests); ReportStatus($"[{request.Build}] Test Instructions sent."); // Add the build instruction to the queue ReportStatus($"[{request.Build}] Sending Build Instruction ..."); buildInstructionSender = ConfigureSender(QueueNames.Build()); buildInstructionSender.Send(buildInstruction); ReportStatus($"[{request.Build}] Build Instruction sent."); // Subscribe to the test result queue until all the tests have been completed (notifying subscribers) testResultReceiver.Receive <TestResult>(TestResultReceived); statusMessageReceiver.Receive <StatusMessage>(StatusMessageReceived); // Wait for tests to complete await TestsStillRunning(_cancellationTokenSource.Token); ReportStatus($"DONE"); // Notify cubscribers that the run is complete _testResultMonitor.notifyComplete(); _statusMessageMonitor.notifyComplete(); } catch (Exception ex) { ReportError(ex.Message); } }
private async Task <(string stdOut, string stdErr)> RunProcess(RunBuild build, Action <(string status, string warning, string error)> notify)
public void RemoveBuild(RunBuild build) { Builds.Remove(build); }