Several Fixes and improvements.
ln.build build job pending
ln.build build job pending
parent
9885e21d60
commit
8455a2dad4
|
@ -13,8 +13,7 @@ namespace ln.build.server
|
|||
class Program
|
||||
{
|
||||
|
||||
static Pool pool = new Pool(2);
|
||||
|
||||
static CIService CIService;
|
||||
static HttpResponse WebHookRequest(HttpRoutingContext context, HttpRequest request)
|
||||
{
|
||||
HttpResponse response = new HttpResponse(request);
|
||||
|
@ -32,28 +31,24 @@ namespace ln.build.server
|
|||
{
|
||||
try
|
||||
{
|
||||
string repoName = message["repository"]["name"].ToNative().ToString();
|
||||
string cloneUrl = message["repository"]["clone_url"].ToNative().ToString();
|
||||
string notifyEmail = message["pusher"]["email"].ToNative().ToString();
|
||||
|
||||
foreach (JSONValue commit in (message["commits"] as JSONArray).Children)
|
||||
{
|
||||
string commitID = commit["id"].ToNative().ToString();
|
||||
Logging.Log("Received CI request of repository {0} for commit {1}", cloneUrl, commitID);
|
||||
|
||||
Logging.Log("Received CI request for repository {2} [{0}] for the commit {1}", cloneUrl, commitID, repoName);
|
||||
|
||||
CIJob job = new CIJob(repoName, cloneUrl, commitID, notifyEmail);
|
||||
|
||||
job.SetVariable("REPO_OWNER", message["repository"]["owner"]["username"].ToNative().ToString());
|
||||
job.SetVariable("REPO_NAME", message["repository"]["name"].ToNative().ToString());
|
||||
job.SetVariable("COMMIT_ID", commitID);
|
||||
CIJob job = new CIJob(cloneUrl)
|
||||
.SetVariable("REPO_OWNER", message["repository"]["owner"]["username"].ToNative().ToString())
|
||||
.SetVariable("REPO_NAME", message["repository"]["name"].ToNative().ToString())
|
||||
.SetVariable("COMMIT_ID", commitID)
|
||||
.SetVariable("NOTIFY", message["pusher"]["email"].ToNative().ToString());
|
||||
|
||||
job.UpdateBuildState(BuildState.PENDING);
|
||||
|
||||
pool.Enqueue(job);
|
||||
CIService.Enqueue(job);
|
||||
}
|
||||
|
||||
|
||||
} catch (Exception e)
|
||||
{
|
||||
response.StatusCode = 500;
|
||||
|
@ -74,15 +69,17 @@ namespace ln.build.server
|
|||
|
||||
static void Main(string[] args)
|
||||
{
|
||||
CommandRunner.DefaultThrow = CRThrow.NEGATIVE;
|
||||
CIService = new CIService();
|
||||
CIService.Start();
|
||||
|
||||
CIService.AddPipeline(new DotNetPipeLine());
|
||||
|
||||
|
||||
SimpleRouter genericRouter = new SimpleRouter();
|
||||
genericRouter.AddSimpleRoute("/", WebHookRequest);
|
||||
|
||||
HTTPServer httpServer = new HTTPServer(new Endpoint(IPv6.ANY, 1888), new LoggingRouter(genericRouter));
|
||||
|
||||
pool.Start();
|
||||
|
||||
Logging.Log("Starting http listener...");
|
||||
httpServer.Start();
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<Version>0.1.0-test</Version>
|
||||
<Version>0.1.0-test1</Version>
|
||||
<Authors>Harald Wolff-Thobaben</Authors>
|
||||
<Company>l--n.de</Company>
|
||||
<Description>A simple build server scheduling builds triggered via web-hooks</Description>
|
||||
|
|
|
@ -4,6 +4,7 @@ using System.IO;
|
|||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Reflection;
|
||||
using System.Reflection.Metadata.Ecma335;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Text;
|
||||
using ln.json;
|
||||
|
@ -16,15 +17,12 @@ namespace ln.build
|
|||
{
|
||||
static HttpClient httpClient = new HttpClient();
|
||||
|
||||
|
||||
public string JobID { get; } = Guid.NewGuid().ToString("N");
|
||||
|
||||
public string RepositoryURL { get; }
|
||||
public string RepositoryName { get; }
|
||||
public string Commit { get; }
|
||||
public string NotifyEMail { get; set; }
|
||||
|
||||
public string WorkingDirectory { get; set; }
|
||||
public CIService CurrentCIService { get; set; }
|
||||
|
||||
public Logger Logger { get; private set; }
|
||||
|
||||
|
@ -34,16 +32,13 @@ namespace ln.build
|
|||
Dictionary<string,MemoryStream> logStreams = new Dictionary<string, MemoryStream>();
|
||||
Dictionary<string,Logger> logStreamLoggers = new Dictionary<string, Logger>();
|
||||
|
||||
public CIJob(string repositoryName, string repositoryURL, string commit, string notifyEMail)
|
||||
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);
|
||||
|
||||
RepositoryName = repositoryName;
|
||||
RepositoryURL = repositoryURL;
|
||||
Commit = commit;
|
||||
NotifyEMail = notifyEMail;
|
||||
}
|
||||
|
||||
public Stream GetLogStream(string name)
|
||||
|
@ -73,12 +68,14 @@ namespace ln.build
|
|||
value = defValue;
|
||||
return value;
|
||||
}
|
||||
public void SetVariable(string varName,string value)
|
||||
public CIJob SetVariable(string varName,string value)
|
||||
{
|
||||
if (value != null)
|
||||
variables[varName] = value;
|
||||
else
|
||||
variables.Remove(varName);
|
||||
|
||||
return this;
|
||||
}
|
||||
public void ExtendVariable(string varName,string value) => ExtendVariable(varName, value, ':');
|
||||
public void ExtendVariable(string varName, string value, char seperator)
|
||||
|
@ -93,6 +90,16 @@ namespace ln.build
|
|||
SetVariable(varName, currentValue);
|
||||
}
|
||||
|
||||
public bool ContainsVariable(string varName) => variables.ContainsKey(varName);
|
||||
public bool ContainsVariable(params string[] varNames)
|
||||
{
|
||||
foreach (string varName in varNames)
|
||||
{
|
||||
if (!variables.ContainsKey(varName))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public async void UpdateBuildState(BuildState buildState)
|
||||
{
|
||||
|
@ -110,7 +117,7 @@ namespace ln.build
|
|||
stateObject.Add("state", buildState.ToString().ToLower());
|
||||
stateObject.Add("target_url", JSONNull.Instance);
|
||||
|
||||
HttpResponseMessage response = await httpClient.PostAsync(buildStateURL, new StringContent(stateObject.ToString(),Encoding.UTF8,"application/json"));
|
||||
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 );
|
||||
|
||||
|
@ -122,39 +129,50 @@ namespace ln.build
|
|||
|
||||
public override void RunJob()
|
||||
{
|
||||
CloneRepository();
|
||||
DetectPipelines();
|
||||
|
||||
try{
|
||||
foreach (PipeLine pipeLine in pipeLines)
|
||||
{
|
||||
pipeLine.Run(this);
|
||||
}
|
||||
UpdateBuildState(BuildState.SUCCESS);
|
||||
} catch (Exception e)
|
||||
if (CloneRepository())
|
||||
{
|
||||
UpdateBuildState(BuildState.FAILURE);
|
||||
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();
|
||||
}
|
||||
|
||||
void DetectPipelines()
|
||||
{
|
||||
string[] sln = Directory.GetFileSystemEntries(WorkingDirectory,"*.sln");
|
||||
if (sln.Length > 0)
|
||||
{
|
||||
pipeLines.Add(new DotNetPipeLine());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void CloneRepository()
|
||||
public bool CloneRepository()
|
||||
{
|
||||
Logging.Log("cloning repository to {0}", WorkingDirectory);
|
||||
new CommandRunner(Logger, "git", "clone",RepositoryURL,WorkingDirectory).Run();
|
||||
new CommandRunner(Logger, "git", "checkout", Commit).Run();
|
||||
return
|
||||
(new CommandRunner(Logger, "git", "clone", RepositoryURL, WorkingDirectory).Run() == 0) &&
|
||||
(!ContainsVariable("COMMIT_ID") || new CommandRunner(Logger, "git", "checkout", GetVariable("COMMIT_ID")){ WorkingDirectory = this.WorkingDirectory, }.Run() == 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()
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
using System.Collections.Generic;
|
||||
using ln.threading;
|
||||
|
||||
namespace ln.build
|
||||
{
|
||||
public class CIService
|
||||
{
|
||||
|
||||
public Pool buildPool;
|
||||
|
||||
HashSet<PipeLine> pipelines = new HashSet<PipeLine>();
|
||||
public IEnumerable<PipeLine> PipeLines => pipelines;
|
||||
|
||||
public CIService()
|
||||
{
|
||||
buildPool = new Pool(2);
|
||||
}
|
||||
|
||||
public void Start()
|
||||
{
|
||||
buildPool.Start();
|
||||
}
|
||||
|
||||
public void AddPipeline(PipeLine pipeLine)
|
||||
{
|
||||
pipelines.Add(pipeLine);
|
||||
}
|
||||
|
||||
public void Enqueue(CIJob job)
|
||||
{
|
||||
job.CurrentCIService = this;
|
||||
buildPool.Enqueue(job);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
|
@ -6,7 +6,6 @@ using ln.logging;
|
|||
namespace ln.build
|
||||
{
|
||||
public enum CRThrow { NEVER, NEGATIVE, NONZERO }
|
||||
|
||||
public class CommandRunner
|
||||
{
|
||||
public static CRThrow DefaultThrow { get; set; } = CRThrow.NONZERO;
|
||||
|
@ -18,12 +17,17 @@ namespace ln.build
|
|||
|
||||
public Logger Logger { get; }
|
||||
|
||||
Func<int,bool> TestExitCode = null;
|
||||
|
||||
public CommandRunner(string executable,params string[] arguments) : this(Logger.Default, executable, arguments){}
|
||||
public CommandRunner(Logger logger, string executable,params string[] arguments)
|
||||
public CommandRunner(Logger logger, string executable,params string[] arguments) : this(logger, null, executable, arguments){}
|
||||
public CommandRunner(Logger logger, Func<int,bool> testExitCode, string executable,params string[] arguments)
|
||||
{
|
||||
Logger = logger;
|
||||
Executable = executable;
|
||||
Arguments = arguments;
|
||||
|
||||
TestExitCode = testExitCode;
|
||||
}
|
||||
|
||||
public string FindFileInPath(string filename)
|
||||
|
@ -68,6 +72,7 @@ namespace ln.build
|
|||
logger.Log(LogLevel.INFO, "Result: {0}", process.ExitCode);
|
||||
|
||||
if (
|
||||
((TestExitCode != null) && !TestExitCode(process.ExitCode)) ||
|
||||
((Throw == CRThrow.NEGATIVE) && (process.ExitCode < 0)) ||
|
||||
((Throw == CRThrow.NONZERO) && (process.ExitCode != 0))
|
||||
)
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using System.Reflection.Metadata.Ecma335;
|
||||
using System.Runtime.InteropServices.WindowsRuntime;
|
||||
using System.Runtime.Serialization.Formatters;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
|
@ -33,7 +34,19 @@ namespace ln.build
|
|||
|
||||
AddStep(new PublishStep());
|
||||
}
|
||||
|
||||
|
||||
public override bool DetectValidity(CIJob job)
|
||||
{
|
||||
string[] sln = Directory.GetFileSystemEntries(job.WorkingDirectory,"*.sln");
|
||||
if (sln.Length > 0)
|
||||
return true;
|
||||
sln = Directory.GetFileSystemEntries(job.WorkingDirectory,"*.csproj");
|
||||
if (sln.Length > 0)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void FilterPackageFilenames(CommandStep commandStep, CIJob job, int exitCode)
|
||||
{
|
||||
Stream outStream = job.GetLogStream(commandStep.DefaultLogFileName);
|
||||
|
|
|
@ -8,7 +8,7 @@ using ln.logging;
|
|||
namespace ln.build
|
||||
{
|
||||
|
||||
public class PipeLine
|
||||
public abstract class PipeLine
|
||||
{
|
||||
|
||||
List<Step> steps = new List<Step>();
|
||||
|
@ -17,6 +17,9 @@ namespace ln.build
|
|||
{
|
||||
}
|
||||
|
||||
public abstract bool DetectValidity(CIJob job);
|
||||
|
||||
|
||||
public void AddStep(Step step) => steps.Add(step);
|
||||
|
||||
public virtual void Run(CIJob job)
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<Version>0.1.0</Version>
|
||||
<Version>0.1.0-test1</Version>
|
||||
<Authors>Harald Wolff-Thobaben</Authors>
|
||||
<Company>l--n.de</Company>
|
||||
<Description>A simple build server scheduling builds triggered via web-hooks</Description>
|
||||
|
|
Loading…
Reference in New Issue