@seayoo-web/scripts 3.1.10 → 4.0.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-C1rpf4Ed.js +343 -0
- package/dist/index.js +391 -398
- package/dist/node.js +538 -606
- package/package.json +17 -33
- package/types/index.d.ts +2 -2
- package/types/src/commit.d.ts +0 -1
- package/types/src/create.d.ts +0 -1
- package/types/src/destroy.d.ts +0 -1
- package/types/src/env.d.ts +0 -1
- package/types/src/oxfmt.d.ts +7 -0
- package/types/src/oxlint.d.ts +43 -0
- package/types/src/stylelint.d.ts +3 -0
- package/types/src/utils.d.ts +0 -1
- package/types/src/vite.lab.d.ts +1 -2
- package/dist/git-B0Cnp5wC.js +0 -310
package/package.json
CHANGED
|
@@ -1,17 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@seayoo-web/scripts",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.0.0",
|
|
4
4
|
"description": "scripts for seayoo web repos",
|
|
5
|
-
"
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": "web@seayoo.com",
|
|
6
7
|
"source": "index.ts",
|
|
7
|
-
"main": "./dist/index.js",
|
|
8
|
-
"module": "./dist/index.js",
|
|
9
|
-
"types": "./types/index.d.ts",
|
|
10
8
|
"files": [
|
|
11
9
|
"dist",
|
|
12
10
|
"types",
|
|
13
11
|
"README.md"
|
|
14
12
|
],
|
|
13
|
+
"type": "module",
|
|
14
|
+
"main": "./dist/index.js",
|
|
15
|
+
"module": "./dist/index.js",
|
|
16
|
+
"types": "./types/index.d.ts",
|
|
15
17
|
"exports": {
|
|
16
18
|
".": {
|
|
17
19
|
"types": "./types/index.d.ts",
|
|
@@ -24,53 +26,35 @@
|
|
|
24
26
|
"default": "./dist/node.js"
|
|
25
27
|
}
|
|
26
28
|
},
|
|
27
|
-
"engines": {
|
|
28
|
-
"node": ">=22"
|
|
29
|
-
},
|
|
30
|
-
"author": "web@seayoo.com",
|
|
31
|
-
"license": "MIT",
|
|
32
29
|
"publishConfig": {
|
|
33
30
|
"access": "public"
|
|
34
31
|
},
|
|
35
32
|
"dependencies": {
|
|
36
33
|
"@sentry/vite-plugin": "^4.9.1",
|
|
37
|
-
"@vitejs/plugin-legacy": "^
|
|
38
|
-
"@vitejs/plugin-vue": "^6.0.
|
|
39
|
-
"@vue/eslint-config-prettier": "^10.2.0",
|
|
40
|
-
"@vue/eslint-config-typescript": "^14.7.0",
|
|
34
|
+
"@vitejs/plugin-legacy": "^8.0.0",
|
|
35
|
+
"@vitejs/plugin-vue": "^6.0.5",
|
|
41
36
|
"chokidar": "^4.0.3",
|
|
42
37
|
"colors": "^1.4.0",
|
|
43
38
|
"commander": "^13.1.0",
|
|
44
|
-
"
|
|
45
|
-
"eslint-plugin-vue": "^10.8.0",
|
|
46
|
-
"fs-extra": "^11.3.3",
|
|
39
|
+
"fs-extra": "^11.3.4",
|
|
47
40
|
"html-minifier-terser": "^7.2.0",
|
|
48
41
|
"inquirer": "^12.11.1",
|
|
49
42
|
"jiti": "^2.6.1",
|
|
50
43
|
"ora": "^8.2.0",
|
|
51
|
-
"
|
|
52
|
-
"
|
|
53
|
-
"
|
|
54
|
-
"terser": "^5.46.
|
|
55
|
-
"vite-plugin-stylelint": "^6.0.4",
|
|
44
|
+
"oxfmt": "^0.41.0",
|
|
45
|
+
"oxlint": "^1.56.0",
|
|
46
|
+
"rollup-plugin-visualizer": "^7.0.1",
|
|
47
|
+
"terser": "^5.46.1",
|
|
56
48
|
"@seayoo-web/finder": "^2.2.2"
|
|
57
49
|
},
|
|
58
50
|
"devDependencies": {
|
|
59
51
|
"@types/fs-extra": "^11.0.4",
|
|
60
52
|
"@types/html-minifier-terser": "^7.0.2",
|
|
61
|
-
"@types/node": "^22.19.
|
|
62
|
-
"@typescript-eslint/utils": "^8.56.1",
|
|
63
|
-
"eslint": "^9.33.0",
|
|
64
|
-
"stylelint": "^16.23.1",
|
|
65
|
-
"stylelint-config-recess-order": "^7.2.0",
|
|
66
|
-
"stylelint-config-standard": "^39.0.0",
|
|
53
|
+
"@types/node": "^22.19.15",
|
|
67
54
|
"@seayoo-web/tsconfig": "^1.0.6"
|
|
68
55
|
},
|
|
69
|
-
"
|
|
70
|
-
"
|
|
71
|
-
"stylelint": "^16.26.1",
|
|
72
|
-
"stylelint-config-recess-order": "^7.6.1",
|
|
73
|
-
"stylelint-config-standard": "^39.0.1"
|
|
56
|
+
"engines": {
|
|
57
|
+
"node": ">=22"
|
|
74
58
|
},
|
|
75
59
|
"scripts": {
|
|
76
60
|
"build": "vite build && tsc --emitDeclarationOnly",
|
package/types/index.d.ts
CHANGED
package/types/src/commit.d.ts
CHANGED
package/types/src/create.d.ts
CHANGED
package/types/src/destroy.d.ts
CHANGED
package/types/src/env.d.ts
CHANGED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { OxlintConfig } from "oxlint";
|
|
2
|
+
export declare function defineOxlintConfig(options?: {
|
|
3
|
+
rules?: OxlintConfig["rules"];
|
|
4
|
+
overrides?: OxlintConfig["overrides"];
|
|
5
|
+
plugins?: OxlintConfig["plugins"];
|
|
6
|
+
/**
|
|
7
|
+
* 设置运行环境可以获得对应的全局变量,默认 `{ browser: true }`
|
|
8
|
+
*
|
|
9
|
+
* https://eslint.org/docs/v8.x/use/configure/language-options#specifying-environments
|
|
10
|
+
*/
|
|
11
|
+
env?: {
|
|
12
|
+
browser?: boolean;
|
|
13
|
+
node?: boolean;
|
|
14
|
+
"shared-node-browser"?: boolean;
|
|
15
|
+
worker?: boolean;
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* 设置全局变量的访问控制
|
|
19
|
+
*
|
|
20
|
+
* https://oxc.rs/docs/guide/usage/linter/config-file-reference.html#globals
|
|
21
|
+
*/
|
|
22
|
+
globals: OxlintConfig["globals"];
|
|
23
|
+
}): {
|
|
24
|
+
plugins: ("eslint" | "react" | "unicorn" | "typescript" | "oxc" | "import" | "jsdoc" | "jest" | "vitest" | "jsx-a11y" | "nextjs" | "react-perf" | "promise" | "node" | "vue")[];
|
|
25
|
+
categories: {
|
|
26
|
+
correctness: "error";
|
|
27
|
+
perf: "warn";
|
|
28
|
+
suspicious: "warn";
|
|
29
|
+
};
|
|
30
|
+
ignorePatterns: string[];
|
|
31
|
+
rules: {
|
|
32
|
+
"vue/multi-word-component-names": "off";
|
|
33
|
+
"import/no-unresolved": "off";
|
|
34
|
+
};
|
|
35
|
+
env: {
|
|
36
|
+
browser?: boolean;
|
|
37
|
+
node?: boolean;
|
|
38
|
+
"shared-node-browser"?: boolean;
|
|
39
|
+
worker?: boolean;
|
|
40
|
+
};
|
|
41
|
+
overrides: import("oxlint").OxlintOverride[] | undefined;
|
|
42
|
+
globals: import("oxlint").OxlintGlobals | undefined;
|
|
43
|
+
};
|
package/types/src/stylelint.d.ts
CHANGED
|
@@ -13,6 +13,9 @@ export declare const stylelintConfig: {
|
|
|
13
13
|
"color-function-notation": string;
|
|
14
14
|
"color-function-alias-notation": string;
|
|
15
15
|
"alpha-value-notation": string;
|
|
16
|
+
"unit-no-unknown": (boolean | {
|
|
17
|
+
ignoreUnits: string[];
|
|
18
|
+
})[];
|
|
16
19
|
"selector-pseudo-class-no-unknown": (boolean | {
|
|
17
20
|
ignorePseudoClasses: string[];
|
|
18
21
|
})[];
|
package/types/src/utils.d.ts
CHANGED
package/types/src/vite.lab.d.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import type { UserConfig } from "vite";
|
|
2
1
|
interface LibBuildOption {
|
|
3
2
|
/** 输出目录,默认为 "dist" */
|
|
4
3
|
outDir?: string;
|
|
@@ -12,5 +11,5 @@ interface LibBuildOption {
|
|
|
12
11
|
*
|
|
13
12
|
* 默认排除 "@seayoo-web/request"、"@seayoo-web/utils"、"@seayoo-web/validator"、"@seayoo-web/combo-webview" 不打包
|
|
14
13
|
*/
|
|
15
|
-
export declare function defineLibBuildConfig(option?: LibBuildOption): UserConfig;
|
|
14
|
+
export declare function defineLibBuildConfig(option?: LibBuildOption): import("vite").UserConfig;
|
|
16
15
|
export {};
|
package/dist/git-B0Cnp5wC.js
DELETED
|
@@ -1,310 +0,0 @@
|
|
|
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
|
-
let _root = null;
|
|
9
|
-
async function getMonorepoRoot(ignoreMissing) {
|
|
10
|
-
if (_root !== null) {
|
|
11
|
-
return _root;
|
|
12
|
-
}
|
|
13
|
-
let currentDir = process.cwd();
|
|
14
|
-
while (currentDir !== path.parse(currentDir).root) {
|
|
15
|
-
if (fs.existsSync(path.join(currentDir, WorkspaceFile))) {
|
|
16
|
-
return currentDir;
|
|
17
|
-
}
|
|
18
|
-
currentDir = path.dirname(currentDir);
|
|
19
|
-
}
|
|
20
|
-
if (fs.existsSync(path.join(currentDir, "pnpm-workspace.yaml"))) {
|
|
21
|
-
_root = currentDir;
|
|
22
|
-
return currentDir;
|
|
23
|
-
}
|
|
24
|
-
if (ignoreMissing) {
|
|
25
|
-
return "";
|
|
26
|
-
}
|
|
27
|
-
throw new Error("当前项目不是 monorepo 项目!");
|
|
28
|
-
}
|
|
29
|
-
async function getTemplates() {
|
|
30
|
-
return await getRepos(TemplateDir);
|
|
31
|
-
}
|
|
32
|
-
async function getRepos(project) {
|
|
33
|
-
const root = await getMonorepoRoot();
|
|
34
|
-
const projectDir = path.join(root, project);
|
|
35
|
-
const dirs = await fs.readdir(projectDir);
|
|
36
|
-
const repos = dirs.filter((item) => fs.statSync(path.join(projectDir, item)).isDirectory());
|
|
37
|
-
const descArr = await Promise.all(repos.map((repo) => getRepoDesc(project, repo)));
|
|
38
|
-
return repos.map((dir, index) => ({ id: dir, desc: descArr[index] })).filter((item) => item.desc !== null);
|
|
39
|
-
}
|
|
40
|
-
async function getRepoDesc(project, dir) {
|
|
41
|
-
const root = await getMonorepoRoot();
|
|
42
|
-
const packageFile = path.join(root, project, dir, "package.json");
|
|
43
|
-
if (!await fs.exists(packageFile)) {
|
|
44
|
-
return null;
|
|
45
|
-
}
|
|
46
|
-
const content = await fs.readJson(packageFile, "utf8");
|
|
47
|
-
return (content.description || "") + "";
|
|
48
|
-
}
|
|
49
|
-
async function getProjects(returnAll) {
|
|
50
|
-
const root = await getMonorepoRoot();
|
|
51
|
-
const rootPkgPath = path.join(root, WorkspaceFile);
|
|
52
|
-
if (await fs.pathExists(rootPkgPath)) {
|
|
53
|
-
const content = await fs.readFile(rootPkgPath, "utf8");
|
|
54
|
-
const dirs = /packages:\n(?:\s+-\s".+"\/\*)+/.test(content) ? (content.match(/- "(?:.+)\/\*"/g) || []).map((t) => t.slice(3, -3)) : (content.match(/- (?:.+)\/\*/g) || []).map((t) => t.slice(2, -2));
|
|
55
|
-
const names = await Promise.all(dirs.map(getProjectName));
|
|
56
|
-
const projects = dirs.map((id, index) => ({ id, name: names[index] })).filter((project) => !project.name.includes("disabled"));
|
|
57
|
-
return returnAll === true ? projects : projects.filter((project) => project.id !== InternalDir && project.id !== TemplateDir);
|
|
58
|
-
}
|
|
59
|
-
return [];
|
|
60
|
-
}
|
|
61
|
-
async function getProjectName(project) {
|
|
62
|
-
const nameOfFile = path.join(project, ".name");
|
|
63
|
-
if (await fs.exists(nameOfFile)) {
|
|
64
|
-
const name = await fs.readFile(nameOfFile, "utf8");
|
|
65
|
-
return name.trim().replace(/\n[\d\D]+/g, "");
|
|
66
|
-
}
|
|
67
|
-
return project;
|
|
68
|
-
}
|
|
69
|
-
async function copyTemplate(templateName, targetDir) {
|
|
70
|
-
const root = await getMonorepoRoot();
|
|
71
|
-
const templateSourceDir = path.join(root, TemplateDir, templateName);
|
|
72
|
-
await fs.copy(templateSourceDir, targetDir, {
|
|
73
|
-
filter: (src) => {
|
|
74
|
-
return !src.includes("node_modules") && !src.includes(".git") && !src.endsWith(".local");
|
|
75
|
-
}
|
|
76
|
-
});
|
|
77
|
-
}
|
|
78
|
-
async function copyGlobalFiles(targetDir) {
|
|
79
|
-
const root = await getMonorepoRoot();
|
|
80
|
-
const globalFiles = await fs.readdir(path.join(root, TemplateDir));
|
|
81
|
-
for (const item of globalFiles) {
|
|
82
|
-
const f = path.join(root, TemplateDir, item);
|
|
83
|
-
if (fs.statSync(f).isFile()) {
|
|
84
|
-
await fs.copy(f, path.join(targetDir, item));
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
async function addProjectToWorkspace(project) {
|
|
89
|
-
const root = await getMonorepoRoot();
|
|
90
|
-
const rootWorkspacePath = path.join(root, WorkspaceFile);
|
|
91
|
-
if (await fs.pathExists(rootWorkspacePath)) {
|
|
92
|
-
let content = await fs.readFile(rootWorkspacePath, "utf8");
|
|
93
|
-
if (/packages:\n(?:\s+-\s".+"\/*)+/.test(content)) {
|
|
94
|
-
if (!content.includes(`- "${project}/*"`)) {
|
|
95
|
-
content = content.replace(/(packages:\n(?:\s{2,}-\s.+\n?)+)/, `$1
|
|
96
|
-
- "${project}/*"
|
|
97
|
-
`).replace(/\n{2,}/g, "\n");
|
|
98
|
-
}
|
|
99
|
-
} else {
|
|
100
|
-
if (!content.includes(`- ${project}/*`)) {
|
|
101
|
-
content = content.replace(/(packages:\n(?:\s{2,}-\s.+\n?)+)/, `$1
|
|
102
|
-
- ${project}/*
|
|
103
|
-
`).replace(/\n{2,}/g, "\n");
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
await fs.writeFile(rootWorkspacePath, content);
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
async function removeProjectFromWorkspace(project) {
|
|
110
|
-
const root = await getMonorepoRoot();
|
|
111
|
-
const rootWorkspacePath = path.join(root, WorkspaceFile);
|
|
112
|
-
if (await fs.pathExists(rootWorkspacePath)) {
|
|
113
|
-
const content = (await fs.readFile(rootWorkspacePath, "utf8")).replace(
|
|
114
|
-
new RegExp(`\\n.*\\- "${project}\\/\\*"`),
|
|
115
|
-
""
|
|
116
|
-
);
|
|
117
|
-
await fs.writeFile(rootWorkspacePath, content);
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
function getNowTime() {
|
|
121
|
-
const now = /* @__PURE__ */ new Date();
|
|
122
|
-
return `${now.getFullYear()}/${fillZ(now.getMonth() + 1)}/${fillZ(now.getDate())} ${fillZ(now.getHours())}:${fillZ(now.getMinutes())}`;
|
|
123
|
-
}
|
|
124
|
-
function fillZ(a) {
|
|
125
|
-
return ("0" + a).slice(-2);
|
|
126
|
-
}
|
|
127
|
-
function deepMerge(target, ...sourceList) {
|
|
128
|
-
for (const source of sourceList) {
|
|
129
|
-
if (!source || typeof source !== "object") continue;
|
|
130
|
-
for (const key in source) {
|
|
131
|
-
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
132
|
-
const sourceValue = source[key];
|
|
133
|
-
const targetValue = target[key];
|
|
134
|
-
if (isPlainObject(targetValue) && isPlainObject(sourceValue)) {
|
|
135
|
-
target[key] = deepMerge({ ...targetValue }, sourceValue);
|
|
136
|
-
} else if (isPlainObject(sourceValue)) {
|
|
137
|
-
target[key] = deepMerge({}, sourceValue);
|
|
138
|
-
} else if (Array.isArray(sourceValue)) {
|
|
139
|
-
target[key] = [...sourceValue];
|
|
140
|
-
} else {
|
|
141
|
-
target[key] = sourceValue;
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
return target;
|
|
147
|
-
}
|
|
148
|
-
function isPlainObject(value) {
|
|
149
|
-
return typeof value === "object" && value !== null && !Array.isArray(value) && Object.prototype.toString.call(value) === "[object Object]";
|
|
150
|
-
}
|
|
151
|
-
const formatReg = /\{\{\s*([\w\.]+)\s*\}\}/g;
|
|
152
|
-
function format(string, source) {
|
|
153
|
-
return string.replace(formatReg, function(_, keys) {
|
|
154
|
-
let val = source;
|
|
155
|
-
const keyPath = keys.split(".");
|
|
156
|
-
for (let i = 0; i < keyPath.length; i++) {
|
|
157
|
-
const p = keyPath[i];
|
|
158
|
-
val = typeof val === "object" && !!val ? p in val ? val[p] : void 0 : void 0;
|
|
159
|
-
}
|
|
160
|
-
return val === void 0 || val === null ? "" : val + "";
|
|
161
|
-
});
|
|
162
|
-
}
|
|
163
|
-
const MainBranchName = "main";
|
|
164
|
-
const DeployTagPrefix = "deploy_";
|
|
165
|
-
const BackupTagPrefix = "backup_";
|
|
166
|
-
function convertToDeployTagName(deployTo) {
|
|
167
|
-
return `${DeployTagPrefix}${deployTo.toLowerCase().replace(/(?:^https?:\/\/|\/*$)/gi, "").replace(/\//g, "_")}`;
|
|
168
|
-
}
|
|
169
|
-
async function execCmd(cmd, ignoreWarning = false) {
|
|
170
|
-
const root = await getMonorepoRoot(true);
|
|
171
|
-
return new Promise((resolve, reject) => {
|
|
172
|
-
exec(cmd, { cwd: root || "./", env: { ...process.env } }, (error, stdout, stderr) => {
|
|
173
|
-
if (error || stderr && !ignoreWarning) {
|
|
174
|
-
console.error(cmd, error, stderr);
|
|
175
|
-
reject(`执行命令时出错: ${error?.message || stderr}`);
|
|
176
|
-
return;
|
|
177
|
-
}
|
|
178
|
-
resolve(stdout.trim());
|
|
179
|
-
});
|
|
180
|
-
});
|
|
181
|
-
}
|
|
182
|
-
async function getCommitInfo(command, mode, page, deployTo) {
|
|
183
|
-
if (command !== "build") {
|
|
184
|
-
return { hash: await getCommitHash(), logs: [] };
|
|
185
|
-
}
|
|
186
|
-
if (mode === "preview" || mode === "prev") {
|
|
187
|
-
if (!deployTo.includes("preview")) {
|
|
188
|
-
console.error(`预览部署的目标路径必须包含 preview 字样!`.red);
|
|
189
|
-
process.exit(1);
|
|
190
|
-
}
|
|
191
|
-
return { hash: await getCommitHash(), logs: [] };
|
|
192
|
-
}
|
|
193
|
-
if (await hasUncommittedChanges()) {
|
|
194
|
-
console.error(`部署前需要提交所有代码!`.red);
|
|
195
|
-
process.exit(1);
|
|
196
|
-
}
|
|
197
|
-
if (await getCurrentBranchName() !== MainBranchName) {
|
|
198
|
-
console.error(`部署需要在 ${`${MainBranchName}分支`.bgRed} 操作!`.red);
|
|
199
|
-
process.exit(1);
|
|
200
|
-
}
|
|
201
|
-
const unCommitChanges = await countUnSubmitChanges(MainBranchName);
|
|
202
|
-
if (unCommitChanges > 0) {
|
|
203
|
-
console.error("部署前需要先将代码同步到服务器!".red, `发现 ${unCommitChanges} 个 commit 差异`.red);
|
|
204
|
-
process.exit(1);
|
|
205
|
-
}
|
|
206
|
-
await execCmd("git pull", true);
|
|
207
|
-
const [currentCommit, lastDeployTag] = await Promise.all([getCommitHash(), getLastDeployTag(deployTo)]);
|
|
208
|
-
const commitLogs = await getCommitLogs(currentCommit, lastDeployTag, page || "./");
|
|
209
|
-
return { hash: currentCommit, logs: commitLogs };
|
|
210
|
-
}
|
|
211
|
-
async function getLastDeployTag(deployTo) {
|
|
212
|
-
await fetchTags();
|
|
213
|
-
const deployTags = await getDeployTags();
|
|
214
|
-
const tag = convertToDeployTagName(deployTo);
|
|
215
|
-
return deployTags.includes(tag) ? tag : "";
|
|
216
|
-
}
|
|
217
|
-
async function createPageDeployTag(page, deployTo, finderUser) {
|
|
218
|
-
const tagName = convertToDeployTagName(deployTo);
|
|
219
|
-
const gitUser = await execCmd(`git config user.email`).catch(() => "");
|
|
220
|
-
const user = (gitUser || finderUser).replace(/@.+/g, "");
|
|
221
|
-
await execCmd(
|
|
222
|
-
[`git tag -f ${tagName} -m "${getNowTime()} deployed by ${user}`, page ? `from ${page}` : "", '"'].filter((c) => !!c).join(" ")
|
|
223
|
-
);
|
|
224
|
-
try {
|
|
225
|
-
await execCmd(`git push origin -f ${tagName}`, true);
|
|
226
|
-
} catch {
|
|
227
|
-
await execCmd(`git push origin -f --tags`, true);
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
async function getCommitHash() {
|
|
231
|
-
return (await execCmd("git rev-parse HEAD")).slice(0, 8);
|
|
232
|
-
}
|
|
233
|
-
async function getCurrentBranchName() {
|
|
234
|
-
return await execCmd("git rev-parse --abbrev-ref HEAD");
|
|
235
|
-
}
|
|
236
|
-
async function fetchTags() {
|
|
237
|
-
await execCmd("git fetch --tags --force", true);
|
|
238
|
-
}
|
|
239
|
-
async function getDeployTags() {
|
|
240
|
-
const result = await execCmd("git tag");
|
|
241
|
-
return result.split("\n").filter((tag) => tag.startsWith(DeployTagPrefix));
|
|
242
|
-
}
|
|
243
|
-
async function getCommitLogs(branchOrCommit, sinceCommit, codePath) {
|
|
244
|
-
const cmd = [
|
|
245
|
-
"git log",
|
|
246
|
-
sinceCommit ? `${sinceCommit}..${branchOrCommit || "HEAD"}` : branchOrCommit || "",
|
|
247
|
-
/** spell-checker:disable-next-line */
|
|
248
|
-
`--oneline --pretty=format:"[%cd] %s" --date=short -n 60`,
|
|
249
|
-
`-- ${codePath}`
|
|
250
|
-
].filter((f) => !!f && !f.includes("Merge branch")).join(" ");
|
|
251
|
-
const result = await execCmd(cmd);
|
|
252
|
-
return result ? result.split("\n") : [];
|
|
253
|
-
}
|
|
254
|
-
async function hasUncommittedChanges() {
|
|
255
|
-
const result = await execCmd("git status --porcelain");
|
|
256
|
-
return result !== "";
|
|
257
|
-
}
|
|
258
|
-
async function countUnSubmitChanges(branch) {
|
|
259
|
-
const result = await execCmd(`git rev-list --count ${branch} "^origin/${branch}"`);
|
|
260
|
-
return parseInt(result, 10);
|
|
261
|
-
}
|
|
262
|
-
async function checkGitStatusBeforeDestroy() {
|
|
263
|
-
if (await hasUncommittedChanges()) {
|
|
264
|
-
console.error(`在销毁前需要提交所有代码!`.red);
|
|
265
|
-
process.exit(1);
|
|
266
|
-
}
|
|
267
|
-
if (await getCurrentBranchName() !== MainBranchName) {
|
|
268
|
-
console.error(`销毁操作需要在 ${`${MainBranchName}分支`.bgRed} 进行!`.red);
|
|
269
|
-
process.exit(1);
|
|
270
|
-
}
|
|
271
|
-
const unCommitChanges = await countUnSubmitChanges(MainBranchName);
|
|
272
|
-
if (unCommitChanges > 0) {
|
|
273
|
-
console.error("销毁操作需要先将代码同步到服务器!".red, `发现 ${unCommitChanges} 个 commit 差异`.red);
|
|
274
|
-
process.exit(1);
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
|
-
async function createBackupTag(action, info) {
|
|
278
|
-
const tagName = `${BackupTagPrefix}${action}_${info.replace(/\//g, "-")}`;
|
|
279
|
-
const gitUser = await execCmd(`git config user.email`).catch(() => "");
|
|
280
|
-
const user = (gitUser || "unknown").replace(/@.+/g, "");
|
|
281
|
-
await execCmd(`git tag -f ${tagName} -m "${getNowTime()} destroyed by ${user}"`);
|
|
282
|
-
try {
|
|
283
|
-
await execCmd(`git push origin -f ${tagName}`, true);
|
|
284
|
-
} catch {
|
|
285
|
-
await execCmd(`git push origin --tags`, true);
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
async function submitAllDeletionChanges(message) {
|
|
289
|
-
const branch = await getCurrentBranchName();
|
|
290
|
-
await execCmd(`git add --all :/ && git commit -m "${message}" && git push origin ${branch}`, true);
|
|
291
|
-
}
|
|
292
|
-
export {
|
|
293
|
-
getCommitInfo as a,
|
|
294
|
-
getMonorepoRoot as b,
|
|
295
|
-
createPageDeployTag as c,
|
|
296
|
-
addProjectToWorkspace as d,
|
|
297
|
-
copyTemplate as e,
|
|
298
|
-
copyGlobalFiles as f,
|
|
299
|
-
getNowTime as g,
|
|
300
|
-
getProjects as h,
|
|
301
|
-
getTemplates as i,
|
|
302
|
-
checkGitStatusBeforeDestroy as j,
|
|
303
|
-
createBackupTag as k,
|
|
304
|
-
getRepos as l,
|
|
305
|
-
isPlainObject as m,
|
|
306
|
-
format as n,
|
|
307
|
-
deepMerge as o,
|
|
308
|
-
removeProjectFromWorkspace as r,
|
|
309
|
-
submitAllDeletionChanges as s
|
|
310
|
-
};
|