-
Notifications
You must be signed in to change notification settings - Fork 70
/
Copy pathdeploy.js
149 lines (126 loc) · 3.87 KB
/
deploy.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
'use strict';
// eslint-disable-next-line camelcase
var child_process = require('child_process');
var format = require('util').format;
var path = require('path');
var series = require('run-series');
var tv4 = require('tv4');
var schema = {
type: 'object',
properties: {
user: { type: 'string', minLength: 1 },
host: { type: ['string', 'array'] },
repo: { type: 'string' },
path: { type: 'string' },
ref: { type: 'string' },
fetch: { type: 'string' },
},
required: ['host', 'repo', 'path', 'ref'],
};
/**
* Spawn a modified version of visionmedia/deploy
* @private
* @param {object} config config to be piped to deploy
* @param {array} args custom deploy command-line arguments
* @param {DeployCallback} cb done callback
*/
function spawn(config, args, cb) {
var cmd = format('echo \'%j\' | "%s"', config, require.resolve('./deploy'));
args = args || [];
if (args.length > 0) {
var cmdArgs = args.map(function (arg) {
return format('"%s"', arg);
}).join(' ');
cmd = [cmd, cmdArgs].join(' ');
}
var proc = child_process.spawn('sh', ['-c', cmd], { stdio: 'inherit' });
var error;
proc.on('error', function (err) {
error = err;
});
proc.on('close', function (code) {
if (code === 0) return cb(null, args);
error = error || new Error(format('Deploy failed with exit code: %s', code));
error.code = code;
return cb(error);
});
}
function clone(obj) {
return JSON.parse(JSON.stringify(obj));
}
function castArray(arg) {
return Array.isArray(arg) ? arg : [arg];
}
/**
* Deploy to a single environment
* @param {object} deployConfig object containing deploy configs for all environments
* @param {string} env the name of the environment to deploy to
* @param {array} args custom deploy command-line arguments
* @param {DeployCallback} cb done callback
* @returns {boolean} return value is always `false`
*/
function deployForEnv(deployConfig, env, args, cb) {
if (!deployConfig[env]) {
return cb(new Error(format('%s not defined in deploy section', env)));
}
var envConfig = clone(deployConfig[env]);
if (envConfig.ssh_options) {
envConfig.ssh_options = castArray(envConfig.ssh_options).map(function (option) {
return format('-o %s', option);
}).join(' ');
}
var result = tv4.validateResult(envConfig, schema);
if (!result.valid) {
return cb(result.error);
}
if (process.env.NODE_ENV !== 'test') {
console.log('--> Deploying to %s environment', env);
}
if (process.platform !== 'win32') {
envConfig.path = path.resolve(envConfig.path);
}
var hosts = castArray(envConfig.host);
var jobs = hosts.map(function (host) {
return function job(done) {
if (process.env.NODE_ENV !== 'test') {
console.log('--> on host %s', host.host ? host.host : host);
}
var config = clone(envConfig);
config.host = host;
config['post-deploy'] = prependEnv(config['post-deploy'], config.env);
spawn(config, args, done);
};
});
series(jobs, function (err, result) {
result = Array.isArray(envConfig.host) ? result : result[0];
cb(err, result);
});
return false;
}
function envToString(env) {
env = env || {};
return Object.keys(env).map(function (name) {
return format('%s=%s', name.toUpperCase(), env[name]);
}).join(' ');
}
/**
* Prepend command with environment variables
* @private
* @param {string} cmd command
* @param {object} env object containing environment variables
* @returns {string} concatenated shell command
*/
function prependEnv(cmd, env) {
const envVars = envToString(env);
if (!envVars) return cmd;
if (!cmd) return format('export %s', envVars);
return format('export %s && %s', envVars, cmd);
}
module.exports = {
deployForEnv: deployForEnv,
};
/**
* @callback DeployCallback
* @param {Error} error deployment error
* @param {array} args custom command-line arguments provided to deploy
*/