public PublishCommand( IBuildConfigurationBuilder buildConfigurationBuilder, IConfigurationFileMerger configurationFileMerger, IConfigurationFileValidator configurationFileValidator, IConfigurationFileUploader configurationFileUploader, IStaticAssetProcessor staticAssetProcessor, IAccessor <S3AssetHostConfiguration> assetHostConfigurationAccessor) { _buildConfigurationBuilder = buildConfigurationBuilder.ThrowIfNull(nameof(buildConfigurationBuilder)); _configurationFileUploader = configurationFileUploader.ThrowIfNull(nameof(configurationFileUploader)); _configurationFileMerger = configurationFileMerger.ThrowIfNull(nameof(configurationFileMerger)); _configurationFileValidator = configurationFileValidator.ThrowIfNull(nameof(configurationFileValidator)); _staticAssetProcessor = staticAssetProcessor.ThrowIfNull(nameof(staticAssetProcessor)); _assetHostConfigurationAccessor = assetHostConfigurationAccessor.ThrowIfNull(nameof(assetHostConfigurationAccessor)); }
public static async Task <int> Build(MarvelMicroserviceConfig config, string publishedRuntimeImageName, BuildConfig buildConfig, IStaticAssetProcessor staticAssetProcessor) { var buildImageUri = await EcrResources.DotnetMicroserviceBuildImageUrl.EnsureImageIsPulled(); if (!buildImageUri.WasSuccessful) { return(1); } var taskTimer = Stopwatch.StartNew(); // Clear the old temp dir to ensure a fresh publish if running locally var outputPath = config.DotnetPublishOutputPath; if (Directory.Exists(outputPath)) { Directory.Delete(outputPath, true); } Directory.CreateDirectory(outputPath); var dockerRunOptions = new List <string> { $"--rm", $"-e \"{LaunchCommand.ProjectNameEnvVariable}={config.ProjectName}\"", $"-e \"{LaunchCommand.SolutionNameEnvVariable}={config.SolutionName}\"", $"-e \"{WebappDirEnvVariable}={ContainerPaths.GetWebappDirectory(config)}\"", $"-e \"{BrowserAppDirEnvVariable}={ContainerPaths.GetBrowserAppDirectory(config)}\"", $"-v {config.BaseDirectory}:{ContainerPaths.MountedSourceDirectory}", $"-v {outputPath}:{ContainerPaths.BuildOutputDirectory}", }; var runtimeImageLabelsTask = new LabelBuilder(config).GetLabels(buildConfig); var exitCode = 0; var dotnetBuildTimer = Stopwatch.StartNew(); Output.Info($"Building dotnet webapp."); // Run container to build app and copy published resources to mounted output directory exitCode = CommandUtilities.ExecuteCommand("docker", $"run {string.Join(" ", dockerRunOptions)} {buildImageUri.Value} /bin/bash {ContainerPaths.DockerTaskScriptPath} buildWithoutCompose"); if (exitCode != 0) { return(exitCode); } Output.Info($"dotnet webapp build completed {dotnetBuildTimer.Elapsed}"); // Run static asset build from output directory await staticAssetProcessor.ProcessStaticAssets(Path.Combine(config.DotnetPublishOutputPath, "wwwroot")); // Build the image from the source output var dockerBuildTimer = Stopwatch.StartNew(); Output.Info($"Building docker image {publishedRuntimeImageName}."); var labelArgs = LabelUtilities.FormatLabelsAsArguments(await runtimeImageLabelsTask); var buildArgs = labelArgs.Concat(new List <string> { $"-t {publishedRuntimeImageName}", $"--build-arg webappAssemblyPath={config.PublishedWebappAssemblyPath}", config.DotnetPublishOutputPath, }); exitCode = CommandUtilities.ExecuteCommand("docker", $"build {string.Join(" ", buildArgs)}"); if (exitCode != 0) { return(exitCode); } Output.Info($"Docker build completed {dockerBuildTimer.Elapsed}"); Output.Info($"Build time elapsed {taskTimer.Elapsed}"); return(exitCode); }
public BuildCommand(IStaticAssetProcessor staticAssetProcessor, IAccessor <S3AssetHostConfiguration> assetHostConfigurationAccessor) { _staticAssetProcessor = staticAssetProcessor.ThrowIfNull(nameof(staticAssetProcessor)); _assetHostConfigurationAccessor = assetHostConfigurationAccessor.ThrowIfNull(nameof(assetHostConfigurationAccessor)); }
internal static async Task <int> Publish(MarvelMicroserviceConfig config, IBuildConfigurationBuilder configBuilder, IConfigurationFileMerger configMerger, IConfigurationFileUploader configUploader, IConfigurationFileValidator configValidator, IStaticAssetProcessor staticAssetProcessor, string nugetApiKey, string awsAccessKey, string awsAccessSecret, string branch, string gitSha, string buildNumber, bool mergeAndUploadServiceConfig, bool mergeServiceConfig) { Security.UseAwsCredentials(awsAccessKey, awsAccessSecret); var publishImage = ImageNameBuilder.CreateImageNameAndTag( config.ServiceName, branch, gitSha, DateTime.UtcNow, buildNumber); string[] serviceConfigFiles = null; if (mergeAndUploadServiceConfig || mergeServiceConfig) { GenerateBuildFile(configBuilder, config.BuildConfigFilePath, gitSha, branch, publishImage.FullPath, buildNumber); serviceConfigFiles = await MergeAllServiceConfigFiles(configMerger, config.SourceDirectory, config.ServiceConfigFileName, config.BuildConfigFilePath); var configIsValid = await ValidateAllServiceConfigFiles(configValidator, config.SourceDirectory, serviceConfigFiles); if (!configIsValid) { Output.Error("Invalid service configuration."); return(1); } } var exitCode = await BuildCommand.Build(config, publishImage.FullPath, new BuildConfig { BranchName = branch, BuildNumber = buildNumber, }, staticAssetProcessor); if (exitCode != 0) { return(exitCode); } try { exitCode = PublishClientPackage(config, nugetApiKey, awsAccessKey, awsAccessSecret, branch, gitSha, buildNumber); if (exitCode != 0) { return(exitCode); } // Publish to ECR Output.Info($"Publishing {publishImage.FullPath}"); await Security.EnsureAuthenticatedWithEcr(); exitCode = CommandUtilities.ExecuteCommand("docker", $"push {publishImage.FullPath}"); if (exitCode != 0) { return(exitCode); } } finally { // TODO always remove image, even on publish failure await CommandUtilities.RunCommandAsync("docker", $"rmi {publishImage.FullPath}", errorMessage : $"Failed to remove image {publishImage.FullPath}."); Output.Info($"Removed local image {publishImage.FullPath}"); } try { if (mergeAndUploadServiceConfig && serviceConfigFiles != null) { await UploadAllServiceConfigFiles(configUploader, config.SourceDirectory, serviceConfigFiles, publishImage.Tag); } } catch (Exception ex) { Output.Error($"Unable to upload service configuration files. Error: {ex.Message}"); return(1); } File.WriteAllText(Path.Combine(config.WebappDirectory, "PublishedImageUrl.txt"), publishImage.FullPath); Output.Info("Publish successful"); return(0); }