Пример #1
0
        public static Task ReadProjectDetailsAsync(OutputContext output, DotnetProjectServiceBuilder project)
        {
            if (output is null)
            {
                throw new ArgumentNullException(nameof(output));
            }

            if (project is null)
            {
                throw new ArgumentNullException(nameof(project));
            }

            EnsureMSBuildRegistered(output, project.ProjectFile);

            EvaluateProject(output, project);

            if (!SemVersion.TryParse(project.Version, out var version))
            {
                output.WriteInfoLine($"No version or invalid version '{project.Version}' found, using default.");
                version         = new SemVersion(0, 1, 0);
                project.Version = version.ToString();
            }

            return(Task.CompletedTask);
        }
Пример #2
0
        public static void ReadProjectDetails(OutputContext output, DotnetProjectServiceBuilder project, string metadataFile)
        {
            if (output is null)
            {
                throw new ArgumentNullException(nameof(output));
            }

            if (project is null)
            {
                throw new ArgumentNullException(nameof(project));
            }

            if (project is null)
            {
                throw new ArgumentNullException(nameof(metadataFile));
            }

            EvaluateProject(output, project, metadataFile);

            if (!SemVersion.TryParse(project.Version, out var version))
            {
                output.WriteInfoLine($"No version or invalid version '{project.Version}' found, using default.");
                version         = new SemVersion(0, 1, 0);
                project.Version = version.ToString();
            }
        }
Пример #3
0
        public static void ApplyContainerDefaults(ApplicationBuilder application, DotnetProjectServiceBuilder project, ContainerInfo container)
        {
            if (application is null)
            {
                throw new ArgumentNullException(nameof(application));
            }

            if (project is null)
            {
                throw new ArgumentNullException(nameof(project));
            }

            if (container is null)
            {
                throw new ArgumentNullException(nameof(container));
            }

            if (string.IsNullOrEmpty(container.BaseImageName) && project.IsAspNet)
            {
                container.BaseImageName = "mcr.microsoft.com/dotnet/core/aspnet";
            }
            else if (string.IsNullOrEmpty(container.BaseImageName))
            {
                container.BaseImageName = "mcr.microsoft.com/dotnet/core/runtime";
            }

            if (string.IsNullOrEmpty(container.BaseImageTag) && (project.TargetFrameworkName == "netcoreapp" || project.TargetFrameworkName == "net"))
            {
                container.BaseImageTag = project.TargetFrameworkVersion;
            }

            if (string.IsNullOrEmpty(container.BaseImageTag))
            {
                throw new CommandException($"Unsupported TFM {project.TargetFramework}.");
            }

            container.BuildImageName ??= "mcr.microsoft.com/dotnet/core/sdk";
            container.BuildImageTag ??= project.TargetFrameworkVersion;

            if (container.ImageName == null && application.Registry?.Hostname == null)
            {
                container.ImageName ??= project.Name.ToLowerInvariant();
            }
            else if (container.ImageName == null && application.Registry?.Hostname != null)
            {
                container.ImageName ??= $"{application.Registry?.Hostname}/{project.Name.ToLowerInvariant()}";
            }

            container.ImageTag ??= project.Version?.Replace("+", "-") ?? "latest";

            // Disable color in the logs
            project.EnvironmentVariables.Add(new EnvironmentVariableBuilder("DOTNET_LOGGING__CONSOLE__DISABLECOLORS")
            {
                Value = "true"
            });
        }
Пример #4
0
        public static void ApplyContainerDefaults(ApplicationBuilder application, DotnetProjectServiceBuilder project, ContainerInfo container)
        {
            if (application is null)
            {
                throw new ArgumentNullException(nameof(application));
            }

            if (project is null)
            {
                throw new ArgumentNullException(nameof(project));
            }

            if (container is null)
            {
                throw new ArgumentNullException(nameof(container));
            }

            if (string.IsNullOrEmpty(container.BaseImageName) && project.IsAspNet)
            {
                container.BaseImageName = "mcr.microsoft.com/dotnet/core/aspnet";
            }
            else if (string.IsNullOrEmpty(container.BaseImageName))
            {
                container.BaseImageName = "mcr.microsoft.com/dotnet/core/runtime";
            }

            if (string.IsNullOrEmpty(container.BaseImageTag) && project.TargetFrameworkName == "netcoreapp")
            {
                container.BaseImageTag = project.TargetFrameworkVersion;
            }

            if (string.IsNullOrEmpty(container.BaseImageTag))
            {
                throw new CommandException($"Unsupported TFM {project.TargetFramework}.");
            }

            container.BuildImageName ??= "mcr.microsoft.com/dotnet/core/sdk";
            container.BuildImageTag ??= "3.1";

            if (container.ImageName == null && application.Registry?.Hostname == null)
            {
                container.ImageName ??= project.Name.ToLowerInvariant();
            }
            else if (container.ImageName == null && application.Registry?.Hostname != null)
            {
                container.ImageName ??= $"{application.Registry?.Hostname}/{project.Name.ToLowerInvariant()}";
            }

            container.ImageTag ??= project.Version?.Replace("+", "-") ?? "latest";
        }
Пример #5
0
        public static SidecarBuilder GetOrAddSidecar(DotnetProjectServiceBuilder project)
        {
            // Bring your rain boots.
            project.RelocateDiagnosticsDomainSockets = true;

            var sidecar = project.Sidecars.FirstOrDefault(s => s.Name == "tye-diag-agent");

            if (sidecar is object)
            {
                return(sidecar);
            }

            sidecar = new SidecarBuilder("tye-diag-agent", "rynowak/tye-diag-agent", "0.1")
            {
                Args =
                {
                    "--kubernetes=true",
                    $"--service={project.Name}",
                    $"--assemblyName={project.AssemblyName}",
                },
            };
            project.Sidecars.Add(sidecar);
            return(sidecar);
        }
Пример #6
0
        public static async Task WriteDockerfileAsync(OutputContext output, ApplicationBuilder application, DotnetProjectServiceBuilder project, ContainerInfo container, string filePath)
        {
            if (output is null)
            {
                throw new ArgumentNullException(nameof(output));
            }

            if (application is null)
            {
                throw new ArgumentNullException(nameof(application));
            }

            if (project is null)
            {
                throw new ArgumentNullException(nameof(project));
            }

            if (container is null)
            {
                throw new ArgumentNullException(nameof(container));
            }

            if (filePath is null)
            {
                throw new ArgumentNullException(nameof(filePath));
            }

            await using var stream = File.OpenWrite(filePath);
            await using var writer = new StreamWriter(stream, encoding: new UTF8Encoding(encoderShouldEmitUTF8Identifier: false), bufferSize: -1, leaveOpen: true);

            var entryPoint = project.AssemblyName;

            output.WriteDebugLine($"Writing Dockerfile to '{filePath}'.");
            if (container.UseMultiphaseDockerfile ?? true)
            {
                await WriteMultiphaseDockerfileAsync(writer, entryPoint, container);
            }
            else
            {
                await WriteLocalPublishDockerfileAsync(writer, entryPoint, container);
            }
            output.WriteDebugLine("Done writing Dockerfile.");
        }
Пример #7
0
        private static void EvaluateProject(OutputContext output, DotnetProjectServiceBuilder project, string metadataFile)
        {
            var sw = Stopwatch.StartNew();

            var metadata     = new Dictionary <string, string>();
            var metadataKVPs = File.ReadLines(metadataFile).Select(l => l.Split(new[] { ':' }, 2));

            foreach (var metadataKVP in metadataKVPs)
            {
                if (!string.IsNullOrEmpty(metadataKVP[1]))
                {
                    metadata.Add(metadataKVP[0], metadataKVP[1].Trim());
                }
            }

            // Reading a few different version properties to be more resilient.
            var version = GetMetadataValueOrNull("AssemblyInformationalVersion") ??
                          GetMetadataValueOrNull("InformationalVersion") ??
                          GetMetadataValueOrEmpty("Version");

            project.Version = version;
            output.WriteDebugLine($"Found application version: {version}");

            project.TargetFrameworks = GetMetadataValueOrNull("TargetFrameworks")?.Split(';', StringSplitOptions.RemoveEmptyEntries) ?? Array.Empty <string>();

            // Figure out if functions app.
            // If so, run app with function host.
            project.RunCommand             = GetMetadataValueOrEmpty("RunCommand");
            project.RunArguments           = GetMetadataValueOrEmpty("RunArguments");
            project.TargetPath             = GetMetadataValueOrEmpty("TargetPath");
            project.PublishDir             = GetMetadataValueOrEmpty("PublishDir");
            project.AssemblyName           = GetMetadataValueOrEmpty("AssemblyName");
            project.IntermediateOutputPath = GetMetadataValueOrEmpty("IntermediateOutputPath");

            output.WriteDebugLine($"RunCommand={project.RunCommand}");
            output.WriteDebugLine($"RunArguments={project.RunArguments}");
            output.WriteDebugLine($"TargetPath={project.TargetPath}");
            output.WriteDebugLine($"PublishDir={project.PublishDir}");
            output.WriteDebugLine($"AssemblyName={project.AssemblyName}");
            output.WriteDebugLine($"IntermediateOutputPath={project.IntermediateOutputPath}");

            // Normalize directories to their absolute paths
            project.IntermediateOutputPath = Path.Combine(project.ProjectFile.DirectoryName !, NormalizePath(project.IntermediateOutputPath));
            project.TargetPath             = Path.Combine(project.ProjectFile.DirectoryName !, NormalizePath(project.TargetPath));
            project.PublishDir             = Path.Combine(project.ProjectFile.DirectoryName !, NormalizePath(project.PublishDir));

            var targetFramework = GetMetadataValueOrEmpty("TargetFramework");

            project.TargetFramework = targetFramework;
            output.WriteDebugLine($"Found target framework: {targetFramework}");

            // TODO: Parse the name and version manually out of the TargetFramework field if it's non-null
            project.TargetFrameworkName    = GetMetadataValueOrNull("_ShortFrameworkIdentifier") ?? project.TargetFramework.TrimEnd(".0123456789".ToCharArray());
            project.TargetFrameworkVersion = GetMetadataValueOrNull("_ShortFrameworkVersion") ?? GetMetadataValueOrEmpty("_TargetFrameworkVersionWithoutV");
            output.WriteDebugLine($"Parsed target framework name: {project.TargetFrameworkName}");
            output.WriteDebugLine($"Parsed target framework version: {project.TargetFrameworkVersion}");

            var sharedFrameworks = GetMetadataValueOrNull("FrameworkReference")?.Split(';') ?? Enumerable.Empty <string>();

            project.Frameworks.AddRange(sharedFrameworks.Select(s => new Framework(s)));
            output.WriteDebugLine($"Found shared frameworks: {string.Join(", ", sharedFrameworks)}");

            // determine container base image
            if (project.ContainerInfo != null)
            {
                project.ContainerInfo.BaseImageName = GetMetadataValueOrEmpty("ContainerBaseImage");
                project.ContainerInfo.BaseImageTag  = GetMetadataValueOrEmpty("ContainerBaseTag");
            }

            project.IsAspNet = project.Frameworks.Any(f => f.Name == "Microsoft.AspNetCore.App") ||
                               GetMetadataValueOrEmpty("MicrosoftNETPlatformLibrary") == "Microsoft.AspNetCore.App" ||
                               MetadataIsTrue("_AspNetCoreAppSharedFxIsEnabled") ||
                               MetadataIsTrue("UsingMicrosoftNETSdkWeb");

            output.WriteDebugLine($"IsAspNet={project.IsAspNet}");

            output.WriteDebugLine($"Evaluation Took: {sw.Elapsed.TotalMilliseconds}ms");

            string?GetMetadataValueOrNull(string key) => metadata !.TryGetValue(key, out var value) ? value : null;
            string GetMetadataValueOrEmpty(string key) => metadata !.TryGetValue(key, out var value) ? value : string.Empty;
            bool MetadataIsTrue(string key) => metadata !.TryGetValue(key, out var value) && bool.Parse(value);
        }
Пример #8
0
        private static void EvaluateProject(OutputContext output, DotnetProjectServiceBuilder project)
        {
            var sw = Stopwatch.StartNew();

            // Currently we only log at debug level.
            var logger = new ConsoleLogger(
                verbosity: LoggerVerbosity.Normal,
                write: message => output.WriteDebug(message),
                colorSet: null,
                colorReset: null);

            // We need to isolate projects from each other for testing. MSBuild does not support
            // loading the same project twice in the same collection.
            var projectCollection = new ProjectCollection();

            ProjectInstance projectInstance;

            Microsoft.Build.Evaluation.Project msbuildProject;

            try
            {
                output.WriteDebugLine($"Loading project '{project.ProjectFile.FullName}'.");
                msbuildProject = Microsoft.Build.Evaluation.Project.FromFile(project.ProjectFile.FullName, new ProjectOptions()
                {
                    ProjectCollection = projectCollection,
                    GlobalProperties  = project.BuildProperties
                });
                projectInstance = msbuildProject.CreateProjectInstance();
                output.WriteDebugLine($"Loaded project '{project.ProjectFile.FullName}'.");
            }
            catch (Exception ex)
            {
                throw new CommandException($"Failed to load project: '{project.ProjectFile.FullName}'.", ex);
            }

            try
            {
                AssemblyLoadContext.Default.Resolving += ResolveAssembly;

                output.WriteDebugLine($"Restoring project '{project.ProjectFile.FullName}'.");

                // Similar to what MSBuild does for restore:
                // https://github.com/microsoft/msbuild/blob/3453beee039fb6f5ccc54ac783ebeced31fec472/src/MSBuild/XMake.cs#L1417
                //
                // We need to do restore as a separate operation
                var restoreRequest = new BuildRequestData(
                    projectInstance,
                    targetsToBuild: new[] { "Restore" },
                    hostServices: null,
                    flags: BuildRequestDataFlags.ClearCachesAfterBuild | BuildRequestDataFlags.SkipNonexistentTargets | BuildRequestDataFlags.IgnoreMissingEmptyAndInvalidImports);

                var parameters = new BuildParameters(projectCollection)
                {
                    Loggers = new[] { logger, },
                };

                // We don't really look at the result, because it's not clear we should halt totally
                // if restore fails.
                var restoreResult = BuildManager.DefaultBuildManager.Build(parameters, restoreRequest);
                output.WriteDebugLine($"Restored project '{project.ProjectFile.FullName}'.");

                msbuildProject.MarkDirty();
                projectInstance = msbuildProject.CreateProjectInstance();

                var targets = new List <string>()
                {
                    "ResolveReferences",
                    "ResolvePackageDependenciesDesignTime",
                    "PrepareResources",
                    "GetAssemblyAttributes",
                };

                var result = projectInstance.Build(
                    targets: targets.ToArray(),
                    loggers: new[] { logger, });

                // If the build fails, we're not really blocked from doing our work.
                // For now we just log the output to debug. There are errors that occur during
                // running these targets we don't really care as long as we get the data.
            }
            finally
            {
                AssemblyLoadContext.Default.Resolving -= ResolveAssembly;
            }

            // Reading a few different version properties to be more resilient.
            var version =
                projectInstance.GetProperty("AssemblyInformationalVersion")?.EvaluatedValue ??
                projectInstance.GetProperty("InformationalVersion")?.EvaluatedValue ??
                projectInstance.GetProperty("Version").EvaluatedValue;

            project.Version = version;
            output.WriteDebugLine($"Found application version: {version}");

            var targetFrameworks = projectInstance.GetPropertyValue("TargetFrameworks");

            project.TargetFrameworks = targetFrameworks.Split(';', StringSplitOptions.RemoveEmptyEntries) ?? Array.Empty <string>();

            // Figure out if functions app.
            // If so, run app with function host.
            project.RunCommand             = projectInstance.GetPropertyValue("RunCommand");
            project.RunArguments           = projectInstance.GetPropertyValue("RunArguments");
            project.TargetPath             = projectInstance.GetPropertyValue("TargetPath");
            project.PublishDir             = projectInstance.GetPropertyValue("PublishDir");
            project.AssemblyName           = projectInstance.GetPropertyValue("AssemblyName");
            project.IntermediateOutputPath = projectInstance.GetPropertyValue("IntermediateOutputPath");

            output.WriteDebugLine($"RunCommand={project.RunCommand}");
            output.WriteDebugLine($"RunArguments={project.RunArguments}");
            output.WriteDebugLine($"TargetPath={project.TargetPath}");
            output.WriteDebugLine($"PublishDir={project.PublishDir}");
            output.WriteDebugLine($"AssemblyName={project.AssemblyName}");
            output.WriteDebugLine($"IntermediateOutputPath={project.IntermediateOutputPath}");

            // Normalize directories to their absolute paths
            project.IntermediateOutputPath = Path.Combine(project.ProjectFile.DirectoryName !, NormalizePath(project.IntermediateOutputPath));
            project.TargetPath             = Path.Combine(project.ProjectFile.DirectoryName !, NormalizePath(project.TargetPath));
            project.PublishDir             = Path.Combine(project.ProjectFile.DirectoryName !, NormalizePath(project.PublishDir));

            var targetFramework = projectInstance.GetPropertyValue("TargetFramework");

            project.TargetFramework = targetFramework;
            output.WriteDebugLine($"Found target framework: {targetFramework}");

            // TODO: Parse the name and version manually out of the TargetFramework field if it's non-null
            project.TargetFrameworkName    = projectInstance.GetPropertyValue("_ShortFrameworkIdentifier");
            project.TargetFrameworkVersion = projectInstance.GetPropertyValue("_ShortFrameworkVersion") ?? projectInstance.GetPropertyValue("_TargetFrameworkVersionWithoutV");

            var sharedFrameworks = projectInstance.GetItems("FrameworkReference").Select(i => i.EvaluatedInclude).ToList();

            project.Frameworks.AddRange(sharedFrameworks.Select(s => new Framework(s)));
            output.WriteDebugLine($"Found shared frameworks: {string.Join(", ", sharedFrameworks)}");

            // determine container base image
            if (project.ContainerInfo != null)
            {
                project.ContainerInfo.BaseImageName = projectInstance.GetPropertyValue("ContainerBaseImage");
                project.ContainerInfo.BaseImageTag  = projectInstance.GetPropertyValue("ContainerBaseTag");
            }

            bool PropertyIsTrue(string property)
            {
                return(projectInstance.GetPropertyValue(property) is string s && !string.IsNullOrEmpty(s) && bool.Parse(s));
            }

            project.IsAspNet = project.Frameworks.Any(f => f.Name == "Microsoft.AspNetCore.App") ||
                               projectInstance.GetPropertyValue("MicrosoftNETPlatformLibrary") == "Microsoft.AspNetCore.App" ||
                               PropertyIsTrue("_AspNetCoreAppSharedFxIsEnabled") ||
                               PropertyIsTrue("UsingMicrosoftNETSdkWeb");

            output.WriteDebugLine($"IsAspNet={project.IsAspNet}");

            output.WriteDebugLine($"Evaluation Took: {sw.Elapsed.TotalMilliseconds}ms");

            // The Microsoft.Build.Locator doesn't handle the loading of other assemblies
            // that are shipped with MSBuild (ex NuGet).
            //
            // This means that the set of assemblies that need special handling depends on the targets
            // that we run :(
            //
            // This is workaround for this limitation based on the targets we need to run
            // to resolve references and versions.
            //
            // See: https://github.com/microsoft/MSBuildLocator/issues/86
            Assembly?ResolveAssembly(AssemblyLoadContext context, AssemblyName assemblyName)
            {
                if (assemblyName.Name is object)
                {
                    var msbuildDirectory = Environment.GetEnvironmentVariable("MSBuildExtensionsPath") !;
                    var assemblyFilePath = Path.Combine(msbuildDirectory, assemblyName.Name + ".dll");
                    if (File.Exists(assemblyFilePath))
                    {
                        return(context.LoadFromAssemblyPath(assemblyFilePath));
                    }
                }

                return(default);
Пример #9
0
        public static async Task GenerateAsync(OutputContext output, ApplicationBuilder application, DotnetProjectServiceBuilder project, ContainerInfo container, HelmChartStep chart, DirectoryInfo outputDirectory)
        {
            if (output is null)
            {
                throw new ArgumentNullException(nameof(output));
            }

            if (application is null)
            {
                throw new ArgumentNullException(nameof(application));
            }

            if (project is null)
            {
                throw new ArgumentNullException(nameof(project));
            }

            if (container is null)
            {
                throw new ArgumentNullException(nameof(container));
            }

            if (chart is null)
            {
                throw new ArgumentNullException(nameof(chart));
            }

            if (outputDirectory is null)
            {
                throw new ArgumentNullException(nameof(outputDirectory));
            }

            ApplyHelmChartDefaults(application, project, container, chart);

            // The directory with the charts needs to be the same as the chart name
            var chartDirectoryPath = Path.Combine(outputDirectory.FullName, chart.ChartName);

            Directory.CreateDirectory(chartDirectoryPath);

            var templateDirectoryPath = Path.Combine(
                Path.GetDirectoryName(typeof(HelmChartGenerator).Assembly.Location) !,
                "Templates",
                "Helm");

            DirectoryCopy.Copy(templateDirectoryPath, chartDirectoryPath);

            // Write Chart.yaml
            //
            // apiVersion: v1
            // name: <appname>
            // version: <version>
            // appVersion: <version>
            await File.WriteAllLinesAsync(Path.Combine(chartDirectoryPath, "Chart.yaml"), new[]
            {
                $"apiVersion: v1",
                $"name: {chart.ChartName}",
                $"# helm requires the version and appVersion to specified in Chart.yaml",
                $"# tye will override these values when packaging the chart",
                $"version: {project.Version.Replace('+', '-')}",
                $"appVersion: {project.Version.Replace('+', '-')}"
            });

            // Write values.yaml
            //
            // image:
            //   repository: rynowak.azurecr.io/rochambot/gamemaster
            await File.WriteAllLinesAsync(Path.Combine(chartDirectoryPath, "values.yaml"), new[]
            {
                $"image:",
                $"  repository: {container.ImageName}",
            });
        }
Пример #10
0
        public static async Task BuildContainerImageAsync(OutputContext output, ApplicationBuilder application, DotnetProjectServiceBuilder project, ContainerInfo container)
        {
            if (output is null)
            {
                throw new ArgumentNullException(nameof(output));
            }

            if (application is null)
            {
                throw new ArgumentNullException(nameof(application));
            }

            if (project is null)
            {
                throw new ArgumentNullException(nameof(project));
            }

            if (container is null)
            {
                throw new ArgumentNullException(nameof(container));
            }

            string contextDirectory;
            var    dockerFilePath = Path.Combine(project.ProjectFile.DirectoryName !, "Dockerfile");

            TempFile?     tempFile      = null;
            TempDirectory?tempDirectory = null;

            try
            {
                // We need to know if this is a single-phase or multi-phase Dockerfile because the context directory will be
                // different depending on that choice.
                //
                // For the cases where generate a Dockerfile, we have the constraint that we need
                // to place it on the same drive (Windows) as the docker context.
                if (container.UseMultiphaseDockerfile ?? true)
                {
                    // For a multi-phase Docker build, the context is always the project directory.
                    contextDirectory = ".";

                    if (File.Exists(dockerFilePath))
                    {
                        output.WriteDebugLine($"Using existing Dockerfile '{dockerFilePath}'.");
                    }
                    else
                    {
                        // We need to write the file, let's stick it under obj.
                        Directory.CreateDirectory(project.IntermediateOutputPath);
                        dockerFilePath = Path.Combine(project.IntermediateOutputPath, "Dockerfile");

                        // Clean up file when done building image
                        tempFile = new TempFile(dockerFilePath);

                        await DockerfileGenerator.WriteDockerfileAsync(output, application, project, container, tempFile.FilePath);
                    }
                }
                else
                {
                    // For a single-phase Docker build the context is always the directory containing the publish
                    // output. We need to put the Dockerfile in the context directory so it's on the same drive (Windows).
                    var publishOutput = project.Outputs.OfType <ProjectPublishOutput>().FirstOrDefault();
                    if (publishOutput is null)
                    {
                        throw new InvalidOperationException("We should have published the project for a single-phase Dockerfile.");
                    }

                    contextDirectory = publishOutput.Directory.FullName;

                    // Clean up directory when done building image
                    tempDirectory = new TempDirectory(publishOutput.Directory);

                    if (File.Exists(dockerFilePath))
                    {
                        output.WriteDebugLine($"Using existing Dockerfile '{dockerFilePath}'.");
                        File.Copy(dockerFilePath, Path.Combine(contextDirectory, "Dockerfile"));
                        dockerFilePath = Path.Combine(contextDirectory, "Dockerfile");
                    }
                    else
                    {
                        // No need to clean up, it's in a directory we're already cleaning up.
                        dockerFilePath = Path.Combine(contextDirectory, "Dockerfile");
                        await DockerfileGenerator.WriteDockerfileAsync(output, application, project, container, dockerFilePath);
                    }
                }

                output.WriteDebugLine("Running 'docker build'.");
                output.WriteCommandLine("docker", $"build \"{contextDirectory}\" -t {container.ImageName}:{container.ImageTag} -f \"{dockerFilePath}\"");
                var capture  = output.Capture();
                var exitCode = await application.ContainerEngine.ExecuteAsync(
                    $"build \"{contextDirectory}\" -t {container.ImageName}:{container.ImageTag} -f \"{dockerFilePath}\"",
                    project.ProjectFile.DirectoryName,
                    stdOut : capture.StdOut,
                    stdErr : capture.StdErr);

                output.WriteDebugLine($"Done running 'docker build' exit code: {exitCode}");
                if (exitCode != 0)
                {
                    throw new CommandException("'docker build' failed.");
                }

                output.WriteInfoLine($"Created Docker Image: '{container.ImageName}:{container.ImageTag}'");
                project.Outputs.Add(new DockerImageOutput(container.ImageName !, container.ImageTag !));
            }
            finally
            {
                tempDirectory?.Dispose();
                tempFile?.Dispose();
            }
        }
Пример #11
0
            protected bool SkipWithoutDotnetProject(OutputContext output, ServiceBuilder service, [MaybeNullWhen(returnValue: true)] out DotnetProjectServiceBuilder project)
            {
                if (output is null)
                {
                    throw new ArgumentNullException(nameof(output));
                }

                if (service is null)
                {
                    throw new ArgumentNullException(nameof(service));
                }

                if (service is DotnetProjectServiceBuilder p)
                {
                    project = p;
                    return(false);
                }

                output.WriteInfoLine($"Service '{service.Name}' does not have a project associated. Skipping.");
                project = default !;