ln.build/ln.build/CIJob.cs

178 lines
6.4 KiB
C#

using System;
using System.Collections.Generic;
using System.IO;
using System.Net.Http;
using System.Text;
using ln.build.commands;
using ln.build.repositories;
using ln.json;
using ln.logging;
using ln.threading;
namespace ln.build
{
public class CIJob : PoolJob
{
static HttpClient httpClient = new HttpClient();
public string JobID { get; } = Guid.NewGuid().ToString("N");
public string RepositoryURL { get; }
public string WorkingDirectory { get; set; }
public CIService CurrentCIService { get; set; }
public Logger Logger { get; private set; }
public CommandEnvironment Environment { get; }
public RepositoryInterface RepositoryInterface { get; set; }
List<PipeLine> pipeLines = new List<PipeLine>();
public BuildState BuildState { get; private set; }
Dictionary<string,MemoryStream> logStreams = new Dictionary<string, MemoryStream>();
Dictionary<string,Logger> logStreamLoggers = new Dictionary<string, Logger>();
public CIJob(string repositoryURL)
{
WorkingDirectory = Path.Combine(Path.GetTempPath(), JobID);
Logger = new Logger(new FileLogger(Path.Combine(Path.GetTempPath(), String.Format("{0}.log", JobID))));
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<string> 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 async void UpdateBuildState(BuildState buildState)
{
BuildState = buildState;
string buildStateURL = String.Format("https://git.l--n.de/api/v1/repos/{0}/{1}/statuses/{2}",
GetVariable("REPO_OWNER"),
GetVariable("REPO_NAME"),
GetVariable("COMMIT_ID")
);
if (buildStateURL != null)
{
JSONObject stateObject = new JSONObject();
stateObject.Add("context", "ln.build");
stateObject.Add("description", "build job pending");
stateObject.Add("state", buildState.ToString().ToLower());
stateObject.Add("target_url", JSONNull.Instance);
HttpResponseMessage response = httpClient.PostAsync(buildStateURL, new StringContent(stateObject.ToString(),Encoding.UTF8,"application/json")).Result;
Logger.Log(LogLevel.DEBUG, "UpdateBuildState({0}): {1}", buildState, buildStateURL);
Logger.Log(LogLevel.DEBUG, "Response: {0}", response );
}
}
public override void RunJob()
{
if (CloneRepository())
{
if (DetectPipelines())
{
UpdateBuildState(BuildState.PENDING);
try{
foreach (PipeLine pipeLine in pipeLines)
{
pipeLine.Run(this);
}
UpdateBuildState(BuildState.SUCCESS);
} catch (Exception e)
{
UpdateBuildState(BuildState.FAILURE);
}
}
} else {
Logger.Log(LogLevel.ERROR, "CIJob failed at CloneRepository()");
}
Notify();
Cleanup();
}
public bool CloneRepository()
{
Logging.Log("cloning repository to {0}", WorkingDirectory);
return
(new CommandRunner(Logger, "git", "clone", RepositoryURL, WorkingDirectory).Run(Environment) == 0) &&
(!ContainsVariable("COMMIT_ID") || new CommandRunner(Logger, "git", "checkout", GetVariable("COMMIT_ID")){ WorkingDirectory = this.WorkingDirectory, }.Run(Environment) == 0);
}
public bool DetectPipelines()
{
if (CurrentCIService != null)
{
foreach (PipeLine pipeLine in CurrentCIService.PipeLines)
{
if (pipeLine.DetectValidity(this))
pipeLines.Add(pipeLine);
}
}
return pipeLines.Count > 0;
}
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()
{
CurrentCIService.CreateReport(this);
Directory.Delete(WorkingDirectory, true);
}
static CIJob()
{
httpClient.DefaultRequestHeaders.Add("Authorization","token 1d03e9577c404b5b4f46b340147b1d500ff95b2e");
}
}
}