コード例 #1
0
        private ProcessStartInfo CreateContainerBuildProcess(string buildDir, ContainerBuildTask containerBuildTask)
        {
            if (!PathUtil.IsValidSubPath(containerBuildTask.Dockerfile))
            {
                throw new Exception("Invalid Dockerfile path.");
            }

            if (!PathUtil.IsValidSubPath(containerBuildTask.ImageFileName) ||
                containerBuildTask.ImageFileName.Contains(Path.DirectorySeparatorChar) ||
                containerBuildTask.ImageFileName.Contains(Path.AltDirectorySeparatorChar))
            {
                throw new Exception("Invalid image file name.");
            }

            var workspaceDir = WorkspaceDir;

            var psi = new ProcessStartInfo {
                FileName               = "helium",
                UseShellExecute        = false,
                RedirectStandardError  = true,
                RedirectStandardOutput = true,
                ArgumentList           =
                {
                    "container-build",

                    "--os",
                    containerBuildTask.Platform.OS.ToString(),

                    "--arch",
                    containerBuildTask.Platform.Arch.ToString(),

                    "--file",
                    Path.Combine(workspaceDir,                  containerBuildTask.Dockerfile),

                    "--build-context",
                    workspaceDir,
                },
            };

            switch (containerBuildTask.ReplayMode)
            {
            case ReplayMode.Discard:
                break;

            case ReplayMode.RecordCache:
                psi.ArgumentList.Add("--archive");
                psi.ArgumentList.Add(ReplayFile);
                break;

            default:
                throw new Exception("Invalid build task");
            }

            psi.ArgumentList.Add(buildDir);
            psi.ArgumentList.Add(containerBuildTask.ImageFileName);

            return(psi);
        }
コード例 #2
0
        public async Task RunJob(BuildTaskBase?buildTaskBase)
        {
            await SetupWorkspace();

            logger.LogTrace("Copied workspace");

            Directory.CreateDirectory(ArtifactDir);

            var psi = buildTaskBase switch {
                BuildTask buildTask => CreateBuildProcess(buildDir, buildTask),
                ContainerBuildTask containerBuildTask => CreateContainerBuildProcess(buildDir, containerBuildTask),
                _ => throw new Exception("Invalid build task")
            };

            cancellationToken.ThrowIfCancellationRequested();

            var process = Process.Start(psi);

            logger.LogTrace("Running external process");

            var exitTask = process.WaitForExitAsync();


            var writerLock = new AsyncLock();

            async Task PipeData(Stream stream)
            {
                byte[] buffer = new byte[4096];
                int    bytesRead;

                while ((bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length, cancellationToken)) > 0)
                {
                    cancellationToken.ThrowIfCancellationRequested();
                    using (await writerLock.LockAsync()) {
                        cancellationToken.ThrowIfCancellationRequested();
                        await updateStream.WriteAsync(new BuildStatusUpdate {
                            BuildOutput = ByteString.CopyFrom(buffer.AsSpan(0, bytesRead)),
                        });
                    }
                    cancellationToken.ThrowIfCancellationRequested();
                }

                stream.Close();
            }

            var outputTask = Task.Run(() => PipeData(process.StandardOutput.BaseStream), cancellationToken);
            var errorTask  = Task.Run(() => PipeData(process.StandardError.BaseStream), cancellationToken);

            await Task.WhenAll(outputTask, errorTask, exitTask);

            var artifactDir = ArtifactDir;
            var artifacts   = Directory.EnumerateFiles(artifactDir, "*.json", SearchOption.AllDirectories)
                              .Select(file => new ArtifactInfo {
                Name = file.Substring(artifactDir.Length)
                       .TrimStart(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar)
            });

            var jobResult = new JobResult {
                ExitCode = process.ExitCode,
            };

            jobResult.Artifacts.AddRange(artifacts);

            await updateStream.WriteAsync(new BuildStatusUpdate {
                JobFinished = jobResult,
            });

            logger.LogTrace("Finished job");
        }