/
index.js
116 lines (98 loc) · 3.45 KB
/
index.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
/* eslint-env node, es6 */
'use strict';
const fs = require('fs-extra');
const path = require('path');
const os = require('os');
const execa = require('execa');
const DeployPlugin = require('ember-cli-deploy-plugin');
module.exports = {
name: 'ember-cli-deploy-git-ci',
createDeployPlugin(options) {
return new GitCIDeployPlugin(options);
}
};
const DEFAULT_USER_NAME = 'Tomster';
const DEFAULT_USER_EMAIL = 'tomster@emberjs.com';
// ssh-add requires the key file to be private
const KEY_PERMISSIONS = 0o600;
class GitCIDeployPlugin extends DeployPlugin {
constructor(options) {
super(options);
this.name = options.name;
this.defaultConfig = {
enabled: !!process.env.CI,
deployKey: process.env.DEPLOY_KEY
};
}
setup(context) {
let config = context.config['git-ci'];
if (!config.enabled) return;
return this.determineDeployKeyPath(config)
.then((keyPath) => this.registerDeployKey(keyPath))
.then(() => this.configureDeployUser(config));
}
teardown(context) {
let config = context.config['git-ci'];
if (!config.enabled) return;
// If we wrote the deploy key to a temporary path, remove it
if (config.tempDeployKeyPath) {
fs.unlinkSync(config.tempDeployKeyPath);
}
// Kill the SSH agent we started
return execa('pkill', ['ssh-agent']);
}
configureDeployUser(config) {
return Promise.all([
this.ensureGitConfig('user.name', config.userName, DEFAULT_USER_NAME),
this.ensureGitConfig('user.email', config.userEmail, DEFAULT_USER_EMAIL)
]);
}
// Set the given git config value for the given key, defaulting to a fallback value
// if no explicit one was configured and no existing value is present.
ensureGitConfig(key, explicitValue, defaultValue) {
let force = !!explicitValue;
return execa('git', ['config', key])
.then(() => force, () => true)
.then((set) => {
if (set) {
return execa('git', ['config', '--global', key, explicitValue || defaultValue]);
}
});
}
// Start an SSH agent and add our deploy key, then export the socket that the
// agent is listening on so subsequent git invocations will talk to it.
registerDeployKey(keyPath) {
return execa.shell(`
eval $(ssh-agent) > /dev/null &&
ssh-add "${keyPath}" &&
echo $SSH_AUTH_SOCK
`).then((result) => {
process.env.SSH_AUTH_SOCK = result.stdout.trim();
});
}
// Determine where the deploy key lives, writing an in-memory one to disk if necessary
determineDeployKeyPath(config) {
if (config.deployKey) {
return this.writeDeployKey(config);
} else {
return this.validateDeployKey(config);
}
}
// Write the given key out to a temporary location on disk
writeDeployKey(config) {
let keyPath = config.tempDeployKeyPath = path.join(os.tmpdir(), `deploy_key_${process.pid}`);
return fs.writeFile(keyPath, config.deployKey, { mode: KEY_PERMISSIONS })
.then(() => keyPath);
}
// Validate the given deploy key path, ensuring the key exists and has the right permissions
validateDeployKey(config) {
let keyPath = config.deployKeyPath;
if (!keyPath) throw new Error('No `deployKey` or `deployKeyPath` configured; unable to deploy');
return fs.exists(keyPath)
.then((exists) => {
if (!exists) throw new Error(`Unable to load deploy key at path '${keyPath}'`);
})
.then(() => fs.chmod(keyPath, KEY_PERMISSIONS))
.then(() => keyPath);
}
}