using System; using System.Collections.Generic; using System.IO; using ln.build.commands; using ln.build.pipeline; using ln.build.repositories; using ln.build.secrets; using ln.build.semver; using ln.json; using ln.logging; using ln.threading; namespace ln.build { public delegate void CIJobCompleted(CIJob cIJob); public class CIJob : PoolJob { public event CIJobCompleted OnJobCompleted; public string JobID { get; } = Guid.NewGuid().ToString("N"); public CIService CIService { get; } public Repository Repository { get; set; } public SecretStorage SecretStorage { get; set; } public string WorkingDirectory { get; set; } public Logger Logger { get; private set; } public CommandEnvironment Environment { get; } public DefaultPipeLine PipeLine { get; set; } public BuildState BuildState { get; private set; } Dictionary logStreams = new Dictionary(); Dictionary logStreamLoggers = new Dictionary(); public CIJob(CIService ciService, Repository repository, SecretStorage secretStorage) :this(ciService, repository) { SecretStorage = secretStorage; Environment.SecretStorage = secretStorage; } public CIJob(CIService ciService, Repository repository) { CIService = ciService; Repository = repository; 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); Environment = new CommandEnvironment(){ CIJob = this, WorkingDirectory = WorkingDirectory }; } 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; Repository?.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()"); } OnJobCompleted?.Invoke(this); Notify(); Cleanup(); } public bool CloneRepository() { Repository?.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 (Repository != null) Directory.Delete(WorkingDirectory, true); } public void PublishRelease(SemVerLevels releaseLevel) { if (BuildState == BuildState.SUCCESS) { if (PipeLine.Versioning != null) { Versioning versioning = PipeLine.Versioning; SemVersion version = versioning.GetCurrentVersion(this); if (version.IsPreRelease) { SemVersion releaseVersion = new SemVersion(version); releaseVersion.PreRelease = null; versioning.SetVersion(this, releaseVersion); } else if (version.IsRelease) { } } } } } }