From 3fa778c4f0d48d2f968e3bc3b35b1b9f63c23e25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8C=BF=E4=BA=BA=E6=98=93?= Date: Mon, 23 Sep 2024 10:40:36 +0800 Subject: [PATCH] =?UTF-8?q?[feat]=E5=8F=91=E5=B8=83=E4=B8=AD=E5=BF=83?= =?UTF-8?q?=E8=A6=81=E6=94=AF=E6=8C=81=E5=8D=95=E4=B8=AA=E5=BA=94=E7=94=A8?= =?UTF-8?q?=E5=9C=A8=E6=8C=87=E5=AE=9A=E6=9C=8D=E5=8A=A1=E5=99=A8=E4=B8=8A?= =?UTF-8?q?=E9=83=A8=E7=BD=B2=E5=A4=9A=E4=B8=AA=E7=89=88=E6=9C=AC=E3=80=82?= =?UTF-8?q?=E5=BA=94=E7=94=A8=E5=9C=BA=E6=99=AF=E9=9C=80=E6=B1=82=EF=BC=8C?= =?UTF-8?q?=E5=B8=8C=E6=9C=9B=E5=BA=94=E7=94=A8App1=E8=83=BD=E5=A4=9F?= =?UTF-8?q?=E5=9C=A8=E8=8A=82=E7=82=B9Node1=E4=B8=8A=E9=83=A8=E7=BD=B2?= =?UTF-8?q?=E5=A4=9A=E4=B8=AA=E7=89=88=E6=9C=AC=EF=BC=8C=E5=A6=82=EF=BC=9A?= =?UTF-8?q?App1A/App1B/App1C=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 场景一 用户资源有限,希望在一台服务器上部署应用App1的测试版和生产版,端口不同。 可在发布节点里面添加两次节点Node1,命名发布集为:App1A/App1B,原来发布集统一使用应用名App1。 需要关闭自动发布,上传版本后,手工选择使用最新版本,然后在测试版App1B上点击发布。 待新版测试通过后,再电机App1A发布。 场景二 重要应用App1,仅有1台服务器,发布时需要重启,耗时1分钟左右,导致业务中断影响体验。 可在发布节点里面添加两次节点Node1,命名发布集为:App1A/App1B,原来发布集统一使用应用名App1。 配置两个发布的顺序和延迟时间(60秒),自动发布时,依次部署,间隔60秒。 前端nginx使用主备机制,确保发布过程中也有可用节点。 https://github.com/NewLifeX/Stardust/issues/72 --- .github/workflows/publish-beta.yml | 3 +- .github/workflows/publish.yml | 3 +- Stardust.Data/Deployment/Model.xml | 7 +- ...47\224\250\350\212\202\347\202\271.Biz.cs" | 4 +- ...24\347\224\250\350\212\202\347\202\271.cs" | 121 ++++++++++-------- Stardust.Web.Vue/package.json | 2 +- Stardust.Web.Vue/yarn.lock | 8 +- .../Controllers/AppDeployVersionController.cs | 4 +- .../Views/AppDeployNode/_List_Data.cshtml | 4 +- 9 files changed, 87 insertions(+), 69 deletions(-) diff --git a/.github/workflows/publish-beta.yml b/.github/workflows/publish-beta.yml index 3be5e73..364f830 100644 --- a/.github/workflows/publish-beta.yml +++ b/.github/workflows/publish-beta.yml @@ -33,5 +33,6 @@ jobs: - name: Publish run: | - dotnet nuget push .\out\*.nupkg --skip-duplicate --source https://nuget.pkg.github.com/PeiKeSmart/index.json --api-key ${{ github.token }} + #dotnet nuget push .\out\*.nupkg --skip-duplicate --source https://nuget.pkg.github.com/PeiKeSmart/index.json --api-key ${{ github.token }} dotnet nuget push .\out\*.nupkg --skip-duplicate --source https://api.nuget.org/v3/index.json --api-key ${{ secrets.nugetKey }} + dotnet nuget push ./out/*.nupkg --skip-duplicate --source https://nuget.chuangchu.net/v3/index.json --api-key ${{ secrets.mynugetKey }} \ No newline at end of file diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index a52119c..fca877b 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -28,5 +28,6 @@ jobs: - name: Publish run: | - dotnet nuget push .\out\*.nupkg --skip-duplicate --source https://nuget.pkg.github.com/PeiKeSmart/index.json --api-key ${{ github.token }} + #dotnet nuget push .\out\*.nupkg --skip-duplicate --source https://nuget.pkg.github.com/PeiKeSmart/index.json --api-key ${{ github.token }} dotnet nuget push .\out\*.nupkg --skip-duplicate --source https://api.nuget.org/v3/index.json --api-key ${{ secrets.nugetKey }} + dotnet nuget push ./out/*.nupkg --skip-duplicate --source https://nuget.chuangchu.net/v3/index.json --api-key ${{ secrets.mynugetKey }} \ No newline at end of file diff --git a/Stardust.Data/Deployment/Model.xml b/Stardust.Data/Deployment/Model.xml index 6dee080..743cfcb 100644 --- a/Stardust.Data/Deployment/Model.xml +++ b/Stardust.Data/Deployment/Model.xml @@ -82,19 +82,20 @@ + - - + + - + diff --git "a/Stardust.Data/Deployment/\345\272\224\347\224\250\350\212\202\347\202\271.Biz.cs" "b/Stardust.Data/Deployment/\345\272\224\347\224\250\350\212\202\347\202\271.Biz.cs" index b58ea89..dda9884 100644 --- "a/Stardust.Data/Deployment/\345\272\224\347\224\250\350\212\202\347\202\271.Biz.cs" +++ "b/Stardust.Data/Deployment/\345\272\224\347\224\250\350\212\202\347\202\271.Biz.cs" @@ -175,9 +175,10 @@ public ServiceInfo ToService(AppDeploy app) var inf = new ServiceInfo { - Name = app.Name, + Name = DeployName, FileName = FileName, Arguments = Arguments, + Environments = Environments, WorkingDirectory = WorkingDirectory, Enable = app.Enable && Enable, @@ -187,6 +188,7 @@ public ServiceInfo ToService(AppDeploy app) MaxMemory = app.MaxMemory, Mode = Mode, }; + if (inf.Name.IsNullOrEmpty()) inf.Name = app.Name; if (inf.FileName.IsNullOrEmpty()) inf.FileName = app.FileName; if (inf.Arguments.IsNullOrEmpty()) inf.Arguments = app.Arguments; if (inf.Environments.IsNullOrEmpty()) inf.Environments = app.Environments; diff --git "a/Stardust.Data/Deployment/\345\272\224\347\224\250\350\212\202\347\202\271.cs" "b/Stardust.Data/Deployment/\345\272\224\347\224\250\350\212\202\347\202\271.cs" index 44e5e0f..cebfc84 100644 --- "a/Stardust.Data/Deployment/\345\272\224\347\224\250\350\212\202\347\202\271.cs" +++ "b/Stardust.Data/Deployment/\345\272\224\347\224\250\350\212\202\347\202\271.cs" @@ -31,6 +31,14 @@ public partial class AppDeployNode [BindColumn("Id", "编号", "")] public Int32 Id { get => _Id; set { if (OnPropertyChanging("Id", value)) { _Id = value; OnPropertyChanged("Id"); } } } + private String _DeployName; + /// 发布名。默认为空,使用部署集上名字。可用于单节点多发布场景 + [DisplayName("发布名")] + [Description("发布名。默认为空,使用部署集上名字。可用于单节点多发布场景")] + [DataObjectField(false, false, true, 50)] + [BindColumn("DeployName", "发布名。默认为空,使用部署集上名字。可用于单节点多发布场景", "")] + public String DeployName { get => _DeployName; set { if (OnPropertyChanging("DeployName", value)) { _DeployName = value; OnPropertyChanged("DeployName"); } } } + private Int32 _DeployId; /// 应用部署集。对应AppDeploy [DisplayName("应用部署集")] @@ -55,14 +63,6 @@ public partial class AppDeployNode [BindColumn("IP", "IP地址。节点所在内网IP地址", "")] public String IP { get => _IP; set { if (OnPropertyChanging("IP", value)) { _IP = value; OnPropertyChanged("IP"); } } } - private Int32 _Sort; - /// 顺序。较小在前,同时表示延迟发布秒数 - [DisplayName("顺序")] - [Description("顺序。较小在前,同时表示延迟发布秒数")] - [DataObjectField(false, false, false, 0)] - [BindColumn("Sort", "顺序。较小在前,同时表示延迟发布秒数", "")] - public Int32 Sort { get => _Sort; set { if (OnPropertyChanging("Sort", value)) { _Sort = value; OnPropertyChanged("Sort"); } } } - private Boolean _Enable; /// 启用 [DisplayName("启用")] @@ -71,15 +71,6 @@ public partial class AppDeployNode [BindColumn("Enable", "启用", "")] public Boolean Enable { get => _Enable; set { if (OnPropertyChanging("Enable", value)) { _Enable = value; OnPropertyChanged("Enable"); } } } - private String _Environment; - /// 环境。prod/test/dev/uat等 - [Category("发布参数")] - [DisplayName("环境")] - [Description("环境。prod/test/dev/uat等")] - [DataObjectField(false, false, true, 50)] - [BindColumn("Environment", "环境。prod/test/dev/uat等", "")] - public String Environment { get => _Environment; set { if (OnPropertyChanging("Environment", value)) { _Environment = value; OnPropertyChanged("Environment"); } } } - private String _FileName; /// 文件。应用启动文件,可直接使用zip包,支持差异定制,为空时使用应用集配置 [Category("发布参数")] @@ -107,6 +98,15 @@ public partial class AppDeployNode [BindColumn("WorkingDirectory", "工作目录。应用根目录,为空时使用应用集配置", "")] public String WorkingDirectory { get => _WorkingDirectory; set { if (OnPropertyChanging("WorkingDirectory", value)) { _WorkingDirectory = value; OnPropertyChanged("WorkingDirectory"); } } } + private String _Environments; + /// 环境变量。启动应用前设置的环境变量 + [Category("发布参数")] + [DisplayName("环境变量")] + [Description("环境变量。启动应用前设置的环境变量")] + [DataObjectField(false, false, true, 500)] + [BindColumn("Environments", "环境变量。启动应用前设置的环境变量", "")] + public String Environments { get => _Environments; set { if (OnPropertyChanging("Environments", value)) { _Environments = value; OnPropertyChanged("Environments"); } } } + private Stardust.Models.ServiceModes _Mode; /// 工作模式。0默认exe/zip;1仅解压;2解压后运行;3仅运行一次;4多实例exe/zip。为空时使用应用集配置 [Category("发布参数")] @@ -116,6 +116,15 @@ public partial class AppDeployNode [BindColumn("Mode", "工作模式。0默认exe/zip;1仅解压;2解压后运行;3仅运行一次;4多实例exe/zip。为空时使用应用集配置", "")] public Stardust.Models.ServiceModes Mode { get => _Mode; set { if (OnPropertyChanging("Mode", value)) { _Mode = value; OnPropertyChanged("Mode"); } } } + private Int32 _Delay; + /// 延迟。批量发布时,需要延迟执行的时间,用于滚动发布,单位秒 + [Category("发布参数")] + [DisplayName("延迟")] + [Description("延迟。批量发布时,需要延迟执行的时间,用于滚动发布,单位秒")] + [DataObjectField(false, false, false, 0)] + [BindColumn("Delay", "延迟。批量发布时,需要延迟执行的时间,用于滚动发布,单位秒", "")] + public Int32 Delay { get => _Delay; set { if (OnPropertyChanging("Delay", value)) { _Delay = value; OnPropertyChanged("Delay"); } } } + private Int32 _ProcessId; /// 进程 [Category("状态")] @@ -125,15 +134,6 @@ public partial class AppDeployNode [BindColumn("ProcessId", "进程", "")] public Int32 ProcessId { get => _ProcessId; set { if (OnPropertyChanging("ProcessId", value)) { _ProcessId = value; OnPropertyChanged("ProcessId"); } } } - private String _ProcessName; - /// 进程名称 - [Category("状态")] - [DisplayName("进程名称")] - [Description("进程名称")] - [DataObjectField(false, false, true, 200)] - [BindColumn("ProcessName", "进程名称", "")] - public String ProcessName { get => _ProcessName; set { if (OnPropertyChanging("ProcessName", value)) { _ProcessName = value; OnPropertyChanged("ProcessName"); } } } - private String _UserName; /// 用户名。启动该进程的用户名 [Category("状态")] @@ -143,6 +143,15 @@ public partial class AppDeployNode [BindColumn("UserName", "用户名。启动该进程的用户名", "")] public String UserName { get => _UserName; set { if (OnPropertyChanging("UserName", value)) { _UserName = value; OnPropertyChanged("UserName"); } } } + private String _ProcessName; + /// 进程名称 + [Category("状态")] + [DisplayName("进程名称")] + [Description("进程名称")] + [DataObjectField(false, false, true, 200)] + [BindColumn("ProcessName", "进程名称", "")] + public String ProcessName { get => _ProcessName; set { if (OnPropertyChanging("ProcessName", value)) { _ProcessName = value; OnPropertyChanged("ProcessName"); } } } + private DateTime _StartTime; /// 进程时间 [Category("状态")] @@ -279,19 +288,20 @@ public override Object this[String name] get => name switch { "Id" => _Id, + "DeployName" => _DeployName, "DeployId" => _DeployId, "NodeId" => _NodeId, "IP" => _IP, - "Sort" => _Sort, "Enable" => _Enable, - "Environment" => _Environment, "FileName" => _FileName, "Arguments" => _Arguments, "WorkingDirectory" => _WorkingDirectory, + "Environments" => _Environments, "Mode" => _Mode, + "Delay" => _Delay, "ProcessId" => _ProcessId, - "ProcessName" => _ProcessName, "UserName" => _UserName, + "ProcessName" => _ProcessName, "StartTime" => _StartTime, "Version" => _Version, "Compile" => _Compile, @@ -313,19 +323,20 @@ public override Object this[String name] switch (name) { case "Id": _Id = value.ToInt(); break; + case "DeployName": _DeployName = Convert.ToString(value); break; case "DeployId": _DeployId = value.ToInt(); break; case "NodeId": _NodeId = value.ToInt(); break; case "IP": _IP = Convert.ToString(value); break; - case "Sort": _Sort = value.ToInt(); break; case "Enable": _Enable = value.ToBoolean(); break; - case "Environment": _Environment = Convert.ToString(value); break; case "FileName": _FileName = Convert.ToString(value); break; case "Arguments": _Arguments = Convert.ToString(value); break; case "WorkingDirectory": _WorkingDirectory = Convert.ToString(value); break; + case "Environments": _Environments = Convert.ToString(value); break; case "Mode": _Mode = (Stardust.Models.ServiceModes)value.ToInt(); break; + case "Delay": _Delay = value.ToInt(); break; case "ProcessId": _ProcessId = value.ToInt(); break; - case "ProcessName": _ProcessName = Convert.ToString(value); break; case "UserName": _UserName = Convert.ToString(value); break; + case "ProcessName": _ProcessName = Convert.ToString(value); break; case "StartTime": _StartTime = value.ToDateTime(); break; case "Version": _Version = Convert.ToString(value); break; case "Compile": _Compile = value.ToDateTime(); break; @@ -351,10 +362,6 @@ public override Object this[String name] [XmlIgnore, IgnoreDataMember, ScriptIgnore] public AppDeploy Deploy => Extends.Get(nameof(Deploy), k => AppDeploy.FindById(DeployId)); - /// 应用部署集 - [Map(nameof(DeployId), typeof(AppDeploy), "Id")] - public String DeployName => Deploy?.ToString(); - #endregion #region 扩展查询 @@ -367,6 +374,9 @@ public partial class _ /// 编号 public static readonly Field Id = FindByName("Id"); + /// 发布名。默认为空,使用部署集上名字。可用于单节点多发布场景 + public static readonly Field DeployName = FindByName("DeployName"); + /// 应用部署集。对应AppDeploy public static readonly Field DeployId = FindByName("DeployId"); @@ -376,15 +386,9 @@ public partial class _ /// IP地址。节点所在内网IP地址 public static readonly Field IP = FindByName("IP"); - /// 顺序。较小在前,同时表示延迟发布秒数 - public static readonly Field Sort = FindByName("Sort"); - /// 启用 public static readonly Field Enable = FindByName("Enable"); - /// 环境。prod/test/dev/uat等 - public static readonly Field Environment = FindByName("Environment"); - /// 文件。应用启动文件,可直接使用zip包,支持差异定制,为空时使用应用集配置 public static readonly Field FileName = FindByName("FileName"); @@ -394,18 +398,24 @@ public partial class _ /// 工作目录。应用根目录,为空时使用应用集配置 public static readonly Field WorkingDirectory = FindByName("WorkingDirectory"); + /// 环境变量。启动应用前设置的环境变量 + public static readonly Field Environments = FindByName("Environments"); + /// 工作模式。0默认exe/zip;1仅解压;2解压后运行;3仅运行一次;4多实例exe/zip。为空时使用应用集配置 public static readonly Field Mode = FindByName("Mode"); + /// 延迟。批量发布时,需要延迟执行的时间,用于滚动发布,单位秒 + public static readonly Field Delay = FindByName("Delay"); + /// 进程 public static readonly Field ProcessId = FindByName("ProcessId"); - /// 进程名称 - public static readonly Field ProcessName = FindByName("ProcessName"); - /// 用户名。启动该进程的用户名 public static readonly Field UserName = FindByName("UserName"); + /// 进程名称 + public static readonly Field ProcessName = FindByName("ProcessName"); + /// 进程时间 public static readonly Field StartTime = FindByName("StartTime"); @@ -457,6 +467,9 @@ public partial class __ /// 编号 public const String Id = "Id"; + /// 发布名。默认为空,使用部署集上名字。可用于单节点多发布场景 + public const String DeployName = "DeployName"; + /// 应用部署集。对应AppDeploy public const String DeployId = "DeployId"; @@ -466,15 +479,9 @@ public partial class __ /// IP地址。节点所在内网IP地址 public const String IP = "IP"; - /// 顺序。较小在前,同时表示延迟发布秒数 - public const String Sort = "Sort"; - /// 启用 public const String Enable = "Enable"; - /// 环境。prod/test/dev/uat等 - public const String Environment = "Environment"; - /// 文件。应用启动文件,可直接使用zip包,支持差异定制,为空时使用应用集配置 public const String FileName = "FileName"; @@ -484,18 +491,24 @@ public partial class __ /// 工作目录。应用根目录,为空时使用应用集配置 public const String WorkingDirectory = "WorkingDirectory"; + /// 环境变量。启动应用前设置的环境变量 + public const String Environments = "Environments"; + /// 工作模式。0默认exe/zip;1仅解压;2解压后运行;3仅运行一次;4多实例exe/zip。为空时使用应用集配置 public const String Mode = "Mode"; + /// 延迟。批量发布时,需要延迟执行的时间,用于滚动发布,单位秒 + public const String Delay = "Delay"; + /// 进程 public const String ProcessId = "ProcessId"; - /// 进程名称 - public const String ProcessName = "ProcessName"; - /// 用户名。启动该进程的用户名 public const String UserName = "UserName"; + /// 进程名称 + public const String ProcessName = "ProcessName"; + /// 进程时间 public const String StartTime = "StartTime"; diff --git a/Stardust.Web.Vue/package.json b/Stardust.Web.Vue/package.json index ce2dfd0..17aae44 100644 --- a/Stardust.Web.Vue/package.json +++ b/Stardust.Web.Vue/package.json @@ -22,7 +22,7 @@ "sass": "^1.26.2", "sass-loader": "^8.0.2", "typescript": "^4.5.2", - "vite": "^4.5.2", + "vite": "^4.5.5", "vue-tsc": "^1.0.24" } } \ No newline at end of file diff --git a/Stardust.Web.Vue/yarn.lock b/Stardust.Web.Vue/yarn.lock index 94dee76..b9b5348 100644 --- a/Stardust.Web.Vue/yarn.lock +++ b/Stardust.Web.Vue/yarn.lock @@ -830,10 +830,10 @@ uri-js@^4.2.2: dependencies: punycode "^2.1.0" -vite@^4.5.2: - version "4.5.2" - resolved "https://registry.yarnpkg.com/vite/-/vite-4.5.2.tgz#d6ea8610e099851dad8c7371599969e0f8b97e82" - integrity sha512-tBCZBNSBbHQkaGyhGCDUGqeo2ph8Fstyp6FMSvTtsXeZSPpSMGlviAOav2hxVTqFcx8Hj/twtWKsMJXNY0xI8w== +vite@^4.5.5: + version "4.5.5" + resolved "https://registry.yarnpkg.com/vite/-/vite-4.5.5.tgz#639b9feca5c0a3bfe3c60cb630ef28bf219d742e" + integrity sha512-ifW3Lb2sMdX+WU91s3R0FyQlAyLxOzCSCP37ujw0+r5POeHPwe6udWVIElKQq8gk3t7b8rkmvqC6IHBpCff4GQ== dependencies: esbuild "^0.18.10" postcss "^8.4.27" diff --git a/Stardust.Web/Areas/Deployment/Controllers/AppDeployVersionController.cs b/Stardust.Web/Areas/Deployment/Controllers/AppDeployVersionController.cs index 8176231..96de3f6 100644 --- a/Stardust.Web/Areas/Deployment/Controllers/AppDeployVersionController.cs +++ b/Stardust.Web/Areas/Deployment/Controllers/AppDeployVersionController.cs @@ -266,7 +266,7 @@ async Task Publish(AppDeploy app) var ts = new List(); var appNodes = AppDeployNode.FindAllByAppId(app.Id); // 排序和延迟 - appNodes = appNodes.OrderBy(e => e.Sort).ToList(); + appNodes = appNodes.OrderBy(e => e.Delay).ToList(); foreach (var item in appNodes) { //span?.AppendTag(item); @@ -275,7 +275,7 @@ async Task Publish(AppDeploy app) { ts.Add(Task.Run(async () => { - if (item.Sort > 0) await Task.Delay(item.Sort * 1000); + if (item.Delay > 0) await Task.Delay(item.Delay * 1000); await _deployService.Control(app, item, "install", UserHost, 0); })); } diff --git a/Stardust.Web/Areas/Deployment/Views/AppDeployNode/_List_Data.cshtml b/Stardust.Web/Areas/Deployment/Views/AppDeployNode/_List_Data.cshtml index 7339179..8375a1b 100644 --- a/Stardust.Web/Areas/Deployment/Views/AppDeployNode/_List_Data.cshtml +++ b/Stardust.Web/Areas/Deployment/Views/AppDeployNode/_List_Data.cshtml @@ -34,7 +34,7 @@ } - + @@ -66,7 +66,7 @@ } - +
节点IP顺序顺序 启用 进程 进程时间@entity.NodeName@entity.IP@entity.Sort.ToString("n0")@entity.Delay