@seayoo-web/scripts 1.0.6 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/git-6CgysH-T.cjs +223 -0
- package/dist/git-DqZLg6mx.js +224 -0
- package/dist/index.cjs.js +257 -0
- package/dist/index.js +19 -481
- package/dist/node.cjs +278 -0
- package/dist/node.es.js +278 -0
- package/package.json +24 -1
- package/types/index.d.ts +3 -4
- package/types/node.d.ts +3 -0
- package/types/src/postcss.d.ts +7 -0
- package/types/src/stylelint.d.ts +11 -0
- package/types/src/vite.lab.d.ts +2 -2
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
const child_process = require("child_process");
|
|
3
|
+
const path = require("path");
|
|
4
|
+
const fs = require("fs-extra");
|
|
5
|
+
require("colors");
|
|
6
|
+
const TemplateDir = "template";
|
|
7
|
+
const InternalDir = "internal";
|
|
8
|
+
const WorkspaceFile = "pnpm-workspace.yaml";
|
|
9
|
+
const root = function() {
|
|
10
|
+
let currentDir = process.cwd();
|
|
11
|
+
while (currentDir !== path.parse(currentDir).root) {
|
|
12
|
+
if (fs.existsSync(path.join(currentDir, WorkspaceFile))) {
|
|
13
|
+
return currentDir;
|
|
14
|
+
}
|
|
15
|
+
currentDir = path.dirname(currentDir);
|
|
16
|
+
}
|
|
17
|
+
if (fs.existsSync(path.join(currentDir, "pnpm-workspace.yaml"))) {
|
|
18
|
+
return currentDir;
|
|
19
|
+
}
|
|
20
|
+
throw new Error("Could not find repository root with pnpm-workspace.yaml".bgRed);
|
|
21
|
+
}();
|
|
22
|
+
async function getTemplates() {
|
|
23
|
+
return await getRepos(TemplateDir);
|
|
24
|
+
}
|
|
25
|
+
async function getRepos(project) {
|
|
26
|
+
const projectDir = path.join(root, project);
|
|
27
|
+
const dirs = await fs.readdir(projectDir);
|
|
28
|
+
const repos = dirs.filter((item) => fs.statSync(path.join(projectDir, item)).isDirectory());
|
|
29
|
+
const descs = await Promise.all(repos.map((repo) => getRepoDesc(project, repo)));
|
|
30
|
+
return repos.map((dir, index) => ({ id: dir, desc: descs[index] })).filter((item) => item.desc !== null);
|
|
31
|
+
}
|
|
32
|
+
async function getRepoDesc(project, dir) {
|
|
33
|
+
const packageFile = path.join(root, project, dir, "package.json");
|
|
34
|
+
if (!await fs.exists(packageFile)) {
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
const content = await fs.readJson(packageFile, "utf8");
|
|
38
|
+
return (content.description || "") + "";
|
|
39
|
+
}
|
|
40
|
+
async function getProjects(returnAll) {
|
|
41
|
+
const rootPkgPath = path.join(root, WorkspaceFile);
|
|
42
|
+
if (await fs.pathExists(rootPkgPath)) {
|
|
43
|
+
const content = await fs.readFile(rootPkgPath, "utf8");
|
|
44
|
+
const dirs = (content.match(/- "(?:.+?)\/*"/g) || []).map((t) => t.slice(3, -3));
|
|
45
|
+
const names = await Promise.all(dirs.map(getProjectName));
|
|
46
|
+
const projects = dirs.map((id, index) => ({ id, name: names[index] })).filter((project) => !project.name.includes("disabled"));
|
|
47
|
+
return returnAll === true ? projects : projects.filter((project) => project.id !== InternalDir && project.id !== TemplateDir);
|
|
48
|
+
}
|
|
49
|
+
return [];
|
|
50
|
+
}
|
|
51
|
+
async function getProjectName(project) {
|
|
52
|
+
const namef = path.join(project, ".name");
|
|
53
|
+
if (await fs.exists(namef)) {
|
|
54
|
+
const name = await fs.readFile(namef, "utf8");
|
|
55
|
+
return name.trim().replace(/\n[\d\D]+/g, "");
|
|
56
|
+
}
|
|
57
|
+
return project;
|
|
58
|
+
}
|
|
59
|
+
async function copyTemplate(templateName, targetDir) {
|
|
60
|
+
const templateSourceDir = path.join(root, TemplateDir, templateName);
|
|
61
|
+
await fs.copy(templateSourceDir, targetDir, {
|
|
62
|
+
filter: (src) => {
|
|
63
|
+
return !src.includes("node_modules") && !src.includes(".git") && !src.endsWith(".local");
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
async function addProjectToWorkspace(project) {
|
|
68
|
+
const rootWorkspacePath = path.join(root, WorkspaceFile);
|
|
69
|
+
if (await fs.pathExists(rootWorkspacePath)) {
|
|
70
|
+
let content = await fs.readFile(rootWorkspacePath, "utf8");
|
|
71
|
+
if (!content.includes(`- "${project}/*"`)) {
|
|
72
|
+
content += ` - "${project}/*"
|
|
73
|
+
`;
|
|
74
|
+
}
|
|
75
|
+
await fs.writeFile(rootWorkspacePath, content);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
async function removeProjectFromWorkspace(project) {
|
|
79
|
+
const rootWorkspacePath = path.join(root, WorkspaceFile);
|
|
80
|
+
if (await fs.pathExists(rootWorkspacePath)) {
|
|
81
|
+
const content = (await fs.readFile(rootWorkspacePath, "utf8")).replace(
|
|
82
|
+
new RegExp(`\\n.*\\- "${project}\\/\\*"`),
|
|
83
|
+
""
|
|
84
|
+
);
|
|
85
|
+
await fs.writeFile(rootWorkspacePath, content);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
function getNowTime() {
|
|
89
|
+
const now = /* @__PURE__ */ new Date();
|
|
90
|
+
return `${now.getFullYear()}/${fillZ(now.getMonth() + 1)}/${fillZ(now.getDate())} ${fillZ(now.getHours())}:${fillZ(now.getMinutes())}`;
|
|
91
|
+
}
|
|
92
|
+
function fillZ(a) {
|
|
93
|
+
return ("0" + a).slice(-2);
|
|
94
|
+
}
|
|
95
|
+
const MainBranchName = "main";
|
|
96
|
+
const DeployTagPrefix = "deploy#";
|
|
97
|
+
function converToDeployTagName(deployTo) {
|
|
98
|
+
return `${DeployTagPrefix}${deployTo.toLowerCase().replace(/(?:^https?:\/\/|\/*$)/gi, "")}`;
|
|
99
|
+
}
|
|
100
|
+
async function execCmd(cmd, ignoreWarning = false) {
|
|
101
|
+
return new Promise((resolve, reject) => {
|
|
102
|
+
child_process.exec(cmd, { cwd: root, env: { ...process.env } }, (error, stdout, stderr) => {
|
|
103
|
+
if (error || stderr && !ignoreWarning) {
|
|
104
|
+
console.error(cmd, error, stderr);
|
|
105
|
+
reject(`执行命令时出错: ${(error == null ? void 0 : error.message) || stderr}`);
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
resolve(stdout.trim());
|
|
109
|
+
});
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
async function getCommitInfo(command, mode, deployTo) {
|
|
113
|
+
if (command !== "build" || mode === "preview" || mode === "prev") {
|
|
114
|
+
return { hash: await getCommitHash(), logs: [] };
|
|
115
|
+
}
|
|
116
|
+
if (await hasUncommittedChanges()) {
|
|
117
|
+
console.error(`在部署前需要提交所有代码!`.red);
|
|
118
|
+
process.exit(1);
|
|
119
|
+
}
|
|
120
|
+
if (await getCurrentBranchName() !== MainBranchName) {
|
|
121
|
+
console.error(`正式环境部署需要在 ${`${MainBranchName}分支`.bgRed} 操作!`.red);
|
|
122
|
+
process.exit(1);
|
|
123
|
+
}
|
|
124
|
+
const unCommitChanges = await countUnsubmitChanges(MainBranchName);
|
|
125
|
+
if (unCommitChanges > 0) {
|
|
126
|
+
console.error("正式环境部署需要先将代码同步到服务器!".red, `发现 ${unCommitChanges} 个 commit 差异`.red);
|
|
127
|
+
process.exit(1);
|
|
128
|
+
}
|
|
129
|
+
const [currentCommit, lastDeployTag] = await Promise.all([getCommitHash(), getLastDeployTag(deployTo)]);
|
|
130
|
+
const commitLogs = await getCommitLogs(currentCommit, lastDeployTag, "./");
|
|
131
|
+
return { hash: currentCommit, logs: commitLogs };
|
|
132
|
+
}
|
|
133
|
+
async function getLastDeployTag(deployTo) {
|
|
134
|
+
await fetchTags();
|
|
135
|
+
const deployTags = await getDeployTags();
|
|
136
|
+
const tag = converToDeployTagName(deployTo);
|
|
137
|
+
return deployTags.includes(tag) ? tag : "";
|
|
138
|
+
}
|
|
139
|
+
async function createPageDeployTag(page, deployTo, finderUser) {
|
|
140
|
+
const tagName = converToDeployTagName(deployTo);
|
|
141
|
+
const gitUser = await execCmd(`git config user.email`).catch(() => "");
|
|
142
|
+
await execCmd(
|
|
143
|
+
[`git tag -f ${tagName} -m "${getNowTime()} deployed by ${gitUser || finderUser}`, page ? `from ${page}` : ""].filter((c) => !!c).join(" ")
|
|
144
|
+
);
|
|
145
|
+
try {
|
|
146
|
+
await execCmd(`git push origin -f ${tagName}`, true);
|
|
147
|
+
} catch (e) {
|
|
148
|
+
await execCmd(`git push origin --tags`, true);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
async function getCommitHash() {
|
|
152
|
+
return (await execCmd("git rev-parse HEAD")).slice(0, 8);
|
|
153
|
+
}
|
|
154
|
+
async function getCurrentBranchName() {
|
|
155
|
+
return await execCmd("git rev-parse --abbrev-ref HEAD");
|
|
156
|
+
}
|
|
157
|
+
async function fetchTags() {
|
|
158
|
+
await execCmd("git fetch --tags", true);
|
|
159
|
+
}
|
|
160
|
+
async function getDeployTags() {
|
|
161
|
+
const result = await execCmd("git tag");
|
|
162
|
+
return result.split("\n").filter((tag) => tag.startsWith(DeployTagPrefix));
|
|
163
|
+
}
|
|
164
|
+
async function getCommitLogs(branchOrCommit, sinceCommit, codePath) {
|
|
165
|
+
const cmd = [
|
|
166
|
+
"git log",
|
|
167
|
+
sinceCommit ? `${sinceCommit}..${branchOrCommit || "HEAD"}` : branchOrCommit || "",
|
|
168
|
+
`--oneline --pretty=format:"[%cd][%h] %s" --date=short -n 60`,
|
|
169
|
+
`-- ${codePath}`
|
|
170
|
+
].filter((f) => !!f).join(" ");
|
|
171
|
+
const result = await execCmd(cmd);
|
|
172
|
+
return result ? result.split("\n") : [];
|
|
173
|
+
}
|
|
174
|
+
async function hasUncommittedChanges() {
|
|
175
|
+
const result = await execCmd("git status --porcelain");
|
|
176
|
+
return result !== "";
|
|
177
|
+
}
|
|
178
|
+
async function countUnsubmitChanges(branch) {
|
|
179
|
+
const result = await execCmd(`git rev-list --count ${branch} "^origin/${branch}"`);
|
|
180
|
+
return parseInt(result, 10);
|
|
181
|
+
}
|
|
182
|
+
async function checkGitStatusBeforeDestory() {
|
|
183
|
+
if (await hasUncommittedChanges()) {
|
|
184
|
+
console.error(`在销毁前需要提交所有代码!`.red);
|
|
185
|
+
process.exit(1);
|
|
186
|
+
}
|
|
187
|
+
if (await getCurrentBranchName() !== MainBranchName) {
|
|
188
|
+
console.error(`销毁操作需要在 ${`${MainBranchName}分支`.bgRed} 进行!`.red);
|
|
189
|
+
process.exit(1);
|
|
190
|
+
}
|
|
191
|
+
const unCommitChanges = await countUnsubmitChanges(MainBranchName);
|
|
192
|
+
if (unCommitChanges > 0) {
|
|
193
|
+
console.error("销毁操作需要先将代码同步到服务器!".red, `发现 ${unCommitChanges} 个 commit 差异`.red);
|
|
194
|
+
process.exit(1);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
async function createBackupTag(action, info) {
|
|
198
|
+
const tagName = `backup#${action}-${info}`;
|
|
199
|
+
const gitUser = await execCmd(`git config user.email`).catch(() => "");
|
|
200
|
+
await execCmd(`git tag -f ${tagName} -m "${getNowTime()} destroyed by ${gitUser || "unknown"}`);
|
|
201
|
+
try {
|
|
202
|
+
await execCmd(`git push origin -f ${tagName}`, true);
|
|
203
|
+
} catch (e) {
|
|
204
|
+
await execCmd(`git push origin --tags`, true);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
async function submitAllDeletionChanges(message) {
|
|
208
|
+
const branch = await getCurrentBranchName();
|
|
209
|
+
await execCmd(`git add --all :/ && git commit -m "${message}" && git push origin ${branch}`, true);
|
|
210
|
+
}
|
|
211
|
+
exports.addProjectToWorkspace = addProjectToWorkspace;
|
|
212
|
+
exports.checkGitStatusBeforeDestory = checkGitStatusBeforeDestory;
|
|
213
|
+
exports.copyTemplate = copyTemplate;
|
|
214
|
+
exports.createBackupTag = createBackupTag;
|
|
215
|
+
exports.createPageDeployTag = createPageDeployTag;
|
|
216
|
+
exports.getCommitInfo = getCommitInfo;
|
|
217
|
+
exports.getNowTime = getNowTime;
|
|
218
|
+
exports.getProjects = getProjects;
|
|
219
|
+
exports.getRepos = getRepos;
|
|
220
|
+
exports.getTemplates = getTemplates;
|
|
221
|
+
exports.removeProjectFromWorkspace = removeProjectFromWorkspace;
|
|
222
|
+
exports.root = root;
|
|
223
|
+
exports.submitAllDeletionChanges = submitAllDeletionChanges;
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
import { exec } from "child_process";
|
|
2
|
+
import path from "path";
|
|
3
|
+
import fs from "fs-extra";
|
|
4
|
+
import "colors";
|
|
5
|
+
const TemplateDir = "template";
|
|
6
|
+
const InternalDir = "internal";
|
|
7
|
+
const WorkspaceFile = "pnpm-workspace.yaml";
|
|
8
|
+
const root = function() {
|
|
9
|
+
let currentDir = process.cwd();
|
|
10
|
+
while (currentDir !== path.parse(currentDir).root) {
|
|
11
|
+
if (fs.existsSync(path.join(currentDir, WorkspaceFile))) {
|
|
12
|
+
return currentDir;
|
|
13
|
+
}
|
|
14
|
+
currentDir = path.dirname(currentDir);
|
|
15
|
+
}
|
|
16
|
+
if (fs.existsSync(path.join(currentDir, "pnpm-workspace.yaml"))) {
|
|
17
|
+
return currentDir;
|
|
18
|
+
}
|
|
19
|
+
throw new Error("Could not find repository root with pnpm-workspace.yaml".bgRed);
|
|
20
|
+
}();
|
|
21
|
+
async function getTemplates() {
|
|
22
|
+
return await getRepos(TemplateDir);
|
|
23
|
+
}
|
|
24
|
+
async function getRepos(project) {
|
|
25
|
+
const projectDir = path.join(root, project);
|
|
26
|
+
const dirs = await fs.readdir(projectDir);
|
|
27
|
+
const repos = dirs.filter((item) => fs.statSync(path.join(projectDir, item)).isDirectory());
|
|
28
|
+
const descs = await Promise.all(repos.map((repo) => getRepoDesc(project, repo)));
|
|
29
|
+
return repos.map((dir, index) => ({ id: dir, desc: descs[index] })).filter((item) => item.desc !== null);
|
|
30
|
+
}
|
|
31
|
+
async function getRepoDesc(project, dir) {
|
|
32
|
+
const packageFile = path.join(root, project, dir, "package.json");
|
|
33
|
+
if (!await fs.exists(packageFile)) {
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
const content = await fs.readJson(packageFile, "utf8");
|
|
37
|
+
return (content.description || "") + "";
|
|
38
|
+
}
|
|
39
|
+
async function getProjects(returnAll) {
|
|
40
|
+
const rootPkgPath = path.join(root, WorkspaceFile);
|
|
41
|
+
if (await fs.pathExists(rootPkgPath)) {
|
|
42
|
+
const content = await fs.readFile(rootPkgPath, "utf8");
|
|
43
|
+
const dirs = (content.match(/- "(?:.+?)\/*"/g) || []).map((t) => t.slice(3, -3));
|
|
44
|
+
const names = await Promise.all(dirs.map(getProjectName));
|
|
45
|
+
const projects = dirs.map((id, index) => ({ id, name: names[index] })).filter((project) => !project.name.includes("disabled"));
|
|
46
|
+
return returnAll === true ? projects : projects.filter((project) => project.id !== InternalDir && project.id !== TemplateDir);
|
|
47
|
+
}
|
|
48
|
+
return [];
|
|
49
|
+
}
|
|
50
|
+
async function getProjectName(project) {
|
|
51
|
+
const namef = path.join(project, ".name");
|
|
52
|
+
if (await fs.exists(namef)) {
|
|
53
|
+
const name = await fs.readFile(namef, "utf8");
|
|
54
|
+
return name.trim().replace(/\n[\d\D]+/g, "");
|
|
55
|
+
}
|
|
56
|
+
return project;
|
|
57
|
+
}
|
|
58
|
+
async function copyTemplate(templateName, targetDir) {
|
|
59
|
+
const templateSourceDir = path.join(root, TemplateDir, templateName);
|
|
60
|
+
await fs.copy(templateSourceDir, targetDir, {
|
|
61
|
+
filter: (src) => {
|
|
62
|
+
return !src.includes("node_modules") && !src.includes(".git") && !src.endsWith(".local");
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
async function addProjectToWorkspace(project) {
|
|
67
|
+
const rootWorkspacePath = path.join(root, WorkspaceFile);
|
|
68
|
+
if (await fs.pathExists(rootWorkspacePath)) {
|
|
69
|
+
let content = await fs.readFile(rootWorkspacePath, "utf8");
|
|
70
|
+
if (!content.includes(`- "${project}/*"`)) {
|
|
71
|
+
content += ` - "${project}/*"
|
|
72
|
+
`;
|
|
73
|
+
}
|
|
74
|
+
await fs.writeFile(rootWorkspacePath, content);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
async function removeProjectFromWorkspace(project) {
|
|
78
|
+
const rootWorkspacePath = path.join(root, WorkspaceFile);
|
|
79
|
+
if (await fs.pathExists(rootWorkspacePath)) {
|
|
80
|
+
const content = (await fs.readFile(rootWorkspacePath, "utf8")).replace(
|
|
81
|
+
new RegExp(`\\n.*\\- "${project}\\/\\*"`),
|
|
82
|
+
""
|
|
83
|
+
);
|
|
84
|
+
await fs.writeFile(rootWorkspacePath, content);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
function getNowTime() {
|
|
88
|
+
const now = /* @__PURE__ */ new Date();
|
|
89
|
+
return `${now.getFullYear()}/${fillZ(now.getMonth() + 1)}/${fillZ(now.getDate())} ${fillZ(now.getHours())}:${fillZ(now.getMinutes())}`;
|
|
90
|
+
}
|
|
91
|
+
function fillZ(a) {
|
|
92
|
+
return ("0" + a).slice(-2);
|
|
93
|
+
}
|
|
94
|
+
const MainBranchName = "main";
|
|
95
|
+
const DeployTagPrefix = "deploy#";
|
|
96
|
+
function converToDeployTagName(deployTo) {
|
|
97
|
+
return `${DeployTagPrefix}${deployTo.toLowerCase().replace(/(?:^https?:\/\/|\/*$)/gi, "")}`;
|
|
98
|
+
}
|
|
99
|
+
async function execCmd(cmd, ignoreWarning = false) {
|
|
100
|
+
return new Promise((resolve, reject) => {
|
|
101
|
+
exec(cmd, { cwd: root, env: { ...process.env } }, (error, stdout, stderr) => {
|
|
102
|
+
if (error || stderr && !ignoreWarning) {
|
|
103
|
+
console.error(cmd, error, stderr);
|
|
104
|
+
reject(`执行命令时出错: ${(error == null ? void 0 : error.message) || stderr}`);
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
resolve(stdout.trim());
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
async function getCommitInfo(command, mode, deployTo) {
|
|
112
|
+
if (command !== "build" || mode === "preview" || mode === "prev") {
|
|
113
|
+
return { hash: await getCommitHash(), logs: [] };
|
|
114
|
+
}
|
|
115
|
+
if (await hasUncommittedChanges()) {
|
|
116
|
+
console.error(`在部署前需要提交所有代码!`.red);
|
|
117
|
+
process.exit(1);
|
|
118
|
+
}
|
|
119
|
+
if (await getCurrentBranchName() !== MainBranchName) {
|
|
120
|
+
console.error(`正式环境部署需要在 ${`${MainBranchName}分支`.bgRed} 操作!`.red);
|
|
121
|
+
process.exit(1);
|
|
122
|
+
}
|
|
123
|
+
const unCommitChanges = await countUnsubmitChanges(MainBranchName);
|
|
124
|
+
if (unCommitChanges > 0) {
|
|
125
|
+
console.error("正式环境部署需要先将代码同步到服务器!".red, `发现 ${unCommitChanges} 个 commit 差异`.red);
|
|
126
|
+
process.exit(1);
|
|
127
|
+
}
|
|
128
|
+
const [currentCommit, lastDeployTag] = await Promise.all([getCommitHash(), getLastDeployTag(deployTo)]);
|
|
129
|
+
const commitLogs = await getCommitLogs(currentCommit, lastDeployTag, "./");
|
|
130
|
+
return { hash: currentCommit, logs: commitLogs };
|
|
131
|
+
}
|
|
132
|
+
async function getLastDeployTag(deployTo) {
|
|
133
|
+
await fetchTags();
|
|
134
|
+
const deployTags = await getDeployTags();
|
|
135
|
+
const tag = converToDeployTagName(deployTo);
|
|
136
|
+
return deployTags.includes(tag) ? tag : "";
|
|
137
|
+
}
|
|
138
|
+
async function createPageDeployTag(page, deployTo, finderUser) {
|
|
139
|
+
const tagName = converToDeployTagName(deployTo);
|
|
140
|
+
const gitUser = await execCmd(`git config user.email`).catch(() => "");
|
|
141
|
+
await execCmd(
|
|
142
|
+
[`git tag -f ${tagName} -m "${getNowTime()} deployed by ${gitUser || finderUser}`, page ? `from ${page}` : ""].filter((c) => !!c).join(" ")
|
|
143
|
+
);
|
|
144
|
+
try {
|
|
145
|
+
await execCmd(`git push origin -f ${tagName}`, true);
|
|
146
|
+
} catch (e) {
|
|
147
|
+
await execCmd(`git push origin --tags`, true);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
async function getCommitHash() {
|
|
151
|
+
return (await execCmd("git rev-parse HEAD")).slice(0, 8);
|
|
152
|
+
}
|
|
153
|
+
async function getCurrentBranchName() {
|
|
154
|
+
return await execCmd("git rev-parse --abbrev-ref HEAD");
|
|
155
|
+
}
|
|
156
|
+
async function fetchTags() {
|
|
157
|
+
await execCmd("git fetch --tags", true);
|
|
158
|
+
}
|
|
159
|
+
async function getDeployTags() {
|
|
160
|
+
const result = await execCmd("git tag");
|
|
161
|
+
return result.split("\n").filter((tag) => tag.startsWith(DeployTagPrefix));
|
|
162
|
+
}
|
|
163
|
+
async function getCommitLogs(branchOrCommit, sinceCommit, codePath) {
|
|
164
|
+
const cmd = [
|
|
165
|
+
"git log",
|
|
166
|
+
sinceCommit ? `${sinceCommit}..${branchOrCommit || "HEAD"}` : branchOrCommit || "",
|
|
167
|
+
`--oneline --pretty=format:"[%cd][%h] %s" --date=short -n 60`,
|
|
168
|
+
`-- ${codePath}`
|
|
169
|
+
].filter((f) => !!f).join(" ");
|
|
170
|
+
const result = await execCmd(cmd);
|
|
171
|
+
return result ? result.split("\n") : [];
|
|
172
|
+
}
|
|
173
|
+
async function hasUncommittedChanges() {
|
|
174
|
+
const result = await execCmd("git status --porcelain");
|
|
175
|
+
return result !== "";
|
|
176
|
+
}
|
|
177
|
+
async function countUnsubmitChanges(branch) {
|
|
178
|
+
const result = await execCmd(`git rev-list --count ${branch} "^origin/${branch}"`);
|
|
179
|
+
return parseInt(result, 10);
|
|
180
|
+
}
|
|
181
|
+
async function checkGitStatusBeforeDestory() {
|
|
182
|
+
if (await hasUncommittedChanges()) {
|
|
183
|
+
console.error(`在销毁前需要提交所有代码!`.red);
|
|
184
|
+
process.exit(1);
|
|
185
|
+
}
|
|
186
|
+
if (await getCurrentBranchName() !== MainBranchName) {
|
|
187
|
+
console.error(`销毁操作需要在 ${`${MainBranchName}分支`.bgRed} 进行!`.red);
|
|
188
|
+
process.exit(1);
|
|
189
|
+
}
|
|
190
|
+
const unCommitChanges = await countUnsubmitChanges(MainBranchName);
|
|
191
|
+
if (unCommitChanges > 0) {
|
|
192
|
+
console.error("销毁操作需要先将代码同步到服务器!".red, `发现 ${unCommitChanges} 个 commit 差异`.red);
|
|
193
|
+
process.exit(1);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
async function createBackupTag(action, info) {
|
|
197
|
+
const tagName = `backup#${action}-${info}`;
|
|
198
|
+
const gitUser = await execCmd(`git config user.email`).catch(() => "");
|
|
199
|
+
await execCmd(`git tag -f ${tagName} -m "${getNowTime()} destroyed by ${gitUser || "unknown"}`);
|
|
200
|
+
try {
|
|
201
|
+
await execCmd(`git push origin -f ${tagName}`, true);
|
|
202
|
+
} catch (e) {
|
|
203
|
+
await execCmd(`git push origin --tags`, true);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
async function submitAllDeletionChanges(message) {
|
|
207
|
+
const branch = await getCurrentBranchName();
|
|
208
|
+
await execCmd(`git add --all :/ && git commit -m "${message}" && git push origin ${branch}`, true);
|
|
209
|
+
}
|
|
210
|
+
export {
|
|
211
|
+
getCommitInfo as a,
|
|
212
|
+
addProjectToWorkspace as b,
|
|
213
|
+
createPageDeployTag as c,
|
|
214
|
+
copyTemplate as d,
|
|
215
|
+
getProjects as e,
|
|
216
|
+
getTemplates as f,
|
|
217
|
+
getNowTime as g,
|
|
218
|
+
checkGitStatusBeforeDestory as h,
|
|
219
|
+
createBackupTag as i,
|
|
220
|
+
removeProjectFromWorkspace as j,
|
|
221
|
+
getRepos as k,
|
|
222
|
+
root as r,
|
|
223
|
+
submitAllDeletionChanges as s
|
|
224
|
+
};
|