mirror of
https://github.com/serverless/serverless.git
synced 2026-01-18 14:58:43 +00:00
add support for bitbucket and add more tests
This commit is contained in:
parent
c66d2c92fc
commit
1baaf8de65
@ -5,6 +5,7 @@ const download = require('download');
|
||||
const BbPromise = require('bluebird');
|
||||
const fse = require('fs-extra');
|
||||
const chalk = require('chalk');
|
||||
const qs = require('querystring');
|
||||
|
||||
const { renameService } = require('./renameService');
|
||||
const { ServerlessError } = require('../classes/Error');
|
||||
@ -28,23 +29,15 @@ function dirExistsSync(dirPath) {
|
||||
}
|
||||
}
|
||||
|
||||
function downloadTemplateFromRepo(name, inputUrl) {
|
||||
const url = URL.parse(inputUrl.replace(/\/$/, ''));
|
||||
|
||||
// check if url parameter is a valid url
|
||||
if (!url.host) {
|
||||
throw new ServerlessError('The URL you passed is not a valid URL');
|
||||
}
|
||||
|
||||
function parseGitHubURL(url) {
|
||||
const parts = url.pathname.split('/');
|
||||
const parsedGitHubUrl = {
|
||||
owner: parts[1],
|
||||
repo: parts[2],
|
||||
branch: parts[4] || 'master',
|
||||
};
|
||||
const isSubdirectory = parts.length > 4;
|
||||
const owner = parts[1];
|
||||
const repo = parts[2];
|
||||
const branch = isSubdirectory ? parts[4] : 'master';
|
||||
|
||||
// validate if given url is a valid GitHub url
|
||||
if (url.hostname !== 'github.com' || !parsedGitHubUrl.owner || !parsedGitHubUrl.repo) {
|
||||
if (url.hostname !== 'github.com' || !owner || !repo) {
|
||||
const errorMessage = [
|
||||
'The URL must be a valid GitHub URL in the following format:',
|
||||
' https://github.com/serverless/serverless',
|
||||
@ -52,35 +45,120 @@ function downloadTemplateFromRepo(name, inputUrl) {
|
||||
throw new ServerlessError(errorMessage);
|
||||
}
|
||||
|
||||
let pathToDirectory = '';
|
||||
for (let i = 5; i <= (parts.length - 1); i++) {
|
||||
pathToDirectory = path.join(pathToDirectory, parts[i]);
|
||||
}
|
||||
|
||||
const downloadUrl = [
|
||||
'https://github.com/',
|
||||
parsedGitHubUrl.owner,
|
||||
owner,
|
||||
'/',
|
||||
parsedGitHubUrl.repo,
|
||||
repo,
|
||||
'/archive/',
|
||||
parsedGitHubUrl.branch,
|
||||
branch,
|
||||
'.zip',
|
||||
].join('');
|
||||
|
||||
const endIndex = parts.length - 1;
|
||||
let dirName;
|
||||
return {
|
||||
owner,
|
||||
repo,
|
||||
branch,
|
||||
downloadUrl,
|
||||
isSubdirectory,
|
||||
pathToDirectory,
|
||||
};
|
||||
}
|
||||
|
||||
function parseBitBucketURL(url) {
|
||||
const parts = url.pathname.split('/');
|
||||
const isSubdirectory = parts.length > 4;
|
||||
const owner = parts[1];
|
||||
const repo = parts[2];
|
||||
|
||||
const query = qs.parse(url.query);
|
||||
const branch = 'at' in query ? query.at : 'master';
|
||||
|
||||
// validate if given url is a valid GitHub url
|
||||
if (url.hostname !== 'bitbucket.org' || !owner || !repo) {
|
||||
const errorMessage = [
|
||||
'The URL must be a valid GitHub URL in the following format:',
|
||||
' https://github.com/serverless/serverless',
|
||||
].join('');
|
||||
throw new ServerlessError(errorMessage);
|
||||
}
|
||||
|
||||
let pathToDirectory = '';
|
||||
for (let i = 5; i <= (parts.length - 1); i++) {
|
||||
pathToDirectory = path.join(pathToDirectory, parts[i]);
|
||||
}
|
||||
|
||||
const downloadUrl = [
|
||||
'https://bitbucket.org/',
|
||||
owner,
|
||||
'/',
|
||||
repo,
|
||||
'/get/',
|
||||
branch,
|
||||
'.zip',
|
||||
].join('');
|
||||
|
||||
return {
|
||||
owner,
|
||||
repo,
|
||||
branch,
|
||||
downloadUrl,
|
||||
isSubdirectory,
|
||||
pathToDirectory,
|
||||
};
|
||||
}
|
||||
|
||||
function parseRepoURL(inputUrl) {
|
||||
if (!inputUrl) {
|
||||
throw new ServerlessError('URL is required');
|
||||
}
|
||||
|
||||
const url = URL.parse(inputUrl.replace(/\/$/, ''));
|
||||
|
||||
// check if url parameter is a valid url
|
||||
if (!url.host) {
|
||||
throw new ServerlessError('The URL you passed is not a valid URL');
|
||||
}
|
||||
|
||||
switch (url.hostname) {
|
||||
case 'github.com': {
|
||||
return parseGitHubURL(url);
|
||||
}
|
||||
case 'bitbucket.org': {
|
||||
return parseBitBucketURL(url);
|
||||
}
|
||||
default: {
|
||||
const msg = 'The URL you passed is not one of the valid providers: "GitHub", "BitBucket".';
|
||||
throw new ServerlessError(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function downloadTemplateFromRepo(name, inputUrl) {
|
||||
const repoInformation = parseRepoURL(inputUrl);
|
||||
|
||||
let serviceName;
|
||||
let dirName;
|
||||
let downloadServicePath;
|
||||
|
||||
// check if it's a directory or the whole repository
|
||||
if (parts.length > 4) {
|
||||
serviceName = parts[endIndex];
|
||||
dirName = name || parts[endIndex];
|
||||
// download the repo into a temporary directory
|
||||
downloadServicePath = path.join(os.tmpdir(), parsedGitHubUrl.repo);
|
||||
if (repoInformation.isSubdirectory) {
|
||||
const folderName = repoInformation.pathToDirectory.split('/').splice(-1)[0];
|
||||
serviceName = folderName;
|
||||
dirName = name || folderName;
|
||||
downloadServicePath = path.join(os.tmpdir(), repoInformation.repo);
|
||||
} else {
|
||||
serviceName = parsedGitHubUrl.repo;
|
||||
dirName = name || parsedGitHubUrl.repo;
|
||||
serviceName = repoInformation.repo;
|
||||
dirName = name || repoInformation.repo;
|
||||
downloadServicePath = path.join(process.cwd(), dirName);
|
||||
}
|
||||
|
||||
const servicePath = path.join(process.cwd(), dirName);
|
||||
const renamed = dirName !== (parts.length > 4 ? parts[endIndex] : parsedGitHubUrl.repo);
|
||||
const renamed = dirName !== repoInformation.repo;
|
||||
|
||||
if (dirExistsSync(path.join(process.cwd(), dirName))) {
|
||||
const errorMessage = `A folder named "${dirName}" already exists.`;
|
||||
@ -91,16 +169,13 @@ function downloadTemplateFromRepo(name, inputUrl) {
|
||||
|
||||
// download service
|
||||
return download(
|
||||
downloadUrl,
|
||||
repoInformation.downloadUrl,
|
||||
downloadServicePath,
|
||||
{ timeout: 30000, extract: true, strip: 1, mode: '755' }
|
||||
).then(() => {
|
||||
// if it's a directory inside of git
|
||||
if (parts.length > 4) {
|
||||
let directory = downloadServicePath;
|
||||
for (let i = 5; i <= endIndex; i++) {
|
||||
directory = path.join(directory, parts[i]);
|
||||
}
|
||||
if (repoInformation.isSubdirectory) {
|
||||
const directory = path.join(downloadServicePath, repoInformation.pathToDirectory);
|
||||
copyDirContentsSync(directory, servicePath);
|
||||
fse.removeSync(downloadServicePath);
|
||||
}
|
||||
@ -113,4 +188,5 @@ function downloadTemplateFromRepo(name, inputUrl) {
|
||||
|
||||
module.exports = {
|
||||
downloadTemplateFromRepo,
|
||||
parseRepoURL,
|
||||
};
|
||||
|
||||
@ -13,6 +13,8 @@ const readFileSync = require('./fs/readFileSync');
|
||||
|
||||
const remove = BbPromise.promisify(fse.remove);
|
||||
|
||||
const { parseRepoURL } = require('./downloadTemplateFromRepo');
|
||||
|
||||
describe('downloadTemplateFromRepo', () => {
|
||||
let downloadTemplateFromRepo;
|
||||
let downloadStub;
|
||||
@ -121,4 +123,79 @@ describe('downloadTemplateFromRepo', () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('parseRepoURL', () => {
|
||||
|
||||
it('should throw an error if no URL is provided', () => {
|
||||
expect(parseRepoURL).to.throw(Error);
|
||||
});
|
||||
|
||||
it('should throw an error if URL is not valid', () => {
|
||||
try {
|
||||
parseRepoURL('non_valid_url')
|
||||
} catch(e) {
|
||||
expect(e).to.be.an.instanceOf(Error);
|
||||
}
|
||||
});
|
||||
|
||||
it('should throw an error if URL is not of valid provider', () => {
|
||||
try {
|
||||
parseRepoURL('https://kostasbariotis.com/repo/owner');
|
||||
} catch(e) {
|
||||
expect(e).to.be.an.instanceOf(Error);
|
||||
}
|
||||
});
|
||||
|
||||
it('should parse a valid GitHub URL', () => {
|
||||
const output = parseRepoURL('https://github.com/serverless/serverless');
|
||||
|
||||
expect(output).to.deep.eq({
|
||||
owner: 'serverless',
|
||||
repo: 'serverless',
|
||||
branch: 'master',
|
||||
downloadUrl: 'https://github.com/serverless/serverless/archive/master.zip',
|
||||
isSubdirectory: false,
|
||||
pathToDirectory: '',
|
||||
});
|
||||
});
|
||||
|
||||
it('should parse a valid GitHub URL with subdirectory', () => {
|
||||
const output = parseRepoURL('https://github.com/serverless/serverless/tree/master/assets');
|
||||
|
||||
expect(output).to.deep.eq({
|
||||
owner: 'serverless',
|
||||
repo: 'serverless',
|
||||
branch: 'master',
|
||||
downloadUrl: 'https://github.com/serverless/serverless/archive/master.zip',
|
||||
isSubdirectory: true,
|
||||
pathToDirectory: 'assets',
|
||||
});
|
||||
});
|
||||
|
||||
it('should parse a valid BitBucket URL ', () => {
|
||||
const output = parseRepoURL('https://bitbucket.org/atlassian/localstack');
|
||||
|
||||
expect(output).to.deep.eq({
|
||||
owner: 'atlassian',
|
||||
repo: 'localstack',
|
||||
branch: 'master',
|
||||
downloadUrl: 'https://bitbucket.org/atlassian/localstack/get/master.zip',
|
||||
isSubdirectory: false,
|
||||
pathToDirectory: '',
|
||||
});
|
||||
});
|
||||
|
||||
it('should parse a valid BitBucket URL with subdirectory', () => {
|
||||
const output = parseRepoURL('https://bitbucket.org/atlassian/localstack/src/85870856fd6941ae75c0fa946a51cf756ff2f53a/localstack/dashboard/?at=mvn');
|
||||
|
||||
expect(output).to.deep.eq({
|
||||
owner: 'atlassian',
|
||||
repo: 'localstack',
|
||||
branch: 'mvn',
|
||||
downloadUrl: 'https://bitbucket.org/atlassian/localstack/get/mvn.zip',
|
||||
isSubdirectory: true,
|
||||
pathToDirectory: 'localstack/dashboard',
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user