/// <summary> /// Builds the full build script from the list of snippets for each platform. /// </summary> /// <returns>Finalized build script as a string.</returns> private string BuildScriptFromSnippets( BuildScriptGeneratorContext context, IList <BuildScriptSnippet> snippets, IDictionary <string, string> toolsToVersion, List <string> directoriesToExcludeFromCopyToIntermediateDir, List <string> directoriesToExcludeFromCopyToBuildOutputDir) { string script; string benvArgs = StringExtensions.JoinKeyValuePairs(toolsToVersion); Dictionary <string, string> buildProperties = snippets .Where(s => s.BuildProperties != null) .SelectMany(s => s.BuildProperties) .ToDictionary(p => p.Key, p => p.Value); buildProperties[ManifestFilePropertyKeys.OperationId] = context.OperationId; (var preBuildCommand, var postBuildCommand) = PreAndPostBuildCommandHelper.GetPreAndPostBuildScriptsOrCommands( context.SourceRepo, _environment); var outputIsSubDirOfSourceDir = false; if (!string.IsNullOrEmpty(_cliOptions.DestinationDir)) { outputIsSubDirOfSourceDir = DirectoryHelper.IsSubDirectory( _cliOptions.DestinationDir, _cliOptions.SourceDir); } var buildScriptProps = new BaseBashBuildScriptProperties() { OsPackagesToInstall = context.RequiredOsPackages ?? new string[0], BuildScriptSnippets = snippets.Select(s => s.BashBuildScriptSnippet), BenvArgs = benvArgs, PreBuildCommand = preBuildCommand, PostBuildCommand = postBuildCommand, DirectoriesToExcludeFromCopyToIntermediateDir = directoriesToExcludeFromCopyToIntermediateDir, DirectoriesToExcludeFromCopyToBuildOutputDir = directoriesToExcludeFromCopyToBuildOutputDir, ManifestFileName = FilePaths.BuildManifestFileName, ManifestDir = context.ManifestDir, BuildProperties = buildProperties, BenvPath = FilePaths.Benv, PlatformInstallationScriptSnippets = snippets.Select(s => s.PlatformInstallationScriptSnippet), OutputDirectoryIsNested = outputIsSubDirOfSourceDir, }; LogScriptIfGiven("pre-build", buildScriptProps.PreBuildCommand); LogScriptIfGiven("post-build", buildScriptProps.PostBuildCommand); script = TemplateHelper.Render( TemplateHelper.TemplateResource.BaseBashScript, buildScriptProps, _logger); return(script); }
/// <summary> /// Builds the full build script from the list of snippets for each platform. /// </summary> /// <returns>Finalized build script as a string.</returns> private string BuildScriptFromSnippets( BuildScriptGeneratorContext context, IList <BuildScriptSnippet> snippets, IDictionary <string, string> toolsToVersion, List <string> directoriesToExcludeFromCopyToIntermediateDir, List <string> directoriesToExcludeFromCopyToBuildOutputDir) { string script; string benvArgs = StringExtensions.JoinKeyValuePairs(toolsToVersion); _environmentSettingsProvider.TryGetAndLoadSettings(out var environmentSettings); Dictionary <string, string> buildProperties = snippets .Where(s => s.BuildProperties != null) .SelectMany(s => s.BuildProperties) .ToDictionary(p => p.Key, p => p.Value); buildProperties[ManifestFilePropertyKeys.OperationId] = context.OperationId; (var preBuildCommand, var postBuildCommand) = PreAndPostBuildCommandHelper.GetPreAndPostBuildCommands( context.SourceRepo, environmentSettings); var buildScriptProps = new BaseBashBuildScriptProperties() { BuildScriptSnippets = snippets.Select(s => s.BashBuildScriptSnippet), BenvArgs = benvArgs, PreBuildCommand = preBuildCommand, PostBuildCommand = postBuildCommand, DirectoriesToExcludeFromCopyToIntermediateDir = directoriesToExcludeFromCopyToIntermediateDir, DirectoriesToExcludeFromCopyToBuildOutputDir = directoriesToExcludeFromCopyToBuildOutputDir, ManifestFileName = FilePaths.BuildManifestFileName, ManifestDir = context.ManifestDir, BuildProperties = buildProperties, }; LogScriptIfGiven("pre-build", buildScriptProps.PreBuildCommand); LogScriptIfGiven("post-build", buildScriptProps.PostBuildCommand); script = TemplateHelper.Render( TemplateHelper.TemplateResource.BaseBashScript, buildScriptProps, _logger); return(script); }
public string GenerateDockerfile(DockerfileContext ctx) { var buildImageTag = "lts-versions"; var runImage = string.Empty; var runImageTag = string.Empty; var compatiblePlatforms = GetCompatiblePlatforms(ctx); if (!compatiblePlatforms.Any()) { throw new UnsupportedPlatformException(Labels.UnableToDetectPlatformMessage); } foreach (var platformAndDetectorResult in compatiblePlatforms) { var platform = platformAndDetectorResult.Key; var detectorResult = platformAndDetectorResult.Value; if (!_slimPlatformVersions.ContainsKey(platform.Name) || (!_slimPlatformVersions[platform.Name].Any(v => detectorResult.PlatformVersion.StartsWith(v)) && !_slimPlatformVersions[platform.Name].Any(v => v.StartsWith(detectorResult.PlatformVersion)))) { buildImageTag = "latest"; runImageTag = GenerateRuntimeTag(detectorResult.PlatformVersion); } else { runImageTag = _slimPlatformVersions[platform.Name] .Where(v => detectorResult.PlatformVersion.StartsWith(v)).FirstOrDefault(); } runImage = ConvertToRuntimeName(platform.Name); } var properties = new DockerfileProperties() { RuntimeImageName = runImage, RuntimeImageTag = runImageTag, BuildImageTag = buildImageTag, }; return(TemplateHelper.Render( TemplateHelper.TemplateResource.Dockerfile, properties, _logger)); }
public string GenerateDockerfile(DockerfileContext ctx) { var buildImageTag = "slim"; var runImage = string.Empty; var runImageTag = string.Empty; var compatiblePlatforms = GetCompatiblePlatforms(ctx); if (!compatiblePlatforms.Any()) { throw new UnsupportedLanguageException(Labels.UnableToDetectLanguageMessage); } foreach (var platformAndVersion in compatiblePlatforms) { var platform = platformAndVersion.Key; var version = platformAndVersion.Value; if (!_slimPlatformVersions.ContainsKey(platform.Name) || !_slimPlatformVersions[platform.Name].Any(v => version.StartsWith(v))) { buildImageTag = "latest"; } runImage = platform.Name == "dotnet" ? "dotnetcore" : platform.Name; runImageTag = GenerateRuntimeTag(version); } var properties = new DockerfileProperties() { RuntimeImageName = runImage, RuntimeImageTag = runImageTag, BuildImageTag = buildImageTag, }; return(TemplateHelper.Render( TemplateHelper.TemplateResource.Dockerfile, properties, _logger)); }
/// <summary> /// Builds the full build script from the list of snippets for each platform. /// </summary> /// <returns>Finalized build script as a string.</returns> private string BuildScriptFromSnippets( BuildScriptGeneratorContext context, string installationScript, IList <BuildScriptSnippet> buildScriptSnippets, IDictionary <string, string> toolsToVersion, List <string> directoriesToExcludeFromCopyToIntermediateDir, List <string> directoriesToExcludeFromCopyToBuildOutputDir, IEnumerable <PlatformDetectorResult> detectionResults) { string script; string benvArgs = StringExtensions.JoinKeyValuePairs(toolsToVersion); benvArgs = $"{benvArgs} {Constants.BenvDynamicInstallRootDirKey}=\"{this.cliOptions.DynamicInstallRootDir}\""; Dictionary <string, string> buildProperties = buildScriptSnippets .Where(s => s.BuildProperties != null) .SelectMany(s => s.BuildProperties) .ToDictionary(p => p.Key, p => p.Value); buildProperties[ManifestFilePropertyKeys.OperationId] = context.OperationId; var sourceDirInBuildContainer = this.cliOptions.SourceDir; if (!string.IsNullOrEmpty(this.cliOptions.IntermediateDir)) { sourceDirInBuildContainer = this.cliOptions.IntermediateDir; } buildProperties[ManifestFilePropertyKeys.SourceDirectoryInBuildContainer] = sourceDirInBuildContainer; var allPlatformNames = detectionResults .Where(s => s.Platform != null) .Select(s => s.Platform) .ToList(); foreach (var eachPlatformName in allPlatformNames) { this.logger.LogInformation($"Build Property Key:{ManifestFilePropertyKeys.PlatformName} value: {eachPlatformName} is written into manifest"); if (buildProperties.ContainsKey(ManifestFilePropertyKeys.PlatformName)) { var previousValue = buildProperties[ManifestFilePropertyKeys.PlatformName]; buildProperties[ManifestFilePropertyKeys.PlatformName] = string.Join( ",", previousValue, eachPlatformName); } else { buildProperties[ManifestFilePropertyKeys.PlatformName] = eachPlatformName; } } buildProperties[ManifestFilePropertyKeys.CompressDestinationDir] = this.cliOptions.CompressDestinationDir.ToString().ToLower(); // Workaround for bug in TestSourceRepo class in validation tests // Should be using context.SourceRepo.FileExists string filePathForAppYaml = Path.Combine(context.SourceRepo.RootPath, "appsvc.yaml"); this.logger.LogDebug("Path to appsvc.yaml " + filePathForAppYaml); // Override the prebuild and postbuild commands if BuildConfigurationFile exists if (File.Exists(filePathForAppYaml)) { this.logger.LogDebug("Found BuildConfigurationFile"); this.writer.WriteLine(Environment.NewLine + "Found BuildConfigurationFile"); try { BuildConfigurationFIle buildConfigFile = BuildConfigurationFIle.Create(context.SourceRepo.ReadFile("appsvc.yaml")); if (!string.IsNullOrEmpty(buildConfigFile.Prebuild)) { this.cliOptions.PreBuildCommand = buildConfigFile.Prebuild.Replace("\r\n", ";").Replace("\n", ";"); this.cliOptions.PreBuildScriptPath = null; this.logger.LogDebug("Overriding the pre-build commands with the BuildConfigurationFile section"); this.logger.LogDebug(this.cliOptions.PreBuildCommand.ToString()); this.writer.WriteLine("Overriding the pre-build commands with the BuildConfigurationFile section"); this.writer.WriteLine("\t" + this.cliOptions.PreBuildCommand.ToString()); } if (!string.IsNullOrEmpty(buildConfigFile.Postbuild)) { this.cliOptions.PostBuildCommand = buildConfigFile.Postbuild.Replace("\r\n", ";").Replace("\n", ";"); this.cliOptions.PostBuildScriptPath = null; this.logger.LogDebug("Overriding the post-build commands with the BuildConfigurationFile section"); this.logger.LogDebug(this.cliOptions.PostBuildCommand.ToString()); this.writer.WriteLine("Overriding the post-build commands with the BuildConfigurationFile section"); this.writer.WriteLine("\t" + this.cliOptions.PostBuildCommand.ToString()); } } catch (Exception ex) { this.logger.LogWarning("Invalid BuildConfigurationFile " + ex.ToString()); this.writer.WriteLine(Environment.NewLine + "\"" + DateTime.UtcNow.ToString("yyyy-MM-dd hh:mm:ss") + "\" | WARNING | Invalid BuildConfigurationFile | Exit Code: 1 | Please review your appsvc.yaml | " + Constants.BuildConfigurationFileHelp); this.writer.WriteLine("This is the structure of a valid appsvc.yaml"); this.writer.WriteLine("-------------------------------------------"); this.writer.WriteLine("version: 1" + Environment.NewLine); this.writer.WriteLine("pre-build: apt-get install xyz" + Environment.NewLine); this.writer.WriteLine("post-build: |"); this.writer.WriteLine(" python manage.py makemigrations"); this.writer.WriteLine(" python manage.py migrate"); this.writer.WriteLine("-------------------------------------------"); } } else { this.logger.LogDebug("No appsvc.yaml found"); } (var preBuildCommand, var postBuildCommand) = PreAndPostBuildCommandHelper.GetPreAndPostBuildCommands( context.SourceRepo, this.cliOptions); var outputIsSubDirOfSourceDir = false; if (!string.IsNullOrEmpty(this.cliOptions.DestinationDir)) { outputIsSubDirOfSourceDir = DirectoryHelper.IsSubDirectory( this.cliOptions.DestinationDir, this.cliOptions.SourceDir); } // Copy the source content to destination only if all the platforms involved in generating the build script // say yes. var copySourceDirectoryContentToDestinationDirectory = buildScriptSnippets.All( snippet => snippet.CopySourceDirectoryContentToDestinationDirectory); var buildScriptProps = new BaseBashBuildScriptProperties() { OsPackagesToInstall = this.cliOptions.RequiredOsPackages ?? Array.Empty <string>(), BuildScriptSnippets = buildScriptSnippets.Select(s => s.BashBuildScriptSnippet), BenvArgs = benvArgs, PreBuildCommand = preBuildCommand, PostBuildCommand = postBuildCommand, DirectoriesToExcludeFromCopyToIntermediateDir = directoriesToExcludeFromCopyToIntermediateDir, DirectoriesToExcludeFromCopyToBuildOutputDir = directoriesToExcludeFromCopyToBuildOutputDir, ManifestFileName = FilePaths.BuildManifestFileName, ManifestDir = context.ManifestDir, BuildCommandsFileName = context.BuildCommandsFileName, BuildProperties = buildProperties, BenvPath = FilePaths.Benv, LoggerPath = FilePaths.Logger, PlatformInstallationScript = installationScript, OutputDirectoryIsNested = outputIsSubDirOfSourceDir, CopySourceDirectoryContentToDestinationDirectory = copySourceDirectoryContentToDestinationDirectory, CompressDestinationDir = this.cliOptions.CompressDestinationDir, }; this.LogScriptIfGiven("pre-build", buildScriptProps.PreBuildCommand); this.LogScriptIfGiven("post-build", buildScriptProps.PostBuildCommand); script = TemplateHelper.Render( TemplateHelper.TemplateResource.BaseBashScript, buildScriptProps, this.logger); return(script); }
/// <summary> /// Builds the full build script from the list of snippets for each platform. /// </summary> /// <returns>Finalized build script as a string.</returns> private string BuildScriptFromSnippets( BuildScriptGeneratorContext context, string installationScript, IList <BuildScriptSnippet> buildScriptSnippets, IDictionary <string, string> toolsToVersion, List <string> directoriesToExcludeFromCopyToIntermediateDir, List <string> directoriesToExcludeFromCopyToBuildOutputDir, IEnumerable <PlatformDetectorResult> detectionResults) { string script; string benvArgs = StringExtensions.JoinKeyValuePairs(toolsToVersion); benvArgs = $"{benvArgs} {Constants.BenvDynamicInstallRootDirKey}=\"{_cliOptions.DynamicInstallRootDir}\""; Dictionary <string, string> buildProperties = buildScriptSnippets .Where(s => s.BuildProperties != null) .SelectMany(s => s.BuildProperties) .ToDictionary(p => p.Key, p => p.Value); buildProperties[ManifestFilePropertyKeys.OperationId] = context.OperationId; var sourceDirInBuildContainer = _cliOptions.SourceDir; if (!string.IsNullOrEmpty(_cliOptions.IntermediateDir)) { sourceDirInBuildContainer = _cliOptions.IntermediateDir; } buildProperties[ManifestFilePropertyKeys.SourceDirectoryInBuildContainer] = sourceDirInBuildContainer; var allPlatformNames = detectionResults .Where(s => s.Platform != null) .Select(s => s.Platform) .ToList(); foreach (var eachPlatformName in allPlatformNames) { _logger.LogInformation($"Build Property Key:{ManifestFilePropertyKeys.PlatformName} value: {eachPlatformName} is written into manifest"); if (buildProperties.ContainsKey(ManifestFilePropertyKeys.PlatformName)) { var previousValue = buildProperties[ManifestFilePropertyKeys.PlatformName]; buildProperties[ManifestFilePropertyKeys.PlatformName] = string.Join( ",", previousValue, eachPlatformName); } else { buildProperties[ManifestFilePropertyKeys.PlatformName] = eachPlatformName; } } buildProperties[ManifestFilePropertyKeys.CompressDestinationDir] = _cliOptions.CompressDestinationDir.ToString().ToLower(); (var preBuildCommand, var postBuildCommand) = PreAndPostBuildCommandHelper.GetPreAndPostBuildCommands( context.SourceRepo, _cliOptions); var outputIsSubDirOfSourceDir = false; if (!string.IsNullOrEmpty(_cliOptions.DestinationDir)) { outputIsSubDirOfSourceDir = DirectoryHelper.IsSubDirectory( _cliOptions.DestinationDir, _cliOptions.SourceDir); } // Copy the source content to destination only if all the platforms involved in generating the build script // say yes. var copySourceDirectoryContentToDestinationDirectory = buildScriptSnippets.All( snippet => snippet.CopySourceDirectoryContentToDestinationDirectory); var buildScriptProps = new BaseBashBuildScriptProperties() { OsPackagesToInstall = _cliOptions.RequiredOsPackages ?? new string[0], BuildScriptSnippets = buildScriptSnippets.Select(s => s.BashBuildScriptSnippet), BenvArgs = benvArgs, PreBuildCommand = preBuildCommand, PostBuildCommand = postBuildCommand, DirectoriesToExcludeFromCopyToIntermediateDir = directoriesToExcludeFromCopyToIntermediateDir, DirectoriesToExcludeFromCopyToBuildOutputDir = directoriesToExcludeFromCopyToBuildOutputDir, ManifestFileName = FilePaths.BuildManifestFileName, ManifestDir = context.ManifestDir, BuildCommandsFileName = context.BuildCommandsFileName, BuildProperties = buildProperties, BenvPath = FilePaths.Benv, PlatformInstallationScript = installationScript, OutputDirectoryIsNested = outputIsSubDirOfSourceDir, CopySourceDirectoryContentToDestinationDirectory = copySourceDirectoryContentToDestinationDirectory, CompressDestinationDir = _cliOptions.CompressDestinationDir, }; LogScriptIfGiven("pre-build", buildScriptProps.PreBuildCommand); LogScriptIfGiven("post-build", buildScriptProps.PostBuildCommand); script = TemplateHelper.Render( TemplateHelper.TemplateResource.BaseBashScript, buildScriptProps, _logger); return(script); }
public string GenerateDockerfile(DockerfileContext ctx) { var dockerfileBuildImageName = "build"; var dockerfileBuildImageTag = "azfunc-jamstack"; var dockerfileRuntimeImage = !string.IsNullOrEmpty(this.commonOptions.RuntimePlatformName) ? ConvertToRuntimeName(this.commonOptions.RuntimePlatformName) : string.Empty; var dockerfileRuntimeImageTag = !string.IsNullOrEmpty(this.commonOptions.RuntimePlatformVersion) ? this.commonOptions.RuntimePlatformVersion : string.Empty; var compatiblePlatforms = this.GetCompatiblePlatforms(ctx); if (!compatiblePlatforms.Any()) { throw new UnsupportedPlatformException(Labels.UnableToDetectPlatformMessage); } foreach (var platformAndDetectorResult in compatiblePlatforms) { var platform = platformAndDetectorResult.Key; var platformDetectorResult = platformAndDetectorResult.Value; var detectedRuntimeName = ConvertToRuntimeName(platform.Name); // If the runtime platform name wasn't previously provided, see if we can use the current detected platform as the runtime image. if (string.IsNullOrEmpty(dockerfileRuntimeImage)) { // If the detected platform isn't in our currently list of runtime versions, skip it with a notice to the user. if (!this.supportedRuntimeVersions.ContainsKey(detectedRuntimeName)) { this.logger.LogDebug($"The detected platform {platform.Name} does not currently have a supported runtime image." + $"If this Dockerfile command or image is outdated, please provide the runtime platform name manually."); continue; } dockerfileRuntimeImage = detectedRuntimeName; } // If the runtime platform version wasn't previously provided, see if we can detect one from the current detected platform. // Note: we first need to ensure that the current detected platform is the same as the runtime platform name previously set or pvodied. if (!string.IsNullOrEmpty(dockerfileRuntimeImage) && dockerfileRuntimeImage.Equals(detectedRuntimeName, StringComparison.OrdinalIgnoreCase) && string.IsNullOrEmpty(dockerfileRuntimeImageTag)) { dockerfileRuntimeImageTag = this.ConvertToRuntimeVersion(dockerfileRuntimeImage, platformDetectorResult.PlatformVersion); } // If the runtime image has been set manually or by the platform detection result, stop searching. if (!string.IsNullOrEmpty(dockerfileRuntimeImage)) { break; } } var properties = new DockerfileProperties() { RuntimeImageName = dockerfileRuntimeImage, RuntimeImageTag = dockerfileRuntimeImageTag, BuildImageName = dockerfileBuildImageName, BuildImageTag = dockerfileBuildImageTag, }; return(TemplateHelper.Render( TemplateHelper.TemplateResource.Dockerfile, properties, this.logger)); }