Merge branch 'dev'
This commit is contained in:
commit
125660bf8a
|
@ -33,14 +33,6 @@
|
||||||
transform: none;
|
transform: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.header .badge {
|
|
||||||
top: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.userinfo .badge {
|
|
||||||
top: 64px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.username {
|
.username {
|
||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
|
@ -109,6 +101,12 @@
|
||||||
margin-right: 10px;
|
margin-right: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.userinfo .dropdown-item a .badge {
|
||||||
|
top: 74px;
|
||||||
|
left: auto;
|
||||||
|
right: 42px;
|
||||||
|
}
|
||||||
|
|
||||||
.userinfo .dropdown-item:last-child {
|
.userinfo .dropdown-item:last-child {
|
||||||
border-bottom: none;
|
border-bottom: none;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
body {
|
body {
|
||||||
color: #797979;
|
color: #797979;
|
||||||
background: #f1f2f7;
|
background: #f1f2f7;
|
||||||
text-rendering: optimizeLegibility;
|
|
||||||
-webkit-font-smoothing: antialiased;
|
-webkit-font-smoothing: antialiased;
|
||||||
-webkit-overflow-scrolling: touch;
|
-webkit-overflow-scrolling: touch;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,8 @@
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Bootstrap.Security.DataAccess" Version="2.2.21" />
|
<PackageReference Include="Bootstrap.Security.DataAccess" Version="2.2.21" />
|
||||||
<PackageReference Include="Longbow" Version="3.0.0-beta4" />
|
<PackageReference Include="Longbow" Version="3.0.0-beta5" />
|
||||||
|
<PackageReference Include="Longbow.Cache" Version="3.0.0-beta1" />
|
||||||
<PackageReference Include="Longbow.Configuration" Version="2.2.7" />
|
<PackageReference Include="Longbow.Configuration" Version="2.2.7" />
|
||||||
<PackageReference Include="Longbow.Data" Version="2.3.8" />
|
<PackageReference Include="Longbow.Data" Version="2.3.8" />
|
||||||
<PackageReference Include="Longbow.GiteeAuth" Version="2.2.0" />
|
<PackageReference Include="Longbow.GiteeAuth" Version="2.2.0" />
|
||||||
|
|
|
@ -6,8 +6,8 @@
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Bootstrap.Security.DataAccess" Version="2.2.21" />
|
<PackageReference Include="Bootstrap.Security.DataAccess" Version="2.2.21" />
|
||||||
<PackageReference Include="Longbow" Version="3.0.0-beta4" />
|
<PackageReference Include="Longbow" Version="3.0.0-beta5" />
|
||||||
<PackageReference Include="Longbow.Cache" Version="2.2.15" />
|
<PackageReference Include="Longbow.Cache" Version="3.0.0-beta1" />
|
||||||
<PackageReference Include="Longbow.Configuration" Version="2.2.7" />
|
<PackageReference Include="Longbow.Configuration" Version="2.2.7" />
|
||||||
<PackageReference Include="Longbow.Data" Version="2.3.8" />
|
<PackageReference Include="Longbow.Data" Version="2.3.8" />
|
||||||
<PackageReference Include="Longbow.Logging" Version="3.0.0" />
|
<PackageReference Include="Longbow.Logging" Version="3.0.0" />
|
||||||
|
|
|
@ -24,7 +24,7 @@ namespace Bootstrap.Client.Controllers.Api
|
||||||
var sum = datas.Sum();
|
var sum = datas.Sum();
|
||||||
var avg = sum * 1.0 / datas.Count;
|
var avg = sum * 1.0 / datas.Count;
|
||||||
var stddev = datas.Select(v => Math.Pow(v - avg, 2)).Sum() / datas.Count;
|
var stddev = datas.Select(v => Math.Pow(v - avg, 2)).Sum() / datas.Count;
|
||||||
return stddev != 0;
|
return stddev > 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
using Bootstrap.Client.Tasks;
|
||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
|
||||||
|
namespace Bootstrap.Client.Controllers.Api
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 自动发布 WebApi 接口
|
||||||
|
/// </summary>
|
||||||
|
[Route("api/[controller]")]
|
||||||
|
[ApiController]
|
||||||
|
[AllowAnonymous]
|
||||||
|
public class DeployController : ControllerBase
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 自动发布 webhook 接口
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="args"></param>
|
||||||
|
[HttpPost]
|
||||||
|
public void Post([FromBody]GiteePushEventArgs args)
|
||||||
|
{
|
||||||
|
DeployTaskManager.Add(args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,5 @@
|
||||||
using Bootstrap.Client.Models;
|
using Bootstrap.Client.Models;
|
||||||
|
using Bootstrap.Client.Tasks;
|
||||||
using Longbow.Configuration;
|
using Longbow.Configuration;
|
||||||
using Microsoft.AspNetCore;
|
using Microsoft.AspNetCore;
|
||||||
using Microsoft.AspNetCore.Authentication.Cookies;
|
using Microsoft.AspNetCore.Authentication.Cookies;
|
||||||
|
@ -10,28 +11,30 @@ using System;
|
||||||
namespace Bootstrap.Client.Controllers
|
namespace Bootstrap.Client.Controllers
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
/// 前台主页控制器
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class HomeController : Controller
|
public class HomeController : Controller
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
/// 默认视图
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public IActionResult Index()
|
public IActionResult Index()
|
||||||
{
|
{
|
||||||
return View(new NavigatorBarModel(this));
|
return View(new NavigatorBarModel(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
/// About 视图
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public IActionResult About()
|
public IActionResult About()
|
||||||
{
|
{
|
||||||
return View(new NavigatorBarModel(this));
|
return View(new NavigatorBarModel(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
/// 错误视图
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="id"></param>
|
/// <param name="id"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
|
|
|
@ -56,11 +56,8 @@ namespace Bootstrap.Client
|
||||||
services.AddResponseCompression();
|
services.AddResponseCompression();
|
||||||
services.AddBootstrapAdminAuthentication();
|
services.AddBootstrapAdminAuthentication();
|
||||||
services.AddAuthorization(options => options.DefaultPolicy = new AuthorizationPolicyBuilder().RequireBootstrapAdminAuthorizate().Build());
|
services.AddAuthorization(options => options.DefaultPolicy = new AuthorizationPolicyBuilder().RequireBootstrapAdminAuthorizate().Build());
|
||||||
services.AddControllersWithViews(options =>
|
services.AddControllersWithViews(options => options.Filters.Add<ExceptionFilter>()).AddJsonOptions(op => op.JsonSerializerOptions.AddDefaultConverters());
|
||||||
{
|
services.AddAutoPublish();
|
||||||
options.Filters.Add<ExceptionFilter>();
|
|
||||||
options.Filters.Add<SignalRExceptionFilter<SignalRHub>>();
|
|
||||||
}).AddJsonOptions(op => op.JsonSerializerOptions.AddDefaultConverters());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
|
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
using Bootstrap.Client.Tasks;
|
||||||
|
|
||||||
|
namespace Microsoft.Extensions.DependencyInjection
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 自动发布服务扩展操作类
|
||||||
|
/// </summary>
|
||||||
|
public static class DeployExtensions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 注入自动发布到容器内
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="services"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static IServiceCollection AddAutoPublish(this IServiceCollection services)
|
||||||
|
{
|
||||||
|
DeployTaskManager.RegisterServices(services);
|
||||||
|
return services;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
namespace Bootstrap.Client.Tasks
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 自动发布配置类
|
||||||
|
/// </summary>
|
||||||
|
public class DeployOptions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 获得/设置 是否启用自动部署功能
|
||||||
|
/// </summary>
|
||||||
|
public bool Enabled { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获得/设置 自动部署脚本文件
|
||||||
|
/// </summary>
|
||||||
|
public string DeployFile { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获得/设置 自动部署分支
|
||||||
|
/// </summary>
|
||||||
|
public string Branch { get; set; } = "release";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获得/设置 自动部署平台
|
||||||
|
/// </summary>
|
||||||
|
public string OSPlatform { get; set; } = "Windows";
|
||||||
|
}
|
||||||
|
}
|
|
@ -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
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 发布任务管理操作类
|
||||||
|
/// </summary>
|
||||||
|
public static class DeployTaskManager
|
||||||
|
{
|
||||||
|
private static BlockingCollection<GiteePushEventArgs> _pool = new BlockingCollection<GiteePushEventArgs>(new ConcurrentQueue<GiteePushEventArgs>());
|
||||||
|
private static IServiceCollection _services;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// IServiceCollection 实例
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="services"></param>
|
||||||
|
internal static void RegisterServices(IServiceCollection services) => _services = services;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 添加自动发布任务到队列中
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="args"></param>
|
||||||
|
public static void Add(GiteePushEventArgs args)
|
||||||
|
{
|
||||||
|
// 判断是否需要自动发布
|
||||||
|
var sp = _services.BuildServiceProvider();
|
||||||
|
var config = sp.GetRequiredService<IConfiguration>();
|
||||||
|
var logger = sp.GetRequiredService<ILogger<DeployController>>();
|
||||||
|
var option = config.GetSection<DeployOptions>().Get<DeployOptions>();
|
||||||
|
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<DeployController> 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<DeployController> 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, "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,88 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Bootstrap.Client.Tasks
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gitee 提交事件参数实体类
|
||||||
|
/// </summary>
|
||||||
|
public class GiteePushEventArgs
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 获得/设置 提交分支信息
|
||||||
|
/// </summary>
|
||||||
|
public string Ref { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获得/设置 提交信息集合
|
||||||
|
/// </summary>
|
||||||
|
public ICollection<GiteeCommit> Commits { get; set; } = new HashSet<GiteeCommit>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获得/设置 提交信息数量
|
||||||
|
/// </summary>
|
||||||
|
public int Total_Commits_Count { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获得/设置 提交信息实体类
|
||||||
|
/// </summary>
|
||||||
|
public class GiteeCommit
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 获得/设置 提交消息
|
||||||
|
/// </summary>
|
||||||
|
public string Message { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获得/设置 提交时间戳
|
||||||
|
/// </summary>
|
||||||
|
public DateTimeOffset Timestamp { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获得/设置 提交地址
|
||||||
|
/// </summary>
|
||||||
|
public string Url { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获得/设置 提交作者
|
||||||
|
/// </summary>
|
||||||
|
public GiteeAuthor Author { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获得/设置 提交作者信息
|
||||||
|
/// </summary>
|
||||||
|
public class GiteeAuthor
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 获得/设置 提交时间
|
||||||
|
/// </summary>
|
||||||
|
public DateTimeOffset Time { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获得/设置 提交人 ID
|
||||||
|
/// </summary>
|
||||||
|
public int Id { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获得/设置 提交人名称
|
||||||
|
/// </summary>
|
||||||
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获得/设置 提交人邮件地址
|
||||||
|
/// </summary>
|
||||||
|
public string Email { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获得/设置 提交人名称
|
||||||
|
/// </summary>
|
||||||
|
public string UserName { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获得/设置 提交人 Gitee 地址
|
||||||
|
/// </summary>
|
||||||
|
public string Url { get; set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -46,6 +46,12 @@
|
||||||
"AuthHost": "http://localhost:50852",
|
"AuthHost": "http://localhost:50852",
|
||||||
"KeyPath": "..\\..\\admin\\keys"
|
"KeyPath": "..\\..\\admin\\keys"
|
||||||
},
|
},
|
||||||
|
"DeployOptions": {
|
||||||
|
"Enabled": false,
|
||||||
|
"DeployFile": "..\\..\\publish-admin.sh",
|
||||||
|
"OSPlatform": "Windows",
|
||||||
|
"Branch": "release"
|
||||||
|
},
|
||||||
"AllowOrigins": "http://localhost:50852",
|
"AllowOrigins": "http://localhost:50852",
|
||||||
"LongbowCache": {
|
"LongbowCache": {
|
||||||
"Enabled": true,
|
"Enabled": true,
|
||||||
|
|
|
@ -41,6 +41,12 @@
|
||||||
"BootstrapAdminAuthenticationOptions": {
|
"BootstrapAdminAuthenticationOptions": {
|
||||||
"AuthHost": "http://argo.zylweb.cn/BA"
|
"AuthHost": "http://argo.zylweb.cn/BA"
|
||||||
},
|
},
|
||||||
|
"DeployOptions": {
|
||||||
|
"Enabled": false,
|
||||||
|
"DeployFile": "..\\..\\..\\..\\publish.ps1",
|
||||||
|
"OSPlatform": "Windows",
|
||||||
|
"Branch": "release"
|
||||||
|
},
|
||||||
"AllowOrigins": "http://localhost,http://argo.zylweb.cn",
|
"AllowOrigins": "http://localhost,http://argo.zylweb.cn",
|
||||||
"LongbowCache": {
|
"LongbowCache": {
|
||||||
"Enabled": true,
|
"Enabled": true,
|
||||||
|
|
|
@ -35,14 +35,6 @@
|
||||||
transform: none;
|
transform: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.header .badge {
|
|
||||||
top: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.userinfo .badge {
|
|
||||||
top: 64px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.username {
|
.username {
|
||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
|
@ -111,6 +103,12 @@
|
||||||
margin-right: 10px;
|
margin-right: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.userinfo .dropdown-item a .badge {
|
||||||
|
top: 74px;
|
||||||
|
left: auto;
|
||||||
|
right: 42px;
|
||||||
|
}
|
||||||
|
|
||||||
.userinfo .dropdown-item:last-child {
|
.userinfo .dropdown-item:last-child {
|
||||||
border-bottom: none;
|
border-bottom: none;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
body {
|
body {
|
||||||
color: #797979;
|
color: #797979;
|
||||||
background: #f1f2f7;
|
background: #f1f2f7;
|
||||||
text-rendering: optimizeLegibility;
|
|
||||||
-webkit-font-smoothing: antialiased;
|
-webkit-font-smoothing: antialiased;
|
||||||
-webkit-overflow-scrolling: touch;
|
-webkit-overflow-scrolling: touch;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue