using System; using System.Collections.Generic; using System.IO; using System.Net.Http; using System.Text; using ln.build.commands; using ln.build.pipeline; using ln.build.repositories; using ln.json; using ln.logging; using ln.threading; namespace ln.build { public class CIJob : PoolJob { public string JobID { get; } = Guid.NewGuid().ToString("N"); public string RepositoryURL { get; } public string WorkingDirectory { get; set; } public CIService CIService { get; } public Logger Logger { get; private set; } public CommandEnvironment Environment { get; } public RepositoryInterface RepositoryInterface { get; set; } public DefaultPipeLine PipeLine { get; set; } public BuildState BuildState { get; private set; } Dictionary logStreams = new Dictionary(); Dictionary logStreamLoggers = new Dictionary(); public CIJob(CIService ciService, string repositoryURL) :this(ciService, null, repositoryURL){ } public CIJob(CIService ciService, RepositoryInterface repositoryInterface ,string repositoryURL) { CIService = ciService; RepositoryInterface = repositoryInterface; WorkingDirectory = Path.Combine(Path.GetTempPath(), JobID); Directory.CreateDirectory(Path.Combine(ciService.ReportsDirectory, JobID)); Logger = new Logger(new FileLogger(Path.Combine(ciService.ReportsDirectory, JobID, "build.log"))); Logger.Backends.Add(Logger.ConsoleLogger); RepositoryURL = repositoryURL; Environment = new CommandEnvironment(); } public Stream GetLogStream(string name) { if (!logStreams.TryGetValue(name,out MemoryStream logStream)) { logStream = new MemoryStream(); logStreams.Add(name, logStream); } return logStream; } public Logger GetLogger(string name) { if (!logStreamLoggers.TryGetValue(name, out Logger logStreamLogger)) { logStreamLogger = new Logger(GetLogStream(name)); logStreamLogger.Backends.Add(Logger.ConsoleLogger); logStreamLoggers.Add(name, logStreamLogger); } return logStreamLogger; } public string GetLoggedContent(string name) { logStreams[name].Position = 0; using StreamReader sr = new StreamReader(logStreams[name]); return sr.ReadToEnd(); } public IEnumerable GetLogStreamNames() => logStreams.Keys; public string GetVariable(string varName) => Environment.Get(varName); public string GetVariable(string varName,string defValue) => Environment.Get(varName, defValue); public bool ContainsVariable(string varName) => Environment.Contains(varName); public CIJob SetVariable(string varName,string varValue){ Environment.Set(varName,varValue); return this; } public void UpdateBuildState(BuildState buildState) { BuildState = buildState; RepositoryInterface?.UpdateBuildState(this); } public override void RunJob() { if (CloneRepository()) { try { LoadPipeLine(); PipeLine.Run(); UpdateBuildState(BuildState.SUCCESS); } catch (Exception e) { Logger.Log(e); UpdateBuildState(BuildState.FAILURE); } } else { Logger.Log(LogLevel.ERROR, "CIJob failed at CloneRepository()"); } Notify(); Cleanup(); } public bool CloneRepository() { RepositoryInterface?.CloneSources(this); return true; } public void LoadPipeLine() { JSONObject jsonPipeLine = JSONParser.ParseFile(Path.Combine(WorkingDirectory, "build.ln")) as JSONObject; if (jsonPipeLine != null) { DefaultPipeLine pipeLine = new DefaultPipeLine(CIService, Environment); pipeLine.LoadJson(jsonPipeLine); PipeLine = pipeLine; } } public void Notify() { // foreach (string key in logStreams.Keys) // { // logStreams[key].Position = 0; // string logContent; // using (StreamReader sr = new StreamReader(logStreams[key])) // logContent = sr.ReadToEnd(); // Logger.Log(LogLevel.INFO, "------------------- LogStream {0} ---------------------------\n{1}", key, logContent); // } } public void Cleanup() { CIService.CreateReport(this); if (RepositoryInterface != null) Directory.Delete(WorkingDirectory, true); } } }