184 lines
5.8 KiB
C#
184 lines
5.8 KiB
C#
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using ln.build.commands;
|
|
using ln.json;
|
|
using ln.logging;
|
|
|
|
namespace ln.build.pipeline
|
|
{
|
|
|
|
public class DefaultPipeLine
|
|
{
|
|
public CommandEnvironment CommandEnvironment { get; }
|
|
public CIService CIService { get; }
|
|
|
|
List<Stage> stages = new List<Stage>();
|
|
public IEnumerable<Stage> Stages => stages;
|
|
|
|
public DefaultPipeLine(CIService ciService)
|
|
{
|
|
CIService = ciService;
|
|
CommandEnvironment = new CommandEnvironment();
|
|
}
|
|
public DefaultPipeLine(CIService ciService, CommandEnvironment commandEnvironment)
|
|
{
|
|
CIService = ciService;
|
|
CommandEnvironment = new CommandEnvironment(commandEnvironment);
|
|
}
|
|
|
|
public void LoadJson(JSONObject jsonPipeLine)
|
|
{
|
|
if (jsonPipeLine.ContainsKey("env"))
|
|
CommandEnvironment.Apply(jsonPipeLine["env"] as JSONObject);
|
|
|
|
if (jsonPipeLine.ContainsKey("stages"))
|
|
{
|
|
JSONArray jsonStages = jsonPipeLine["stages"] as JSONArray;
|
|
foreach (JSONObject jsonStage in jsonStages.Children)
|
|
{
|
|
Stage stage = new Stage(this);
|
|
stage.LoadJson(jsonStage);
|
|
|
|
stages.Add(stage);
|
|
}
|
|
}
|
|
}
|
|
|
|
public void Run()
|
|
{
|
|
foreach (Stage stage in stages)
|
|
{
|
|
CommandEnvironment.Logger.Log(LogLevel.INFO,"-------------------------------------------------------------------------------------");
|
|
CommandEnvironment.Logger.Log(LogLevel.INFO,"STAGE: {0}", stage.Name);
|
|
CommandEnvironment.Logger.Log(LogLevel.INFO,"-------------------------------------------------------------------------------------");
|
|
stage.Run();
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
|
|
public class Stage
|
|
{
|
|
public DefaultPipeLine PipeLine { get; }
|
|
public string Name { get; set; }
|
|
|
|
public CommandEnvironment CommandEnvironment { get; }
|
|
|
|
List<StageCommand> commands = new List<StageCommand>();
|
|
public IEnumerable<StageCommand> Commands => commands;
|
|
|
|
public Stage(DefaultPipeLine pipeLine)
|
|
{
|
|
PipeLine = pipeLine;
|
|
CommandEnvironment = new CommandEnvironment(pipeLine.CommandEnvironment);
|
|
}
|
|
|
|
public void LoadJson(JSONObject jsonStage)
|
|
{
|
|
Name = jsonStage["name"].ToNative().ToString();
|
|
|
|
if (jsonStage.ContainsKey("env"))
|
|
{
|
|
CommandEnvironment.Apply(jsonStage["env"] as JSONObject);
|
|
}
|
|
if (jsonStage.ContainsKey("commands"))
|
|
{
|
|
JSONArray jsonCommands = jsonStage["commands"] as JSONArray;
|
|
foreach (JSONValue jsonValue in jsonCommands.Children)
|
|
{
|
|
commands.Add(StageCommand.Create(jsonValue.ToNative().ToString()));
|
|
}
|
|
}
|
|
if (jsonStage.ContainsKey("secrets"))
|
|
{
|
|
JSONObject jsonSecrets = jsonStage["secrets"] as JSONObject;
|
|
foreach (string key in jsonSecrets.Keys)
|
|
{
|
|
CommandEnvironment.Set(key, PipeLine.CIService.GetSecret(jsonSecrets[key].ToNative().ToString()));
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
|
|
public void Run()
|
|
{
|
|
foreach (StageCommand command in commands)
|
|
command.Run(this);
|
|
}
|
|
}
|
|
|
|
public abstract class StageCommand
|
|
{
|
|
public string Name { get; }
|
|
|
|
public StageCommand(string name)
|
|
{
|
|
Name = name;
|
|
}
|
|
|
|
public abstract void Run(Stage stage);
|
|
|
|
|
|
|
|
|
|
|
|
static Dictionary<string,Func<string,StageCommand>> commandFactories = new Dictionary<string, Func<string, StageCommand>>();
|
|
|
|
public static StageCommand Create(string cmdline)
|
|
{
|
|
string[] tokens = cmdline.Split(new char[]{' ','\t'}, 2);
|
|
|
|
if (commandFactories.TryGetValue(tokens[0],out Func<string,StageCommand> factory))
|
|
{
|
|
return factory(tokens[1]);
|
|
}
|
|
throw new Exception(string.Format("can't find factory for command keyword '{0}'", tokens[0]));
|
|
}
|
|
|
|
static StageCommand()
|
|
{
|
|
commandFactories.Add("SH", (args) => new ShellCommand(args));
|
|
commandFactories.Add("DOTNET", (args) => new DotNetCommand(args));
|
|
commandFactories.Add("GITEA", (args) => new DotNetCommand(args));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
public class ShellCommand : StageCommand
|
|
{
|
|
public event CommandExitedDelegate OnCommandExited;
|
|
|
|
public CommandRunner CommandRunner { get; }
|
|
|
|
public ShellCommand(string filename,params CommandRunner.Argument[] arguments)
|
|
:base("SH")
|
|
{
|
|
CommandRunner = new CommandRunner("/bin/bash", "-c"){ Throw = CRThrow.NEVER, };
|
|
CommandRunner.AddArguments(arguments);
|
|
}
|
|
public ShellCommand(string cmdline)
|
|
:base("SH")
|
|
{
|
|
CommandRunner = new CommandRunner("/bin/bash", "-c", string.Format("\"{0}\"",cmdline)){ Throw = CRThrow.NEVER, };
|
|
}
|
|
|
|
public override void Run(Stage stage)
|
|
{
|
|
MemoryStream logStream = new MemoryStream();
|
|
int result = CommandRunner.Run(stage.CommandEnvironment, logStream);
|
|
stage.CommandEnvironment.Logger.Log(LogLevel.INFO, "command output:\n{0}", Encoding.UTF8.GetString(logStream.ToArray()));
|
|
stage.CommandEnvironment.Logger.Log(LogLevel.INFO, "command exit code: {0}", result);
|
|
if (result != 0)
|
|
throw new Exception(String.Format("command exited with code {0} [0x{0:x}]", result));
|
|
}
|
|
}
|
|
|
|
} |