Ejemplo n.º 1
0
        internal override int Execute(IServiceProvider serviceProvider, IConsole console)
        {
            var scriptGenerator = new BuildScriptGenerator(
                serviceProvider,
                console,
                checkerMessageSink: null,
                operationId: null);

            if (!scriptGenerator.TryGenerateScript(out var generatedScript))
            {
                return(ProcessConstants.ExitFailure);
            }

            if (string.IsNullOrEmpty(OutputPath))
            {
                console.WriteLine(generatedScript);
            }
            else
            {
                OutputPath.SafeWriteAllText(generatedScript);
                console.WriteLine($"Script written to '{OutputPath}'");

                // Try making the script executable
                ProcessHelper.TrySetExecutableMode(OutputPath);
            }

            return(ProcessConstants.ExitSuccess);
        }
Ejemplo n.º 2
0
        internal override int Execute(IServiceProvider serviceProvider, IConsole console)
        {
            var scriptGenerator = new BuildScriptGenerator(console, serviceProvider);

            if (!scriptGenerator.TryGenerateScript(out var generatedScript))
            {
                return(ProcessConstants.ExitFailure);
            }

            console.WriteLine(generatedScript);

            return(ProcessConstants.ExitSuccess);
        }
Ejemplo n.º 3
0
        internal override int Execute(IServiceProvider serviceProvider, IConsole console)
        {
            var scriptGenerator = new BuildScriptGenerator(
                serviceProvider,
                console,
                checkerMessageSink: null,
                operationId: null);

            if (!scriptGenerator.TryGenerateScript(out var generatedScript))
            {
                return(ProcessConstants.ExitFailure);
            }

            console.WriteLine(generatedScript);

            return(ProcessConstants.ExitSuccess);
        }
Ejemplo n.º 4
0
        internal override int Execute(IServiceProvider serviceProvider, IConsole console)
        {
            var generator = serviceProvider.GetRequiredService <IBuildScriptGenerator>();

            var ctx         = BuildScriptGenerator.CreateContext(serviceProvider, operationId: null);
            var compatPlats = generator.GetCompatiblePlatforms(ctx);

            if (compatPlats != null && compatPlats.Any())
            {
                console.WriteLine("Detected platforms:");
                console.WriteLine(string.Join(' ', compatPlats.Select(pair => $"{pair.Item1.Name}=\"{pair.Item2}\"")));

                // Write the detected platforms into the build plan as TOML
                File.WriteAllLines(PlanPath, compatPlats.Select(pair => $"{pair.Item1.Name} = {{ version = \"{pair.Item2}\" }}"));

                return(ProcessConstants.ExitSuccess);
            }

            return(DetectorFailCode);
        }
Ejemplo n.º 5
0
        internal override int Execute(IServiceProvider serviceProvider, IConsole console)
        {
            var generator = serviceProvider.GetRequiredService <IBuildScriptGenerator>();

            var options = serviceProvider.GetRequiredService <IOptions <BuildScriptGeneratorOptions> >().Value;
            var env     = serviceProvider.GetRequiredService <CliEnvironmentSettings>();
            var repo    = serviceProvider.GetRequiredService <ISourceRepoProvider>().GetSourceRepo();

            var ctx         = BuildScriptGenerator.CreateContext(options, env, repo, operationId: null);
            var compatPlats = generator.GetCompatiblePlatforms(ctx);

            if (compatPlats != null && compatPlats.Any())
            {
                console.WriteLine("# Detected platforms:");
                console.WriteLine(string.Join(' ', compatPlats.Select(pair => $"{pair.Item1.Name}=\"{pair.Item2}\"")));
                return(ProcessConstants.ExitSuccess);
            }

            return(DetectorFailCode);
        }
Ejemplo n.º 6
0
        internal override int Execute(IServiceProvider serviceProvider, IConsole console)
        {
            var logger = serviceProvider.GetRequiredService <ILogger <ExecCommand> >();
            var env    = serviceProvider.GetRequiredService <IEnvironment>();
            var opts   = serviceProvider.GetRequiredService <IOptions <BuildScriptGeneratorOptions> >().Value;

            var beginningOutputLog = GetBeginningCommandOutputLog();

            console.WriteLine(beginningOutputLog);

            if (string.IsNullOrWhiteSpace(Command))
            {
                logger.LogDebug("Command is empty; exiting");
                return(ProcessConstants.ExitSuccess);
            }

            var shellPath         = env.GetEnvironmentVariable("BASH") ?? FilePaths.Bash;
            var context           = BuildScriptGenerator.CreateContext(serviceProvider, operationId: null);
            var detector          = serviceProvider.GetRequiredService <DefaultPlatformDetector>();
            var detectedPlatforms = detector.DetectPlatforms(context);

            if (!detectedPlatforms.Any())
            {
                return(ProcessConstants.ExitFailure);
            }

            int exitCode;

            using (var timedEvent = logger.LogTimedEvent("ExecCommand"))
            {
                // Build envelope script
                var scriptBuilder = new ShellScriptBuilder("\n")
                                    .AddShebang(shellPath)
                                    .AddCommand("set -e");

                var envSetupProvider   = serviceProvider.GetRequiredService <PlatformsInstallationScriptProvider>();
                var installationScript = envSetupProvider.GetBashScriptSnippet(
                    context,
                    detectedPlatforms);
                if (!string.IsNullOrEmpty(installationScript))
                {
                    scriptBuilder.AddCommand(installationScript);
                }

                scriptBuilder.Source(
                    $"{FilePaths.Benv} " +
                    $"{string.Join(" ", detectedPlatforms.Select(p => $"{p.Platform}={p.PlatformVersion}"))}");

                scriptBuilder
                .AddCommand("echo Executing supplied command...")
                .AddCommand(Command);

                // Create temporary file to store script
                // Get the path where the generated script should be written into.
                var tempDirectoryProvider = serviceProvider.GetRequiredService <ITempDirectoryProvider>();
                var tempScriptPath        = Path.Combine(tempDirectoryProvider.GetTempDirectory(), "execCommand.sh");
                var script = scriptBuilder.ToString();
                File.WriteAllText(tempScriptPath, script);
                console.WriteLine("Finished generating script.");

                timedEvent.AddProperty(nameof(tempScriptPath), tempScriptPath);

                if (DebugMode)
                {
                    console.WriteLine($"Temporary script @ {tempScriptPath}:");
                    console.WriteLine("---");
                    console.WriteLine(script);
                    console.WriteLine("---");
                }

                console.WriteLine();
                console.WriteLine("Executing generated script...");
                console.WriteLine();

                exitCode = ProcessHelper.RunProcess(
                    shellPath,
                    new[] { tempScriptPath },
                    opts.SourceDir,
                    (sender, args) =>
                {
                    if (args.Data != null)
                    {
                        console.WriteLine(args.Data);
                    }
                },
                    (sender, args) =>
                {
                    if (args.Data != null)
                    {
                        console.Error.WriteLine(args.Data);
                    }
                },
                    waitTimeForExit: null);
                timedEvent.AddProperty("exitCode", exitCode.ToString());
            }

            return(exitCode);
        }
Ejemplo n.º 7
0
        // To enable unit testing
        internal int Execute(
            IServiceProvider serviceProvider,
            IConsole console,
            DataReceivedEventHandler stdOutHandler,
            DataReceivedEventHandler stdErrHandler)
        {
            var logger = serviceProvider.GetRequiredService <ILogger <BuildCommand> >();

            // This will be an App Service app name if Oryx was invoked by Kudu
            var appName = Environment.GetEnvironmentVariable(
                LoggingConstants.AppServiceAppNameEnvironmentVariableName) ?? ".oryx";
            var buildOpId = logger.StartOperation(appName);

            console.WriteLine("Build orchestrated by Microsoft Oryx, https://github.com/Microsoft/Oryx");
            console.WriteLine("You can report issues at https://github.com/Microsoft/Oryx/issues");
            console.WriteLine();

            var buildInfo = new DefinitionListFormatter();

            buildInfo.AddDefinition("Oryx Version", $"{Program.GetVersion()}, Commit: {Program.GetCommit()}");
            buildInfo.AddDefinition("Build Operation ID", buildOpId);

            var sourceRepo = serviceProvider.GetRequiredService <ISourceRepoProvider>().GetSourceRepo();
            var commitId   = GetSourceRepoCommitId(
                serviceProvider.GetRequiredService <IEnvironment>(),
                sourceRepo,
                logger);

            if (!string.IsNullOrWhiteSpace(commitId))
            {
                buildInfo.AddDefinition("Repository Commit", commitId);
            }

            console.WriteLine(buildInfo.ToString());

            // Try writing the ID to a file in the source directory
            try
            {
                using (logger.LogTimedEvent("WriteBuildIdFile"))
                    using (var idFileWriter = new StreamWriter(
                               Path.Combine(sourceRepo.RootPath, Common.FilePaths.BuildIdFileName)))
                    {
                        idFileWriter.Write(buildOpId);
                    }
            }
            catch (Exception exc)
            {
                logger.LogError(exc, "Exception caught while trying to write build ID file");
            }

            var environmentSettingsProvider = serviceProvider.GetRequiredService <IEnvironmentSettingsProvider>();

            if (!environmentSettingsProvider.TryGetAndLoadSettings(out var environmentSettings))
            {
                return(ProcessConstants.ExitFailure);
            }

            // Generate build script
            string scriptContent;

            using (var stopwatch = logger.LogTimedEvent("GenerateBuildScript"))
            {
                var scriptGenerator = new BuildScriptGenerator(console, serviceProvider);
                if (!scriptGenerator.TryGenerateScript(out scriptContent))
                {
                    stopwatch.AddProperty("failed", "true");
                    return(ProcessConstants.ExitFailure);
                }
            }

            // Get the path where the generated script should be written into.
            var tempDirectoryProvider = serviceProvider.GetRequiredService <ITempDirectoryProvider>();
            var buildScriptPath       = Path.Combine(tempDirectoryProvider.GetTempDirectory(), "build.sh");

            // Write build script to selected path
            File.WriteAllText(buildScriptPath, scriptContent);
            logger.LogTrace("Build script written to file");

            var buildEventProps = new Dictionary <string, string>()
            {
                { "oryxVersion", Program.GetVersion() },
                { "oryxCommitId", Program.GetCommit() },
                {
                    "oryxCommandLine",
                    string.Join(
                        ' ',
                        serviceProvider.GetRequiredService <IEnvironment>().GetCommandLineArgs())
                },
                { nameof(commitId), commitId },
                { "scriptPath", buildScriptPath },
                { "envVars", string.Join(",", GetEnvVarNames(serviceProvider.GetRequiredService <IEnvironment>())) },
            };

            var buildScriptOutput = new StringBuilder();
            var stdOutEventLogger = new TextSpanEventLogger(logger, _measurableStdOutSpans);

            DataReceivedEventHandler stdOutBaseHandler = (sender, args) =>
            {
                string line = args.Data;
                if (line == null)
                {
                    return;
                }

                console.WriteLine(line);
                buildScriptOutput.AppendLine(line);
                stdOutEventLogger.CheckString(line);
            };

            DataReceivedEventHandler stdErrBaseHandler = (sender, args) =>
            {
                string line = args.Data;
                if (line == null)
                {
                    return;
                }

                console.Error.WriteLine(args.Data);
                buildScriptOutput.AppendLine(args.Data);
            };

            // Try make the pre-build & post-build scripts executable
            ProcessHelper.TrySetExecutableMode(environmentSettings.PreBuildScriptPath);
            ProcessHelper.TrySetExecutableMode(environmentSettings.PostBuildScriptPath);

            // Run the generated script
            var options = serviceProvider.GetRequiredService <IOptions <BuildScriptGeneratorOptions> >().Value;
            int exitCode;

            using (var timedEvent = logger.LogTimedEvent("RunBuildScript", buildEventProps))
            {
                exitCode = serviceProvider.GetRequiredService <IScriptExecutor>().ExecuteScript(
                    buildScriptPath,
                    new[]
                {
                    sourceRepo.RootPath,
                    options.DestinationDir ?? string.Empty,
                    options.IntermediateDir ?? string.Empty
                },
                    workingDirectory: sourceRepo.RootPath,
                    stdOutHandler == null ? stdOutBaseHandler : stdOutBaseHandler + stdOutHandler,
                    stdErrHandler == null ? stdErrBaseHandler : stdErrBaseHandler + stdErrHandler);
            }

            logger.LogDebug("Build script content:\n" + scriptContent);
            logger.LogDebug("Build script output:\n" + buildScriptOutput.ToString());

            if (exitCode != ProcessConstants.ExitSuccess)
            {
                logger.LogError("Build script exited with {exitCode}", exitCode);
                return(exitCode);
            }

            return(ProcessConstants.ExitSuccess);
        }
Ejemplo n.º 8
0
        internal override int Execute(IServiceProvider serviceProvider, IConsole console)
        {
            var logger  = serviceProvider.GetRequiredService <ILogger <PrepareEnvironmentCommand> >();
            var options = serviceProvider.GetRequiredService <IOptions <BuildScriptGeneratorOptions> >().Value;

            var beginningOutputLog = GetBeginningCommandOutputLog();

            console.WriteLine(beginningOutputLog);

            int exitCode;

            using (var timedEvent = logger.LogTimedEvent("EnvSetupCommand"))
            {
                var context = BuildScriptGenerator.CreateContext(serviceProvider, operationId: null);

                IEnumerable <PlatformDetectorResult> detectedPlatforms = null;
                if (SkipDetection)
                {
                    console.WriteLine(
                        $"Skipping platform detection since '{SkipDetectionTemplate}' switch was used...");

                    var platforms = serviceProvider.GetRequiredService <IEnumerable <IProgrammingPlatform> >();
                    if (TryValidateSuppliedPlatformsAndVersions(
                            platforms,
                            PlatformsAndVersions,
                            PlatformsAndVersionsFile,
                            console,
                            out var results))
                    {
                        detectedPlatforms = results;
                    }
                    else
                    {
                        console.WriteErrorLine(
                            $"Invalid value for switch '{PlatformsAndVersionsTemplate}'.");
                        return(ProcessConstants.ExitFailure);
                    }
                }
                else
                {
                    var detector      = serviceProvider.GetRequiredService <DefaultPlatformsInformationProvider>();
                    var platformInfos = detector.GetPlatformsInfo(context);
                    if (!platformInfos.Any())
                    {
                        return(ProcessConstants.ExitFailure);
                    }
                    detectedPlatforms = platformInfos.Select(pi => pi.DetectorResult);
                }

                var environmentScriptProvider = serviceProvider.GetRequiredService <PlatformsInstallationScriptProvider>();
                var snippet = environmentScriptProvider.GetBashScriptSnippet(context, detectedPlatforms);

                var scriptBuilder = new StringBuilder()
                                    .AppendLine($"#!{FilePaths.Bash}")
                                    .AppendLine("set -e")
                                    .AppendLine();

                if (!string.IsNullOrEmpty(snippet))
                {
                    scriptBuilder
                    .AppendLine("echo")
                    .AppendLine("echo Setting up environment...")
                    .AppendLine("echo")
                    .AppendLine(snippet)
                    .AppendLine("echo")
                    .AppendLine("echo Done setting up environment.")
                    .AppendLine("echo");
                }

                // Create temporary file to store script
                // Get the path where the generated script should be written into.
                var tempDirectoryProvider = serviceProvider.GetRequiredService <ITempDirectoryProvider>();
                var tempScriptPath        = Path.Combine(tempDirectoryProvider.GetTempDirectory(), "setupEnvironment.sh");
                var script = scriptBuilder.ToString();
                File.WriteAllText(tempScriptPath, script);
                timedEvent.AddProperty(nameof(tempScriptPath), tempScriptPath);

                if (DebugMode)
                {
                    console.WriteLine($"Temporary script @ {tempScriptPath}:");
                    console.WriteLine("---");
                    console.WriteLine(scriptBuilder);
                    console.WriteLine("---");
                }

                var environment = serviceProvider.GetRequiredService <IEnvironment>();
                var shellPath   = environment.GetEnvironmentVariable("BASH") ?? FilePaths.Bash;

                exitCode = ProcessHelper.RunProcess(
                    shellPath,
                    new[] { tempScriptPath },
                    options.SourceDir,
                    (sender, args) =>
                {
                    if (args.Data != null)
                    {
                        console.WriteLine(args.Data);
                    }
                },
                    (sender, args) =>
                {
                    if (args.Data != null)
                    {
                        console.Error.WriteLine(args.Data);
                    }
                },
                    waitTimeForExit: null);
                timedEvent.AddProperty("exitCode", exitCode.ToString());
            }

            return(exitCode);
        }
Ejemplo n.º 9
0
        // To enable unit testing
        internal int Execute(
            IServiceProvider serviceProvider,
            IConsole console,
            DataReceivedEventHandler stdOutHandler,
            DataReceivedEventHandler stdErrHandler)
        {
            var logger           = serviceProvider.GetRequiredService <ILogger <BuildCommand> >();
            var buildOperationId = logger.StartOperation(
                BuildOperationName(serviceProvider.GetRequiredService <IEnvironment>()));

            var options = serviceProvider.GetRequiredService <IOptions <BuildScriptGeneratorOptions> >().Value;

            console.WriteLine("Build orchestrated by Microsoft Oryx, https://github.com/Microsoft/Oryx");
            console.WriteLine("You can report issues at https://github.com/Microsoft/Oryx/issues");
            console.WriteLine();

            var buildInfo = new DefinitionListFormatter();

            buildInfo.AddDefinition("Oryx Version", $"{Program.GetVersion()}, Commit: {Program.GetCommit()}");
            buildInfo.AddDefinition("Build Operation ID", buildOperationId);

            var sourceRepo = serviceProvider.GetRequiredService <ISourceRepoProvider>().GetSourceRepo();
            var commitId   = GetSourceRepoCommitId(
                serviceProvider.GetRequiredService <IEnvironment>(),
                sourceRepo,
                logger);

            if (!string.IsNullOrWhiteSpace(commitId))
            {
                buildInfo.AddDefinition("Repository Commit", commitId);
            }

            console.WriteLine(buildInfo.ToString());

            var environmentSettingsProvider = serviceProvider.GetRequiredService <IEnvironmentSettingsProvider>();

            if (!environmentSettingsProvider.TryGetAndLoadSettings(out var environmentSettings))
            {
                return(ProcessConstants.ExitFailure);
            }

            // Generate build script
            string scriptContent;

            using (var stopwatch = logger.LogTimedEvent("GenerateBuildScript"))
            {
                var checkerMessages = new List <ICheckerMessage>();
                var scriptGenerator = new BuildScriptGenerator(
                    serviceProvider, console, checkerMessages, buildOperationId);

                var generated = scriptGenerator.TryGenerateScript(out scriptContent);
                stopwatch.AddProperty("generateSucceeded", generated.ToString());

                if (checkerMessages.Count > 0)
                {
                    var messageFormatter = new DefinitionListFormatter();
                    checkerMessages.ForEach(msg => messageFormatter.AddDefinition(msg.Level.ToString(), msg.Content));
                    console.WriteLine(messageFormatter.ToString());
                }
                else
                {
                    logger.LogDebug("No checker messages emitted");
                }

                if (!generated)
                {
                    return(ProcessConstants.ExitFailure);
                }
            }

            // Get the path where the generated script should be written into.
            var tempDirectoryProvider = serviceProvider.GetRequiredService <ITempDirectoryProvider>();
            var buildScriptPath       = Path.Combine(tempDirectoryProvider.GetTempDirectory(), "build.sh");

            // Write build script to selected path
            File.WriteAllText(buildScriptPath, scriptContent);
            logger.LogTrace("Build script written to file");

            var buildEventProps = new Dictionary <string, string>()
            {
                { "oryxVersion", Program.GetVersion() },
                { "oryxCommitId", Program.GetCommit() },
                {
                    "oryxCommandLine",
                    string.Join(
                        ' ',
                        serviceProvider.GetRequiredService <IEnvironment>().GetCommandLineArgs())
                },
                { nameof(commitId), commitId },
                { "scriptPath", buildScriptPath },
                { "envVars", string.Join(",", GetEnvVarNames(serviceProvider.GetRequiredService <IEnvironment>())) },
            };

            var buildScriptOutput = new StringBuilder();
            var stdOutEventLogger = new TextSpanEventLogger(logger, _measurableStdOutSpans);

            DataReceivedEventHandler stdOutBaseHandler = (sender, args) =>
            {
                string line = args.Data;
                if (line == null)
                {
                    return;
                }

                console.WriteLine(line);
                buildScriptOutput.AppendLine(line);
                stdOutEventLogger.CheckString(line);
            };

            DataReceivedEventHandler stdErrBaseHandler = (sender, args) =>
            {
                string line = args.Data;
                if (line == null)
                {
                    return;
                }

                console.Error.WriteLine(args.Data);
                buildScriptOutput.AppendLine(args.Data);
            };

            // Try make the pre-build & post-build scripts executable
            ProcessHelper.TrySetExecutableMode(environmentSettings.PreBuildScriptPath);
            ProcessHelper.TrySetExecutableMode(environmentSettings.PostBuildScriptPath);

            // Run the generated script
            int exitCode;

            using (var timedEvent = logger.LogTimedEvent("RunBuildScript", buildEventProps))
            {
                exitCode = serviceProvider.GetRequiredService <IScriptExecutor>().ExecuteScript(
                    buildScriptPath,
                    new[]
                {
                    sourceRepo.RootPath,
                    options.DestinationDir ?? string.Empty,
                    options.IntermediateDir ?? string.Empty
                },
                    workingDirectory: sourceRepo.RootPath,
                    stdOutHandler == null ? stdOutBaseHandler : stdOutBaseHandler + stdOutHandler,
                    stdErrHandler == null ? stdErrBaseHandler : stdErrBaseHandler + stdErrHandler);

                timedEvent.AddProperty("exitCode", exitCode.ToString());
            }

            logger.LogDebug("Build script content:\n" + scriptContent);
            logger.LogLongMessage(LogLevel.Debug, "Build script output", buildScriptOutput.ToString());

            if (exitCode != ProcessConstants.ExitSuccess)
            {
                logger.LogError("Build script exited with {exitCode}", exitCode);
                return(exitCode);
            }

            return(ProcessConstants.ExitSuccess);
        }
Ejemplo n.º 10
0
        internal override int Execute(IServiceProvider serviceProvider, IConsole console)
        {
            var logger    = serviceProvider.GetRequiredService <ILogger <ExecCommand> >();
            var env       = serviceProvider.GetRequiredService <IEnvironment>();
            var generator = serviceProvider.GetRequiredService <IBuildScriptGenerator>();
            var opts      = serviceProvider.GetRequiredService <IOptions <BuildScriptGeneratorOptions> >().Value;

            if (string.IsNullOrWhiteSpace(Command))
            {
                logger.LogDebug("Command is empty; exiting");
                return(ProcessConstants.ExitSuccess);
            }

            var shellPath = env.GetEnvironmentVariable("BASH") ?? FilePaths.Bash;
            var ctx       = BuildScriptGenerator.CreateContext(serviceProvider, operationId: null);

            ctx.DisableMultiPlatformBuild = false;
            var tools = generator.GetRequiredToolVersions(ctx);

            int exitCode;

            using (var timedEvent = logger.LogTimedEvent("ExecCommand"))
            {
                // Build envelope script
                var scriptBuilder = new ShellScriptBuilder("\n")
                                    .AddShebang(shellPath)
                                    .AddCommand("set -e");

                if (tools.Count > 0)
                {
                    scriptBuilder.Source($"{FilePaths.Benv} {StringExtensions.JoinKeyValuePairs(tools)}");
                }

                var script = scriptBuilder.AddCommand(Command).ToString();

                // Create temporary file to store script
                var tempScriptPath = Path.GetTempFileName();
                File.WriteAllText(tempScriptPath, script);
                timedEvent.AddProperty(nameof(tempScriptPath), tempScriptPath);

                if (DebugMode)
                {
                    console.WriteLine($"Temporary script @ {tempScriptPath}:");
                    console.WriteLine("---");
                    console.WriteLine(script);
                    console.WriteLine("---");
                }

                exitCode = ProcessHelper.RunProcess(
                    shellPath,
                    new[] { tempScriptPath },
                    opts.SourceDir,
                    (sender, args) => { if (args.Data != null)
                                        {
                                            console.WriteLine(args.Data);
                                        }
                    },
                    (sender, args) => { if (args.Data != null)
                                        {
                                            console.Error.WriteLine(args.Data);
                                        }
                    },
                    waitTimeForExit: null);
                timedEvent.AddProperty("exitCode", exitCode.ToString());
            }

            return(exitCode);
        }