Merge branch 'dev'

This commit is contained in:
Argo Zhang 2019-10-05 14:09:25 +08:00
commit 125660bf8a
No known key found for this signature in database
GPG Key ID: 152E398953DDF19F
16 changed files with 312 additions and 31 deletions

View File

@ -33,14 +33,6 @@
transform: none;
}
.header .badge {
top: 4px;
}
.userinfo .badge {
top: 64px;
}
.username {
font-size: 1rem;
vertical-align: middle;
@ -109,6 +101,12 @@
margin-right: 10px;
}
.userinfo .dropdown-item a .badge {
top: 74px;
left: auto;
right: 42px;
}
.userinfo .dropdown-item:last-child {
border-bottom: none;
}

View File

@ -6,7 +6,6 @@
body {
color: #797979;
background: #f1f2f7;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-webkit-overflow-scrolling: touch;
}

View File

@ -6,7 +6,8 @@
<ItemGroup>
<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.Data" Version="2.3.8" />
<PackageReference Include="Longbow.GiteeAuth" Version="2.2.0" />

View File

@ -6,8 +6,8 @@
<ItemGroup>
<PackageReference Include="Bootstrap.Security.DataAccess" Version="2.2.21" />
<PackageReference Include="Longbow" Version="3.0.0-beta4" />
<PackageReference Include="Longbow.Cache" Version="2.2.15" />
<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.Data" Version="2.3.8" />
<PackageReference Include="Longbow.Logging" Version="3.0.0" />

View File

@ -24,7 +24,7 @@ namespace Bootstrap.Client.Controllers.Api
var sum = datas.Sum();
var avg = sum * 1.0 / datas.Count;
var stddev = datas.Select(v => Math.Pow(v - avg, 2)).Sum() / datas.Count;
return stddev != 0;
return stddev > 0;
}
}
}

View File

@ -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);
}
}
}

View File

@ -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
{
/// <summary>
///
/// 前台主页控制器
/// </summary>
public class HomeController : Controller
{
/// <summary>
///
/// 默认视图
/// </summary>
/// <returns></returns>
public IActionResult Index()
{
return View(new NavigatorBarModel(this));
}
/// <summary>
///
/// About 视图
/// </summary>
/// <returns></returns>
public IActionResult About()
{
return View(new NavigatorBarModel(this));
}
/// <summary>
///
/// 错误视图
/// </summary>
/// <param name="id"></param>
/// <returns></returns>

View File

@ -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<ExceptionFilter>();
options.Filters.Add<SignalRExceptionFilter<SignalRHub>>();
}).AddJsonOptions(op => op.JsonSerializerOptions.AddDefaultConverters());
services.AddControllersWithViews(options => options.Filters.Add<ExceptionFilter>()).AddJsonOptions(op => op.JsonSerializerOptions.AddDefaultConverters());
services.AddAutoPublish();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.

View File

@ -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;
}
}
}

View File

@ -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";
}
}

View File

@ -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, "");
}
}
}
}

View File

@ -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; }
}
}

View File

@ -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,

View File

@ -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,

View File

@ -35,14 +35,6 @@
transform: none;
}
.header .badge {
top: 4px;
}
.userinfo .badge {
top: 64px;
}
.username {
font-size: 1rem;
vertical-align: middle;
@ -111,6 +103,12 @@
margin-right: 10px;
}
.userinfo .dropdown-item a .badge {
top: 74px;
left: auto;
right: 42px;
}
.userinfo .dropdown-item:last-child {
border-bottom: none;
}

View File

@ -6,7 +6,6 @@
body {
color: #797979;
background: #f1f2f7;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-webkit-overflow-scrolling: touch;
}