Skip to content

Commit 1833331

Browse files
committed
🎨 重构自动提交逻辑, 增加对指定文件夹进行提交. 支持多数组提交.
1 parent 6014892 commit 1833331

File tree

19 files changed

+589
-294
lines changed

19 files changed

+589
-294
lines changed

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2019-present, Zyao89
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,5 +72,7 @@ module.exports = {
7272
name: '',
7373
email: '',
7474
},
75+
dist: '', // 可选原数据
76+
cname: '', // 可选
7577
}
7678
```

micro-app.deploy.config.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,15 @@
22

33
module.exports = {
44
disabled: false,
5-
git: '',
5+
git: '[email protected]:MicrosApp/MicroApp-Plugin-Deploy-Command.git',
66
branch: {
7-
name: '',
8-
extends: true,
7+
name: 'gh-pages',
8+
// extends: true,
99
},
1010
message: '',
1111
user: {
1212
name: '',
1313
email: '',
1414
},
15+
dist: 'test/gitinfo',
1516
};

package.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@micro-app/plugin-deploy-command",
3-
"version": "0.0.6",
3+
"version": "0.1.0",
44
"description": "[Plugin] auto deploy command plugin.",
55
"main": "src/index.js",
66
"scripts": {
@@ -30,11 +30,11 @@
3030
},
3131
"license": "MIT",
3232
"peerDependencies": {
33-
"@micro-app/core": ">=0.1.5"
33+
"@micro-app/core": ">=0.2.2"
3434
},
3535
"devDependencies": {
36-
"@micro-app/cli": "0.1.5",
37-
"@micro-app/core": "0.1.5",
36+
"@micro-app/cli": "0.2.0",
37+
"@micro-app/core": "0.2.2",
3838
"@types/jest": "^24.0.18",
3939
"babel-eslint": "^10.0.3",
4040
"coveralls": "^3.0.6",

src/commands/deploy/deploy.test.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
'use strict';
2+
3+
/* global expect */
4+
5+
process.env.NODE_ENV = 'MICRO_APP_TEST';
6+
7+
const path = require('path');
8+
9+
describe('Command deploy', () => {
10+
11+
it('deploy', async () => {
12+
13+
const { service } = require('@micro-app/cli');
14+
15+
service.registerPlugin({
16+
id: 'test:DeployCommand',
17+
link: path.join(__dirname, './index.js'),
18+
});
19+
20+
const result = await service.run('deploy');
21+
console.log(result);
22+
});
23+
24+
});

src/commands/deploy/deployCommit.js

Lines changed: 244 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,244 @@
1+
'use strict';
2+
3+
const shelljs = require('shelljs');
4+
const path = require('path');
5+
const { fs, _, chalk, tryRequire } = require('@micro-app/shared-utils');
6+
const CONSTANTS = require('../../constants');
7+
8+
function execJS(execStr, options = {}) {
9+
return new Promise((resolve, reject) => {
10+
shelljs.exec(execStr, Object.assign({ silent: true, async: true }, options), function(code, stdout, stderr) {
11+
if (code && stderr) {
12+
reject(new Error(stderr));
13+
} else {
14+
resolve(stdout);
15+
}
16+
});
17+
});
18+
}
19+
20+
function getGitBranch(deployConfig) {
21+
let gitBranch = deployConfig.branch || 'master';
22+
const currBranch = ((shelljs.exec('git rev-parse --abbrev-ref HEAD', { silent: true }) || {}).stdout || '').trim();
23+
// 继承当前分支
24+
if (currBranch && deployConfig.extends === true) {
25+
gitBranch = currBranch;
26+
} else if (deployConfig.branch) {
27+
gitBranch = deployConfig.branch;
28+
} else {
29+
gitBranch = 'master';
30+
}
31+
return gitBranch;
32+
}
33+
34+
function getGitUser(deployConfig) {
35+
let userName = deployConfig.userName;
36+
if (_.isEmpty(userName)) {
37+
userName = ((shelljs.exec('git config user.name', { silent: true }) || {}).stdout || '').trim();
38+
}
39+
let userEmail = deployConfig.userEmail;
40+
if (_.isEmpty(userEmail)) {
41+
userEmail = ((shelljs.exec('git config user.email', { silent: true }) || {}).stdout || '').trim();
42+
}
43+
return {
44+
name: userName || '',
45+
email: userEmail || '',
46+
};
47+
}
48+
49+
function createCNAMEFile({ deployConfig, deployDir }) {
50+
const cname = deployConfig.cname;
51+
if (!_.isEmpty(cname) && _.isString(cname)) {
52+
const filepath = path.resolve(deployDir, 'CNAME');
53+
fs.writeFileSync(filepath, cname, 'utf8');
54+
}
55+
}
56+
57+
function modifyFile(api, { args, deployConfig, deployDir, gitURL, gitBranch, commitHash, gitUser, gitMessage }) {
58+
const logger = api.logger;
59+
const microAppConfig = api.self;
60+
61+
const pkgPath = path.resolve(deployDir, 'package.json');
62+
const pkg = tryRequire(pkgPath) || {};
63+
const { dependencies = {}, devDependencies = {} } = pkg;
64+
const deps = Object.assign({}, dependencies, devDependencies);
65+
66+
const MICRO_APP_CONFIG_NAME = microAppConfig.packageName;
67+
if (deps[MICRO_APP_CONFIG_NAME]) {
68+
const gitp = deps[MICRO_APP_CONFIG_NAME];
69+
// update
70+
const ngitp = gitp.replace(/#[-_\d\w]+$/igm, `#${commitHash}`);
71+
72+
if (gitp === ngitp) { // not change
73+
return false;
74+
}
75+
if (ngitp) {
76+
if (dependencies[MICRO_APP_CONFIG_NAME]) {
77+
dependencies[MICRO_APP_CONFIG_NAME] = ngitp;
78+
}
79+
if (devDependencies[MICRO_APP_CONFIG_NAME]) {
80+
devDependencies[MICRO_APP_CONFIG_NAME] = ngitp;
81+
}
82+
fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 4), 'utf8');
83+
84+
return true;
85+
}
86+
}
87+
88+
return false;
89+
}
90+
91+
async function clone(api, { deployDir, gitURL, gitBranch }) {
92+
const execStr = `git clone "${gitURL}" -b ${gitBranch} "${deployDir}"`;
93+
return await execJS(execStr);
94+
}
95+
96+
async function push(api, { args, deployConfig, deployDir, gitURL, gitBranch, commitHash, gitUser, gitMessage, name }) {
97+
// git config
98+
if (gitUser.name && typeof gitUser.name === 'string') {
99+
await execJS(`git config user.name ${gitUser.name}`, { cwd: deployDir });
100+
}
101+
if (gitUser.email && typeof gitUser.email === 'string') {
102+
await execJS(`git config user.email ${gitUser.email}`, { cwd: deployDir });
103+
}
104+
// commit + push
105+
const { message } = api.applyPluginHooks('modifyCommandDeployMessage', {
106+
args, config: deployConfig,
107+
message: `:rocket: auto deploy from ${name} [${gitBranch}] - ${commitHash.substr(0, 8)}${gitMessage}`,
108+
branch: gitBranch,
109+
gitMessage,
110+
commitHash,
111+
name,
112+
});
113+
114+
if (_.isEmpty(message)) {
115+
throw new Error('modifyCommandDeployMessage() must be retrun { message } !!!');
116+
}
117+
118+
if (process.env.NODE_ENV === 'MICRO_APP_TEST') {
119+
api.logger.debug('MICRO_APP_TEST --> Exit!!!');
120+
return;
121+
}
122+
123+
await execJS('git add -A', { cwd: deployDir });
124+
await execJS(`git commit -a -m "${message}"`, { cwd: deployDir });
125+
await execJS(`git push -u "${gitURL}" HEAD:${gitBranch} --force`, { cwd: deployDir });
126+
}
127+
128+
async function setup(deployDir) {
129+
if (!fs.existsSync(deployDir)) {
130+
fs.mkdirpSync(deployDir);
131+
}
132+
await fs.emptyDir(deployDir);
133+
134+
const execStr = 'git init';
135+
return await execJS(execStr, { cwd: deployDir });
136+
}
137+
138+
async function runDeploy(api, { args, deployConfig, deployDir, gitURL, gitBranch, commitHash, gitUser, gitMessage }) {
139+
const logger = api.logger;
140+
const microAppConfig = api.self;
141+
const MICRO_APP_CONFIG_NAME = microAppConfig.packageName;
142+
143+
logger.logo(`Deploy: ${chalk.blueBright(gitURL)}`);
144+
logger.logo(`Branch: ${chalk.blueBright(gitBranch)}`);
145+
logger.logo(`Hash: ${chalk.blueBright(commitHash)}`);
146+
logger.logo(`Name: ${chalk.blueBright(gitUser.name)}`);
147+
logger.logo(`Email: ${chalk.blueBright(gitUser.email)}`);
148+
149+
const spinner = logger.spinner('Auto Deploy...');
150+
spinner.start();
151+
try {
152+
await setup(deployDir);
153+
const hasDist = deployConfig.dist;
154+
let bModify = false;
155+
if (!hasDist) { // 需要 clone
156+
spinner.text = 'Cloning...';
157+
await clone(api, { args, deployConfig, deployDir, gitURL, gitBranch, commitHash, gitUser });
158+
spinner.text = 'Modify files...';
159+
bModify = modifyFile(api, { args, deployConfig, deployDir, gitURL, gitBranch, commitHash, gitUser, gitMessage });
160+
} else { // copy dist to deployDir
161+
const opts = {};
162+
spinner.text = 'Copying files from dist folder...';
163+
await fs.copy(hasDist, deployDir, opts);
164+
bModify = true;
165+
}
166+
167+
// 如果是发布到自定义域名, cname
168+
createCNAMEFile({ deployConfig, deployDir });
169+
170+
if (bModify) {
171+
spinner.text = 'Push files...';
172+
await push(api, { args, deployConfig, deployDir, gitURL, gitBranch, commitHash, gitUser, gitMessage, name: MICRO_APP_CONFIG_NAME });
173+
spinner.succeed(chalk.green('Success!'));
174+
} else {
175+
spinner.succeed(chalk.yellow('NOT MODIFIED!'));
176+
}
177+
return true;
178+
} catch (error) {
179+
spinner.fail(chalk.red('Fail! ') + chalk.yellow(error.message));
180+
}
181+
return false;
182+
}
183+
184+
module.exports = async function deployCommit(api, args, deployConfigs) {
185+
const logger = api.logger;
186+
const root = api.root;
187+
188+
const isHooks = args.hooks;
189+
190+
return Promise.all(deployConfigs.map(async (deployConfig, index) => {
191+
192+
const gitURL = deployConfig.url || '';
193+
if (_.isEmpty(gitURL)) {
194+
logger.warn('repository is required!');
195+
return;
196+
}
197+
const gitBranch = getGitBranch(deployConfig);
198+
if (_.isEmpty(gitBranch)) {
199+
logger.warn('branch is required!');
200+
return;
201+
}
202+
const gitUser = getGitUser(deployConfig);
203+
204+
let commitHash = '';
205+
if (isHooks) {
206+
commitHash = ((shelljs.exec('git rev-parse --verify HEAD', { silent: true }) || {}).stdout || '').trim();
207+
} else {
208+
commitHash = ((shelljs.exec(`git rev-parse origin/${gitBranch}`, { silent: true }) || {}).stdout || '').trim();
209+
}
210+
if (_.isEmpty(commitHash)) {
211+
logger.warn('Not Found commit Hash!');
212+
return;
213+
}
214+
215+
let gitMessage = deployConfig.message && ` | ${deployConfig.message}` || '';
216+
if (!gitMessage) {
217+
const msg = ((shelljs.exec(`git log --pretty=format:“%s” ${commitHash} -1`, { silent: true }) || {}).stdout || '').trim();
218+
if (msg) {
219+
gitMessage = ` | ${msg}`;
220+
}
221+
}
222+
223+
const gitRoot = path.resolve(root, CONSTANTS.GIT_NAME);
224+
if (!fs.existsSync(gitRoot)) {
225+
fs.mkdirpSync(gitRoot);
226+
}
227+
const deployDir = path.resolve(gitRoot, CONSTANTS.GIT_SCOPE_NAME);
228+
229+
const params = { args, deployConfig, deployDir, gitURL, gitBranch, commitHash, gitUser, gitMessage };
230+
231+
if (fs.statSync(gitRoot).isDirectory()) {
232+
const bSuccessful = await runDeploy(api, params);
233+
if (!bSuccessful) {
234+
logger.error(`Fail [${index}]! Check your config, please!`);
235+
}
236+
// 清空
237+
if (fs.existsSync(deployDir)) {
238+
fs.removeSync(deployDir);
239+
}
240+
}
241+
242+
return params;
243+
}));
244+
};

0 commit comments

Comments
 (0)