fix & feat: 改了数据库发布的bug,单脚本前端完成

- local server 前端页面
This commit is contained in:
zerlei 2024-10-12 17:25:18 +08:00
parent 84ba994048
commit f47975af06
4 changed files with 213 additions and 91 deletions

View file

@ -211,7 +211,7 @@ public class FileDirOpForUnpack(string srcRootPath, string dstRootPath) : FileDi
ZipEntry theEntry; ZipEntry theEntry;
while ((theEntry = s.GetNextEntry()) != null) while ((theEntry = s.GetNextEntry()) != null)
{ {
Console.WriteLine(theEntry.Name); //Console.WriteLine(theEntry.Name);
string directoryName = string directoryName =
dstPath + $"/{Id}/" + Path.GetDirectoryName(theEntry.Name) dstPath + $"/{Id}/" + Path.GetDirectoryName(theEntry.Name)

View file

@ -6,7 +6,6 @@ using Common;
namespace RemoteServer; namespace RemoteServer;
public abstract class StateHelpBase( public abstract class StateHelpBase(
RemoteSyncServer context, RemoteSyncServer context,
SyncProcessStep step = SyncProcessStep.Connect SyncProcessStep step = SyncProcessStep.Connect
@ -132,7 +131,11 @@ public class UnPackAndReleaseHelper(RemoteSyncServer context)
Context.Pipe.SendMsg(CreateMsg("解压完成!")).Wait(); Context.Pipe.SendMsg(CreateMsg("解压完成!")).Wait();
var h = new FinallyPublishHelper(Context); var h = new FinallyPublishHelper(Context);
Context.SetStateHelpBase(h); Context.SetStateHelpBase(h);
Context.Pipe.SendMsg(h.CreateMsg("将要发布数据库,可能时间会较长!")).Wait();
Task.Run(() =>
{
h.FinallyPublish(); h.FinallyPublish();
});
} }
protected override void HandleMsg(SyncMsg msg) { } protected override void HandleMsg(SyncMsg msg) { }
@ -144,10 +147,10 @@ public class FinallyPublishHelper(RemoteSyncServer context)
public void FinallyPublish() public void FinallyPublish()
{ {
// 发布数据库 // 发布数据库
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) if (Context.NotNullSyncConfig.IsDeployDb)
{ {
var arguments = var arguments =
$" /Action:Publish /SourceFile:{RemoteSyncServer.TempRootFile}/{Context.NotNullSyncConfig.Id}/{Context.NotNullSyncConfig.Id}.dacpac" $" /Action:Publish /SourceFile:{RemoteSyncServer.TempRootFile}/{Context.NotNullSyncConfig.Id.ToString()}/{Context.NotNullSyncConfig.Id}.dacpac"
+ $" /TargetServerName:{Context.NotNullSyncConfig.DstDb.ServerName} /TargetDatabaseName:{Context.NotNullSyncConfig.DstDb.DatebaseName}" + $" /TargetServerName:{Context.NotNullSyncConfig.DstDb.ServerName} /TargetDatabaseName:{Context.NotNullSyncConfig.DstDb.DatebaseName}"
+ $" /TargetUser:{Context.NotNullSyncConfig.DstDb.User} /TargetPassword:{Context.NotNullSyncConfig.DstDb.Password} /TargetTrustServerCertificate:True"; + $" /TargetUser:{Context.NotNullSyncConfig.DstDb.User} /TargetPassword:{Context.NotNullSyncConfig.DstDb.Password} /TargetTrustServerCertificate:True";
@ -155,6 +158,7 @@ public class FinallyPublishHelper(RemoteSyncServer context)
new() new()
{ {
StandardOutputEncoding = System.Text.Encoding.UTF8, StandardOutputEncoding = System.Text.Encoding.UTF8,
Arguments = arguments,
FileName = RemoteSyncServer.SqlPackageAbPath, // The command to execute (can be any command line tool) FileName = RemoteSyncServer.SqlPackageAbPath, // The command to execute (can be any command line tool)
// The arguments to pass to the command (e.g., list directory contents) // The arguments to pass to the command (e.g., list directory contents)
RedirectStandardOutput = true, // Redirect the standard output to a string RedirectStandardOutput = true, // Redirect the standard output to a string

View file

@ -0,0 +1 @@
{ "dependencies": { "chalk": "^5.3.0", "ws": "^8.18.0" } }

View file

@ -1,44 +1,123 @@
import chalk from "chalk"; import chalk from "chalk";
import WebSocket from "ws"; import WebSocket from "ws";
//#region ############################## 配置文件 ################################### //#region ############################## 配置文件 ###################################
const LocalHost = "127.0.0.1";
//这是个例子,请在`config`中写你的配置 //这是个例子,请在`config`中写你的配置
const example_config = { const example_config = {
//发布的项目名称,它的目的是为了防止有两个人同时发布一个项目,和便于排查发布历史记录 //发布的名称,每个项目具有唯一的一个名称
Name: "", Name: "Test",
//发布服务器的地址 RemotePwd: "t123",
RemoteUrl: "http://192.168.1.100:8067", //远程服务器地址,也就是发布的目的地,它是正式环境
//源SqlServer数据库的链接字符串一般是开发或者测试数据库**此数据库的ip是相对于运行此脚本的机器** RemoteUrl: "127.0.0.1:6819",
SrcDbConnection: "", //是否发布数据库 sqlserver
//目的SqlServer数据库的链接字符串一般是正式环境数据库**此数据库的ip是相对于运行RemoteServer的机器** IsDeployDb: false,
DstDbConnection: "", //是否发布前重新构建项目
IsDeployProject: false,
//发布数据库时,只同步结构。此数组中的表,将会连数据也一起同步 //项目地址
SyncDataTables:[], LocalProjectAbsolutePath:
"D:/git/HMES-H7-HNFY/HMES-H7-HNFYMF/HMES-H7-HNFYMF.WEB",
//源文件目录地址,是要发布的文件根目录,它是绝对路径,!执行发布时将发布到这个目录! //源文件目录地址,是要发布的文件根目录,它是绝对路径,!执行发布时将发布到这个目录!
LocalRootPath: "", LocalRootPath: "D:/FileSyncTest/src",
//目标文件目录地址,也就是部署服务的机器上的项目文件根目录,它是绝对路径 //目标文件目录地址,也就是部署服务的机器上的项目文件根目录,它是绝对路径
RemoteRootPath: "", RemoteRootPath: "D:/FileSyncTest/dst",
//源数据库配置 SqlServer,将会同步数据库的结构
//根目录下的子目录分子目录是为了针对不同的目录有不同的发布策略它是相对路径即相对于LocalRootPath和RemoteRootPath文件数据依此进行 SrcDb: {
//Host
ServerName: "172.16.12.2",
//数据库名
DatebaseName: "HMES_H7_HNFYMF",
User: "hmes-h7",
Password: "Hmes-h7666",
//是否信任服务器证书
TrustServerCertificate: "True",
//同步的数据,这些数据将会同步
SyncTablesData: [
"dbo.sys_Button",
"dbo.sys_Menu",
"dbo.sys_Module",
"dbo.sys_Page",
],
},
//目标数据库配置 sqlserver
DstDb: {
ServerName: "127.0.0.1",
DatebaseName: "HMES_H7_HNFYMF",
User: "sa",
Password: "0",
TrustServerCertificate: "True",
},
//子目录配置每个子目录都有自己不同的发布策略它是相对路径即相对于LocalRootPath和RemoteRootPath(注意 '/',这将拼成一个完整的路径),文件数据依此进行,
DirFileConfigs: [ DirFileConfigs: [
{ {
//子目录的相对路径 DirPath: "/bin",
DirPath: "",
//排除的文件或目录它是相对路径相对于LocalRootPath和RemoteRootPath //排除的文件或目录它是相对路径相对于LocalRootPath和RemoteRootPath
Excludes: [], Excludes: ["/roslyn", "/Views"],
//只追踪文件或目录它是相对路径相对于LocalRootPath和RemoteRootPath它的优先级最高如果你指定了它的值Excludes将会失效 //只追踪文件或目录它是相对路径相对于LocalRootPath和RemoteRootPath它的优先级最高如果你指定了它的值Excludes将会失效
CherryPicks: [], // CherryPicks:[]
},
],
};
const config = {
//发布的名称,每个项目具有唯一的一个名称
Name: "Test",
RemotePwd: "t123",
//远程服务器地址,也就是发布的目的地,它是正式环境
RemoteUrl: "127.0.0.1:6819",
//是否发布数据库 sqlserver
IsDeployDb: true,
//是否发布前重新构建项目
IsDeployProject: true,
//项目地址
LocalProjectAbsolutePath:
"D:/git/HMES-H7-HNFY/HMES-H7-HNFYMF/HMES-H7-HNFYMF.WEB",
//源文件目录地址,是要发布的文件根目录,它是绝对路径,!执行发布时将发布到这个目录!
LocalRootPath: "D:/FileSyncTest/src",
//目标文件目录地址,也就是部署服务的机器上的项目文件根目录,它是绝对路径
RemoteRootPath: "D:/FileSyncTest/dst",
//源数据库配置 SqlServer,将会同步数据库的结构
SrcDb: {
//Host
ServerName: "172.16.12.2",
//数据库名
DatebaseName: "HMES_H7_HNFYMF",
User: "hmes-h7",
Password: "Hmes-h7666",
//是否信任服务器证书
TrustServerCertificate: "True",
//同步的数据,这些数据将会同步
SyncTablesData: [
"dbo.sys_Button",
"dbo.sys_Menu",
"dbo.sys_Module",
"dbo.sys_Page",
],
},
//目标数据库配置 sqlserver
DstDb: {
ServerName: "127.0.0.1",
DatebaseName: "HMES_H7_HNFYMF",
User: "sa",
Password: "0",
TrustServerCertificate: "True",
},
//子目录配置每个子目录都有自己不同的发布策略它是相对路径即相对于LocalRootPath和RemoteRootPath(注意 '/',这将拼成一个完整的路径),文件数据依此进行,
DirFileConfigs: [
{
DirPath: "/bin",
//排除的文件或目录它是相对路径相对于LocalRootPath和RemoteRootPath
Excludes: ["/roslyn", "/Views"],
//只追踪文件或目录它是相对路径相对于LocalRootPath和RemoteRootPath它的优先级最高如果你指定了它的值Excludes将会失效
// CherryPicks:[]
}, },
], ],
}; };
const config = {};
//#endregion //#endregion
//#region ############################## 打印函数 ################################### //#region ############################## 打印函数 ###################################
let IsSuccess = false;
/** /**
* 在新行打印错误信息 * 在新行打印错误信息
*/ */
@ -62,9 +141,12 @@ function PrintSuccessInNewLine(str) {
/** /**
* 在新行打印一般信息 * 在新行打印一般信息
*/ */
function PrintGeneralInNewLine(str) { function PrintCloseNewLine(str) {
process.stdout.write("\n"); if(IsSuccess) {
process.stdout.write(str); PrintSuccessInNewLine(str)
} else {
PrintErrInNewLine(str)
}
} }
/** /**
* 在当前行打印一般信息打印此行信息之前会清除当前行 * 在当前行打印一般信息打印此行信息之前会清除当前行
@ -80,36 +162,71 @@ function PrintGeneralInCurrentLine(str) {
/** /**
* 1-n. localServer 工作此处只展示信息 * 1-n. localServer 工作此处只展示信息
*/ */
let ws = null;
//这个是固定死的 function MsgCb(MsgIt) {
const wsUrl = `ws://127.0.0.1:4538/websoc?Name=${config.Name}`; if (MsgIt.Type == 2) {
const ws = new WebSocket(wsUrl); PrintGeneralInCurrentLine(MsgIt.Body);
ws.on('open', () => {
//上传配置
ws.send(JSON.stringify(config),(err)=>{
console.log(err)
ws.close()
})
});
ws.on('message', (message) => {
var msg = message.toString('utf8')
DealMsg(msg)
});
ws.on('close', () => {
});
function DealMsg(str) {
var msg = JSON.parse(str)
if(msg.IsSuccess) {
} else { } else {
PrintErrInNewLine(msg.Body) if (MsgIt.Step <= 6) {
ws.close() PrintSuccessInNewLine(`(${MsgIt.Step}/6) ${MsgIt.Body}`);
if (MsgIt.Step == 6) {
if (MsgIt.Body == "发布完成!") {
IsSuccess = true
ws.close();
}
}
} else if(MsgIt == 7) {
PrintErrInNewLine(MsgIt.Body);
} else {
PrintCloseNewLine("(关闭)"+ MsgIt.Body);
}
} }
} }
//#endregion //#endregion
async function connectWebSocket() {
return new Promise((resolve, reject) => {
const wsUrl = `ws://${LocalHost}:6818/websoc?Name=${config.Name}`;
ws = new WebSocket(wsUrl);
ws.onopen = (event) => {
var starter = {
Body: JSON.stringify(config),
Type: 1,
Step: 1,
};
// console.warn("websocket connected!");
ws.send(JSON.stringify(starter));
};
ws.onmessage = (event) => {
// console.log(event.data);
MsgCb(JSON.parse(event.data));
};
ws.onclose = (event) => {
// console.warn(event)
MsgCb({
Type: 0,
Step: 8,
Body: event.reason,
});
// resolve()
};
ws.onerror = (e) => {
// console.error(e);
MsgCb({
Type: 0,
Body: "异常错误,查看 Console",
Step: 7,
});
reject(err);
};
});
}
(async function main() {
try {
await connectWebSocket();
// console.log('WebSocket has closed');
// The script will wait here until the WebSocket connection is closed
} catch (err) {
console.error("Failed to connect or an error occurred:", err);
}
})();