aberlaas-setup 2.22.2 → 2.23.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/circleci.js +11 -8
- package/lib/github.js +9 -6
- package/lib/helpers/circleci.js +36 -32
- package/lib/helpers/github.js +72 -56
- package/lib/renovate.js +16 -15
- package/package.json +4 -3
- package/lib/helpers/npm.js +0 -16
- package/lib/helpers/ssh.js +0 -77
package/lib/circleci.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { _ } from 'golgoth';
|
|
2
2
|
import { consoleError, consoleInfo, consoleSuccess } from 'firost';
|
|
3
|
-
import
|
|
4
|
-
import
|
|
3
|
+
import { api, hasToken } from './helpers/circleci.js';
|
|
4
|
+
import { getRepoData } from './helpers/github.js';
|
|
5
5
|
|
|
6
6
|
export let __;
|
|
7
7
|
|
|
@@ -11,11 +11,11 @@ export let __;
|
|
|
11
11
|
* @returns {boolean} True if enabled, false otherwise
|
|
12
12
|
*/
|
|
13
13
|
export async function enable() {
|
|
14
|
-
const { username, repo } = await
|
|
14
|
+
const { username, repo } = await __.getRepoData();
|
|
15
15
|
const projectUrl = `https://app.circleci.com/pipelines/github/${username}/${repo}`;
|
|
16
16
|
|
|
17
17
|
// Fail early if no token available
|
|
18
|
-
if (!
|
|
18
|
+
if (!__.hasToken()) {
|
|
19
19
|
__.consoleError(
|
|
20
20
|
'CircleCI: ABERLAAS_CIRCLECI_TOKEN environment variable must be set',
|
|
21
21
|
);
|
|
@@ -46,8 +46,8 @@ __ = {
|
|
|
46
46
|
async isEnabled() {
|
|
47
47
|
// There is no endpoint to check if a project is followed or not, so we get
|
|
48
48
|
// the list of all followed projects and check if the current one is in it
|
|
49
|
-
const allProjects = await
|
|
50
|
-
const { username, repo } = await
|
|
49
|
+
const allProjects = await __.api('projects');
|
|
50
|
+
const { username, repo } = await __.getRepoData();
|
|
51
51
|
const thisProject = _.find(allProjects, { username, reponame: repo });
|
|
52
52
|
return !!thisProject;
|
|
53
53
|
},
|
|
@@ -55,14 +55,17 @@ __ = {
|
|
|
55
55
|
* Automatically follow the repo on CircleCI.
|
|
56
56
|
*/
|
|
57
57
|
async followRepo() {
|
|
58
|
-
const { username, repo } = await
|
|
59
|
-
await
|
|
58
|
+
const { username, repo } = await __.getRepoData();
|
|
59
|
+
await __.api(`project/github/${username}/${repo}/follow`, {
|
|
60
60
|
method: 'post',
|
|
61
61
|
});
|
|
62
62
|
},
|
|
63
63
|
consoleInfo,
|
|
64
64
|
consoleSuccess,
|
|
65
65
|
consoleError,
|
|
66
|
+
getRepoData,
|
|
67
|
+
hasToken,
|
|
68
|
+
api,
|
|
66
69
|
};
|
|
67
70
|
|
|
68
71
|
export default { enable };
|
package/lib/github.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { _ } from 'golgoth';
|
|
2
2
|
import { consoleError, consoleInfo, consoleSuccess } from 'firost';
|
|
3
|
-
import
|
|
3
|
+
import { getRepoData, hasToken, octokit } from './helpers/github.js';
|
|
4
4
|
|
|
5
5
|
export let __;
|
|
6
6
|
|
|
@@ -18,11 +18,11 @@ const gitHubSettings = {
|
|
|
18
18
|
* @returns {boolean} True if enabled, false otherwise
|
|
19
19
|
*/
|
|
20
20
|
export async function enable() {
|
|
21
|
-
const { username, repo } = await
|
|
21
|
+
const { username, repo } = await __.getRepoData();
|
|
22
22
|
const settingsUrl = `https://github.com/${username}/${repo}/settings`;
|
|
23
23
|
|
|
24
24
|
// Fail early if no token available
|
|
25
|
-
if (!
|
|
25
|
+
if (!__.hasToken()) {
|
|
26
26
|
__.consoleError(
|
|
27
27
|
'GitHub: ABERLAAS_GITHUB_TOKEN environment variable must be set',
|
|
28
28
|
);
|
|
@@ -48,7 +48,7 @@ export async function enable() {
|
|
|
48
48
|
throw error;
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
-
await
|
|
51
|
+
await __.octokit('repos.update', {
|
|
52
52
|
owner: username,
|
|
53
53
|
repo,
|
|
54
54
|
...gitHubSettings,
|
|
@@ -65,8 +65,8 @@ __ = {
|
|
|
65
65
|
* @returns {boolean} True if already configured, false otherwise
|
|
66
66
|
*/
|
|
67
67
|
async isAlreadyConfigured() {
|
|
68
|
-
const { username, repo } = await
|
|
69
|
-
const repoData = await
|
|
68
|
+
const { username, repo } = await __.getRepoData();
|
|
69
|
+
const repoData = await __.octokit('repos.get', {
|
|
70
70
|
owner: username,
|
|
71
71
|
repo,
|
|
72
72
|
});
|
|
@@ -76,6 +76,9 @@ __ = {
|
|
|
76
76
|
consoleSuccess,
|
|
77
77
|
consoleInfo,
|
|
78
78
|
consoleError,
|
|
79
|
+
getRepoData,
|
|
80
|
+
hasToken,
|
|
81
|
+
octokit,
|
|
79
82
|
};
|
|
80
83
|
|
|
81
84
|
export default { enable };
|
package/lib/helpers/circleci.js
CHANGED
|
@@ -1,7 +1,41 @@
|
|
|
1
1
|
import { _, got } from 'golgoth';
|
|
2
2
|
import { firostError } from 'firost';
|
|
3
3
|
|
|
4
|
-
export
|
|
4
|
+
export let __;
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Check if a CircleCI token is available
|
|
8
|
+
* @returns {boolean} True if a token is defined
|
|
9
|
+
*/
|
|
10
|
+
export function hasToken() {
|
|
11
|
+
return !!__.token();
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Make a call to the CircleCI v1 API
|
|
16
|
+
* @param {string} urlPath Part of the url after the /api/v1.1/
|
|
17
|
+
* @param {object} userGotOptions Options to pass to the got call
|
|
18
|
+
* @returns {object} Object returned by the API
|
|
19
|
+
*/
|
|
20
|
+
export async function api(urlPath, userGotOptions = {}) {
|
|
21
|
+
const token = __.token();
|
|
22
|
+
const apiUrl = `https://circleci.com/api/v1.1/${urlPath}?circle-token=${token}`;
|
|
23
|
+
const defaultGotOptions = {
|
|
24
|
+
responseType: 'json',
|
|
25
|
+
};
|
|
26
|
+
const gotOptions = _.merge({}, defaultGotOptions, userGotOptions);
|
|
27
|
+
try {
|
|
28
|
+
const response = await __.got(apiUrl, gotOptions);
|
|
29
|
+
return response.body;
|
|
30
|
+
} catch (_error) {
|
|
31
|
+
throw firostError(
|
|
32
|
+
'ABERLAAS_SETUP_CIRCLECI_API',
|
|
33
|
+
"Can't connect to CircleCI API. Check that you have a valid ABERLAAS_CIRCLECI_TOKEN",
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
__ = {
|
|
5
39
|
/**
|
|
6
40
|
* Returns the CircleCI token saved in ENV
|
|
7
41
|
* @returns {string} The CircleCI token
|
|
@@ -9,35 +43,5 @@ export default {
|
|
|
9
43
|
token() {
|
|
10
44
|
return process.env.ABERLAAS_CIRCLECI_TOKEN;
|
|
11
45
|
},
|
|
12
|
-
|
|
13
|
-
* Check if a CircleCI token is available
|
|
14
|
-
* @returns {boolean} True if a token is defined
|
|
15
|
-
*/
|
|
16
|
-
hasToken() {
|
|
17
|
-
return !!this.token();
|
|
18
|
-
},
|
|
19
|
-
/**
|
|
20
|
-
* Make a call to the CircleCI v1 API
|
|
21
|
-
* @param {string} urlPath Part of the url after the /api/v1.1/
|
|
22
|
-
* @param {object} userGotOptions Options to pass to the got call
|
|
23
|
-
* @returns {object} Object returned by the API
|
|
24
|
-
*/
|
|
25
|
-
async api(urlPath, userGotOptions = {}) {
|
|
26
|
-
const token = this.token();
|
|
27
|
-
const apiUrl = `https://circleci.com/api/v1.1/${urlPath}?circle-token=${token}`;
|
|
28
|
-
const defaultGotOptions = {
|
|
29
|
-
responseType: 'json',
|
|
30
|
-
};
|
|
31
|
-
const gotOptions = _.merge({}, defaultGotOptions, userGotOptions);
|
|
32
|
-
try {
|
|
33
|
-
const response = await this.__got(apiUrl, gotOptions);
|
|
34
|
-
return response.body;
|
|
35
|
-
} catch (_error) {
|
|
36
|
-
throw firostError(
|
|
37
|
-
'ABERLAAS_SETUP_CIRCLECI_API',
|
|
38
|
-
"Can't connect to CircleCI API. Check that you have a valid ABERLAAS_CIRCLECI_TOKEN",
|
|
39
|
-
);
|
|
40
|
-
}
|
|
41
|
-
},
|
|
42
|
-
__got: got,
|
|
46
|
+
got,
|
|
43
47
|
};
|
package/lib/helpers/github.js
CHANGED
|
@@ -1,9 +1,68 @@
|
|
|
1
1
|
import { _ } from 'golgoth';
|
|
2
2
|
import { run } from 'firost';
|
|
3
3
|
import { Octokit } from '@octokit/rest';
|
|
4
|
+
import { hostGitRoot } from 'aberlaas-helper';
|
|
5
|
+
import Gilmore from 'gilmore';
|
|
4
6
|
import parseGithubUrl from 'parse-github-repo-url';
|
|
5
7
|
|
|
6
|
-
export
|
|
8
|
+
export let __;
|
|
9
|
+
/**
|
|
10
|
+
* Check if a GitHub token is available
|
|
11
|
+
* @returns {boolean} True if a token is defined
|
|
12
|
+
*/
|
|
13
|
+
export function hasToken() {
|
|
14
|
+
return !!__.token();
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Returns some data from the git config
|
|
18
|
+
* @returns {object} Object with .username, .repo and .email keys
|
|
19
|
+
*/
|
|
20
|
+
export async function getRepoData() {
|
|
21
|
+
if (__.cache.repoData) {
|
|
22
|
+
return __.cache.repoData;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const email = await __.config('user.email');
|
|
26
|
+
const remoteUrl = await __.config('remote.origin.url');
|
|
27
|
+
const [username, repo] = parseGithubUrl(remoteUrl);
|
|
28
|
+
|
|
29
|
+
const result = { username, repo, email };
|
|
30
|
+
__.cache.repoData = result;
|
|
31
|
+
return result;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Wraps Octokit and return the results
|
|
35
|
+
* @param {string} methodPath Path of the method to call
|
|
36
|
+
* @param {object} options Options to pass to the method
|
|
37
|
+
* @returns {*} Response from the API
|
|
38
|
+
*/
|
|
39
|
+
export async function octokit(methodPath, options) {
|
|
40
|
+
// Instanciate Octokit if not available
|
|
41
|
+
if (!__.cache.octokit) {
|
|
42
|
+
const githubToken = __.token();
|
|
43
|
+
__.cache.octokit = __.newOctokit({
|
|
44
|
+
auth: githubToken,
|
|
45
|
+
log: {
|
|
46
|
+
debug: __.noOp,
|
|
47
|
+
info: __.noOp,
|
|
48
|
+
warn: __.noOp,
|
|
49
|
+
error: __.noOp,
|
|
50
|
+
},
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const octokitInstance = __.cache.octokit;
|
|
55
|
+
const method = _.get(octokitInstance, methodPath);
|
|
56
|
+
const response = await method(options);
|
|
57
|
+
return response.data;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
__ = {
|
|
61
|
+
cache: {},
|
|
62
|
+
clearCache() {
|
|
63
|
+
__.cache = {};
|
|
64
|
+
},
|
|
65
|
+
noOp: () => {},
|
|
7
66
|
/**
|
|
8
67
|
* Returns the GitHub token saved in ENV
|
|
9
68
|
* @returns {string} The GitHub token
|
|
@@ -11,69 +70,26 @@ export default {
|
|
|
11
70
|
token() {
|
|
12
71
|
return process.env.ABERLAAS_GITHUB_TOKEN;
|
|
13
72
|
},
|
|
14
|
-
/**
|
|
15
|
-
* Check if a GitHub token is available
|
|
16
|
-
* @returns {boolean} True if a token is defined
|
|
17
|
-
*/
|
|
18
|
-
hasToken() {
|
|
19
|
-
return !!this.token();
|
|
20
|
-
},
|
|
21
|
-
/**
|
|
22
|
-
* Returns some data from the git config
|
|
23
|
-
* @returns {object} Object with .username, .repo and .email keys
|
|
24
|
-
*/
|
|
25
|
-
async repoData() {
|
|
26
|
-
if (this.__cache.repoData) {
|
|
27
|
-
return this.__cache.repoData;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
const email = await this.config('user.email');
|
|
31
|
-
const remoteUrl = await this.config('remote.origin.url');
|
|
32
|
-
const [username, repo] = parseGithubUrl(remoteUrl);
|
|
33
|
-
|
|
34
|
-
const result = { username, repo, email };
|
|
35
|
-
this.__cache.githubData = result;
|
|
36
|
-
return result;
|
|
37
|
-
},
|
|
38
73
|
/**
|
|
39
74
|
* Return the value of a git config
|
|
40
75
|
* @param {string} key Config key
|
|
41
76
|
* @returns {string} Config value
|
|
42
77
|
*/
|
|
43
78
|
async config(key) {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
}
|
|
47
|
-
|
|
79
|
+
if (!__.cache.repository) {
|
|
80
|
+
__.cache.repository = new Gilmore(hostGitRoot());
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const repository = __.cache.repository;
|
|
84
|
+
return await repository.getConfig(key);
|
|
48
85
|
},
|
|
49
86
|
/**
|
|
50
|
-
*
|
|
51
|
-
* @param {
|
|
52
|
-
* @
|
|
53
|
-
* @returns {*} Response from the API
|
|
87
|
+
* Creates a new Octokit instance
|
|
88
|
+
* @param {...any} args - Arguments to pass to the Octokit constructor
|
|
89
|
+
* @returns {Octokit} A new Octokit instance
|
|
54
90
|
*/
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
if (!this.__cache.octokit) {
|
|
58
|
-
const githubToken = this.token();
|
|
59
|
-
this.__cache.octokit = new this.__Octokit({
|
|
60
|
-
auth: githubToken,
|
|
61
|
-
log: {
|
|
62
|
-
debug: this.__noOp,
|
|
63
|
-
info: this.__noOp,
|
|
64
|
-
warn: this.__noOp,
|
|
65
|
-
error: this.__noOp,
|
|
66
|
-
},
|
|
67
|
-
});
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
const octokit = this.__cache.octokit;
|
|
71
|
-
const method = _.get(octokit, methodPath);
|
|
72
|
-
const response = await method(options);
|
|
73
|
-
return response.data;
|
|
91
|
+
newOctokit(...args) {
|
|
92
|
+
return new Octokit(...args);
|
|
74
93
|
},
|
|
75
|
-
|
|
76
|
-
__Octokit: Octokit,
|
|
77
|
-
__cache: {},
|
|
78
|
-
__noOp: () => {},
|
|
94
|
+
run,
|
|
79
95
|
};
|
package/lib/renovate.js
CHANGED
|
@@ -1,22 +1,20 @@
|
|
|
1
1
|
import { consoleError, consoleInfo, consoleSuccess } from 'firost';
|
|
2
|
-
import
|
|
2
|
+
import { getRepoData, hasToken, octokit } from './helpers/github.js';
|
|
3
3
|
|
|
4
4
|
export let __;
|
|
5
5
|
|
|
6
|
-
const RENOVATE_ID = 2471197;
|
|
7
|
-
|
|
8
6
|
/**
|
|
9
7
|
* Attempt to automatically add the current repo to renovate, otherwise
|
|
10
8
|
* display the link to do it manually
|
|
11
9
|
* @returns {boolean} True if enabled, false otherwise
|
|
12
10
|
*/
|
|
13
11
|
export async function enable() {
|
|
14
|
-
const { username, repo } = await
|
|
15
|
-
const manualUrl = `https://github.com/settings/installations/${
|
|
12
|
+
const { username, repo } = await __.getRepoData();
|
|
13
|
+
const manualUrl = `https://github.com/settings/installations/${__.renovateId}`;
|
|
16
14
|
const renovateDashboardUrl = `https://developer.mend.io/github/${username}/${repo}`;
|
|
17
15
|
|
|
18
16
|
// Fail early if no token available
|
|
19
|
-
if (!
|
|
17
|
+
if (!__.hasToken()) {
|
|
20
18
|
__.consoleError(
|
|
21
19
|
'Renovate: ABERLAAS_GITHUB_TOKEN environment variable must be set',
|
|
22
20
|
);
|
|
@@ -34,8 +32,8 @@ export async function enable() {
|
|
|
34
32
|
|
|
35
33
|
try {
|
|
36
34
|
const repositoryId = await __.getRepositoryId();
|
|
37
|
-
await
|
|
38
|
-
installation_id:
|
|
35
|
+
await __.octokit('apps.addRepoToInstallation', {
|
|
36
|
+
installation_id: __.renovateId,
|
|
39
37
|
repository_id: repositoryId,
|
|
40
38
|
});
|
|
41
39
|
} catch (_err) {
|
|
@@ -51,13 +49,14 @@ export async function enable() {
|
|
|
51
49
|
}
|
|
52
50
|
|
|
53
51
|
__ = {
|
|
52
|
+
renovateId: 2471197,
|
|
54
53
|
/**
|
|
55
54
|
* Returns the GitHub repository Id
|
|
56
55
|
* @returns {number} Repository Id
|
|
57
56
|
*/
|
|
58
57
|
async getRepositoryId() {
|
|
59
|
-
const { username, repo } = await
|
|
60
|
-
const { id } = await
|
|
58
|
+
const { username, repo } = await __.getRepoData();
|
|
59
|
+
const { id } = await __.octokit('repos.get', {
|
|
61
60
|
owner: username,
|
|
62
61
|
repo,
|
|
63
62
|
});
|
|
@@ -69,17 +68,16 @@ __ = {
|
|
|
69
68
|
*/
|
|
70
69
|
async isAlreadyEnabled() {
|
|
71
70
|
try {
|
|
72
|
-
const { username, repo } = await
|
|
73
|
-
const installations = await
|
|
71
|
+
const { username, repo } = await __.getRepoData();
|
|
72
|
+
const installations = await __.octokit(
|
|
74
73
|
'apps.listReposAccessibleToInstallation',
|
|
75
74
|
{
|
|
76
|
-
installation_id:
|
|
75
|
+
installation_id: __.renovateId,
|
|
77
76
|
},
|
|
78
77
|
);
|
|
79
78
|
|
|
80
79
|
return installations.repositories.some(
|
|
81
|
-
(
|
|
82
|
-
repoData.owner.login === username && repoData.name === repo,
|
|
80
|
+
(item) => item.owner.login === username && item.name === repo,
|
|
83
81
|
);
|
|
84
82
|
} catch {
|
|
85
83
|
// API call fails if Renovate app is not installed - treat as not enabled
|
|
@@ -89,6 +87,9 @@ __ = {
|
|
|
89
87
|
consoleSuccess,
|
|
90
88
|
consoleInfo,
|
|
91
89
|
consoleError,
|
|
90
|
+
getRepoData,
|
|
91
|
+
hasToken,
|
|
92
|
+
octokit,
|
|
92
93
|
};
|
|
93
94
|
|
|
94
95
|
export default { enable };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "aberlaas-setup",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.23.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "aberlaas setup helper: Setup third parties like GitHub, Netlify or CircleCI",
|
|
6
6
|
"author": "Tim Carry <tim@pixelastic.com>",
|
|
@@ -21,8 +21,9 @@
|
|
|
21
21
|
"main": "./lib/main.js",
|
|
22
22
|
"dependencies": {
|
|
23
23
|
"@octokit/rest": "22.0.1",
|
|
24
|
-
"aberlaas-helper": "2.
|
|
25
|
-
"firost": "5.5.
|
|
24
|
+
"aberlaas-helper": "2.23.0",
|
|
25
|
+
"firost": "5.5.2",
|
|
26
|
+
"gilmore": "1.2.0",
|
|
26
27
|
"golgoth": "3.1.0",
|
|
27
28
|
"parse-github-repo-url": "1.4.1"
|
|
28
29
|
},
|
package/lib/helpers/npm.js
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
export default {
|
|
2
|
-
/**
|
|
3
|
-
* Returns the npm token saved in ENV
|
|
4
|
-
* @returns {string} The npm token
|
|
5
|
-
*/
|
|
6
|
-
token() {
|
|
7
|
-
return process.env.ABERLAAS_NPM_TOKEN;
|
|
8
|
-
},
|
|
9
|
-
/**
|
|
10
|
-
* Check if a npm token is available
|
|
11
|
-
* @returns {boolean} True if a token is defined
|
|
12
|
-
*/
|
|
13
|
-
hasToken() {
|
|
14
|
-
return !!this.token();
|
|
15
|
-
},
|
|
16
|
-
};
|
package/lib/helpers/ssh.js
DELETED
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
import path from 'node:path';
|
|
2
|
-
import { _ } from 'golgoth';
|
|
3
|
-
import { exists, mkdirp, read, run, which } from 'firost';
|
|
4
|
-
import { hostGitPath } from 'aberlaas-helper';
|
|
5
|
-
import githubHelper from './github.js';
|
|
6
|
-
|
|
7
|
-
export default {
|
|
8
|
-
/**
|
|
9
|
-
* Check if ssh-keygen is available
|
|
10
|
-
* @returns {boolean} True if available, false otherwise
|
|
11
|
-
*/
|
|
12
|
-
async hasBinary() {
|
|
13
|
-
const sshKeygenPath = await this.__which('ssh-keygen');
|
|
14
|
-
return !!sshKeygenPath;
|
|
15
|
-
},
|
|
16
|
-
/**
|
|
17
|
-
* Returns SSH keys (generate them if needed)
|
|
18
|
-
* @returns {object} Object with .public, .private and .privateFingerprint
|
|
19
|
-
*/
|
|
20
|
-
async getKeys() {
|
|
21
|
-
const keyPath = hostGitPath('./tmp/ssh/key');
|
|
22
|
-
|
|
23
|
-
// Generating keys if do not exist
|
|
24
|
-
const keyExists = await exists(keyPath);
|
|
25
|
-
if (!keyExists) {
|
|
26
|
-
await this.generateKeys(keyPath);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
const publicKeyPath = `${keyPath}.pub`;
|
|
30
|
-
const publicKey = await read(publicKeyPath);
|
|
31
|
-
const privateKey = await read(keyPath);
|
|
32
|
-
const privateFingerprint = await this.getFingerprint(keyPath);
|
|
33
|
-
|
|
34
|
-
return {
|
|
35
|
-
public: publicKey,
|
|
36
|
-
private: privateKey,
|
|
37
|
-
privateFingerprint,
|
|
38
|
-
};
|
|
39
|
-
},
|
|
40
|
-
/**
|
|
41
|
-
* Generate SSH keys
|
|
42
|
-
* @param {string} keyPath Path to the public key
|
|
43
|
-
*/
|
|
44
|
-
async generateKeys(keyPath) {
|
|
45
|
-
const keyDirectory = path.dirname(keyPath);
|
|
46
|
-
await mkdirp(keyDirectory);
|
|
47
|
-
const { email: keyEmail } = await githubHelper.repoData();
|
|
48
|
-
const sshKeygenArguments = [
|
|
49
|
-
'-m PEM',
|
|
50
|
-
'-t rsa',
|
|
51
|
-
`-C ${keyEmail}`,
|
|
52
|
-
`-f ${keyPath}`,
|
|
53
|
-
"-N ''",
|
|
54
|
-
];
|
|
55
|
-
const command = `ssh-keygen ${sshKeygenArguments.join(' ')}`;
|
|
56
|
-
// Need to run in shell mode, otherwise does not understand the empty
|
|
57
|
-
// passphrase
|
|
58
|
-
await this.__run(command, { shell: true, stdout: false });
|
|
59
|
-
},
|
|
60
|
-
/**
|
|
61
|
-
* Returns the md5 fingerprint from a key path
|
|
62
|
-
* @param {string} keyPath Filepath to the key file
|
|
63
|
-
* @returns {string} Fingerprint as used by CircleCI and GitHub
|
|
64
|
-
*/
|
|
65
|
-
async getFingerprint(keyPath) {
|
|
66
|
-
const command = `ssh-keygen -E md5 -l -f ${keyPath}`;
|
|
67
|
-
const result = await this.__run(command, { stdout: false });
|
|
68
|
-
return _.chain(result)
|
|
69
|
-
.get('stdout')
|
|
70
|
-
.split(' ')
|
|
71
|
-
.nth(1)
|
|
72
|
-
.replace('MD5:', '')
|
|
73
|
-
.value();
|
|
74
|
-
},
|
|
75
|
-
__which: which,
|
|
76
|
-
__run: run,
|
|
77
|
-
};
|