From dcef1e4c1aaacb8f6a07a6fdc4abac52afa4657b Mon Sep 17 00:00:00 2001 From: Argo Zhang Date: Fri, 4 Oct 2019 15:44:39 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E8=87=AA=E5=8A=A8=E5=8F=91=E5=B8=83?= =?UTF-8?q?=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Controllers/Api/DeployController.cs | 25 ++++ .../Controllers/HomeController.cs | 11 +- src/client/Bootstrap.Client/Startup.cs | 7 +- .../Tasks/DeployExtensions.cs | 21 ++++ .../Bootstrap.Client/Tasks/DeployOptions.cs | 28 +++++ .../Tasks/DeployTaskManager.cs | 112 ++++++++++++++++++ .../Tasks/GiteePushEventArgs.cs | 88 ++++++++++++++ .../appsettings.Development.json | 6 + src/client/Bootstrap.Client/appsettings.json | 6 + 9 files changed, 295 insertions(+), 9 deletions(-) create mode 100644 src/client/Bootstrap.Client/Controllers/Api/DeployController.cs create mode 100644 src/client/Bootstrap.Client/Tasks/DeployExtensions.cs create mode 100644 src/client/Bootstrap.Client/Tasks/DeployOptions.cs create mode 100644 src/client/Bootstrap.Client/Tasks/DeployTaskManager.cs create mode 100644 src/client/Bootstrap.Client/Tasks/GiteePushEventArgs.cs diff --git a/src/client/Bootstrap.Client/Controllers/Api/DeployController.cs b/src/client/Bootstrap.Client/Controllers/Api/DeployController.cs new file mode 100644 index 00000000..d12f9ab2 --- /dev/null +++ b/src/client/Bootstrap.Client/Controllers/Api/DeployController.cs @@ -0,0 +1,25 @@ +using Bootstrap.Client.Tasks; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; + +namespace Bootstrap.Client.Controllers.Api +{ + /// + /// 自动发布 WebApi 接口 + /// + [Route("api/[controller]")] + [ApiController] + [AllowAnonymous] + public class DeployController : ControllerBase + { + /// + /// 自动发布 webhook 接口 + /// + /// + [HttpPost] + public void Post([FromBody]GiteePushEventArgs args) + { + DeployTaskManager.Add(args); + } + } +} diff --git a/src/client/Bootstrap.Client/Controllers/HomeController.cs b/src/client/Bootstrap.Client/Controllers/HomeController.cs index 645df249..c837e0b8 100644 --- a/src/client/Bootstrap.Client/Controllers/HomeController.cs +++ b/src/client/Bootstrap.Client/Controllers/HomeController.cs @@ -1,4 +1,5 @@ using Bootstrap.Client.Models; +using Bootstrap.Client.Tasks; using Longbow.Configuration; using Microsoft.AspNetCore; using Microsoft.AspNetCore.Authentication.Cookies; @@ -10,28 +11,30 @@ using System; namespace Bootstrap.Client.Controllers { /// - /// + /// 前台主页控制器 /// public class HomeController : Controller { /// - /// + /// 默认视图 /// /// public IActionResult Index() { return View(new NavigatorBarModel(this)); } + /// - /// + /// About 视图 /// /// public IActionResult About() { return View(new NavigatorBarModel(this)); } + /// - /// + /// 错误视图 /// /// /// diff --git a/src/client/Bootstrap.Client/Startup.cs b/src/client/Bootstrap.Client/Startup.cs index 60cf7bdc..39e34eec 100644 --- a/src/client/Bootstrap.Client/Startup.cs +++ b/src/client/Bootstrap.Client/Startup.cs @@ -56,11 +56,8 @@ namespace Bootstrap.Client services.AddResponseCompression(); services.AddBootstrapAdminAuthentication(); services.AddAuthorization(options => options.DefaultPolicy = new AuthorizationPolicyBuilder().RequireBootstrapAdminAuthorizate().Build()); - services.AddControllersWithViews(options => - { - options.Filters.Add(); - options.Filters.Add>(); - }).AddJsonOptions(op => op.JsonSerializerOptions.AddDefaultConverters()); + services.AddControllersWithViews(options => options.Filters.Add()).AddJsonOptions(op => op.JsonSerializerOptions.AddDefaultConverters()); + services.AddAutoPublish(); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. diff --git a/src/client/Bootstrap.Client/Tasks/DeployExtensions.cs b/src/client/Bootstrap.Client/Tasks/DeployExtensions.cs new file mode 100644 index 00000000..553286c6 --- /dev/null +++ b/src/client/Bootstrap.Client/Tasks/DeployExtensions.cs @@ -0,0 +1,21 @@ +using Bootstrap.Client.Tasks; + +namespace Microsoft.Extensions.DependencyInjection +{ + /// + /// 自动发布服务扩展操作类 + /// + public static class DeployExtensions + { + /// + /// 注入自动发布到容器内 + /// + /// + /// + public static IServiceCollection AddAutoPublish(this IServiceCollection services) + { + DeployTaskManager.RegisterServices(services); + return services; + } + } +} diff --git a/src/client/Bootstrap.Client/Tasks/DeployOptions.cs b/src/client/Bootstrap.Client/Tasks/DeployOptions.cs new file mode 100644 index 00000000..9723d398 --- /dev/null +++ b/src/client/Bootstrap.Client/Tasks/DeployOptions.cs @@ -0,0 +1,28 @@ +namespace Bootstrap.Client.Tasks +{ + /// + /// 自动发布配置类 + /// + public class DeployOptions + { + /// + /// 获得/设置 是否启用自动部署功能 + /// + public bool Enabled { get; set; } + + /// + /// 获得/设置 自动部署脚本文件 + /// + public string DeployFile { get; set; } + + /// + /// 获得/设置 自动部署分支 + /// + public string Branch { get; set; } = "release"; + + /// + /// 获得/设置 自动部署平台 + /// + public string OSPlatform { get; set; } = "Windows"; + } +} diff --git a/src/client/Bootstrap.Client/Tasks/DeployTaskManager.cs b/src/client/Bootstrap.Client/Tasks/DeployTaskManager.cs new file mode 100644 index 00000000..ce492cd6 --- /dev/null +++ b/src/client/Bootstrap.Client/Tasks/DeployTaskManager.cs @@ -0,0 +1,112 @@ +using Bootstrap.Client.Controllers.Api; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using System; +using System.Collections.Concurrent; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices; +using System.Threading.Tasks; + +namespace Bootstrap.Client.Tasks +{ + /// + /// 发布任务管理操作类 + /// + public static class DeployTaskManager + { + private static BlockingCollection _pool = new BlockingCollection(new ConcurrentQueue()); + private static IServiceCollection _services; + + /// + /// IServiceCollection 实例 + /// + /// + internal static void RegisterServices(IServiceCollection services) => _services = services; + + /// + /// 添加自动发布任务到队列中 + /// + /// + public static void Add(GiteePushEventArgs args) + { + // 判断是否需要自动发布 + var sp = _services.BuildServiceProvider(); + var config = sp.GetRequiredService(); + var logger = sp.GetRequiredService>(); + var option = config.GetSection().Get(); + if (option.Enabled && !string.IsNullOrEmpty(option.DeployFile)) + { + if (!_pool.IsAddingCompleted) + { + _pool.Add(args); + } + + RunAsync(logger, option).ConfigureAwait(false); + } + } + + private static bool _running; + private static object _locker = new object(); + + private static async Task RunAsync(ILogger logger, DeployOptions options) + { + if (!_running) + { + await Task.Run(() => + { + // 线程等待防止多个部署任务同时执行 + lock (_locker) + { + if (!_running) + { + _running = true; + while (_pool.TryTake(out var args)) + { + // 分析提交分支 + if (args.Ref.SpanSplit("/").LastOrDefault().Equals(options.Branch, StringComparison.OrdinalIgnoreCase) && CanDeploy(options.OSPlatform)) + { + // 仅部署配置分支代码 + Deploy(logger, options.DeployFile); + } + } + } + } + _running = false; + }); + } + } + + private static bool CanDeploy(string osPlatform) + { + var os = OSPlatform.Create(osPlatform); + return !RuntimeInformation.IsOSPlatform(os); + } + + private static void Deploy(ILogger logger, string deployFile) + { + // 调用部署脚本 + try + { + //var psi = new ProcessStartInfo("sh", "~/BootstrapAdmin/deploy-admin.sh"); + var cmd = deployFile; + if (File.Exists(cmd)) + { + var psi = new ProcessStartInfo("sh", $"\"{cmd}\""); + psi.RedirectStandardOutput = true; + psi.UseShellExecute = false; + var p = Process.Start(psi); + p.WaitForExit(); + var result = p.StandardOutput.ReadToEnd(); + logger.LogError("deploy success: {0}", result); + } + } + catch (Exception ex) + { + logger.LogError(ex, ""); + } + } + } +} diff --git a/src/client/Bootstrap.Client/Tasks/GiteePushEventArgs.cs b/src/client/Bootstrap.Client/Tasks/GiteePushEventArgs.cs new file mode 100644 index 00000000..9bd32785 --- /dev/null +++ b/src/client/Bootstrap.Client/Tasks/GiteePushEventArgs.cs @@ -0,0 +1,88 @@ +using System; +using System.Collections.Generic; + +namespace Bootstrap.Client.Tasks +{ + /// + /// Gitee 提交事件参数实体类 + /// + public class GiteePushEventArgs + { + /// + /// 获得/设置 提交分支信息 + /// + public string Ref { get; set; } + + /// + /// 获得/设置 提交信息集合 + /// + public ICollection Commits { get; set; } = new HashSet(); + + /// + /// 获得/设置 提交信息数量 + /// + public int Total_Commits_Count { get; set; } + } + + /// + /// 获得/设置 提交信息实体类 + /// + public class GiteeCommit + { + /// + /// 获得/设置 提交消息 + /// + public string Message { get; set; } + + /// + /// 获得/设置 提交时间戳 + /// + public DateTimeOffset Timestamp { get; set; } + + /// + /// 获得/设置 提交地址 + /// + public string Url { get; set; } + + /// + /// 获得/设置 提交作者 + /// + public GiteeAuthor Author { get; set; } + } + + /// + /// 获得/设置 提交作者信息 + /// + public class GiteeAuthor + { + /// + /// 获得/设置 提交时间 + /// + public DateTimeOffset Time { get; set; } + + /// + /// 获得/设置 提交人 ID + /// + public int Id { get; set; } + + /// + /// 获得/设置 提交人名称 + /// + public string Name { get; set; } + + /// + /// 获得/设置 提交人邮件地址 + /// + public string Email { get; set; } + + /// + /// 获得/设置 提交人名称 + /// + public string UserName { get; set; } + + /// + /// 获得/设置 提交人 Gitee 地址 + /// + public string Url { get; set; } + } +} diff --git a/src/client/Bootstrap.Client/appsettings.Development.json b/src/client/Bootstrap.Client/appsettings.Development.json index 6bc5d4c7..75fdb315 100644 --- a/src/client/Bootstrap.Client/appsettings.Development.json +++ b/src/client/Bootstrap.Client/appsettings.Development.json @@ -46,6 +46,12 @@ "AuthHost": "http://localhost:50852", "KeyPath": "..\\..\\admin\\keys" }, + "DeployOptions": { + "Enabled": false, + "DeployFile": "..\\..\\publish-admin.sh", + "OSPlatform": "Windows", + "Branch": "release" + }, "AllowOrigins": "http://localhost:50852", "LongbowCache": { "Enabled": true, diff --git a/src/client/Bootstrap.Client/appsettings.json b/src/client/Bootstrap.Client/appsettings.json index 9597da70..25edaef5 100644 --- a/src/client/Bootstrap.Client/appsettings.json +++ b/src/client/Bootstrap.Client/appsettings.json @@ -41,6 +41,12 @@ "BootstrapAdminAuthenticationOptions": { "AuthHost": "http://argo.zylweb.cn/BA" }, + "DeployOptions": { + "Enabled": false, + "DeployFile": "..\\..\\..\\..\\publish.ps1", + "OSPlatform": "Windows", + "Branch": "release" + }, "AllowOrigins": "http://localhost,http://argo.zylweb.cn", "LongbowCache": { "Enabled": true,