/// <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 = GetBenvArgs(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, BuildProperties = buildProperties }; LogScriptIfGiven("pre-build", buildScriptProps.PreBuildCommand); LogScriptIfGiven("post-build", buildScriptProps.PostBuildCommand); script = TemplateHelpers.Render( TemplateHelpers.TemplateResource.BaseBashScript, buildScriptProps, _logger); return(script); }
/// <summary> /// Handles the error when no platform was found, logging information about the repo. /// </summary> private void LogAndThrowNoPlatformFound(BuildScriptGeneratorContext context) { try { var directoryStructureData = OryxDirectoryStructureHelper.GetDirectoryStructure( context.SourceRepo.RootPath); _logger.LogTrace( "logDirectoryStructure", new Dictionary <string, string> { { "directoryStructure", directoryStructureData } }); } catch (Exception ex) { _logger.LogError(ex, "Exception caught"); } finally { throw new UnsupportedLanguageException("Could not detect the language from repo."); } }
/// <summary> /// Gets the installation script snippet which contains snippets for all detected platforms. /// </summary> /// <param name="context">The <see cref="RepositoryContext"/>.</param> /// <param name="detectionResults">Already detected platforms results.</param> /// <returns>A snippet having logic to install all detected platforms.</returns> public string GetBashScriptSnippet( BuildScriptGeneratorContext context, IEnumerable <PlatformDetectorResult> detectionResults = null) { var scriptBuilder = new StringBuilder(); // Avoid detecting again if detection was already run. if (detectionResults == null) { detectionResults = _platformDetector.DetectPlatforms(context); } var snippets = GetInstallationScriptSnippets(detectionResults, context); foreach (var snippet in snippets) { scriptBuilder.AppendLine(snippet); scriptBuilder.AppendLine(); } return(scriptBuilder.ToString()); }
public bool TryGenerateBashScript(BuildScriptGeneratorContext context, out string script) { script = null; var toolsToVersion = new Dictionary <string, string>(); List <BuildScriptSnippet> snippets; var directoriesToExcludeFromCopyToIntermediateDir = new List <string>(); var directoriesToExcludeFromCopyToBuildOutputDir = new List <string>(); using (var timedEvent = _logger.LogTimedEvent("GetBuildSnippets")) { snippets = GetBuildSnippets( context, toolsToVersion, directoriesToExcludeFromCopyToIntermediateDir, directoriesToExcludeFromCopyToBuildOutputDir); timedEvent.SetProperties(toolsToVersion); } if (snippets.Any()) { // By default exclude these irrespective of platform directoriesToExcludeFromCopyToIntermediateDir.Add(".git"); directoriesToExcludeFromCopyToBuildOutputDir.Add(".git"); script = BuildScriptFromSnippets( snippets, toolsToVersion, directoriesToExcludeFromCopyToIntermediateDir, directoriesToExcludeFromCopyToBuildOutputDir); return(true); } else { LogAndThrowNoPlatformFound(context); return(false); } }
private IEnumerable <string> GetInstallationScriptSnippets( IEnumerable <PlatformDetectorResult> detectionResults, BuildScriptGeneratorContext context) { var installationScriptSnippets = new List <string>(); foreach (var detectionResult in detectionResults) { var platform = this.platforms .Where(p => p.Name.EqualsIgnoreCase(detectionResult.Platform)) .First(); var snippet = platform.GetInstallerScriptSnippet(context, detectionResult); if (!string.IsNullOrEmpty(snippet)) { this.outputWriter.WriteLine( $"Version '{detectionResult.PlatformVersion}' of platform '{detectionResult.Platform}' " + $"is not installed. Generating script to install it..."); installationScriptSnippets.Add(snippet); } } return(installationScriptSnippets); }
public bool TryGenerateBashScript(BuildScriptGeneratorContext context, out string script) { script = null; var toolsToVersion = new Dictionary <string, string>(); List <BuildScriptSnippet> snippets; using (var timedEvent = _logger.LogTimedEvent("GetBuildSnippets")) { snippets = GetBuildSnippets(context, toolsToVersion); timedEvent.SetProperties(toolsToVersion); } if (snippets.Any()) { script = BuildScriptFromSnippets(snippets, toolsToVersion); return(true); } else { LogAndThrowNoPlatformFound(context); return(false); } }
public void GenerateBashScript( BuildScriptGeneratorContext context, out string script, List <ICheckerMessage> checkerMessageSink = null) { script = null; // To be populated by GetBuildSnippets var toolsToVersion = new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase); IList <BuildScriptSnippet> snippets; var directoriesToExcludeFromCopyToIntermediateDir = new List <string>(); var directoriesToExcludeFromCopyToBuildOutputDir = new List <string>(); using (var timedEvent = _logger.LogTimedEvent("GetBuildSnippets")) { snippets = GetBuildSnippets( context, toolsToVersion, directoriesToExcludeFromCopyToIntermediateDir, directoriesToExcludeFromCopyToBuildOutputDir); timedEvent.SetProperties(toolsToVersion); } if (_checkers != null && checkerMessageSink != null && context.EnableCheckers) { try { _logger.LogDebug("Running checkers"); RunCheckers(context, toolsToVersion, checkerMessageSink); } catch (Exception exc) { _logger.LogError(exc, "Exception caught while running checkers"); } } else { _logger.LogInformation("Not running checkers - condition evaluates to " + "({checkersNotNull} && {sinkNotNull} && {enableCheckers})", _checkers != null, checkerMessageSink != null, context.EnableCheckers); } if (snippets != null) { foreach (var snippet in snippets) { if (snippet.IsFullScript) { script = snippet.BashBuildScriptSnippet; return; } } } if (snippets.Any()) { // By default exclude these irrespective of platform directoriesToExcludeFromCopyToIntermediateDir.Add(".git"); directoriesToExcludeFromCopyToBuildOutputDir.Add(".git"); script = BuildScriptFromSnippets( context, snippets, new ReadOnlyDictionary <string, string>(toolsToVersion), directoriesToExcludeFromCopyToIntermediateDir, directoriesToExcludeFromCopyToBuildOutputDir); } else { // TODO: Should an UnsupportedLanguageException be thrown here? // Seeing as the issue was that platforms were IDENTIFIED, but no build snippets were emitted from them throw new UnsupportedPlatformException(Labels.UnableToDetectPlatformMessage); } }
public IDictionary <IProgrammingPlatform, string> GetCompatiblePlatforms(BuildScriptGeneratorContext ctx) { return(_platformDetector.GetCompatiblePlatforms(ctx, ctx.Language, ctx.LanguageVersion)); }
public void GenerateBashScript( BuildScriptGeneratorContext context, out string script, List <ICheckerMessage> checkerMessageSink = null) { script = null; IList <BuildScriptSnippet> buildScriptSnippets; var directoriesToExcludeFromCopyToIntermediateDir = new List <string>(); var directoriesToExcludeFromCopyToBuildOutputDir = new List <string>(); // Try detecting ALL platforms since in some scenarios this is required. // For example, in case of a multi-platform app like ASP.NET Core + NodeJs, we might need to dynamically // install both these platforms' sdks before actually using any of their commands. So even though a user // of Oryx might explicitly supply the platform of the app as .NET Core, we still need to make sure the // build environment is setup with detected platforms' sdks. var platformInfos = this.platformsInformationProvider.GetPlatformsInfo(context); var detectionResults = platformInfos.Select(pi => pi.DetectorResult); var installationScript = this.environmentSetupScriptProvider.GetBashScriptSnippet( context, detectionResults); // Get list of tools to be set on benv var toolsToVersion = new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase); foreach (var toolsToBeSetInPath in platformInfos .Where(pi => pi.RequiredToolsInPath != null) .Select(pi => pi.RequiredToolsInPath)) { foreach (var toolNameAndVersion in toolsToBeSetInPath) { if (!string.IsNullOrEmpty( Environment.GetEnvironmentVariable(toolNameAndVersion.Key))) { this.logger.LogInformation($"If {toolNameAndVersion.Key} is set as environment, it'll be not be set via benv"); } else { this.logger.LogInformation($"If {toolNameAndVersion.Key} is not set as environment, it'll be set to {toolNameAndVersion.Value} via benv"); toolsToVersion[toolNameAndVersion.Key] = toolNameAndVersion.Value; } } } using (var timedEvent = this.logger.LogTimedEvent("GetBuildSnippets")) { buildScriptSnippets = this.GetBuildSnippets( context, detectionResults, runDetection: false, directoriesToExcludeFromCopyToIntermediateDir, directoriesToExcludeFromCopyToBuildOutputDir); timedEvent.SetProperties(toolsToVersion); } if (this.checkers != null && checkerMessageSink != null && this.cliOptions.EnableCheckers) { try { this.logger.LogDebug("Running checkers"); this.RunCheckers(context, toolsToVersion, checkerMessageSink); } catch (Exception exc) { this.logger.LogError(exc, "Exception caught while running checkers"); } } else { this.logger.LogInformation( "Not running checkers - condition evaluates to " + "({checkersNotNull} && {sinkNotNull} && {enableCheckers})", this.checkers != null, checkerMessageSink != null, this.cliOptions.EnableCheckers); } if (buildScriptSnippets != null) { foreach (var snippet in buildScriptSnippets) { if (snippet.IsFullScript) { script = snippet.BashBuildScriptSnippet; return; } } } if (buildScriptSnippets.Any()) { // By default exclude these irrespective of platform directoriesToExcludeFromCopyToIntermediateDir.Add(".git"); directoriesToExcludeFromCopyToBuildOutputDir.Add(".git"); script = this.BuildScriptFromSnippets( context, installationScript, buildScriptSnippets, new ReadOnlyDictionary <string, string>(toolsToVersion), directoriesToExcludeFromCopyToIntermediateDir, directoriesToExcludeFromCopyToBuildOutputDir, detectionResults); } else { // TODO: Should an UnsupportedPlatformException be thrown here? // Seeing as the issue was that platforms were IDENTIFIED, but no build snippets were emitted from them throw new UnsupportedPlatformException(Labels.UnableToDetectPlatformMessage); } }
/// <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); }
private IList <BuildScriptSnippet> GetBuildSnippets( BuildScriptGeneratorContext context, IEnumerable <PlatformDetectorResult> detectionResults, bool runDetection, [CanBeNull] List <string> directoriesToExcludeFromCopyToIntermediateDir, [CanBeNull] List <string> directoriesToExcludeFromCopyToBuildOutputDir) { var snippets = new List <BuildScriptSnippet>(); IDictionary <IProgrammingPlatform, PlatformDetectorResult> platformsToUse; if (runDetection) { platformsToUse = this.compatiblePlatformDetector.GetCompatiblePlatforms(context); } else { platformsToUse = this.compatiblePlatformDetector.GetCompatiblePlatforms(context, detectionResults); } foreach (var platformAndDetectorResult in platformsToUse) { var(platform, detectorResult) = platformAndDetectorResult; if (directoriesToExcludeFromCopyToIntermediateDir != null) { var excludedDirs = platform.GetDirectoriesToExcludeFromCopyToIntermediateDir(context); if (excludedDirs.Any()) { directoriesToExcludeFromCopyToIntermediateDir.AddRange(excludedDirs); } } if (directoriesToExcludeFromCopyToBuildOutputDir != null) { var excludedDirs = platform.GetDirectoriesToExcludeFromCopyToBuildOutputDir(context); if (excludedDirs.Any()) { directoriesToExcludeFromCopyToBuildOutputDir.AddRange(excludedDirs); } } string cleanOrNot = platform.IsCleanRepo(context.SourceRepo) ? "clean" : "not clean"; this.logger.LogDebug($"Repo is {cleanOrNot} for {platform.Name}"); var snippet = platform.GenerateBashBuildScriptSnippet(context, detectorResult); if (snippet != null) { this.logger.LogDebug( "Platform {platformName} with version {platformVersion} was used.", platform.Name, detectorResult.PlatformVersion); snippets.Add(snippet); } else { this.logger.LogWarning( "{platformType}.GenerateBashBuildScriptSnippet() returned null", platform.GetType()); } } return(snippets); }
public IList <Tuple <IProgrammingPlatform, string> > GetCompatiblePlatforms(BuildScriptGeneratorContext ctx) { var resultPlatforms = new List <Tuple <IProgrammingPlatform, string> >(); var enabledPlatforms = _programmingPlatforms.Where(p => { if (!p.IsEnabled(ctx)) { _logger.LogDebug("{platformName} has been disabled", p.Name); return(false); } return(true); }); // If a user supplied the language explicitly, check if the platform is enabled for that IProgrammingPlatform userSuppliedPlatform = null; string platformVersion = null; if (!string.IsNullOrEmpty(ctx.Language)) { var selectedPlatform = enabledPlatforms .Where(p => string.Equals(ctx.Language, p.Name, StringComparison.OrdinalIgnoreCase)) .FirstOrDefault(); if (selectedPlatform == null) { ThrowInvalidLanguageProvided(ctx); } userSuppliedPlatform = selectedPlatform; platformVersion = ctx.LanguageVersion; if (string.IsNullOrEmpty(platformVersion)) { var detectionResult = userSuppliedPlatform.Detect(ctx.SourceRepo); if (detectionResult == null || string.IsNullOrEmpty(detectionResult.LanguageVersion)) { throw new UnsupportedVersionException( $"Couldn't detect a version for the platform '{userSuppliedPlatform.Name}' in the repo."); } platformVersion = detectionResult.LanguageVersion; } resultPlatforms.Add(Tuple.Create(userSuppliedPlatform, platformVersion)); // if the user explicitly supplied a platform and if that platform does not want to be part of // multi-platform builds, then short-circuit immediately ignoring going through other platforms if (!IsEnabledForMultiPlatformBuild(userSuppliedPlatform, ctx)) { return(resultPlatforms); } } // Ignore processing the same platform again if (userSuppliedPlatform != null) { enabledPlatforms = enabledPlatforms.Where(p => !ReferenceEquals(p, userSuppliedPlatform)); } foreach (var platform in enabledPlatforms) { string targetVersionSpec = null; _logger.LogDebug("Detecting platform using {platformName}", platform.Name); var detectionResult = platform.Detect(ctx.SourceRepo); if (detectionResult != null) { _logger.LogDebug( "Detected {platformName} version {platformVersion} for app in repo", platform.Name, detectionResult.LanguageVersion); targetVersionSpec = detectionResult.LanguageVersion; if (string.IsNullOrEmpty(targetVersionSpec)) { throw new UnsupportedVersionException( $"Couldn't detect a version for the platform '{platform.Name}' in the repo."); } resultPlatforms.Add(Tuple.Create(platform, targetVersionSpec)); if (!IsEnabledForMultiPlatformBuild(platform, ctx)) { return(resultPlatforms); } } } return(resultPlatforms); }
/// <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) { string script; string benvArgs = StringExtensions.JoinKeyValuePairs(toolsToVersion); 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 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, BuildProperties = buildProperties, BenvPath = FilePaths.Benv, PlatformInstallationScript = installationScript, OutputDirectoryIsNested = outputIsSubDirOfSourceDir, CopySourceDirectoryContentToDestinationDirectory = copySourceDirectoryContentToDestinationDirectory, }; LogScriptIfGiven("pre-build", buildScriptProps.PreBuildCommand); LogScriptIfGiven("post-build", buildScriptProps.PostBuildCommand); script = TemplateHelper.Render( TemplateHelper.TemplateResource.BaseBashScript, buildScriptProps, _logger); return(script); }
private List <BuildScriptSnippet> GetBuildSnippets(BuildScriptGeneratorContext context, Dictionary <string, string> toolsToVersion) { bool providedLanguageFound = false; var snippets = new List <BuildScriptSnippet>(); foreach (var platform in _programmingPlatforms) { if (!platform.IsEnabled(context)) { _logger.LogDebug("{platformName} has been disabled", platform.Name); continue; } bool usePlatform = false; var currPlatformMatchesProvided = !string.IsNullOrEmpty(context.Language) && string.Equals(context.Language, platform.Name, StringComparison.OrdinalIgnoreCase); string targetVersionSpec = null; if (currPlatformMatchesProvided) { providedLanguageFound = true; targetVersionSpec = context.LanguageVersion; usePlatform = true; } else if (context.DisableMultiPlatformBuild && !string.IsNullOrEmpty(context.Language)) { _logger.LogDebug("Multi platform build is disabled and platform was specified. Skipping language {skippedLang}", platform.Name); continue; } if (!currPlatformMatchesProvided || string.IsNullOrEmpty(targetVersionSpec)) { _logger.LogDebug("Detecting platform using {platformName}", platform.Name); var detectionResult = platform.Detect(context.SourceRepo); if (detectionResult != null) { _logger.LogDebug("Detected {platformName} version {platformVersion} for app in repo", platform.Name, detectionResult.LanguageVersion); usePlatform = true; targetVersionSpec = detectionResult.LanguageVersion; if (string.IsNullOrEmpty(targetVersionSpec)) { throw new UnsupportedVersionException($"Couldn't detect a version for the platform '{platform.Name}' in the repo."); } } } if (usePlatform) { string targetVersion = GetMatchingTargetVersion(platform, targetVersionSpec); platform.SetVersion(context, targetVersion); string cleanOrNot = platform.IsCleanRepo(context.SourceRepo) ? "clean" : "not clean"; _logger.LogDebug($"Repo is {cleanOrNot} for {platform.Name}"); var snippet = platform.GenerateBashBuildScriptSnippet(context); if (snippet != null) { _logger.LogDebug("Script generator {scriptGenType} was used", platform.GetType()); snippets.Add(snippet); platform.SetRequiredTools(context.SourceRepo, targetVersion, toolsToVersion); } else { _logger.LogDebug("Script generator {scriptGenType} cannot be used", platform.GetType()); } } } // Even if a language was detected, we throw an error if the user provided an unsupported language as target. if (!string.IsNullOrEmpty(context.Language) && !providedLanguageFound) { ThrowInvalidLanguageProvided(context); } return(snippets); }
/// <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); }