aberlaas 2.2.0 → 2.3.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/README.md +1 -19
- package/commands/ci/index.js +14 -99
- package/commands/init/index.js +19 -7
- package/commands/lint/css.js +2 -2
- package/commands/lint/helpers/prettier.js +2 -2
- package/commands/lint/index.js +1 -1
- package/commands/lint/js.js +1 -1
- package/commands/precommit/index.js +4 -3
- package/commands/setup/index.js +0 -12
- package/commands/test/index.js +50 -48
- package/configs/eslint.cjs +2 -0
- package/configs/lintstaged.js +25 -0
- package/configs/node.cjs +1 -0
- package/configs/{prettier.cjs → prettier.js} +1 -1
- package/configs/{stylelint.cjs → stylelint.js} +1 -1
- package/configs/vite.js +9 -2
- package/main.js +0 -2
- package/package.json +9 -10
- package/templates/_circleci/config.yml +0 -1
- package/templates/_eslintignore.conf +4 -1
- package/templates/_gitattributes +3 -0
- package/templates/_gitignore +28 -0
- package/templates/lintstaged.config.js +4 -0
- package/templates/prettier.config.js +4 -0
- package/templates/scripts/hooks/pre-commit +1 -1
- package/templates/stylelint.config.js +4 -0
- package/commands/ci/autoRelease.js +0 -143
- package/commands/release/index.js +0 -76
- package/commands/setup/autoRelease/envVars.js +0 -56
- package/commands/setup/autoRelease/index.js +0 -59
- package/commands/setup/autoRelease/privateKey.js +0 -41
- package/commands/setup/autoRelease/publicKey.js +0 -55
- package/configs/lintstaged.cjs +0 -31
- package/templates/_lintstagedrc.cjs +0 -4
- package/templates/_prettierrc.cjs +0 -4
- package/templates/_stylelintrc.cjs +0 -4
package/README.md
CHANGED
|
@@ -161,24 +161,6 @@ what most free CI tier offer). If you have access to higher end machines, you
|
|
|
161
161
|
can update this value by passing the `--cpu-count=X` flag to your `aberlaas ci`
|
|
162
162
|
call.
|
|
163
163
|
|
|
164
|
-
### Auto-Releasing
|
|
165
|
-
|
|
166
|
-
As an optional feature, you can have aberlaas automatically release a new
|
|
167
|
-
version of your module from the CI environment when relevant.
|
|
168
|
-
|
|
169
|
-
The CI will then check all the commits since the last release. If any commit is
|
|
170
|
-
a `feat()` it will release a new minor version; it any commit is a `fix()` it
|
|
171
|
-
will release a new patch version. For major release, you'll have to do it
|
|
172
|
-
manually.
|
|
173
|
-
|
|
174
|
-
This option is not enabled by default. If you need it, you need to follow those
|
|
175
|
-
steps:
|
|
176
|
-
|
|
177
|
-
- Run `aberlaas setup --auto-release`. It will setup the required `ENV` variables
|
|
178
|
-
and ssh keys
|
|
179
|
-
- Update your `aberlaas ci` script to `aberlaas ci --auto-release`
|
|
180
|
-
- Uncomment the `add_ssh_keys` in your `.circleci.yml` file
|
|
181
|
-
|
|
182
164
|
## File structure
|
|
183
165
|
|
|
184
166
|
`./lib/configs` contain the default configuration for all the tools. They are
|
|
@@ -188,7 +170,7 @@ exported by the package and thus can be `require`d in userland.
|
|
|
188
170
|
extends the configuration exported in the previous files. Copying files to
|
|
189
171
|
userland allows user to change the files if they want to change the behavior.
|
|
190
172
|
|
|
191
|
-
`.eslintrc.js`,
|
|
173
|
+
`.eslintrc.js`, `stylelint.config.js` and `vite.config.js` are local
|
|
192
174
|
configuration files for `aberlaas` itself. They eat their own dog food by
|
|
193
175
|
referencing the same configs as above.
|
|
194
176
|
|
package/commands/ci/index.js
CHANGED
|
@@ -1,21 +1,10 @@
|
|
|
1
|
-
import helper from '../../helper.js';
|
|
2
1
|
import ciInfo from 'ci-info';
|
|
3
|
-
import _ from 'golgoth/lodash.js';
|
|
4
|
-
import pMap from 'golgoth/pMap.js';
|
|
5
|
-
import readJson from 'firost/readJson.js';
|
|
6
2
|
import run from 'firost/run.js';
|
|
3
|
+
import commandTest from '../test/index.js';
|
|
4
|
+
import commandLint from '../lint/index.js';
|
|
7
5
|
import consoleInfo from 'firost/consoleInfo.js';
|
|
8
|
-
import autoRelease from './autoRelease.js';
|
|
9
6
|
|
|
10
7
|
export default {
|
|
11
|
-
/**
|
|
12
|
-
* Return the value of an environment variable
|
|
13
|
-
* @param {string} key Name of the variable
|
|
14
|
-
* @returns {*} Key value
|
|
15
|
-
**/
|
|
16
|
-
getEnv(key) {
|
|
17
|
-
return _.get(process, `env.${key}`);
|
|
18
|
-
},
|
|
19
8
|
/**
|
|
20
9
|
* Checks if currently running on a CI server
|
|
21
10
|
* @returns {boolean} True if on a CI server
|
|
@@ -23,111 +12,37 @@ export default {
|
|
|
23
12
|
isCI() {
|
|
24
13
|
return ciInfo.isCI;
|
|
25
14
|
},
|
|
26
|
-
/**
|
|
27
|
-
* Checks if currently running on CircleCI
|
|
28
|
-
* @returns {boolean} True if on CircleCI
|
|
29
|
-
**/
|
|
30
|
-
isCircleCI() {
|
|
31
|
-
return ciInfo.CIRCLE;
|
|
32
|
-
},
|
|
33
|
-
/**
|
|
34
|
-
* Checks if currently on a PR
|
|
35
|
-
* @returns {boolean} True if on a PR
|
|
36
|
-
**/
|
|
37
|
-
isPR() {
|
|
38
|
-
return ciInfo.isPR;
|
|
39
|
-
},
|
|
40
|
-
/**
|
|
41
|
-
* Return the name of the originating branch of the PR
|
|
42
|
-
* @returns {string} Name of the PR branch
|
|
43
|
-
**/
|
|
44
|
-
prBranch() {
|
|
45
|
-
if (!this.isPR()) {
|
|
46
|
-
return false;
|
|
47
|
-
}
|
|
48
|
-
if (this.isCircleCI()) {
|
|
49
|
-
return this.getEnv('CIRCLE_BRANCH');
|
|
50
|
-
}
|
|
51
|
-
return false;
|
|
52
|
-
},
|
|
53
|
-
/**
|
|
54
|
-
* Returns the list of scripts defined in the package.json
|
|
55
|
-
* @returns {Array} List of scripts defined
|
|
56
|
-
**/
|
|
57
|
-
async availableScripts() {
|
|
58
|
-
// Get scripts in package.json
|
|
59
|
-
const currentPackage = await readJson(helper.hostPath('package.json'));
|
|
60
|
-
return _.chain(currentPackage).get('scripts').keys().value();
|
|
61
|
-
},
|
|
62
|
-
/**
|
|
63
|
-
* Returns a list of available scripts to run
|
|
64
|
-
* @returns {Array} List of scripts to run
|
|
65
|
-
**/
|
|
66
|
-
async scriptsToRun() {
|
|
67
|
-
const availableScripts = await this.availableScripts();
|
|
68
|
-
|
|
69
|
-
// Get potential scripts to run
|
|
70
|
-
const potentialScripts = ['test', 'lint', 'build:prod'];
|
|
71
|
-
|
|
72
|
-
return _.intersection(potentialScripts, availableScripts);
|
|
73
|
-
},
|
|
74
|
-
/**
|
|
75
|
-
* Display the current node and yarn versions
|
|
76
|
-
**/
|
|
77
|
-
async displayVersion() {
|
|
78
|
-
const { stdout: nodeVersion } = await this.__run('node --version', {
|
|
79
|
-
stdout: false,
|
|
80
|
-
});
|
|
81
|
-
const { stdout: yarnVersion } = await this.__run('yarn --version', {
|
|
82
|
-
stdout: false,
|
|
83
|
-
});
|
|
84
|
-
this.__consoleInfo(`node ${nodeVersion}, yarn v${yarnVersion}`);
|
|
85
|
-
},
|
|
86
15
|
/**
|
|
87
16
|
* Run CI scripts and fail the job if any fails
|
|
17
|
+
* Runs lint and test by default, but can be changed with --no-test and
|
|
18
|
+
* --no-lint
|
|
88
19
|
* @param {object} cliArgs CLI Argument object, as created by minimist
|
|
89
20
|
* @returns {boolean} True on success, throws on error
|
|
90
21
|
**/
|
|
91
22
|
async run(cliArgs = {}) {
|
|
92
23
|
const args = {
|
|
93
|
-
|
|
94
|
-
|
|
24
|
+
test: true,
|
|
25
|
+
lint: true,
|
|
95
26
|
...cliArgs,
|
|
96
27
|
};
|
|
97
28
|
|
|
98
29
|
if (!this.isCI()) {
|
|
30
|
+
this.__consoleInfo('Current system is not a CI, skipping');
|
|
99
31
|
return true;
|
|
100
32
|
}
|
|
101
33
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
await pMap(
|
|
106
|
-
scripts,
|
|
107
|
-
async (scriptName) => {
|
|
108
|
-
let command = scriptName;
|
|
109
|
-
if (command === 'test') {
|
|
110
|
-
command = `test --maxWorkers=${args['cpu-count']}`;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
await helper.yarnRun(command);
|
|
114
|
-
},
|
|
115
|
-
{ concurrency: 1 },
|
|
116
|
-
);
|
|
34
|
+
if (args.test) {
|
|
35
|
+
await this.__runTest();
|
|
36
|
+
}
|
|
117
37
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
await this.autoRelease();
|
|
38
|
+
if (args.lint) {
|
|
39
|
+
await this.__runLint();
|
|
121
40
|
}
|
|
122
41
|
|
|
123
42
|
return true;
|
|
124
43
|
},
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
**/
|
|
128
|
-
async autoRelease() {
|
|
129
|
-
await autoRelease.run();
|
|
130
|
-
},
|
|
44
|
+
__runTest: commandTest.run.bind(commandTest),
|
|
45
|
+
__runLint: commandLint.run.bind(commandLint),
|
|
131
46
|
__run: run,
|
|
132
47
|
__consoleInfo: consoleInfo,
|
|
133
48
|
};
|
package/commands/init/index.js
CHANGED
|
@@ -45,6 +45,10 @@ export default {
|
|
|
45
45
|
* default rules and overwrite them as they see fit
|
|
46
46
|
**/
|
|
47
47
|
async addConfigFiles() {
|
|
48
|
+
// Git
|
|
49
|
+
await this.copyToHost('./templates/_gitignore', './.gitignore');
|
|
50
|
+
await this.copyToHost('./templates/_gitattributes', './.gitattributes');
|
|
51
|
+
|
|
48
52
|
// Yarn
|
|
49
53
|
await this.copyToHost('templates/_yarnrc.yml', '.yarnrc.yml');
|
|
50
54
|
|
|
@@ -53,16 +57,22 @@ export default {
|
|
|
53
57
|
await this.copyToHost('templates/_eslintignore.conf', '.eslintignore');
|
|
54
58
|
|
|
55
59
|
// Lint-staged
|
|
56
|
-
await this.copyToHost(
|
|
60
|
+
await this.copyToHost(
|
|
61
|
+
'templates/lintstaged.config.js',
|
|
62
|
+
'lintstaged.config.js',
|
|
63
|
+
);
|
|
57
64
|
|
|
58
65
|
// Vite
|
|
59
66
|
await this.copyToHost('templates/vite.config.js', 'vite.config.js');
|
|
60
67
|
|
|
61
68
|
// Prettier
|
|
62
|
-
await this.copyToHost('templates/
|
|
69
|
+
await this.copyToHost('templates/prettier.config.js', 'prettier.config.js');
|
|
63
70
|
|
|
64
71
|
// Stylelint
|
|
65
|
-
await this.copyToHost(
|
|
72
|
+
await this.copyToHost(
|
|
73
|
+
'templates/stylelint.config.js',
|
|
74
|
+
'stylelint.config.js',
|
|
75
|
+
);
|
|
66
76
|
|
|
67
77
|
// Renovate
|
|
68
78
|
await this.copyToHost(
|
|
@@ -252,7 +262,9 @@ export default {
|
|
|
252
262
|
await write(nodeConfig.nodeVersion, nvmrcPath);
|
|
253
263
|
|
|
254
264
|
// Download latest yarn version
|
|
255
|
-
await this.__run(
|
|
265
|
+
await this.__run(`yarn set version ${nodeConfig.yarnVersion}`, {
|
|
266
|
+
stdout: false,
|
|
267
|
+
});
|
|
256
268
|
},
|
|
257
269
|
/**
|
|
258
270
|
* Configure git hooks to use scripts/hooks instead of .git/hooks
|
|
@@ -274,6 +286,9 @@ export default {
|
|
|
274
286
|
async run() {
|
|
275
287
|
const progress = spinner();
|
|
276
288
|
|
|
289
|
+
progress.tick('Configuring Git');
|
|
290
|
+
await this.configureGit();
|
|
291
|
+
|
|
277
292
|
progress.tick('Pinning node and yarn versions');
|
|
278
293
|
await this.pinNodeAndYarn();
|
|
279
294
|
await this.addEngineNodeVersion();
|
|
@@ -284,9 +299,6 @@ export default {
|
|
|
284
299
|
progress.tick('Adding yarn scripts');
|
|
285
300
|
await this.addScripts();
|
|
286
301
|
|
|
287
|
-
progress.tick('Configuring git hooks');
|
|
288
|
-
await this.configureGitHooks();
|
|
289
|
-
|
|
290
302
|
progress.tick('Updating LICENSE');
|
|
291
303
|
await this.addLicenseFile();
|
|
292
304
|
await this.addLicenseField();
|
package/commands/lint/css.js
CHANGED
|
@@ -36,8 +36,8 @@ export default {
|
|
|
36
36
|
// Config
|
|
37
37
|
const configFile = await helper.configFile(
|
|
38
38
|
userConfigFile,
|
|
39
|
-
'.
|
|
40
|
-
'configs/stylelint.
|
|
39
|
+
'stylelint.config.js',
|
|
40
|
+
'configs/stylelint.js',
|
|
41
41
|
);
|
|
42
42
|
const config = await helper.import(configFile);
|
|
43
43
|
|
|
@@ -14,8 +14,8 @@ export async function fix(inputFiles) {
|
|
|
14
14
|
// Config file
|
|
15
15
|
const configFile = await helper.configFile(
|
|
16
16
|
null,
|
|
17
|
-
'.
|
|
18
|
-
'
|
|
17
|
+
'prettier.config.js',
|
|
18
|
+
'configs/prettier.js',
|
|
19
19
|
);
|
|
20
20
|
const config = await prettier.resolveConfig(configFile);
|
|
21
21
|
|
package/commands/lint/index.js
CHANGED
|
@@ -21,7 +21,7 @@ export default {
|
|
|
21
21
|
* @param {object} cliArgs CLI Argument object, as created by minimist
|
|
22
22
|
* @returns {boolean} True on success
|
|
23
23
|
**/
|
|
24
|
-
async run(cliArgs) {
|
|
24
|
+
async run(cliArgs = {}) {
|
|
25
25
|
const allTypesKeys = _.keys(this.linters);
|
|
26
26
|
const userTypes = _.intersection(_.keys(cliArgs), allTypesKeys);
|
|
27
27
|
const typesToLint = _.isEmpty(userTypes) ? allTypesKeys : userTypes;
|
package/commands/lint/js.js
CHANGED
|
@@ -7,13 +7,14 @@ export default {
|
|
|
7
7
|
// Config
|
|
8
8
|
const configPath = await helper.configFile(
|
|
9
9
|
cliArgs.config,
|
|
10
|
-
'.
|
|
11
|
-
'
|
|
10
|
+
'lintstaged.config.js',
|
|
11
|
+
'configs/lintstaged.js',
|
|
12
12
|
);
|
|
13
|
+
const config = await helper.import(configPath);
|
|
13
14
|
|
|
14
15
|
try {
|
|
15
16
|
const result = await lintStaged({
|
|
16
|
-
|
|
17
|
+
config,
|
|
17
18
|
});
|
|
18
19
|
// Linting failed
|
|
19
20
|
if (!result) {
|
package/commands/setup/index.js
CHANGED
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
import github from './github.js';
|
|
2
2
|
import circleci from './circleci.js';
|
|
3
3
|
import renovate from './renovate.js';
|
|
4
|
-
import autoRelease from './autoRelease/index.js';
|
|
5
4
|
import _ from 'golgoth/lodash.js';
|
|
6
5
|
|
|
7
6
|
export default {
|
|
8
7
|
/**
|
|
9
8
|
* Enable external services.
|
|
10
9
|
* Will enable CircleCI, GitHub and Renovate by default.
|
|
11
|
-
* If --auto-release is passed, will configure CircleCI
|
|
12
10
|
* @param {object} cliArgs CLI Argument object, as created by minimist
|
|
13
11
|
**/
|
|
14
12
|
async run(cliArgs = {}) {
|
|
@@ -16,7 +14,6 @@ export default {
|
|
|
16
14
|
circleci: true,
|
|
17
15
|
renovate: true,
|
|
18
16
|
github: true,
|
|
19
|
-
'auto-release': false,
|
|
20
17
|
};
|
|
21
18
|
const cliServices = _.omit(cliArgs, ['_']);
|
|
22
19
|
const servicesToEnable = {
|
|
@@ -33,9 +30,6 @@ export default {
|
|
|
33
30
|
if (servicesToEnable.renovate) {
|
|
34
31
|
await this.renovate();
|
|
35
32
|
}
|
|
36
|
-
if (servicesToEnable['auto-release']) {
|
|
37
|
-
await this.autoRelease();
|
|
38
|
-
}
|
|
39
33
|
},
|
|
40
34
|
/**
|
|
41
35
|
* Configure GitHub
|
|
@@ -55,10 +49,4 @@ export default {
|
|
|
55
49
|
async renovate() {
|
|
56
50
|
await renovate.enable();
|
|
57
51
|
},
|
|
58
|
-
/**
|
|
59
|
-
* Enable autoRelease on CircleCI
|
|
60
|
-
**/
|
|
61
|
-
async autoRelease() {
|
|
62
|
-
await autoRelease.enable();
|
|
63
|
-
},
|
|
64
52
|
};
|
package/commands/test/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import { createVitest } from 'vitest/node';
|
|
1
2
|
import helper from '../../helper.js';
|
|
2
|
-
import
|
|
3
|
+
import firostError from 'firost/error.js';
|
|
3
4
|
import _ from 'golgoth/lodash.js';
|
|
4
5
|
|
|
5
6
|
export default {
|
|
@@ -15,69 +16,70 @@ export default {
|
|
|
15
16
|
* @param {object} cliArgs CLI Argument object, as created by minimist
|
|
16
17
|
* @returns {boolean} true on success
|
|
17
18
|
**/
|
|
18
|
-
async run(cliArgs) {
|
|
19
|
-
const options = await this.
|
|
19
|
+
async run(cliArgs = {}) {
|
|
20
|
+
const options = await this.vitestOptions(cliArgs);
|
|
21
|
+
const files = _.isEmpty(cliArgs._) ? [helper.hostPath()] : cliArgs._;
|
|
22
|
+
|
|
23
|
+
const vitest = await createVitest('test', options);
|
|
24
|
+
|
|
25
|
+
// Note: vitest sets process.exitCode to 1 if tests fail
|
|
26
|
+
const initialExitCode = process.exitCode;
|
|
27
|
+
await vitest.start(files);
|
|
28
|
+
|
|
29
|
+
if (!options.watch) {
|
|
30
|
+
await vitest.close();
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (process.exitCode == 1) {
|
|
34
|
+
process.exitCode = initialExitCode;
|
|
35
|
+
throw firostError('ERROR_TEST', 'Error while testing files');
|
|
36
|
+
}
|
|
20
37
|
|
|
21
|
-
await run(`yarn run vitest ${options.join(' ')}`, { stdin: true });
|
|
22
38
|
return true;
|
|
23
39
|
},
|
|
24
40
|
|
|
25
41
|
/**
|
|
26
|
-
* Transform all aberlaas test cli options into suitable vitest
|
|
42
|
+
* Transform all aberlaas test cli options into suitable vitest options
|
|
27
43
|
* @param {object} cliArgs CLI Argument object, as created by minimist
|
|
28
|
-
* @returns {Array} Array of
|
|
44
|
+
* @returns {Array} Array of options for vitest
|
|
29
45
|
**/
|
|
30
|
-
async
|
|
46
|
+
async vitestOptions(cliArgs = {}) {
|
|
31
47
|
// Options that have special meaning in aberlaas and shouldn't be passed
|
|
32
48
|
// as-is to vitest
|
|
33
|
-
const
|
|
49
|
+
const specialMeaningCliArgs = ['_', 'config', 'failFast', 'related'];
|
|
34
50
|
|
|
35
|
-
//
|
|
36
|
-
const inputFiles = _.isEmpty(cliArgs._) ? [helper.hostPath()] : cliArgs._;
|
|
37
|
-
const vitestOptions = [...inputFiles];
|
|
38
|
-
|
|
39
|
-
// Run "vitest related" when --related is passed
|
|
40
|
-
if (cliArgs.related) {
|
|
41
|
-
vitestOptions.unshift('related');
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
// Stop early as soon as one test fails
|
|
45
|
-
if (cliArgs.failFast) {
|
|
46
|
-
vitestOptions.push('--bail=1');
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
// Disable watch by default
|
|
50
|
-
vitestOptions.push(cliArgs.watch ? '--watch=true' : '--watch=false');
|
|
51
|
-
|
|
52
|
-
// Allow a success, even if no files are passed
|
|
53
|
-
vitestOptions.push('--passWithNoTests');
|
|
54
|
-
|
|
55
|
-
// Hide skipped tests, allowing less noisy debug with fit/fdescribe
|
|
56
|
-
vitestOptions.push('--hideSkippedTests');
|
|
57
|
-
|
|
58
|
-
// Config file
|
|
51
|
+
// Reading base options from the config file
|
|
59
52
|
const configFile = await helper.configFile(
|
|
60
53
|
cliArgs.config,
|
|
61
54
|
'vite.config.js',
|
|
62
|
-
'
|
|
55
|
+
'configs/vite.js',
|
|
63
56
|
);
|
|
64
|
-
|
|
57
|
+
const optionsFromConfig = (await helper.import(configFile)).test;
|
|
65
58
|
|
|
66
|
-
//
|
|
67
|
-
|
|
68
|
-
//
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
59
|
+
// Enhancing options with custom CLI arguments
|
|
60
|
+
const optionsFromAberlaas = {
|
|
61
|
+
// We always allow fit/fdescribe, even in CI. Those errors will be caught
|
|
62
|
+
// by the lint command instead
|
|
63
|
+
allowOnly: true,
|
|
64
|
+
};
|
|
65
|
+
// --failFast stops early as soon as one test fails
|
|
66
|
+
if (cliArgs.failFast) {
|
|
67
|
+
optionsFromAberlaas.bail = 1;
|
|
68
|
+
}
|
|
69
|
+
// --related runs also related files
|
|
70
|
+
// Note (2024-01-19): The related option is not documented, but should
|
|
71
|
+
// contain the list of files
|
|
72
|
+
if (cliArgs.related) {
|
|
73
|
+
optionsFromAberlaas.related = cliArgs._;
|
|
74
|
+
}
|
|
77
75
|
|
|
78
|
-
|
|
79
|
-
|
|
76
|
+
// Passing other CLI options directly to vitest
|
|
77
|
+
const optionsFromCli = _.omit(cliArgs, specialMeaningCliArgs);
|
|
80
78
|
|
|
81
|
-
return
|
|
79
|
+
return {
|
|
80
|
+
...optionsFromConfig,
|
|
81
|
+
...optionsFromAberlaas,
|
|
82
|
+
...optionsFromCli,
|
|
83
|
+
};
|
|
82
84
|
},
|
|
83
85
|
};
|
package/configs/eslint.cjs
CHANGED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
const readmeCommands = [
|
|
2
|
+
'yarn run aberlaas readme',
|
|
3
|
+
'git add ./README.md ./lib/README.md',
|
|
4
|
+
];
|
|
5
|
+
|
|
6
|
+
export default {
|
|
7
|
+
// Lint
|
|
8
|
+
'*.css': ['yarn run lint:fix --css'],
|
|
9
|
+
'*.{yml,yaml}': ['yarn run lint:fix --yml'],
|
|
10
|
+
'.circleci/config.yml': ['yarn run lint --circleci'],
|
|
11
|
+
'*.json': ['yarn run lint:fix --json'],
|
|
12
|
+
'*.js': ['yarn run lint:fix --js'],
|
|
13
|
+
|
|
14
|
+
// Test
|
|
15
|
+
'./lib/**/*.js': ['yarn run test --failFast --related'],
|
|
16
|
+
|
|
17
|
+
// Compress
|
|
18
|
+
'*.png': ['yarn run compress --png'],
|
|
19
|
+
|
|
20
|
+
// Documentation
|
|
21
|
+
// Update the README whenever the documentation, or the README template
|
|
22
|
+
// changes
|
|
23
|
+
'docs/src/**/*.md': readmeCommands,
|
|
24
|
+
'.github/README.template.md': readmeCommands,
|
|
25
|
+
};
|
package/configs/node.cjs
CHANGED
package/configs/vite.js
CHANGED
|
@@ -3,8 +3,13 @@ const configDir = new URL('./vite/', import.meta.url).pathname;
|
|
|
3
3
|
|
|
4
4
|
export default defineConfig({
|
|
5
5
|
test: {
|
|
6
|
-
//
|
|
7
|
-
|
|
6
|
+
// vitest default is to run in watch mode, we revert that
|
|
7
|
+
watch: false,
|
|
8
|
+
// Allow a success, even if no files are passed
|
|
9
|
+
passWithNoTests: true,
|
|
10
|
+
// Hide skipped tests, allowing less noisy debug with fit/fdescribe
|
|
11
|
+
hideSkippedTests: true,
|
|
12
|
+
|
|
8
13
|
// Tests should be in a __tests__ folder next to their code
|
|
9
14
|
include: ['**/__tests__/**/*.js?(x)'],
|
|
10
15
|
// We ignore temporary folders from the tests
|
|
@@ -13,6 +18,8 @@ export default defineConfig({
|
|
|
13
18
|
// Restore mocks after each tests
|
|
14
19
|
restoreMocks: true,
|
|
15
20
|
|
|
21
|
+
// Make describe, it, beforeEach and other globally available
|
|
22
|
+
globals: true,
|
|
16
23
|
// Run before each test file
|
|
17
24
|
setupFiles: [
|
|
18
25
|
`${configDir}/test/setupFiles/dedent.js`,
|
package/main.js
CHANGED
|
@@ -6,7 +6,6 @@ import commandCi from './commands/ci/index.js';
|
|
|
6
6
|
import commandCompress from './commands/compress/index.js';
|
|
7
7
|
import commandInit from './commands/init/index.js';
|
|
8
8
|
import commandPrecommit from './commands/precommit/index.js';
|
|
9
|
-
import commandRelease from './commands/release/index.js';
|
|
10
9
|
import commandTest from './commands/test/index.js';
|
|
11
10
|
import commandLint from './commands/lint/index.js';
|
|
12
11
|
import commandReadme from './commands/readme/index.js';
|
|
@@ -25,7 +24,6 @@ export default {
|
|
|
25
24
|
lint: commandLint,
|
|
26
25
|
precommit: commandPrecommit,
|
|
27
26
|
readme: commandReadme,
|
|
28
|
-
release: commandRelease,
|
|
29
27
|
setup: commandSetup,
|
|
30
28
|
test: commandTest,
|
|
31
29
|
};
|
package/package.json
CHANGED
|
@@ -2,17 +2,11 @@
|
|
|
2
2
|
"name": "aberlaas",
|
|
3
3
|
"type": "module",
|
|
4
4
|
"description": "Scaffold your JavaScript projects with tests, lint and release scripts",
|
|
5
|
-
"version": "2.
|
|
5
|
+
"version": "2.3.0",
|
|
6
6
|
"repository": "pixelastic/aberlaas",
|
|
7
7
|
"homepage": "https://projects.pixelastic.com/aberlaas/",
|
|
8
8
|
"author": "Tim Carry (@pixelastic)",
|
|
9
9
|
"license": "MIT",
|
|
10
|
-
"exports": {
|
|
11
|
-
".": "./main.js",
|
|
12
|
-
"./configs/lintstaged.cjs": "./configs/lintstaged.cjs",
|
|
13
|
-
"./configs/prettier.cjs": "./configs/prettier.cjs",
|
|
14
|
-
"./configs/styleling.cjs": "./configs/styleling.cjs"
|
|
15
|
-
},
|
|
16
10
|
"files": [
|
|
17
11
|
"bin/",
|
|
18
12
|
"lib/",
|
|
@@ -27,18 +21,23 @@
|
|
|
27
21
|
"commands/readme/*.js",
|
|
28
22
|
"commands/release/*.js",
|
|
29
23
|
"commands/setup/*.js",
|
|
30
|
-
"commands/setup/autoRelease/*.js",
|
|
31
24
|
"commands/setup/helpers/*.js",
|
|
32
25
|
"commands/test/*.js",
|
|
33
26
|
"configs/",
|
|
34
27
|
"templates/"
|
|
35
28
|
],
|
|
29
|
+
"exports": {
|
|
30
|
+
".": "./main.js",
|
|
31
|
+
"./configs/lintstaged": "./configs/lintstaged.js",
|
|
32
|
+
"./configs/prettier": "./configs/prettier.js",
|
|
33
|
+
"./configs/stylelint": "./configs/stylelint.js"
|
|
34
|
+
},
|
|
36
35
|
"bin": "bin/aberlaas.js",
|
|
37
36
|
"dependencies": {
|
|
38
37
|
"@octokit/rest": "18.12.0",
|
|
39
38
|
"ci-info": "3.9.0",
|
|
40
39
|
"dedent": "1.5.1",
|
|
41
|
-
"eslint": "8.
|
|
40
|
+
"eslint": "8.56.0",
|
|
42
41
|
"eslint-config-prettier": "9.0.0",
|
|
43
42
|
"eslint-plugin-import": "2.29.0",
|
|
44
43
|
"eslint-plugin-jsdoc": "46.9.0",
|
|
@@ -76,5 +75,5 @@
|
|
|
76
75
|
"test:watch": "../scripts/lib/test-watch",
|
|
77
76
|
"postinstall": "./scripts/postinstall"
|
|
78
77
|
},
|
|
79
|
-
"gitHead": "
|
|
78
|
+
"gitHead": "cca93623a1219558bd311aefde796d75d6790009"
|
|
80
79
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Hidden files
|
|
1
|
+
# Hidden files are ignored by default by ESLint
|
|
2
2
|
# The following line will unignore them
|
|
3
3
|
!.*
|
|
4
4
|
|
|
@@ -7,3 +7,6 @@ node_modules/
|
|
|
7
7
|
|
|
8
8
|
# .yarn contains the yarn source code, we don't need to lint it
|
|
9
9
|
.yarn/
|
|
10
|
+
|
|
11
|
+
# Ignore the documentation for now, I haven't migrated it to ESM yet
|
|
12
|
+
docs/
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# Hidden files
|
|
2
|
+
.DS_Store
|
|
3
|
+
.envrc
|
|
4
|
+
|
|
5
|
+
# Directories
|
|
6
|
+
build/
|
|
7
|
+
dist/
|
|
8
|
+
node_modules/
|
|
9
|
+
tmp/
|
|
10
|
+
|
|
11
|
+
# Files
|
|
12
|
+
Thumbs.db
|
|
13
|
+
npm-debug.log
|
|
14
|
+
yarn-error.log
|
|
15
|
+
*~
|
|
16
|
+
|
|
17
|
+
# Yarn
|
|
18
|
+
# https://yarnpkg.com/getting-started/qa#which-files-should-be-gitignored
|
|
19
|
+
.yarn/*
|
|
20
|
+
!.yarn/patches
|
|
21
|
+
!.yarn/plugins
|
|
22
|
+
!.yarn/releases
|
|
23
|
+
!.yarn/sdks
|
|
24
|
+
!.yarn/versions
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
# Netlify
|
|
28
|
+
.netlify
|
|
@@ -1,143 +0,0 @@
|
|
|
1
|
-
import release from '../release/index.js';
|
|
2
|
-
import consoleInfo from 'firost/consoleInfo.js';
|
|
3
|
-
import _ from 'golgoth/lodash.js';
|
|
4
|
-
import run from 'firost/run.js';
|
|
5
|
-
import write from 'firost/write.js';
|
|
6
|
-
import exists from 'firost/exists.js';
|
|
7
|
-
import helper from '../../helper.js';
|
|
8
|
-
|
|
9
|
-
export default {
|
|
10
|
-
/**
|
|
11
|
-
* Run a git command in the repo
|
|
12
|
-
*
|
|
13
|
-
* @param {string} gitCommand Git command to run
|
|
14
|
-
* @returns {string} Command output
|
|
15
|
-
*/
|
|
16
|
-
async gitRun(gitCommand) {
|
|
17
|
-
const repoPath = helper.hostPath();
|
|
18
|
-
const result = await run(`cd ${repoPath} && ${gitCommand}`, {
|
|
19
|
-
shell: true,
|
|
20
|
-
stdout: false,
|
|
21
|
-
});
|
|
22
|
-
return result.stdout;
|
|
23
|
-
},
|
|
24
|
-
/**
|
|
25
|
-
* Set a git config value only if wasn't set before
|
|
26
|
-
* @param {string} name Name of the config
|
|
27
|
-
* @param {string} value Value of the config
|
|
28
|
-
**/
|
|
29
|
-
async gitConfigSet(name, value) {
|
|
30
|
-
// We test to see if there is already a value. If no, we write it
|
|
31
|
-
try {
|
|
32
|
-
await this.gitRun(`git config ${name}`);
|
|
33
|
-
} catch (err) {
|
|
34
|
-
await this.gitRun(`git config ${name} ${value}`);
|
|
35
|
-
}
|
|
36
|
-
},
|
|
37
|
-
/**
|
|
38
|
-
* Returns the latest tag of the repo
|
|
39
|
-
*
|
|
40
|
-
* @returns {string} Latest tag
|
|
41
|
-
**/
|
|
42
|
-
async gitGetLatestTag() {
|
|
43
|
-
const allTags = await this.gitRun('git tag -l --sort=creatordate');
|
|
44
|
-
return _.chain(allTags).split('\n').last().value();
|
|
45
|
-
},
|
|
46
|
-
/**
|
|
47
|
-
* Returns an array of all commit description since last release
|
|
48
|
-
*
|
|
49
|
-
* @returns {Array} List of all commit description
|
|
50
|
-
**/
|
|
51
|
-
async getCommitsSinceLastRelease() {
|
|
52
|
-
const latestTag = await this.gitGetLatestTag();
|
|
53
|
-
const range = latestTag ? `${latestTag}..HEAD` : 'HEAD';
|
|
54
|
-
const commitList = await this.gitRun(`git log ${range} --format=%B`);
|
|
55
|
-
return _.chain(commitList).split('\n').compact().reverse().value();
|
|
56
|
-
},
|
|
57
|
-
/**
|
|
58
|
-
* Determines what version should be released based on the commits since the
|
|
59
|
-
* last release
|
|
60
|
-
* @returns {string|boolean} False if no release, otherwise minor or patch
|
|
61
|
-
**/
|
|
62
|
-
async getReleaseVersion() {
|
|
63
|
-
const commits = await this.getCommitsSinceLastRelease();
|
|
64
|
-
const status = {
|
|
65
|
-
isMinor: false,
|
|
66
|
-
isPatch: false,
|
|
67
|
-
};
|
|
68
|
-
_.each(commits, (commit) => {
|
|
69
|
-
const isMinor = _.startsWith(commit, 'feat(');
|
|
70
|
-
const isPatch = _.startsWith(commit, 'fix(');
|
|
71
|
-
status.isMinor = status.isMinor || isMinor;
|
|
72
|
-
status.isPatch = status.isPatch || isPatch;
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
if (status.isMinor) {
|
|
76
|
-
return 'minor';
|
|
77
|
-
}
|
|
78
|
-
if (status.isPatch) {
|
|
79
|
-
return 'patch';
|
|
80
|
-
}
|
|
81
|
-
return false;
|
|
82
|
-
},
|
|
83
|
-
/**
|
|
84
|
-
* Run the auto-release script.
|
|
85
|
-
* If there had been any feat() of fix() commits since last release,
|
|
86
|
-
* automatically release a new one
|
|
87
|
-
**/
|
|
88
|
-
async run() {
|
|
89
|
-
this.__consoleInfo('Attempt to auto-release...');
|
|
90
|
-
|
|
91
|
-
const releaseVersion = await this.getReleaseVersion();
|
|
92
|
-
// Don't release if no relevant changes
|
|
93
|
-
if (!releaseVersion) {
|
|
94
|
-
this.__consoleInfo('No relevant commits since last release.');
|
|
95
|
-
return;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
this.__consoleInfo(`Releasing a ${releaseVersion} version`);
|
|
99
|
-
await this.configureGit();
|
|
100
|
-
await this.configureNpm();
|
|
101
|
-
|
|
102
|
-
const releaseArguments = {
|
|
103
|
-
_: [releaseVersion],
|
|
104
|
-
test: false,
|
|
105
|
-
};
|
|
106
|
-
await this.__releaseRun(releaseArguments);
|
|
107
|
-
},
|
|
108
|
-
/**
|
|
109
|
-
* Set git user name and email
|
|
110
|
-
* */
|
|
111
|
-
async configureGit() {
|
|
112
|
-
const email = this.getEnvVar('GIT_USER_EMAIL');
|
|
113
|
-
const name = this.getEnvVar('GIT_USER_NAME');
|
|
114
|
-
await this.gitConfigSet('user.email', email);
|
|
115
|
-
await this.gitConfigSet('user.name', name);
|
|
116
|
-
},
|
|
117
|
-
/**
|
|
118
|
-
* Write a ~/.npmrc with the token
|
|
119
|
-
* @returns {boolean} true on success, false if already a .npmrc
|
|
120
|
-
**/
|
|
121
|
-
async configureNpm() {
|
|
122
|
-
const npmRcPath = '~/.npmrc';
|
|
123
|
-
if (await this.__exists(npmRcPath)) {
|
|
124
|
-
return false;
|
|
125
|
-
}
|
|
126
|
-
const token = this.getEnvVar('NPM_TOKEN');
|
|
127
|
-
const content = `//registry.npmjs.org/:_authToken=${token}`;
|
|
128
|
-
await this.__write(content, npmRcPath);
|
|
129
|
-
return true;
|
|
130
|
-
},
|
|
131
|
-
/**
|
|
132
|
-
* Return an ENV var value
|
|
133
|
-
* @param {string} key ENV var key
|
|
134
|
-
* @returns {string} ENV var value
|
|
135
|
-
**/
|
|
136
|
-
getEnvVar(key) {
|
|
137
|
-
return _.get(process, `env.${key}`);
|
|
138
|
-
},
|
|
139
|
-
__releaseRun: release.run.bind(release),
|
|
140
|
-
__consoleInfo: consoleInfo,
|
|
141
|
-
__write: write,
|
|
142
|
-
__exists: exists,
|
|
143
|
-
};
|
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
import _ from 'golgoth/lodash.js';
|
|
2
|
-
import run from 'firost/run.js';
|
|
3
|
-
import readJson from 'firost/readJson.js';
|
|
4
|
-
import helper from '../../helper.js';
|
|
5
|
-
|
|
6
|
-
export default {
|
|
7
|
-
/**
|
|
8
|
-
* Release the host package.
|
|
9
|
-
* @param {object} cliArgs CLI Argument object, as created by minimist
|
|
10
|
-
* @returns {boolean} True on success, false otherwise
|
|
11
|
-
**/
|
|
12
|
-
async run(cliArgs = {}) {
|
|
13
|
-
this.fixNpmRegistry();
|
|
14
|
-
await this.fetchOrigin();
|
|
15
|
-
|
|
16
|
-
const binary = await helper.which('np');
|
|
17
|
-
const npOptions = await this.getNpArguments(cliArgs);
|
|
18
|
-
const command = `FORCE_COLOR=1 ${binary} ${npOptions}`;
|
|
19
|
-
await this.__run(command, {
|
|
20
|
-
stdin: true,
|
|
21
|
-
shell: true,
|
|
22
|
-
});
|
|
23
|
-
},
|
|
24
|
-
/**
|
|
25
|
-
* Returns the CLI options to pass to np
|
|
26
|
-
* @param {object} cliArgs CLI Argument object, as created by minimist
|
|
27
|
-
* @returns {string} Arguments to pass to np
|
|
28
|
-
**/
|
|
29
|
-
async getNpArguments(cliArgs = {}) {
|
|
30
|
-
const options = [
|
|
31
|
-
cliArgs._,
|
|
32
|
-
'--no-release-draft',
|
|
33
|
-
'--no-2fa',
|
|
34
|
-
'--any-branch',
|
|
35
|
-
];
|
|
36
|
-
const packageJson = await this.getHostPackageJson();
|
|
37
|
-
|
|
38
|
-
// Skip tests if called with --no-test or if no scripts.test entry
|
|
39
|
-
const cliTestStatus = _.get(cliArgs, 'test', true);
|
|
40
|
-
const cliPackageStatus = _.get(packageJson, 'scripts.test', false);
|
|
41
|
-
if (!cliTestStatus || !cliPackageStatus) {
|
|
42
|
-
options.push('--no-tests');
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
// Run in preview mode if --dry-run is set
|
|
46
|
-
const isDryRun = _.get(cliArgs, 'dry-run', false);
|
|
47
|
-
if (isDryRun) {
|
|
48
|
-
options.push('--preview');
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
return _.chain(options).compact().join(' ').value();
|
|
52
|
-
},
|
|
53
|
-
/**
|
|
54
|
-
* Yarn changes the npm_config_registry value, preventing npm publish to
|
|
55
|
-
* actually work. We revert it to its default value for publishing to work
|
|
56
|
-
**/
|
|
57
|
-
fixNpmRegistry() {
|
|
58
|
-
// eslint-disable-next-line camelcase
|
|
59
|
-
process.env.npm_config_registry = 'https://registry.npmjs.org/';
|
|
60
|
-
},
|
|
61
|
-
/**
|
|
62
|
-
* Fetches origin information, so np can correctly keep the branch up to date
|
|
63
|
-
**/
|
|
64
|
-
async fetchOrigin() {
|
|
65
|
-
await this.__run('git fetch --all', { stdout: false });
|
|
66
|
-
},
|
|
67
|
-
/**
|
|
68
|
-
* Returns the content of the host package.json
|
|
69
|
-
* @returns {object} The content of the host package.json
|
|
70
|
-
**/
|
|
71
|
-
async getHostPackageJson() {
|
|
72
|
-
return await this.__readJson(helper.hostPath('package.json'));
|
|
73
|
-
},
|
|
74
|
-
__run: run,
|
|
75
|
-
__readJson: readJson,
|
|
76
|
-
};
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
import circleciHelper from '../helpers/circleci.js';
|
|
2
|
-
import githubHelper from '../helpers/github.js';
|
|
3
|
-
import npmHelper from '../helpers/npm.js';
|
|
4
|
-
import consoleInfo from 'firost/consoleInfo.js';
|
|
5
|
-
import consoleSuccess from 'firost/consoleSuccess.js';
|
|
6
|
-
import pMap from 'golgoth/pMap.js';
|
|
7
|
-
|
|
8
|
-
export default {
|
|
9
|
-
/**
|
|
10
|
-
* Save an ENV variable to CircleCI
|
|
11
|
-
* @param {string} name Name of the ENV variable
|
|
12
|
-
* @param {string} value Value of the ENV variable
|
|
13
|
-
**/
|
|
14
|
-
async saveEnvVar(name, value) {
|
|
15
|
-
const { username, repo } = await githubHelper.repoData();
|
|
16
|
-
try {
|
|
17
|
-
await circleciHelper.api(
|
|
18
|
-
`project/github/${username}/${repo}/envvar/${name}`,
|
|
19
|
-
{
|
|
20
|
-
method: 'delete',
|
|
21
|
-
},
|
|
22
|
-
);
|
|
23
|
-
} catch (err) {
|
|
24
|
-
// Ignoring the error, it means the ENV var wasn't set in the first place
|
|
25
|
-
}
|
|
26
|
-
await circleciHelper.api(`project/github/${username}/${repo}/envvar`, {
|
|
27
|
-
method: 'post',
|
|
28
|
-
json: {
|
|
29
|
-
name,
|
|
30
|
-
value,
|
|
31
|
-
},
|
|
32
|
-
});
|
|
33
|
-
this.__consoleSuccess(`${name} saved on CircleCI`);
|
|
34
|
-
},
|
|
35
|
-
/**
|
|
36
|
-
* Save ENV Variables to CircleCI
|
|
37
|
-
**/
|
|
38
|
-
async enable() {
|
|
39
|
-
// Vars to save
|
|
40
|
-
const npmToken = npmHelper.token();
|
|
41
|
-
const gitUserEmail = await githubHelper.config('user.email');
|
|
42
|
-
const gitUserName = await githubHelper.config('user.name');
|
|
43
|
-
const vars = [
|
|
44
|
-
{ name: 'NPM_TOKEN', value: npmToken },
|
|
45
|
-
{ name: 'GIT_USER_EMAIL', value: gitUserEmail },
|
|
46
|
-
{ name: 'GIT_USER_NAME', value: gitUserName },
|
|
47
|
-
];
|
|
48
|
-
|
|
49
|
-
// Saving them in parallel
|
|
50
|
-
await pMap(vars, async ({ name, value }) => {
|
|
51
|
-
await this.saveEnvVar(name, value);
|
|
52
|
-
});
|
|
53
|
-
},
|
|
54
|
-
__consoleInfo: consoleInfo,
|
|
55
|
-
__consoleSuccess: consoleSuccess,
|
|
56
|
-
};
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
import envVars from './envVars.js';
|
|
2
|
-
import privateKey from './privateKey.js';
|
|
3
|
-
import publicKey from './publicKey.js';
|
|
4
|
-
import sshHelper from '../helpers/ssh.js';
|
|
5
|
-
import npmHelper from '../helpers/npm.js';
|
|
6
|
-
import githubHelper from '../helpers/github.js';
|
|
7
|
-
import circleciHelper from '../helpers/circleci.js';
|
|
8
|
-
import _ from 'golgoth/lodash.js';
|
|
9
|
-
import consoleError from 'firost/consoleError.js';
|
|
10
|
-
|
|
11
|
-
export default {
|
|
12
|
-
/**
|
|
13
|
-
* Enable autoRelease by configuring CircleCI and GitHub
|
|
14
|
-
* @returns {boolean} True if enabled, false otherwise
|
|
15
|
-
**/
|
|
16
|
-
async enable() {
|
|
17
|
-
// Fail early if we're missing the required tokens
|
|
18
|
-
const validationErrors = await this.validationErrors();
|
|
19
|
-
if (!_.isEmpty(validationErrors)) {
|
|
20
|
-
this.__consoleError(
|
|
21
|
-
'[autoRelease] Please fix the following errors and try again:',
|
|
22
|
-
);
|
|
23
|
-
_.each(validationErrors, (error) => {
|
|
24
|
-
this.__consoleError(error);
|
|
25
|
-
});
|
|
26
|
-
return false;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
await this.__envVarsEnable();
|
|
30
|
-
await this.__privateKeyEnable();
|
|
31
|
-
await this.__publicKeyEnable();
|
|
32
|
-
},
|
|
33
|
-
/**
|
|
34
|
-
* Returns an array of error messages for every token/binary missing
|
|
35
|
-
* @returns {Array} List of error messages
|
|
36
|
-
**/
|
|
37
|
-
async validationErrors() {
|
|
38
|
-
const validationErrors = [];
|
|
39
|
-
if (!circleciHelper.hasToken()) {
|
|
40
|
-
validationErrors.push('You need a CIRCLECI_TOKEN');
|
|
41
|
-
}
|
|
42
|
-
if (!npmHelper.hasToken()) {
|
|
43
|
-
validationErrors.push('You need a NPM_TOKEN');
|
|
44
|
-
}
|
|
45
|
-
if (!githubHelper.hasToken()) {
|
|
46
|
-
validationErrors.push('You need a GITHUB_TOKEN');
|
|
47
|
-
}
|
|
48
|
-
if (!sshHelper.hasBinary()) {
|
|
49
|
-
validationErrors.push('You need ssh-keygen available in your $PATH');
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
return validationErrors;
|
|
53
|
-
},
|
|
54
|
-
__consoleError: consoleError,
|
|
55
|
-
__envVarsEnable: envVars.enable.bind(envVars),
|
|
56
|
-
__privateKeyEnable: privateKey.enable.bind(privateKey),
|
|
57
|
-
__publicKeyEnable: publicKey.enable.bind(publicKey),
|
|
58
|
-
__cache: {},
|
|
59
|
-
};
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import circleciHelper from '../helpers/circleci.js';
|
|
2
|
-
import githubHelper from '../helpers/github.js';
|
|
3
|
-
import sshHelper from '../helpers/ssh.js';
|
|
4
|
-
import consoleSuccess from 'firost/consoleSuccess.js';
|
|
5
|
-
|
|
6
|
-
export default {
|
|
7
|
-
/**
|
|
8
|
-
* Save a private SSH key on CircleCI.
|
|
9
|
-
* The CircleCI API does not allow checking if a SSH key has been defined,
|
|
10
|
-
* so we will need to re-add it each time. But to avoid creating duplicates,
|
|
11
|
-
* we will delete any key with the same fingerprint first
|
|
12
|
-
**/
|
|
13
|
-
async enable() {
|
|
14
|
-
const keys = await sshHelper.getKeys();
|
|
15
|
-
const privateKey = keys.private;
|
|
16
|
-
const privateFingerprint = keys.privateFingerprint;
|
|
17
|
-
const { username, repo } = await githubHelper.repoData();
|
|
18
|
-
const hostname = 'github.com';
|
|
19
|
-
|
|
20
|
-
// Delete it first
|
|
21
|
-
await circleciHelper.api(`project/github/${username}/${repo}/ssh-key`, {
|
|
22
|
-
method: 'delete',
|
|
23
|
-
json: {
|
|
24
|
-
fingerprint: privateFingerprint,
|
|
25
|
-
hostname,
|
|
26
|
-
},
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
// Then, add it
|
|
30
|
-
await circleciHelper.api(`project/github/${username}/${repo}/ssh-key`, {
|
|
31
|
-
method: 'post',
|
|
32
|
-
json: {
|
|
33
|
-
hostname,
|
|
34
|
-
private_key: privateKey,
|
|
35
|
-
},
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
this.__consoleSuccess('SSH private key force saved on CircleCI');
|
|
39
|
-
},
|
|
40
|
-
__consoleSuccess: consoleSuccess,
|
|
41
|
-
};
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
import githubHelper from '../helpers/github.js';
|
|
2
|
-
import sshHelper from '../helpers/ssh.js';
|
|
3
|
-
import _ from 'golgoth/lodash.js';
|
|
4
|
-
import consoleInfo from 'firost/consoleInfo.js';
|
|
5
|
-
import consoleSuccess from 'firost/consoleSuccess.js';
|
|
6
|
-
import consoleError from 'firost/consoleError.js';
|
|
7
|
-
|
|
8
|
-
export default {
|
|
9
|
-
/**
|
|
10
|
-
* Check if SSH public key is already added to GitHub
|
|
11
|
-
* @returns {boolean} True if already enabled, false otherwise
|
|
12
|
-
**/
|
|
13
|
-
async isEnabled() {
|
|
14
|
-
const { username: owner, repo } = await githubHelper.repoData();
|
|
15
|
-
const keys = await githubHelper.octokit('repos.listDeployKeys', {
|
|
16
|
-
owner,
|
|
17
|
-
repo,
|
|
18
|
-
});
|
|
19
|
-
const { public: publicKey } = await sshHelper.getKeys();
|
|
20
|
-
// GitHub does not save the email as part of the key, so we shave it off our
|
|
21
|
-
// key
|
|
22
|
-
const truncatedKey = _.chain(publicKey)
|
|
23
|
-
.split(' ')
|
|
24
|
-
.slice(0, 2)
|
|
25
|
-
.join(' ')
|
|
26
|
-
.value();
|
|
27
|
-
|
|
28
|
-
const foundKey = _.find(keys, { key: truncatedKey });
|
|
29
|
-
return !!foundKey;
|
|
30
|
-
},
|
|
31
|
-
/**
|
|
32
|
-
* Add the SSH public key to GitHub
|
|
33
|
-
* @returns {boolean} True on success
|
|
34
|
-
**/
|
|
35
|
-
async enable() {
|
|
36
|
-
if (await this.isEnabled()) {
|
|
37
|
-
this.__consoleInfo('SSH public key already saved on GitHub');
|
|
38
|
-
return true;
|
|
39
|
-
}
|
|
40
|
-
const { public: key } = await sshHelper.getKeys();
|
|
41
|
-
const { username: owner, repo } = await githubHelper.repoData();
|
|
42
|
-
await githubHelper.octokit('repos.createDeployKey', {
|
|
43
|
-
owner,
|
|
44
|
-
repo,
|
|
45
|
-
key,
|
|
46
|
-
title: 'aberlaas - Push from CircleCI',
|
|
47
|
-
read_only: false,
|
|
48
|
-
});
|
|
49
|
-
this.__consoleSuccess('SSH public key saved on GitHub');
|
|
50
|
-
return true;
|
|
51
|
-
},
|
|
52
|
-
__consoleInfo: consoleInfo,
|
|
53
|
-
__consoleSuccess: consoleSuccess,
|
|
54
|
-
__consoleError: consoleError,
|
|
55
|
-
};
|
package/configs/lintstaged.cjs
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
const pkg = require(`${process.cwd()}/package.json`);
|
|
2
|
-
|
|
3
|
-
// We update the README.md and ./lib/README.md whenever documentation changes
|
|
4
|
-
const aberlaasRunCommands = [
|
|
5
|
-
'yarn run aberlaas readme',
|
|
6
|
-
'git add ./README.md ./lib/README.md',
|
|
7
|
-
];
|
|
8
|
-
const result = {
|
|
9
|
-
'.github/README.template.md': aberlaasRunCommands,
|
|
10
|
-
'docs/src/**/*.md': aberlaasRunCommands,
|
|
11
|
-
};
|
|
12
|
-
|
|
13
|
-
// Linting and autofixing supported files
|
|
14
|
-
if (pkg.scripts && pkg.scripts.lint) {
|
|
15
|
-
result['*.css'] = ['yarn run lint:fix --css'];
|
|
16
|
-
result['*.{yml,yaml}'] = ['yarn run lint:fix --yml'];
|
|
17
|
-
result['.circleci/config.yml'] = ['yarn run lint --circleci'];
|
|
18
|
-
result['*.json'] = ['yarn run lint:fix --json'];
|
|
19
|
-
result['*.js'] = ['yarn run lint:fix --js'];
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
// Compressing images
|
|
23
|
-
if (pkg.scripts && pkg.scripts.compress) {
|
|
24
|
-
result['*.png'] = ['yarn run compress --png'];
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
// Testing changed js files
|
|
28
|
-
if (pkg.scripts && pkg.scripts.test) {
|
|
29
|
-
result['./lib/**/*.js'] = ['yarn run test --failFast --related'];
|
|
30
|
-
}
|
|
31
|
-
module.exports = result;
|