200 lines
7.2 KiB
C#
200 lines
7.2 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Diagnostics;
|
|
using System.IO;
|
|
using System.Net;
|
|
using System.Net.NetworkInformation;
|
|
using ln.application;
|
|
using ln.build.commands;
|
|
using ln.build.pipeline;
|
|
using ln.build.repositories;
|
|
using ln.build.secrets;
|
|
using ln.build.semver;
|
|
using ln.http;
|
|
using ln.http.router;
|
|
using ln.json;
|
|
using ln.logging;
|
|
using ln.templates.html;
|
|
using ln.templates.http;
|
|
using ln.threading;
|
|
using ln.type;
|
|
using Microsoft.VisualBasic;
|
|
|
|
namespace ln.build
|
|
{
|
|
public class CIService
|
|
{
|
|
[StaticArgument( LongOption = "context-directory")]
|
|
public string ContextDirectory { get; set; } = AppContext.BaseDirectory;
|
|
|
|
[StaticArgument( Option = 'b', LongOption = "base-directory")]
|
|
public string BaseDirectory { get; set; }
|
|
|
|
[StaticArgument( Option = 'u', LongOption = "base-url")]
|
|
public string BaseURL { get; set; }
|
|
|
|
[StaticArgument( Option = 'h', LongOption = "hostname")]
|
|
public string HostName { get; set; }
|
|
|
|
public Pool buildPool;
|
|
public string ReportsDirectory { get; set; }
|
|
|
|
Logger webLogger;
|
|
SimpleRouter httpRouter;
|
|
SimpleRouter hookRouter;
|
|
StaticRouter staticsRouter;
|
|
TemplateRouter templateRouter;
|
|
HTTPServer httpServer;
|
|
|
|
public StageCommandContainer StageCommands { get; } = new StageCommandContainer(null,null);
|
|
|
|
public CIService()
|
|
{
|
|
buildPool = new Pool(2);
|
|
}
|
|
public CIService(string baseDirectory) : this()
|
|
{
|
|
BaseDirectory = baseDirectory;
|
|
ReportsDirectory = Path.Combine(baseDirectory, "builds" );
|
|
}
|
|
|
|
public void Initialize()
|
|
{
|
|
BaseDirectory ??= ContextDirectory;
|
|
|
|
ReportsDirectory ??= Path.Combine(BaseDirectory, "builds" );
|
|
ReportsDirectory = Path.GetFullPath(ReportsDirectory);
|
|
|
|
Logging.Log(LogLevel.INFO, "Commandline: {0}", Environment.CommandLine);
|
|
Logging.Log(LogLevel.INFO, "Working Directory: {0}", Environment.CurrentDirectory);
|
|
Logging.Log(LogLevel.INFO, "Base Directory: {0}", BaseDirectory);
|
|
Logging.Log(LogLevel.INFO, "Reports Directory: {0}", ReportsDirectory);
|
|
|
|
Directory.CreateDirectory(ReportsDirectory);
|
|
Directory.CreateDirectory(Path.Combine(BaseDirectory, "secrets"));
|
|
|
|
InitializeStageCommands();
|
|
|
|
InitializeHttpServer();
|
|
}
|
|
|
|
private void InitializeHttpServer()
|
|
{
|
|
if (HostName == null)
|
|
HostName = FindHostName();
|
|
|
|
if (BaseURL == null)
|
|
BaseURL = string.Format("http://{0}:{1}", HostName, 1888);
|
|
|
|
Logging.Log(LogLevel.DEBUG, "Hostname: {0}", HostName);
|
|
Logging.Log(LogLevel.DEBUG, "BaseURL: {0}", BaseURL);
|
|
|
|
httpRouter = new SimpleRouter();
|
|
httpRouter.AddSimpleRoute("/builds/*", new StaticRouter(ReportsDirectory));
|
|
|
|
hookRouter = new SimpleRouter();
|
|
staticsRouter = new StaticRouter(Path.Combine(ContextDirectory, "html", "static"));
|
|
templateRouter = new TemplateRouter(new FileSystemTemplateSource(Path.Combine(ContextDirectory, "html", "documents"), false));
|
|
templateRouter.DefaultTemplatePath = "index.html";
|
|
templateRouter.OnPrepareRenderContext += (templateRouter, templateDocument, renderContext) => {
|
|
renderContext.SetScriptObject("CIService", this);
|
|
};
|
|
|
|
httpRouter.AddSimpleRoute("/hooks/*", hookRouter);
|
|
httpRouter.AddSimpleRoute("/builds/:buildid/*", templateRouter);
|
|
httpRouter.AddSimpleRoute("/builds/:buildid", templateRouter);
|
|
httpRouter.AddSimpleRoute("/*", staticsRouter);
|
|
|
|
webLogger = new Logger(Logger.ConsoleLogger);
|
|
webLogger.Backends.Add(new FileLogger("ln.build.http.log"));
|
|
|
|
httpServer = new HTTPServer(new LoggingRouter(httpRouter, webLogger));
|
|
|
|
foreach (IPAddress _ip in Dns.GetHostAddresses(HostName))
|
|
{
|
|
IPv6 ip6 = _ip;
|
|
httpServer.AddEndpoint(new Endpoint(ip6, 1888));
|
|
}
|
|
}
|
|
|
|
public void InitializeStageCommands()
|
|
{
|
|
StageCommands.AddCommand(CoreCommands.ShellCommand, "sh");
|
|
|
|
StageCommands.AddCommand(DotNetCommand.Prepare, "dotnet", "prepare" );
|
|
StageCommands.AddCommand(DotNetCommand.Build, "dotnet", "build" );
|
|
StageCommands.AddCommand(DotNetCommand.Test, "dotnet", "test" );
|
|
StageCommands.AddCommand(DotNetCommand.Pack, "dotnet", "pack" );
|
|
StageCommands.AddCommand(DotNetCommand.Push, "dotnet", "push" );
|
|
StageCommands.AddCommand(DotNetCommand.Publish, "dotnet", "publish" );
|
|
|
|
StageCommands.AddCommand(DeployCommand.Deploy, "deploy" );
|
|
StageCommands.AddCommand(DeployCommand.Release, "release" );
|
|
}
|
|
|
|
public string GetJobURL(CIJob job) => string.Format("{0}/builds/{1}", BaseURL, job.JobID);
|
|
|
|
public void Start()
|
|
{
|
|
buildPool.Start();
|
|
httpServer.Start();
|
|
}
|
|
|
|
public void AddWebHookHandler(string name, Func<CIService,HttpRequest,HttpResponse> webHookHandler)
|
|
{
|
|
hookRouter.AddSimpleRoute(String.Format("/{0}", name), (HttpRoutingContext context,HttpRequest request) => webHookHandler(this, request));
|
|
}
|
|
|
|
public SecretStorage GetSecretStorage(string secretName) => new SecretStorage(Path.Combine(BaseDirectory,"secrets", String.Format("{0}.json", secretName)));
|
|
|
|
|
|
public void Enqueue(CIJob job)
|
|
{
|
|
buildPool.Enqueue(job);
|
|
}
|
|
|
|
public void CreateReport(CIJob job)
|
|
{
|
|
JSONObject report = new JSONObject();
|
|
JSONArray steps = new JSONArray();
|
|
report["steps"] = steps;
|
|
report["state"] = new JSONString(job.BuildState.ToString());
|
|
|
|
string reportDirectory = Path.Combine(ReportsDirectory, job.JobID);
|
|
Directory.CreateDirectory(reportDirectory);
|
|
|
|
foreach (string logName in job.GetLogStreamNames())
|
|
{
|
|
string logFileName = Path.Combine(reportDirectory, logName);
|
|
using (FileStream fileStream = new FileStream(logFileName, FileMode.CreateNew))
|
|
{
|
|
job.GetLogStream(logName).Position = 0;
|
|
job.GetLogStream(logName).CopyTo(fileStream);
|
|
fileStream.Flush();
|
|
fileStream.Close();
|
|
}
|
|
|
|
steps.Add(new JSONString(logName));
|
|
}
|
|
|
|
using (StreamWriter writer = new StreamWriter(Path.Combine(reportDirectory, "build.json")))
|
|
writer.Write(report.ToString());
|
|
}
|
|
|
|
|
|
public string FindHostName()
|
|
{
|
|
return Dns.GetHostEntry("LocalHost").HostName;
|
|
/*
|
|
string hostName = IPGlobalProperties.GetIPGlobalProperties().HostName;
|
|
string domainName = IPGlobalProperties.GetIPGlobalProperties().DomainName;
|
|
|
|
if (!hostName.EndsWith(domainName))
|
|
{
|
|
hostName = string.Format("{0}.{1}", hostName, domainName);
|
|
}
|
|
return hostName;
|
|
*/ }
|
|
|
|
}
|
|
} |