Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

18f-pages-server

Package Overview
Dependencies
Maintainers
1
Versions
9
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

18f-pages-server - npm Package Compare versions

Comparing version 0.2.1 to 0.3.0

lib/sync.js

20

lib/command-runner.js

@@ -7,5 +7,6 @@ 'use strict';

function CommandRunner(sitePath, repoName) {
function CommandRunner(sitePath, repoName, logger) {
this.sitePath = sitePath;
this.repoName = repoName;
this.logger = logger;
}

@@ -19,6 +20,19 @@

return new Promise(function(resolve, reject) {
var options = opts || {cwd: runner.sitePath, stdio: 'inherit'},
var command,
options = opts || {cwd: runner.sitePath},
msg = message || 'rebuild failed for';
childProcess.spawn(path, args, options).on('close', function(code) {
command = childProcess.spawn(path, args, options);
command.stdout.setEncoding('utf8');
command.stdout.on('data', function(data) {
runner.logger.log(data);
});
command.stderr.setEncoding('utf8');
command.stderr.on('data', function(data) {
runner.logger.error(data);
});
command.on('close', function(code) {
if (code !== 0) {

@@ -25,0 +39,0 @@ reject('Error: ' + msg + ' ' + runner.repoName + ' with exit code ' +

4

lib/component-factory.js

@@ -8,2 +8,3 @@ 'use strict';

var JekyllCommandHelper = require('./jekyll-command-helper');
var Sync = require('./sync');
var FileLockedOperation = require('file-locked-operation');

@@ -16,3 +17,3 @@ var path = require('path');

this.commandRunner = new CommandRunner(
builderOpts.sitePath, builderOpts.repoName);
builderOpts.sitePath, builderOpts.repoName, logger);
this.configHandler = new ConfigHandler(

@@ -24,2 +25,3 @@ builderOpts, branch,

config, builderOpts, this.commandRunner, logger);
this.sync = new Sync(config, this.commandRunner, logger);
this.updateLock = new FileLockedOperation(

@@ -26,0 +28,0 @@ path.join(builderOpts.destDir, '.update-lock-' + builderOpts.repoName),

@@ -70,3 +70,3 @@ 'use strict';

if (handler.baseurl !== undefined) {
if (handler.baseurl) {
setBuildDestinationFromBaseurl(handler, handler.baseurl);

@@ -77,4 +77,10 @@ }

function setBuildDestinationFromBaseurl(handler, baseurl) {
var destDirPrefix = path.join(handler.destDir, path.sep);
handler.buildDestination = path.join(handler.destDir, baseurl);
if (handler.buildDestination.substr(0, destDirPrefix.length) !==
destDirPrefix) {
throw new Error('baseurl contains relative components: ' + baseurl);
}
if (handler.internalBuildDestination) {

@@ -135,3 +141,6 @@ handler.internalBuildDestination = path.join(

baseurl = handler.baseurl || ('/' + handler.repoName);
baseurl = handler.baseurl;
if (baseurl === undefined) {
baseurl = '/' + handler.repoName;
}
assetRoot = handler.assetRoot;

@@ -138,0 +147,0 @@

@@ -46,3 +46,5 @@ 'use strict';

if (builder.configHandler.usesBundler) {
return builder.commandRunner.run(config.bundler, ['install']);
return builder.commandRunner.run(
config.bundler, ['install',
'--path=' + path.join(config.home, config.bundlerCacheDir)]);
}

@@ -53,2 +55,5 @@ })

buildJekyll(builder) : rsync(builder);
})
.then(function() {
return syncResults(builder);
});

@@ -61,6 +66,16 @@ };

function rsync(builder) {
return builder.commandRunner.run(config.rsync,
config.rsyncOpts.concat(['./', builder.configHandler.buildDestination]));
return builder.configHandler.buildConfigurations().reduce(
function(previousRsync, buildConfig) {
return generateRsyncOp(builder, previousRsync, buildConfig);
},
Promise.resolve());
}
function generateRsyncOp(builder, previousRsync, buildConfig) {
return previousRsync.then(function() {
return builder.commandRunner.run(config.rsync,
config.rsyncOpts.concat(['./', buildConfig.destination]));
});
}
function buildJekyll(builder) {

@@ -80,3 +95,17 @@ var cleanup = function(err) {

SiteBuilder.launchBuilder = function(info, branch, builderConfig, done) {
function syncResults(builder) {
return builder.configHandler.buildConfigurations().reduce(
function(previousSync, buildConfig) {
return generateSyncOp(builder, previousSync, buildConfig);
},
Promise.resolve());
}
function generateSyncOp(builder, previousSync, buildConfig) {
return previousSync.then(function() {
return builder.sync.sync(buildConfig.destination);
});
}
SiteBuilder.launchBuilder = function(info, branch, builderConfig) {
var builderOpts = new Options(info, config, builderConfig),

@@ -100,22 +129,28 @@ commit = info.head_commit,

finishBuild = function(err) {
if (err !== undefined) {
logger.error(err);
logger.error(builderOpts.repoName + ': build failed');
} else {
logger.log(builderOpts.repoName + ': build successful');
}
return new Promise(function(resolve, reject) {
// Provides https://pages.18f.gov/REPO-NAME/build.log as an indicator of
// latest status.
var newLogPath = path.join(
builder.configHandler.buildDestination, 'build.log');
// Provides https://pages.18f.gov/REPO-NAME/build.log as an indicator of
// latest status.
var newLogPath = path.join(
builder.configHandler.buildDestination, 'build.log');
fs.rename(buildLog, newLogPath, function(err) {
if (err !== null) {
console.error('Error moving build log from', buildLog, 'to',
newLogPath);
if (err) {
logger.error(err.message ? err.message : err);
logger.error(builderOpts.repoName + ': build failed');
} else {
logger.log(builderOpts.repoName + ': build successful');
}
logger.close(function() {
if (done) {
done(err);
fs.rename(buildLog, newLogPath, function(renameErr) {
var errMsg;
if (renameErr) {
errMsg = 'Error moving build log: ' + renameErr;
console.error(errMsg);
if (!err) {
reject(errMsg);
}
}
logger.close(function() {
return err ? reject(err) : resolve();
});
});

@@ -128,3 +163,3 @@ });

SiteBuilder.makeBuilderListener = function(webhook, builderConfig, done) {
SiteBuilder.makeBuilderListener = function(webhook, builderConfig) {
var org = builderConfig.githubOrg || config.githubOrg,

@@ -141,3 +176,3 @@ branchPattern = builderConfig.branchInUrlPattern || builderConfig.branch,

if (branch && (info.repository.organization === org)) {
SiteBuilder.launchBuilder(info, branch[1], builderConfig, done);
return SiteBuilder.launchBuilder(info, branch[1], builderConfig);
}

@@ -147,2 +182,3 @@ };

webhook.on('push', handler);
return handler;
};
{
"name": "18f-pages-server",
"version": "0.2.1",
"version": "0.3.0",
"description": "Static website publishing server for 18F Pages",

@@ -5,0 +5,0 @@ "main": "index.js",

{
"port": 5000,
"home": "/home/ubuntu",
"home": "/usr/local/18f/pages",
"git": "/usr/bin/git",
"bundler": "/usr/local/rbenv/shims/bundle",
"jekyll": "/usr/local/rbenv/shims/jekyll",
"bundler": "/usr/local/18f/rbenv/shims/bundle",
"bundlerCacheDir": "bundler-cache",
"jekyll": "/usr/local/18f/rbenv/shims/jekyll",
"rsync": "/usr/bin/rsync",
"rsyncOpts": [
"-vaxp", "--delete", "--ignore-errors", "--exclude=.[A-Za-z0-9]*"
"-vaxp",
"--delete",
"--ignore-errors",
"--exclude=.[A-Za-z0-9]*"
],
"s3": {
"awscli": "/usr/local/18f/pyenv/shims/aws",
"bucket": "s3://18f-pages"
},
"payloadLimit": 1048576,

@@ -18,27 +26,27 @@ "githubOrg": "18F",

"fileLockPollTime": 1000,
"secretKeyFile": "/home/ubuntu/.18f-pages.secret",
"secretKeyFile": "/usr/local/18f/pages/config/pages.secret",
"builders": [
{
"branch": "18f-pages",
"repositoryDir": "pages-repos",
"generatedSiteDir": "pages-generated",
"internalSiteDir": "pages-internal"
"repositoryDir": "repos/pages.18f.gov",
"generatedSiteDir": "sites/pages.18f.gov",
"internalSiteDir": "sites/pages-internal.18f.gov"
},
{
"branch": "18f-pages-staging",
"repositoryDir": "pages-repos-staging",
"generatedSiteDir": "pages-staging",
"internalSiteDir": "pages-internal"
"repositoryDir": "repos/pages-staging.18f.gov",
"generatedSiteDir": "sites/pages-staging.18f.gov",
"internalSiteDir": "sites/pages-internal.18f.gov"
},
{
"branch": "18f-pages-internal",
"repositoryDir": "pages-repos-internal",
"generatedSiteDir": "pages-internal"
"repositoryDir": "repos/pages-internal.18f.gov",
"generatedSiteDir": "sites/pages-internal.18f.gov"
},
{
"branchInUrlPattern": "v[0-9]+.[0-9]+.[0-9]*[a-z]+",
"repositoryDir": "pages-repos-releases",
"generatedSiteDir": "pages-releases"
"branchInUrlPattern": "v[0-9]+.[0-9]+.[0-9]*[a-z]*",
"repositoryDir": "repos/pages-releases.18f.gov",
"generatedSiteDir": "sites/pages-releases.18f.gov"
}
]
}

@@ -228,2 +228,7 @@ # 18f-pages-server

OS X installations in particular may need to adjust these
* **s3 (optional)**: if present, will back up each generated site to
[Amazon S3](https://aws.amazon.com/s3/); attributes are:
* **awscli**: path to the [`aws` command](https://aws.amazon.com/cli/) on
the host machine
* **bucket**: address of the S3 bucket to which to sync generated sites
* **payloadLimit**: maximum allowable size (in bytes) for incoming webhooks

@@ -230,0 +235,0 @@ * **githubOrg**: GitHub organization to which all published repositories

'use strict';
var BuildLogger = require('../lib/build-logger.js');
var BuildLogger = require('../lib/build-logger');
var path = require('path');

@@ -5,0 +5,0 @@ var fs = require('fs');

@@ -6,2 +6,3 @@ 'use strict';

var BuildLogger = require('../lib/build-logger');
var Options = require('../lib/options');
var pagesConfig = require('../pages-config.json');

@@ -21,14 +22,21 @@ var path = require('path');

before(function() {
var payload, builderConfig;
payload = {
repository: {
name: 'repo_name'
},
ref: 'refs/heads/18f-pages'
};
config = JSON.parse(JSON.stringify(pagesConfig));
opts = {
pagesConfig: config.pagesConfig,
pagesYaml: config.pagesYaml,
repoName: 'repo_name',
destDir: 'dest_dir',
internalDestDir: 'internal_dest_dir',
assetRoot: '/guides-template',
branchInUrlPattern: ''
config.home = '/usr/local/18f/pages';
config.assetRoot = '/guides-template';
builderConfig = {
'branch': '18f-pages',
'repositoryDir': 'repo_dir',
'generatedSiteDir': 'dest_dir',
'internalSiteDir': 'internal_dest_dir'
};
opts.sitePath = path.join('some/test/dir', opts.repoName);
fileHandler = new RepositoryFileHandler(opts);
opts = new Options(payload, config, builderConfig);
fileHandler = new RepositoryFileHandler(opts.sitePath);
logger = new BuildLogger();

@@ -45,2 +53,3 @@ });

sinon.stub(fileHandler, 'readFile');
sinon.stub(fileHandler, 'writeFile');
fileHandler.exists.returns(Promise.resolve(false));

@@ -54,2 +63,3 @@ fileHandler.exists.withArgs('_config.yml')

logger.log.restore();
fileHandler.writeFile.restore();
fileHandler.readFile.restore();

@@ -75,3 +85,3 @@ fileHandler.exists.restore();

handler.buildConfigurations().should.eql([
{ destination: path.join('dest_dir/repo_name'),
{ destination: path.join(config.home, 'dest_dir/repo_name'),
configurations: '_config.yml,' + config.pagesConfig

@@ -111,7 +121,8 @@ }

handler.buildConfigurations().should.eql([
{ destination: path.join('internal_dest_dir/repo_name'),
{ destination: path.join(
config.home, 'internal_dest_dir/repo_name'),
configurations: '_config.yml,_config_internal.yml,' +
config.pagesConfig
},
{ destination: path.join('dest_dir/repo_name'),
{ destination: path.join(config.home, 'dest_dir/repo_name'),
configurations: '_config.yml,' + config.pagesConfig

@@ -131,7 +142,8 @@ }

handler.buildConfigurations().should.eql([
{ destination: path.join('internal_dest_dir/repo_name'),
{ destination: path.join(
config.home, 'internal_dest_dir/repo_name'),
configurations: '_config.yml,_config_internal.yml,' +
config.pagesConfig
},
{ destination: path.join('dest_dir/repo_name'),
{ destination: path.join(config.home, 'dest_dir/repo_name'),
configurations: '_config.yml,_config_external.yml,' +

@@ -156,7 +168,8 @@ config.pagesConfig

handler.buildConfigurations().should.eql([
{ destination: path.join('internal_dest_dir/repo_name/v0.9.0'),
{ destination: path.join(config.home,
'internal_dest_dir/repo_name/v0.9.0'),
configurations: '_config.yml,_config_internal.yml,' +
config.pagesConfig
},
{ destination: path.join('dest_dir/repo_name/v0.9.0'),
{ destination: path.join(config.home, 'dest_dir/repo_name/v0.9.0'),
configurations: '_config.yml,' + config.pagesConfig

@@ -200,2 +213,5 @@ }

.returns(Promise.resolve('baseurl: /new-baseurl\n'));
fileHandler.exists.withArgs(pagesConfig.pagesConfig)
.returns(Promise.resolve(false));
fileHandler.writeFile.returns(Promise.resolve());

@@ -215,6 +231,16 @@ handler.branchInUrlPattern = new RegExp(

handler.buildConfigurations().should.eql([
{ destination: path.join('dest_dir/new-baseurl/v0.9.0'),
{ destination: path.join(
config.home, 'dest_dir/new-baseurl/v0.9.0'),
configurations: '_config.yml,' + config.pagesConfig
}
]);
return handler.readOrWriteConfig();
})
.should.be.fulfilled.then(function() {
fileHandler.writeFile.args.should.eql([
[config.pagesConfig,
'baseurl: /new-baseurl/v0.9.0\n' +
'asset_root: /new-baseurl/v0.9.0\n'
]
]);
});

@@ -228,2 +254,5 @@ });

.returns(Promise.resolve('baseurl:\n'));
fileHandler.exists.withArgs(pagesConfig.pagesConfig)
.returns(Promise.resolve(false));
fileHandler.writeFile.returns(Promise.resolve());

@@ -234,10 +263,20 @@ return handler.init().should.be.fulfilled

handler.baseurl.should.eql('');
handler.buildDestination.should.eql(path.join(handler.destDir));
handler.buildDestination.should.eql(
path.join(handler.destDir, handler.repoName));
handler.internalBuildDestination.should.eql(
path.join(handler.internalDestDir));
path.join(handler.internalDestDir, handler.repoName));
handler.buildConfigurations().should.eql([
{ destination: path.join('dest_dir'),
{ destination: path.join(config.home, 'dest_dir', handler.repoName),
configurations: '_config.yml,' + config.pagesConfig
}
]);
return handler.readOrWriteConfig();
})
.should.be.fulfilled.then(function() {
fileHandler.writeFile.args.should.eql([
[config.pagesConfig,
'baseurl: \n' +
'asset_root: ' + config.assetRoot + '\n'
]
]);
});

@@ -256,4 +295,14 @@ });

it('should reject baseurl with relative components', function() {
fileHandler.exists.withArgs(pagesConfig.pagesYaml)
.returns(Promise.resolve(true));
fileHandler.readFile.withArgs(pagesConfig.pagesYaml)
.returns(Promise.resolve('baseurl: ../dest_dir_not'));
return handler.init().should.be.rejectedWith(
'Error: baseurl contains relative components: ../dest_dir_not');
});
it('should not detect YAML file presence if not configured', function() {
// This can happen if the pages-config.json file does not have
// This can happen if the pages-config.json file does not have
// a pagesYaml property defined.

@@ -277,3 +326,4 @@ fileHandler.exists.withArgs(undefined).throws();

handler.parseDestinationFromConfigData('');
handler.buildDestination.should.equal(path.join('dest_dir/repo_name'));
handler.buildDestination.should.equal(
path.join(config.home, 'dest_dir/repo_name'));
});

@@ -283,3 +333,4 @@

handler.parseDestinationFromConfigData('baseurl:\n');
handler.buildDestination.should.equal(path.join('dest_dir/repo_name'));
handler.buildDestination.should.equal(
path.join(config.home, 'dest_dir/repo_name'));
});

@@ -289,3 +340,4 @@

handler.parseDestinationFromConfigData('baseurl: \n');
handler.buildDestination.should.equal(path.join('dest_dir/repo_name'));
handler.buildDestination.should.equal(
path.join(config.home, 'dest_dir/repo_name'));
});

@@ -295,3 +347,4 @@

handler.parseDestinationFromConfigData('baseurl: /\n');
handler.buildDestination.should.equal(path.join('dest_dir/repo_name'));
handler.buildDestination.should.equal(
path.join(config.home, 'dest_dir/repo_name'));
});

@@ -302,12 +355,12 @@

handler.buildDestination.should.equal(
path.join('dest_dir/new-destination'));
path.join(config.home, 'dest_dir/new-destination'));
});
it('should set the internal destination from config data', function() {
handler.internalDestDir = 'internal_dest_dir';
handler.internalDestDir = path.join(config.home, 'internal_dest_dir');
handler.parseDestinationFromConfigData('baseurl: /new-destination\n');
handler.buildDestination.should.equal(
path.join('dest_dir/new-destination'));
path.join(config.home, 'dest_dir/new-destination'));
handler.internalBuildDestination.should.equal(
path.join('internal_dest_dir/new-destination'));
path.join(config.home, 'internal_dest_dir/new-destination'));
});

@@ -318,3 +371,3 @@

handler.buildDestination.should.equal(
path.join('dest_dir/new-destination'));
path.join(config.home, 'dest_dir/new-destination'));
});

@@ -326,4 +379,12 @@

handler.buildDestination.should.equal(
path.join('dest_dir/new-destination'));
path.join(config.home, 'dest_dir/new-destination'));
});
it('should fail if the baseurl contains relative components', function() {
var parse = function() {
handler.parseDestinationFromConfigData('baseurl: ../dest_dir_not');
};
expect(parse).to.throw(
Error, 'baseurl contains relative components: ../dest_dir_not');
});
});

@@ -330,0 +391,0 @@

@@ -13,21 +13,15 @@ 'use strict';

FilesHelper.prototype.init = function(config) {
FilesHelper.prototype.init = function() {
var helper = this;
this.dirs = [];
this.files = [];
return new Promise(function(resolve, reject) {
temp.mkdir(scriptName + '-test-files-', function(err, tempDir) {
var testRepoDir = path.resolve(tempDir, 'site_builder_test'),
lockDir = path.resolve(tempDir, 'site_builder_test_lock_dir');
if (err) {
return reject(err);
}
fs.mkdir(lockDir, '0700', function(err) {
if (err) {
return reject(err);
}
initHelper(helper, config, tempDir, testRepoDir, lockDir);
resolve();
});
helper.tempDir = tempDir;
resolve();
});

@@ -37,33 +31,8 @@ });

function initHelper(helper, config, tempDir, testRepoDir, lockDir) {
helper.dirs = {
testRepoDir: testRepoDir,
lockDir: lockDir,
tempDir: tempDir
};
helper.files = {
gemfile: path.resolve(testRepoDir, 'Gemfile'),
pagesConfig: path.resolve(testRepoDir, config.pagesConfig),
configYml: path.resolve(testRepoDir, '_config.yml'),
internalConfig: path.resolve(testRepoDir, '_config_internal.yml'),
externalConfig: path.resolve(testRepoDir, '_config_external.yml'),
lockfilePath: path.resolve(lockDir, '.update-lock-repo_name')
};
helper.filesToDelete = [];
}
FilesHelper.prototype.afterEach = function() {
var helper = this,
files = helper.filesToDelete.slice();
var helper = this;
helper.filesToDelete = [];
files = files.concat(Object.keys(helper.files).map(function(key) {
return helper.files[key];
}));
return removeItems(files, 'unlink')
return removeItems(this.tempDir, this.files, 'unlink')
.then(function() {
return helper.removeDir(helper.dirs.testRepoDir);
return removeItems(helper.tempDir, helper.dirs.reverse(), 'rmdir');
});

@@ -73,19 +42,15 @@ };

FilesHelper.prototype.after = function() {
return removeItems([this.dirs.lockDir, this.dirs.tempDir], 'rmdir');
return removeItems(this.tempDir, [''], 'rmdir');
};
FilesHelper.prototype.createRepoDir = function() {
FilesHelper.prototype.createDir = function(dirName) {
var helper = this;
return new Promise(function(resolve, reject) {
fs.mkdir(helper.dirs.testRepoDir, '0700', function(err) {
fs.mkdir(path.join(helper.tempDir, dirName), '0700', function(err) {
if (err) {
return reject(err);
}
fs.writeFile(helper.files.configYml, '', function(err) {
if (err) {
return reject(err);
}
resolve();
});
helper.dirs.push(dirName);
resolve();
});

@@ -95,33 +60,3 @@ });

FilesHelper.prototype.createRepoWithFiles = function(nameToContents) {
var helper = this,
writeFile;
this.filesToDelete = Object.keys(nameToContents);
writeFile = function(filename) {
return new Promise(function(resolve, reject) {
fs.writeFile(filename, nameToContents[filename], function(err) {
if (err) {
return reject(err);
}
resolve();
});
});
};
return this.createRepoDir()
.then(function() {
return Promise.all(helper.filesToDelete.map(writeFile));
});
};
FilesHelper.prototype.removeFile = function(filename) {
return removeItem(filename, 'unlink');
};
FilesHelper.prototype.removeDir = function(dirname) {
return removeItem(dirname, 'rmdir');
};
function removeItems(items, operation) {
function removeItems(parentDir, items, operation) {
var remover;

@@ -131,3 +66,3 @@

return result.then(function() {
return removeItem(item, operation);
return removeItem(parentDir, item, operation);
});

@@ -138,9 +73,11 @@ };

function removeItem(name, operation) {
function removeItem(parentDir, name, operation) {
var itemPath = path.join(parentDir, name);
return new Promise(function(resolve, reject) {
fs.exists(name, function(exists) {
fs.exists(itemPath, function(exists) {
if (!exists) {
return resolve();
}
fs[operation](name, function(err) {
fs[operation](itemPath, function(err) {
if (err) {

@@ -147,0 +84,0 @@ return reject(err);

@@ -34,8 +34,8 @@ 'use strict';

var opts = new Options(info, config, builderConfig);
expect(opts.repoDir).to.equal(path.join('/home/ubuntu/repo_dir'));
expect(opts.repoDir).to.equal(path.join(config.home, 'repo_dir'));
expect(opts.repoName).to.equal('repo_name');
expect(opts.sitePath).to.equal(
path.join('/home/ubuntu/repo_dir/repo_name'));
path.join(config.home, 'repo_dir/repo_name'));
expect(opts.branch).to.equal('18f-pages');
expect(opts.destDir).to.equal(path.join('/home/ubuntu/dest_dir'));
expect(opts.destDir).to.equal(path.join(config.home, 'dest_dir'));
expect(opts.internalDestDir).to.be.undefined;

@@ -67,8 +67,8 @@ expect(opts.githubOrg).to.equal('18F');

var opts = new Options(info, config, builderConfig);
expect(opts.repoDir).to.equal(path.join('/home/ubuntu/repo_dir'));
expect(opts.repoDir).to.equal(path.join(config.home, 'repo_dir'));
expect(opts.repoName).to.equal('repo_name');
expect(opts.sitePath).to.equal(
path.join('/home/ubuntu/repo_dir/repo_name'));
path.join(config.home, 'repo_dir/repo_name'));
expect(opts.branch).to.equal('foobar-pages');
expect(opts.destDir).to.equal(path.join('/home/ubuntu/dest_dir'));
expect(opts.destDir).to.equal(path.join(config.home, 'dest_dir'));
expect(opts.internalDestDir).to.be.undefined;

@@ -99,6 +99,6 @@ expect(opts.githubOrg).to.equal('foobar');

var opts = new Options(info, config, builderConfig);
expect(opts.destDir).to.equal(path.join('/home/ubuntu/dest_dir'));
expect(opts.destDir).to.equal(path.join(config.home, 'dest_dir'));
expect(opts.internalDestDir).to.equal(
path.join('/home/ubuntu/internal_dest_dir'));
path.join(config.home, 'internal_dest_dir'));
});
});

@@ -7,3 +7,2 @@ 'use strict';

var ComponentFactory = require('../lib/component-factory');
var FileLockedOperation = require('file-locked-operation');
var fs = require('fs');

@@ -25,9 +24,9 @@ var path = require('path');

describe('SiteBuilder', function() {
var config, origSpawn, mySpawn, logger, filesHelper, expectLogMessages;
var config, origSpawn, mySpawn, logger, expectLogMessages;
function cloneConfig() {
config = JSON.parse(JSON.stringify(OrigConfig));
config.home = '';
config.git = 'git';
config.bundler = 'bundle';
config.bundlerCacheDir = 'bundler_cache_dir';
config.jekyll = 'jekyll';

@@ -40,10 +39,4 @@ config.rsync = 'rsync';

SiteBuilder.setConfiguration(config);
filesHelper = new FilesHelper();
return filesHelper.init(config);
});
after(function() {
return filesHelper.after();
});
beforeEach(function() {

@@ -58,9 +51,4 @@ origSpawn = childProcess.spawn;

childProcess.spawn = origSpawn;
return filesHelper.afterEach();
});
var check = function(done, cb) {
return function(err) { try { cb(err); done(); } catch (e) { done(e); } };
};
var makeOpts = function() {

@@ -87,6 +75,3 @@ var info = {

opts.sitePath = filesHelper.dirs.testRepoDir;
components = new ComponentFactory(config, opts, targetBranch, logger);
components.updateLock = new FileLockedOperation(
filesHelper.files.lockfilePath);
return new SiteBuilder(targetBranch, components);

@@ -108,3 +93,3 @@ };

buildConfigs = [{
destination: 'dest_dir',
destination: path.join(config.home, 'dest_dir/repo_name'),
configurations: '_config.yml,' + config.pagesConfig

@@ -127,2 +112,3 @@ }];

.returns(Promise.resolve());
sinon.stub(builder.sync, 'sync').returns(Promise.resolve());
sinon.stub(builder.updateLock, 'doLockedOperation')

@@ -152,2 +138,5 @@ .returns(Promise.resolve());

]);
builder.sync.sync.args.should.eql([
[path.join(config.home, 'dest_dir/repo_name')]
]);
builder.configHandler.removeGeneratedConfig.called.should.be.true;

@@ -166,3 +155,5 @@ });

builder.commandRunner.run.args.should.eql([
[config.bundler, ['install']]
[config.bundler,
['install',
'--path=' + path.join(config.home, config.bundlerCacheDir)]]
]);

@@ -173,2 +164,5 @@ builder.configHandler.readOrWriteConfig.called.should.be.true;

]);
builder.sync.sync.args.should.eql([
[path.join(config.home, 'dest_dir/repo_name')]
]);
builder.configHandler.removeGeneratedConfig.called.should.be.true;

@@ -179,5 +173,6 @@ });

it('should perform a successful rsync build', function() {
var buildDestination = path.join(config.home, 'dest_dir/repo_name');
builder.configHandler.usesJekyll = false;
builder.configHandler.usesBundler = false;
builder.configHandler.buildDestination = 'dest_dir';

@@ -189,4 +184,5 @@ return runBuild().should.be.fulfilled

builder.commandRunner.run.args.should.eql([
[config.rsync, config.rsyncOpts.concat(['./', 'dest_dir'])]
[config.rsync, config.rsyncOpts.concat(['./', buildDestination])]
]);
builder.sync.sync.args.should.eql([[buildDestination]]);
builder.configHandler.readOrWriteConfig.called.should.be.false;

@@ -208,2 +204,3 @@ builder.jekyllHelper.build.called.should.be.false;

builder.jekyllHelper.build.called.should.be.false;
builder.sync.sync.called.should.be.false;
builder.configHandler.removeGeneratedConfig.called.should.be.false;

@@ -215,3 +212,4 @@ });

describe('makeBuilderListener and launchBuilder', function() {
var webhook, incomingPayload, builderConfig, cloneDir, outputDir, buildLog;
var webhook, incomingPayload, builderConfig, cloneDir, outputDir, buildLog,
filesHelper;

@@ -238,36 +236,38 @@ before(function() {

'branch': '18f-pages',
'repositoryDir': path.join(filesHelper.dirs.testRepoDir, 'repo_dir'),
'generatedSiteDir': path.join(filesHelper.dirs.testRepoDir, 'dest_dir')
'repositoryDir': 'repo_dir',
'generatedSiteDir': 'dest_dir'
};
cloneDir = path.join(filesHelper.dirs.testRepoDir, 'repo_dir/foo');
outputDir = path.join(filesHelper.dirs.testRepoDir, 'dest_dir/foo');
cloneDir = path.join('repo_dir/foo');
outputDir = path.join('dest_dir/foo');
buildLog = path.join(outputDir, 'build.log');
filesHelper = new FilesHelper();
return filesHelper.init(config)
.then(function() {
config.home = filesHelper.tempDir;
});
});
beforeEach(function(done) {
after(function() {
return filesHelper.after();
});
beforeEach(function() {
webhook = { on: sinon.spy() };
fs.mkdir(filesHelper.dirs.testRepoDir, function(err) {
if (err) { return done(err); }
fs.mkdir(builderConfig.repositoryDir, function(err) {
if (err) { return done(err); }
fs.mkdir(builderConfig.generatedSiteDir, function(err) {
if (err) { return done(err); }
fs.mkdir(outputDir, done);
});
filesHelper.files.push(buildLog);
// Note that the site builder will not create the parent directory for
// the generated sites. That should be done before launching the server.
return filesHelper.createDir('repo_dir')
.then(function() {
return filesHelper.createDir('dest_dir');
})
.then(function() {
return filesHelper.createDir(path.join('dest_dir', 'foo'));
});
});
});
// The outer afterEach() will remove the testRepoDir.
afterEach(function(done) {
fs.unlink(buildLog, function() {
fs.rmdir(outputDir, function(err) {
if (err) { return done(err); }
fs.rmdir(builderConfig.generatedSiteDir, function(err) {
if (err) { return done(err); }
fs.rmdir(builderConfig.repositoryDir, done);
});
});
});
afterEach(function() {
return filesHelper.afterEach();
});

@@ -280,96 +280,92 @@

var restoreLogs = function() {
console.error.restore();
console.log.restore();
var restoreLogs = function(err) {
return new Promise(function(resolve, reject) {
console.error.restore();
console.log.restore();
err ? reject(err) : resolve();
});
};
it('should create a function to launch a builder', function() {
SiteBuilder.makeBuilderListener(webhook, builderConfig);
var handler = SiteBuilder.makeBuilderListener(webhook, builderConfig);
expect(handler).to.be.a.Function;
expect(webhook.on.calledTwice).to.be.true;
expect(webhook.on.args[0].length).to.equal(2);
expect(webhook.on.args[0][0]).to.equal('create');
expect(webhook.on.args[0][1]).to.be.handler;
expect(webhook.on.args[1].length).to.equal(2);
expect(webhook.on.args[1][0]).to.equal('push');
expect(webhook.on.args[1].length).to.equal(2);
expect(webhook.on.args[0][1]).to.be.a.Function;
expect(webhook.on.args[1][1]).to.be.a.Function;
expect(webhook.on.args[0][1]).to.equal(webhook.on.args[1][1]);
expect(webhook.on.args[1][1]).to.be.handler;
});
it('should create a builder that builds the site', function(done) {
var checkResult = check(done, function(err) {
var logMsgs = console.log.args,
errorMsgs = console.error.args,
expectedMessages = [
'18F/foo: starting build at commit deadbeef',
'description: Build me',
'timestamp: 2015-09-25',
'committer: michael.bland@gsa.gov',
'pusher: Mike Bland michael.bland@gsa.gov',
'sender: mbland',
'cloning foo into ' + cloneDir,
'foo: build successful'
],
expectedLog = expectedMessages.join('\n') + '\n';
it('should create a builder that builds the site', function() {
var handler = SiteBuilder.makeBuilderListener(webhook, builderConfig);
restoreLogs();
expect(err).to.be.null;
expectLogMessages(logMsgs, expectedMessages);
expect(errorMsgs).to.be.empty;
expect(fs.readFileSync(buildLog, 'utf8')).to.equal(expectedLog);
});
SiteBuilder.makeBuilderListener(webhook, builderConfig, checkResult);
var launcher = webhook.on.args[0][1];
mySpawn.setDefault(mySpawn.simple(0));
captureLogs();
launcher(incomingPayload);
return handler(incomingPayload).should.be.fulfilled
.then(function() {
var logMsgs = console.log.args,
errorMsgs = console.error.args,
expectedMessages = [
'18F/foo: starting build at commit deadbeef',
'description: Build me',
'timestamp: 2015-09-25',
'committer: michael.bland@gsa.gov',
'pusher: Mike Bland michael.bland@gsa.gov',
'sender: mbland',
'cloning foo into ' + path.join(config.home, cloneDir),
'syncing to ' + config.s3.bucket + '/' +
outputDir.replace(/\\/g, '/'),
'foo: build successful'
],
expectedLog = expectedMessages.join('\n') + '\n';
expectLogMessages(logMsgs, expectedMessages);
expect(errorMsgs).to.be.empty;
expect(fs.readFileSync(path.join(config.home, buildLog), 'utf8'))
.to.equal(expectedLog);
})
.then(restoreLogs, restoreLogs);
});
it('should create a builder that fails to build the site', function(done) {
var checkResult = check(done, function(err) {
var logMsgs = console.log.args,
errorMsgs = console.error.args,
expectedMessages = [
'18F/foo: starting build at commit deadbeef',
'description: Build me',
'timestamp: 2015-09-25',
'committer: michael.bland@gsa.gov',
'pusher: Mike Bland michael.bland@gsa.gov',
'sender: mbland',
'cloning foo into ' + cloneDir
],
expectedErrors = [
'Error: failed to clone foo with exit code 1 from command: ' +
'git clone git@github.com:18F/foo.git --branch 18f-pages',
'foo: build failed'
],
expectedLog = expectedMessages.concat(expectedErrors)
.join('\n') + '\n';
it('should create a builder that fails to build the site', function() {
var handler = SiteBuilder.makeBuilderListener(webhook, builderConfig),
errMsg = 'Error: failed to clone foo ' +
'with exit code 1 from command: ' +
'git clone git@github.com:18F/foo.git --branch 18f-pages';
restoreLogs();
expect(err).to.be.null;
expectLogMessages(logMsgs, expectedMessages);
expectLogMessages(errorMsgs, expectedErrors);
expect(fs.readFileSync(buildLog, 'utf8')).to.equal(expectedLog);
});
SiteBuilder.makeBuilderListener(webhook, builderConfig, checkResult);
var launcher = webhook.on.args[0][1];
mySpawn.setDefault(mySpawn.simple(1));
captureLogs();
launcher(incomingPayload);
return handler(incomingPayload).should.be.rejectedWith(errMsg)
.then(function() {
var logMsgs = console.log.args,
errorMsgs = console.error.args,
expectedMessages = [
'18F/foo: starting build at commit deadbeef',
'description: Build me',
'timestamp: 2015-09-25',
'committer: michael.bland@gsa.gov',
'pusher: Mike Bland michael.bland@gsa.gov',
'sender: mbland',
'cloning foo into ' + path.join(config.home, cloneDir)
],
expectedErrors = [errMsg, 'foo: build failed'],
expectedLog = expectedMessages.concat(expectedErrors)
.join('\n') + '\n';
expectLogMessages(logMsgs, expectedMessages);
expectLogMessages(errorMsgs, expectedErrors);
expect(fs.readFileSync(path.join(config.home, buildLog), 'utf8'))
.to.equal(expectedLog);
})
.then(restoreLogs, restoreLogs);
});
it('should ignore payloads from other organizations', function() {
SiteBuilder.makeBuilderListener(webhook, builderConfig);
var launcher = webhook.on.args[0][1];
sinon.spy(SiteBuilder, 'launchBuilder');
var internalLauncher = SiteBuilder.launchBuilder;
var handler = SiteBuilder.makeBuilderListener(webhook, builderConfig);
incomingPayload.repository.organization = 'not18F';
launcher(incomingPayload);
SiteBuilder.launchBuilder.restore();
expect(internalLauncher.called).to.be.false;
expect(handler(incomingPayload)).to.be.undefined;
});
});
});
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc