r8s-cli
Version:
A command line tool for Reaction Commerce to be used with kubernetes
344 lines (261 loc) • 11.6 kB
JavaScript
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.deploy = undefined;
var _filter2 = require('lodash/filter');
var _filter3 = _interopRequireDefault(_filter2);
var _omit2 = require('lodash/omit');
var _omit3 = _interopRequireDefault(_omit2);
var deploy = exports.deploy = function () {
var _ref = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee(yargs) {
var args, app, image, apps, appToDeploy, msg, values, conf, options, notInReactionDir, packageFile, configFilePath, _ref2, download, res, json, configFile, branch, _ref3, push;
return regeneratorRuntime.wrap(function _callee$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
_utils.Log.args(yargs.argv);
args = (0, _omit3.default)(yargs.argv, ['_', '$0']);
app = args.app, image = args.image;
if (!(!app && !image)) {
_context.next = 5;
break;
}
return _context.abrupt('return', _utils.Log.default(helpMessage));
case 5:
if (app) {
_context.next = 7;
break;
}
return _context.abrupt('return', _utils.Log.error('Error: App name required (--app myapp)'));
case 7:
apps = _utils.Config.get('global', 'launchdock.apps', []);
appToDeploy = (0, _filter3.default)(apps, function (a) {
return a.name === app;
})[0];
if (!appToDeploy) {
msg = 'App not found. Run \'reaction apps list\' to see your active apps';
_utils.Log.error(msg);
process.exit(1);
}
values = {};
// convert any supplied env vars into an object
if (Array.isArray(args.e)) {
args.e.forEach(function (val) {
var conf = val.split('=');
values[conf[0]] = conf[1];
});
} else if (typeof args.e === 'string') {
conf = args.e.split('=');
values[conf[0]] = conf[1];
}
// read in a settings file if provided
if (args.settings) {
values.METEOR_SETTINGS = (0, _utils.getStringFromFile)(args.settings);
}
// read in a Reaction registry file if provided
if (args.registry) {
values.REACTION_REGISTRY = (0, _utils.getStringFromFile)(args.registry);
}
options = { _id: appToDeploy._id };
if (Object.keys(values).length > 0) {
options.env = values;
}
if (!(image || appToDeploy.image)) {
_context.next = 22;
break;
}
// docker pull deployment
_utils.Log.warn('Prebuilt Docker image deployment is currently unavailable.');
_utils.Log.warn('Contact support for more info.');
process.exit(1);
// TODO: allow deployment of prebuilt images
//
// options.image = image || appToDeploy.image;
//
// const result = await gql.fetch(`
// mutation appPull($_id: ID!, $image: String! $env: JSON) {
// appPull(_id: $_id, image: $image, env: $env) {
// _id
// name
// image
// defaultUrl
// }
// }
// `, options);
//
// if (!!result.errors) {
// result.errors.forEach((err) => {
// Log.error(err.message);
// });
// process.exit(1);
// }
//
// const { defaultUrl } = result.data.appPull;
//
// Log.success('\nDone!\n');
//
// Log.info(`Updated ${Log.magenta(app)} with image ${Log.magenta(options.image)}\n`);
// Log.info('You will receive a notification email as soon as the deployment finishes.\n');
// Log.info(`App URL: ${Log.magenta(defaultUrl)}\n`);
_context.next = 72;
break;
case 22:
// git push deployment
notInReactionDir = function notInReactionDir() {
_utils.Log.error('\nNot in a Reaction app directory.\n');
_utils.Log.info('To create a new local project, run: ' + _utils.Log.magenta('reaction init') + '\n');
};
packageFile = void 0;
try {
packageFile = _fsExtra2.default.readJSONSync('./package.json');
} catch (e) {
notInReactionDir();
process.exit(1);
}
if (packageFile.name !== 'reaction') {
notInReactionDir();
process.exit(1);
}
// If we don't have a Reaction CI config file,
// prompt the user to download it from Github
// and commit it to their repo
configFilePath = '.reaction/ci/config.yml';
if (!(0, _utils.isEmptyOrMissing)(configFilePath)) {
_context.next = 56;
break;
}
_utils.Log.warn('\nRequired Reaction CI configuration file not found at: ' + configFilePath + '\n');
_context.next = 31;
return _inquirer2.default.prompt([{
type: 'confirm',
name: 'download',
message: '\nWould you like to download the latest from Github and commit it to your repo?',
default: true
}]);
case 31:
_ref2 = _context.sent;
download = _ref2.download;
if (!download) {
_context.next = 54;
break;
}
_context.prev = 34;
_context.next = 37;
return (0, _nodeFetch2.default)('https://api.github.com/repos/reactioncommerce/reaction/contents/' + configFilePath);
case 37:
res = _context.sent;
_context.next = 40;
return res.json();
case 40:
json = _context.sent;
configFile = new Buffer(json.content, 'base64').toString('utf8');
_fsExtra2.default.writeFileSync(_path2.default.resolve(configFilePath), configFile);
_context.next = 50;
break;
case 45:
_context.prev = 45;
_context.t0 = _context['catch'](34);
_utils.Log.debug(_context.t0);
_utils.Log.error('Failed to create Reaction CI config file. Please contact support.');
process.exit(1);
case 50:
try {
(0, _child_process.exec)('git add ' + configFilePath + ' && git commit -m "Add Reaction CI config file"', { stdio: 'inherit' });
} catch (err) {
_utils.Log.error('\nFailed to commit new config file to your repo\n');
process.exit(1);
}
_utils.Log.success('\nReaction CI config file created!\n');
_context.next = 56;
break;
case 54:
_utils.Log.error('\nReaction CI configuration is required. Please add one at: ' + configFilePath + '\n');
process.exit(1);
case 56:
_context.next = 58;
return (0, _utils.ensureSSHKeysExist)();
case 58:
_utils.Log.info('\nPushing updates to be built...\n');
(0, _utils.setGitSSHKeyEnv)();
branch = void 0;
try {
branch = (0, _child_process.execSync)('git rev-parse --abbrev-ref HEAD').toString().replace(/\r?\n|\r/g, '');
} catch (err) {
_utils.Log.error('\nFailed to get current branch. Exiting.');
process.exit(1);
}
if (!(branch !== 'master')) {
_context.next = 71;
break;
}
_utils.Log.warn('You are not on the master branch. A deployment will NOT happen.');
_context.next = 66;
return _inquirer2.default.prompt([{
type: 'confirm',
name: 'push',
message: '\nWould you like to push the branch up anyway?\n',
default: false
}]);
case 66:
_ref3 = _context.sent;
push = _ref3.push;
if (push) {
(0, _child_process.exec)('git push ' + appToDeploy.group.namespace + '-' + app + ' ' + branch, function (err, stdout, stderr) {
if (err) {
_utils.Log.error('\nDeployment failed');
process.exit(1);
}
if (stderr.includes('Everything up-to-date')) {
_utils.Log.info('\nNo committed changes to deploy.\n');
} else {
_utils.Log.info('\nYour branch has been pushed, but this was not the master branch, so nothing will be deployed.\n');
}
_utils.Log.success('Done!\n');
process.exit(0);
});
} else {
_utils.Log.error('Not pushing code. Exiting.');
process.exit(1);
}
_context.next = 72;
break;
case 71:
(0, _child_process.exec)('git push ' + appToDeploy.group.namespace + '-' + app + ' ' + branch, function (err, stdout, stderr) {
if (err) {
_utils.Log.default(stderr);
_utils.Log.error('\nDeployment failed');
process.exit(1);
}
if (stderr.includes('Everything up-to-date')) {
_utils.Log.info('No committed changes to deploy.\n');
} else {
_utils.Log.info('You will be notified as soon as your app finishes building and deploying.\n');
}
_utils.Log.success('Done!\n');
process.exit(0);
});
case 72:
case 'end':
return _context.stop();
}
}
}, _callee, this, [[34, 45]]);
}));
return function deploy(_x) {
return _ref.apply(this, arguments);
};
}();
var _fsExtra = require('fs-extra');
var _fsExtra2 = _interopRequireDefault(_fsExtra);
var _path = require('path');
var _path2 = _interopRequireDefault(_path);
var _child_process = require('child_process');
var _nodeFetch = require('node-fetch');
var _nodeFetch2 = _interopRequireDefault(_nodeFetch);
var _inquirer = require('inquirer');
var _inquirer2 = _interopRequireDefault(_inquirer);
var _utils = require('../utils');
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; }
var helpMessage = '\nUsage:\n\n reaction deploy [options]\n\n Options:\n --app, -a The name of the app to deploy (required)\n --env, -e Set/update an environment varible before deployment\n --image, -i The Docker image to deploy\n';
;