Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions lib/fc.js
Original file line number Diff line number Diff line change
Expand Up @@ -1107,8 +1107,8 @@ function generateSlsProjectName(accountId, region) {
async function generateDefaultLogConfig() {
const profile = await getProfile();
return {
project: generateSlsProjectName(profile.accountId, profile.defaultRegion),
logstore: `function-log`
Project: generateSlsProjectName(profile.accountId, profile.defaultRegion),
Logstore: `function-log`
};
}

Expand Down
Empty file added lib/frameworks/common/common.js
Empty file.
25 changes: 25 additions & 0 deletions lib/frameworks/common/exec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
'use strict';

const process = require('child_process');

function exec(cmd) {
return new Promise((resolve, reject) => {
console.log(`Executing command '${cmd}'...`);
process.exec(cmd, (error, stdout, stderr) => {
console.log(stdout);

if (error) {
console.error(stderr);

reject(error);
return ;
}

resolve();
});
});
}

module.exports = {
exec
};
80 changes: 80 additions & 0 deletions lib/frameworks/common/go.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
'use strict';

const debug = require('debug')('fun:deploy');
const _ = require('lodash');
const fs = require('fs-extra');
const path = require('path');

async function findBinNameByGoMod(codeDir) {
const modFile = path.join(codeDir, 'go.mod');
if (!await fs.pathExists(modFile)) { return null; }

const contents = await fs.readFile(modFile, 'utf8');
for (const line of contents.split(/\r?\n/)) {
const idx = line.indexOf('module ');
if (idx >= 0) {
let moduleName = _.trim(line.substring(idx + 'module '.length));
const guessBinName = path.basename(moduleName);
const guessPaths = ['.', 'bin'];
for (const guessPath of guessPaths) {
const guessBinAbsPath = path.join(codeDir, guessPath, guessBinName);
debug(`checking file ${guessBinAbsPath} exists...`);
if (await fs.pathExists(guessBinAbsPath)) {
return path.posix.join(guessPath, guessBinName);
}
}
}
}

return null;
}

async function findBinNameByBinFolder(codeDir) {
debug(`check bin/ folder exist...`);

const binDir = path.join(codeDir, 'bin');

if (!await fs.pathExists(binDir)) { return null; }

const files = await fs.readdir(binDir);
if (files.length === 1) {
if (files[0] !== 'bootstrap') {
return path.posix.join('bin', files[0]);
}
} else if (files.length === 2 && files.includes(files, 'bootstrap')) {
for (const file of files) {
if (file !== 'bootstrap') {
return path.posix.join('bin', file);
}
}
}

debug('files of bin folder', files);

return null;
}

async function findBinNameByProjectFolder(codeDir) {
const name = path.basename(codeDir);
const binName = path.join(codeDir, name);
if (await fs.pathExists(binName)) { return name; }
return null;
}

async function findBinName(codeDir) {
let binName = await findBinNameByGoMod(codeDir);

if (!binName) {
binName = await findBinNameByProjectFolder(codeDir);
}

if (!binName) {
binName = await findBinNameByBinFolder(codeDir);
}

return binName;
}

module.exports = {
findBinName
};
4 changes: 2 additions & 2 deletions lib/frameworks/express.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,8 @@ npm run start
},
{
'type': 'regex',
'paths': ['index.js', 'application.js', 'server.js'],
'content': '\\.listen\\s*\\(\\s*(\\d+)\\s*,'
'paths': ['index.js', 'application.js', 'server.js', 'app.js'],
'content': '\\.listen\\s*\\('
}
]
},
Expand Down
129 changes: 77 additions & 52 deletions lib/frameworks/framework.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,57 +7,68 @@ const { red, green } = require('colors');
const debug = require('debug')('fun:deploy');

const frameworks = [
// php
require('./thinkphp'),

// java
require('./spring-boot'),

// node
require('./nuxt'),
require('./express'),
require('./next'),
require('./hexo')
require('./hexo'),

// go
require('./go')
];

function resolvePath(p) {
if (_.isArray(p)) {
return path.join(...p);
}
}
return p;

}

const runtimeCheckers = {
'nodejs': async (codeDir) => {
const stat = await fs.lstat(codeDir);

if (stat.isFile()) {
throw new Error('file is not supported');
}

const packageJsonPath = path.join(codeDir, 'package.json');

return await fs.pathExists(packageJsonPath);
'nodejs': {
'type': 'file',
'path': 'package.json'
},
'java': async (codeDir) => {
const stat = await fs.lstat(codeDir);

if (stat.isFile()) {
throw new Error('file is not supported');
}

const pomPath = path.join(codeDir, 'pom.xml');

return await fs.pathExists(pomPath);
'java': {
'type': 'file',
'path': 'pom.xml'
},
'php': async (codeDir) => {
const stat = await fs.lstat(codeDir);
'php': {
'type': 'file',
'path': 'composer.json'
},
'go': {
'type': 'file',
'paths': ['go.mod', 'Gopkg.toml', ['vendor', 'vendor.json'], ['Godeps', 'Godeps.json'], /\.go$/]
}
};

if (stat.isFile()) {
throw new Error('file is not supported');
async function parseRulePaths(codeDir, rule) {
const rs = [];
const paths = rule.paths || [rule.path];
for (const relativePath of paths) {
if (_.isRegExp(relativePath)) {
const pathRegex = relativePath;
const files = await fs.readdir(codeDir);

for (const file of files) {
if (pathRegex.test(file)) {
rs.push(path.join(codeDir, file));
}
}
} else {
rs.push(path.join(codeDir, resolvePath(relativePath)));
}

const pomPath = path.join(codeDir, 'composer.json');

return await fs.pathExists(pomPath);
}
};

return rs;
}

async function readJsonFile(p) {
if (!await fs.pathExists(p)) { return { success: false }; }
Expand Down Expand Up @@ -86,45 +97,53 @@ async function checkJsonRule(codeDir, rule) {
return _.includes(value, jsonValueContains);
}
return true;

}

async function checkContainsRule(codeDir, rule) {
const paths = rule.paths || [rule.path];
const paths = await parseRulePaths(codeDir, rule);
const content = rule.content;
for (const relativePath of paths) {
const p = path.join(codeDir, resolvePath(relativePath));

for (const p of paths) {
if (!await fs.pathExists(p)) { continue; }
const fileContent = await fs.readFile(p, 'utf8');

if (_.includes(fileContent, content)) { return true; }
}

return false;
}

async function checkDirRule(codeDir, rule) {
const paths = rule.paths || [rule.path];
for (const relativePath of paths) {
const p = path.join(codeDir, resolvePath(relativePath));

if (await fs.pathExists(p)) { return true; }
const paths = await parseRulePaths(codeDir, rule);

for (const p of paths) {
if (await fs.pathExists(p)) {
const stat = await fs.stat(p);
return stat.isDirectory();
}
}

return false;
}

async function checkFileRule(codeDir, rule) {
const paths = await parseRulePaths(codeDir, rule);
for (const f of paths) {
if (await fs.pathExists(f)) {
const stat = await fs.stat(f);
if (stat.isFile()) { return true; }
}
}

return false;
}

async function checkRegexRule(codeDir, rule) {
const paths = rule.paths || [rule.path];
const paths = await parseRulePaths(codeDir, rule);

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

if (!paths) { return false; }

for (const relativePath of paths) {
const p = path.join(codeDir, relativePath);
for (const p of paths) {
if (!await fs.pathExists(p)) { continue; }
const fileContent = await fs.readFile(p);

Expand All @@ -147,6 +166,8 @@ async function checkRule(codeDir, rule) {
return await checkContainsRule(codeDir, rule);
case 'dir':
return await checkDirRule(codeDir, rule);
case 'file':
return await checkFileRule(codeDir, rule);
default:
throw new Error(`rule type ${type} not supported`);
}
Expand Down Expand Up @@ -193,19 +214,19 @@ async function execProcessor(codeDir, processor) {
p = path.join(codeDir, p);

await fs.ensureDir(path.dirname(p));

const mode = processor.mode;
const content = processor.content;

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

await fs.copyFile(p, `${p}.bak`, {
overwrite: true
});
});
}
}

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

const checkResult = await runtimeChecker(codeDir);
const checkResult = await checkRule(codeDir, runtimeChecker);

if (checkResult) {
const detectors = framework.detectors;

// no need to detect
if (_.isEmpty(detectors)) { return framework; }

const match = await checkRules(codeDir, detectors);
if (match) {
return framework;
Expand Down
Loading