Skip to content

Commit 290c900

Browse files
authored
add go framework support (#808)
* add go framework support * add go framework support * fix test
1 parent cfabf36 commit 290c900

11 files changed

Lines changed: 307 additions & 60 deletions

File tree

lib/fc.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1107,8 +1107,8 @@ function generateSlsProjectName(accountId, region) {
11071107
async function generateDefaultLogConfig() {
11081108
const profile = await getProfile();
11091109
return {
1110-
project: generateSlsProjectName(profile.accountId, profile.defaultRegion),
1111-
logstore: `function-log`
1110+
Project: generateSlsProjectName(profile.accountId, profile.defaultRegion),
1111+
Logstore: `function-log`
11121112
};
11131113
}
11141114

lib/frameworks/common/common.js

Whitespace-only changes.

lib/frameworks/common/exec.js

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
'use strict';
2+
3+
const process = require('child_process');
4+
5+
function exec(cmd) {
6+
return new Promise((resolve, reject) => {
7+
console.log(`Executing command '${cmd}'...`);
8+
process.exec(cmd, (error, stdout, stderr) => {
9+
console.log(stdout);
10+
11+
if (error) {
12+
console.error(stderr);
13+
14+
reject(error);
15+
return ;
16+
}
17+
18+
resolve();
19+
});
20+
});
21+
}
22+
23+
module.exports = {
24+
exec
25+
};

lib/frameworks/common/go.js

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
'use strict';
2+
3+
const debug = require('debug')('fun:deploy');
4+
const _ = require('lodash');
5+
const fs = require('fs-extra');
6+
const path = require('path');
7+
8+
async function findBinNameByGoMod(codeDir) {
9+
const modFile = path.join(codeDir, 'go.mod');
10+
if (!await fs.pathExists(modFile)) { return null; }
11+
12+
const contents = await fs.readFile(modFile, 'utf8');
13+
for (const line of contents.split(/\r?\n/)) {
14+
const idx = line.indexOf('module ');
15+
if (idx >= 0) {
16+
let moduleName = _.trim(line.substring(idx + 'module '.length));
17+
const guessBinName = path.basename(moduleName);
18+
const guessPaths = ['.', 'bin'];
19+
for (const guessPath of guessPaths) {
20+
const guessBinAbsPath = path.join(codeDir, guessPath, guessBinName);
21+
debug(`checking file ${guessBinAbsPath} exists...`);
22+
if (await fs.pathExists(guessBinAbsPath)) {
23+
return path.posix.join(guessPath, guessBinName);
24+
}
25+
}
26+
}
27+
}
28+
29+
return null;
30+
}
31+
32+
async function findBinNameByBinFolder(codeDir) {
33+
debug(`check bin/ folder exist...`);
34+
35+
const binDir = path.join(codeDir, 'bin');
36+
37+
if (!await fs.pathExists(binDir)) { return null; }
38+
39+
const files = await fs.readdir(binDir);
40+
if (files.length === 1) {
41+
if (files[0] !== 'bootstrap') {
42+
return path.posix.join('bin', files[0]);
43+
}
44+
} else if (files.length === 2 && files.includes(files, 'bootstrap')) {
45+
for (const file of files) {
46+
if (file !== 'bootstrap') {
47+
return path.posix.join('bin', file);
48+
}
49+
}
50+
}
51+
52+
debug('files of bin folder', files);
53+
54+
return null;
55+
}
56+
57+
async function findBinNameByProjectFolder(codeDir) {
58+
const name = path.basename(codeDir);
59+
const binName = path.join(codeDir, name);
60+
if (await fs.pathExists(binName)) { return name; }
61+
return null;
62+
}
63+
64+
async function findBinName(codeDir) {
65+
let binName = await findBinNameByGoMod(codeDir);
66+
67+
if (!binName) {
68+
binName = await findBinNameByProjectFolder(codeDir);
69+
}
70+
71+
if (!binName) {
72+
binName = await findBinNameByBinFolder(codeDir);
73+
}
74+
75+
return binName;
76+
}
77+
78+
module.exports = {
79+
findBinName
80+
};

lib/frameworks/express.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,8 @@ npm run start
5858
},
5959
{
6060
'type': 'regex',
61-
'paths': ['index.js', 'application.js', 'server.js'],
62-
'content': '\\.listen\\s*\\(\\s*(\\d+)\\s*,'
61+
'paths': ['index.js', 'application.js', 'server.js', 'app.js'],
62+
'content': '\\.listen\\s*\\('
6363
}
6464
]
6565
},

lib/frameworks/framework.js

Lines changed: 77 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -7,57 +7,68 @@ const { red, green } = require('colors');
77
const debug = require('debug')('fun:deploy');
88

99
const frameworks = [
10+
// php
1011
require('./thinkphp'),
12+
13+
// java
1114
require('./spring-boot'),
15+
16+
// node
1217
require('./nuxt'),
1318
require('./express'),
1419
require('./next'),
15-
require('./hexo')
20+
require('./hexo'),
21+
22+
// go
23+
require('./go')
1624
];
1725

1826
function resolvePath(p) {
1927
if (_.isArray(p)) {
2028
return path.join(...p);
21-
}
29+
}
2230
return p;
23-
2431
}
2532

2633
const runtimeCheckers = {
27-
'nodejs': async (codeDir) => {
28-
const stat = await fs.lstat(codeDir);
29-
30-
if (stat.isFile()) {
31-
throw new Error('file is not supported');
32-
}
33-
34-
const packageJsonPath = path.join(codeDir, 'package.json');
35-
36-
return await fs.pathExists(packageJsonPath);
34+
'nodejs': {
35+
'type': 'file',
36+
'path': 'package.json'
3737
},
38-
'java': async (codeDir) => {
39-
const stat = await fs.lstat(codeDir);
40-
41-
if (stat.isFile()) {
42-
throw new Error('file is not supported');
43-
}
44-
45-
const pomPath = path.join(codeDir, 'pom.xml');
46-
47-
return await fs.pathExists(pomPath);
38+
'java': {
39+
'type': 'file',
40+
'path': 'pom.xml'
4841
},
49-
'php': async (codeDir) => {
50-
const stat = await fs.lstat(codeDir);
42+
'php': {
43+
'type': 'file',
44+
'path': 'composer.json'
45+
},
46+
'go': {
47+
'type': 'file',
48+
'paths': ['go.mod', 'Gopkg.toml', ['vendor', 'vendor.json'], ['Godeps', 'Godeps.json'], /\.go$/]
49+
}
50+
};
5151

52-
if (stat.isFile()) {
53-
throw new Error('file is not supported');
52+
async function parseRulePaths(codeDir, rule) {
53+
const rs = [];
54+
const paths = rule.paths || [rule.path];
55+
for (const relativePath of paths) {
56+
if (_.isRegExp(relativePath)) {
57+
const pathRegex = relativePath;
58+
const files = await fs.readdir(codeDir);
59+
60+
for (const file of files) {
61+
if (pathRegex.test(file)) {
62+
rs.push(path.join(codeDir, file));
63+
}
64+
}
65+
} else {
66+
rs.push(path.join(codeDir, resolvePath(relativePath)));
5467
}
55-
56-
const pomPath = path.join(codeDir, 'composer.json');
57-
58-
return await fs.pathExists(pomPath);
5968
}
60-
};
69+
70+
return rs;
71+
}
6172

6273
async function readJsonFile(p) {
6374
if (!await fs.pathExists(p)) { return { success: false }; }
@@ -86,45 +97,53 @@ async function checkJsonRule(codeDir, rule) {
8697
return _.includes(value, jsonValueContains);
8798
}
8899
return true;
89-
90100
}
91101

92102
async function checkContainsRule(codeDir, rule) {
93-
const paths = rule.paths || [rule.path];
103+
const paths = await parseRulePaths(codeDir, rule);
94104
const content = rule.content;
95-
for (const relativePath of paths) {
96-
const p = path.join(codeDir, resolvePath(relativePath));
97-
105+
for (const p of paths) {
98106
if (!await fs.pathExists(p)) { continue; }
99107
const fileContent = await fs.readFile(p, 'utf8');
100-
108+
101109
if (_.includes(fileContent, content)) { return true; }
102110
}
103111

104112
return false;
105113
}
106114

107115
async function checkDirRule(codeDir, rule) {
108-
const paths = rule.paths || [rule.path];
109-
for (const relativePath of paths) {
110-
const p = path.join(codeDir, resolvePath(relativePath));
111-
112-
if (await fs.pathExists(p)) { return true; }
116+
const paths = await parseRulePaths(codeDir, rule);
117+
118+
for (const p of paths) {
119+
if (await fs.pathExists(p)) {
120+
const stat = await fs.stat(p);
121+
return stat.isDirectory();
122+
}
123+
}
124+
125+
return false;
126+
}
127+
128+
async function checkFileRule(codeDir, rule) {
129+
const paths = await parseRulePaths(codeDir, rule);
130+
for (const f of paths) {
131+
if (await fs.pathExists(f)) {
132+
const stat = await fs.stat(f);
133+
if (stat.isFile()) { return true; }
134+
}
113135
}
114136

115137
return false;
116138
}
117139

118140
async function checkRegexRule(codeDir, rule) {
119-
const paths = rule.paths || [rule.path];
141+
const paths = await parseRulePaths(codeDir, rule);
120142

121143
const regexContent = rule.content;
122144
const regex = new RegExp(regexContent, 'gm');
123145

124-
if (!paths) { return false; }
125-
126-
for (const relativePath of paths) {
127-
const p = path.join(codeDir, relativePath);
146+
for (const p of paths) {
128147
if (!await fs.pathExists(p)) { continue; }
129148
const fileContent = await fs.readFile(p);
130149

@@ -147,6 +166,8 @@ async function checkRule(codeDir, rule) {
147166
return await checkContainsRule(codeDir, rule);
148167
case 'dir':
149168
return await checkDirRule(codeDir, rule);
169+
case 'file':
170+
return await checkFileRule(codeDir, rule);
150171
default:
151172
throw new Error(`rule type ${type} not supported`);
152173
}
@@ -193,19 +214,19 @@ async function execProcessor(codeDir, processor) {
193214
p = path.join(codeDir, p);
194215

195216
await fs.ensureDir(path.dirname(p));
196-
217+
197218
const mode = processor.mode;
198219
const content = processor.content;
199220

200221
console.log(green('Generating ' + p + '...'));
201-
if (await fs.pathExists(p)) {
222+
if (await fs.pathExists(p)) {
202223
const backup = processor.backup;
203224
if (_.isNil(backup) || backup) {
204225
console.warn(red(`File ${p} already exists, Fun will rename to ${p}.bak`));
205226

206227
await fs.copyFile(p, `${p}.bak`, {
207228
overwrite: true
208-
});
229+
});
209230
}
210231
}
211232

@@ -228,10 +249,14 @@ async function detectFramework(codeDir) {
228249
throw new Error('could not found runtime checker');
229250
}
230251

231-
const checkResult = await runtimeChecker(codeDir);
252+
const checkResult = await checkRule(codeDir, runtimeChecker);
232253

233254
if (checkResult) {
234255
const detectors = framework.detectors;
256+
257+
// no need to detect
258+
if (_.isEmpty(detectors)) { return framework; }
259+
235260
const match = await checkRules(codeDir, detectors);
236261
if (match) {
237262
return framework;

0 commit comments

Comments
 (0)