Skip to content

Commit 890a7fe

Browse files
authoredAug 19, 2024
feat(create-cli): package to align with package managers init command (#779)
1 parent 304b229 commit 890a7fe

38 files changed

+1107
-37
lines changed
 

‎.github/workflows/ci.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ jobs:
133133
- name: Install dependencies
134134
run: npm ci
135135
- name: E2E test affected projects
136-
run: npx nx affected:e2e --parallel=3
136+
run: npx nx affected:e2e --parallel=1
137137

138138
build:
139139
runs-on: ubuntu-latest

‎CONTRIBUTING.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,11 @@ This table provides a quick overview of the environmental setup, with detailed e
2525
**❗️** Test Inclusion Logic
2626

2727
- `INCLUDE_SLOW_TESTS='false'` skips long tests.
28-
- without `INCLUDE_SLOW_TESTS`, tests run if `CI` is set.
28+
- Without `INCLUDE_SLOW_TESTS`, tests run if `CI` is set.
2929

3030
**❗️❗️** Windows specific path set only in CI
3131

32-
- some setups also require this setting locally
32+
- Some setups also require this setting locally.
3333

3434
## Development
3535

‎e2e/create-cli-e2e/.eslintrc.json

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"extends": ["../../.eslintrc.json"],
3+
"ignorePatterns": ["!**/*", "code-pushup.config*.ts"],
4+
"overrides": [
5+
{
6+
"files": ["*.ts", "*.tsx"],
7+
"parserOptions": {
8+
"project": ["e2e/create-cli-e2e/tsconfig.*?.json"]
9+
}
10+
}
11+
]
12+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { mkdir, writeFile } from "node:fs/promises";
2+
import { join } from "node:path";
3+
4+
export async function createNpmWorkspace(cwd: string) {
5+
await mkdir(cwd, { recursive: true });
6+
await writeFile(join(cwd, 'package.json'), JSON.stringify({
7+
name: 'create-npm-workspace',
8+
version: '0.0.1',
9+
scripts: {
10+
test: 'echo "Error: no test specified" && exit 1',
11+
},
12+
keywords: [],
13+
}, null, 2));
14+
}

‎e2e/create-cli-e2e/project.json

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
{
2+
"name": "create-cli-e2e",
3+
"$schema": "../../node_modules/nx/schemas/project-schema.json",
4+
"sourceRoot": "examples/create-cli-e2e/src",
5+
"projectType": "application",
6+
"targets": {
7+
"lint": {
8+
"executor": "@nx/linter:eslint",
9+
"outputs": ["{options.outputFile}"],
10+
"options": {
11+
"lintFilePatterns": ["e2e/create-cli-e2e/**/*.ts"]
12+
}
13+
},
14+
"e2e": {
15+
"executor": "@nx/vite:test",
16+
"options": {
17+
"configFile": "e2e/create-cli-e2e/vite.config.e2e.ts"
18+
}
19+
}
20+
},
21+
"implicitDependencies": ["create-cli"],
22+
"tags": ["scope:tooling", "type:e2e"]
23+
}
+69
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import { rm } from 'node:fs/promises';
2+
import { join, relative } from 'node:path';
3+
import { afterEach, expect } from 'vitest';
4+
import { removeColorCodes } from '@code-pushup/test-utils';
5+
import { executeProcess } from '@code-pushup/utils';
6+
import { createNpmWorkspace } from '../mocks/create-npm-workshpace';
7+
8+
describe('create-cli-node', () => {
9+
const baseDir = join('tmp', 'create-cli-e2e');
10+
const bin = 'dist/packages/create-cli';
11+
const binPath = (cwd?: string) =>
12+
cwd ? relative(join(process.cwd(), cwd), join(process.cwd(), bin)) : bin;
13+
14+
afterEach(async () => {
15+
await rm(baseDir, { recursive: true, force: true });
16+
});
17+
18+
// eslint-disable-next-line vitest/no-disabled-tests
19+
it.skip('should execute index.js correctly over node', async () => {
20+
const cwd = join(baseDir, 'node-index-js');
21+
await createNpmWorkspace(cwd);
22+
const { code, stdout } = await executeProcess({
23+
command: 'node',
24+
args: [join(binPath(cwd), 'index.js')],
25+
cwd,
26+
});
27+
28+
expect(code).toBe(0);
29+
const cleanedStdout = removeColorCodes(stdout);
30+
expect(cleanedStdout).toContain(
31+
'<↗> Generating @code-pushup/nx-plugin:configuration',
32+
);
33+
});
34+
35+
// eslint-disable-next-line vitest/no-disabled-tests
36+
it.skip('should execute package correctly over npm exec', async () => {
37+
const cwd = join(baseDir, 'npm-exec');
38+
await createNpmWorkspace(cwd);
39+
const { code, stdout } = await executeProcess({
40+
command: 'npm',
41+
args: ['exec', '@code-pushup/create-cli'],
42+
cwd,
43+
observer: { onStdout: console.info },
44+
});
45+
46+
expect(code).toBe(0);
47+
const cleanedStdout = removeColorCodes(stdout);
48+
expect(cleanedStdout).toContain(
49+
'<↗> Generating @code-pushup/nx-plugin:configuration',
50+
);
51+
});
52+
53+
it('should execute package correctly over npm init', async () => {
54+
const cwd = join(baseDir, 'npm-init');
55+
await createNpmWorkspace(cwd);
56+
const { code, stdout } = await executeProcess({
57+
command: 'npm',
58+
args: ['init', '@code-pushup/cli'],
59+
cwd,
60+
observer: { onStdout: console.info },
61+
});
62+
63+
expect(code).toBe(0);
64+
const cleanedStdout = removeColorCodes(stdout);
65+
expect(cleanedStdout).toContain(
66+
'<↗> Generating @code-pushup/nx-plugin:configuration',
67+
);
68+
});
69+
});

‎e2e/create-cli-e2e/tsconfig.json

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
{
2+
"extends": "../../tsconfig.base.json",
3+
"compilerOptions": {
4+
"module": "ESNext",
5+
"forceConsistentCasingInFileNames": true,
6+
"strict": true,
7+
"noImplicitOverride": true,
8+
"noPropertyAccessFromIndexSignature": true,
9+
"noImplicitReturns": true,
10+
"noFallthroughCasesInSwitch": true,
11+
"types": ["vitest"]
12+
},
13+
"files": [],
14+
"include": [],
15+
"references": [
16+
{
17+
"path": "./tsconfig.test.json"
18+
}
19+
]
20+
}

‎e2e/create-cli-e2e/tsconfig.test.json

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"extends": "./tsconfig.json",
3+
"compilerOptions": {
4+
"outDir": "../../dist/out-tsc",
5+
"types": ["vitest/globals", "vitest/importMeta", "vite/client", "node"]
6+
},
7+
"include": [
8+
"vite.config.e2e.ts",
9+
"tests/**/*.e2e.test.ts",
10+
"tests/**/*.d.ts",
11+
"mocks/**/*.ts"
12+
]
13+
}

‎e2e/create-cli-e2e/vite.config.e2e.ts

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/// <reference types="vitest" />
2+
import { defineConfig } from 'vite';
3+
import { tsconfigPathAliases } from '../../tools/vitest-tsconfig-path-aliases';
4+
5+
export default defineConfig({
6+
cacheDir: '../../node_modules/.vite/create-cli-e2e',
7+
test: {
8+
reporters: ['basic'],
9+
testTimeout: 60_000,
10+
globals: true,
11+
alias: tsconfigPathAliases(),
12+
pool: 'threads',
13+
poolOptions: { threads: { singleThread: true } },
14+
cache: {
15+
dir: '../../node_modules/.vitest',
16+
},
17+
environment: 'node',
18+
include: ['tests/**/*.e2e.test.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
19+
globalSetup: ['../../global-setup.e2e.ts'],
20+
setupFiles: ['../../testing/test-setup/src/lib/reset.mocks.ts'],
21+
},
22+
});

‎e2e/nx-plugin-e2e/tests/__snapshots__/nx-plugin.e2e.test.ts.snap

-15
Original file line numberDiff line numberDiff line change
@@ -21,21 +21,6 @@ exports[`nx-plugin > should NOT add config targets dynamically if the project is
2121
}
2222
`;
2323

24-
exports[`nx-plugin > should NOT add targets dynamically if plugin is not registered 1`] = `
25-
{
26-
"$schema": "../../node_modules/nx/schemas/project-schema.json",
27-
"implicitDependencies": [],
28-
"name": "my-lib",
29-
"projectType": "library",
30-
"root": "libs/my-lib",
31-
"sourceRoot": "libs/my-lib/src",
32-
"tags": [
33-
"scope:plugin",
34-
],
35-
"targets": {},
36-
}
37-
`;
38-
3924
exports[`nx-plugin > should add configuration target dynamically 1`] = `
4025
{
4126
"$schema": "../../node_modules/nx/schemas/project-schema.json",

‎e2e/nx-plugin-e2e/tests/init.e2e.test.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ describe('nx-plugin g init', () => {
109109
args: [
110110
'nx',
111111
'g',
112-
`${relativePathToDist(cwd)}:init `,
112+
`${relativePathToDist(cwd)}:init`,
113113
project,
114114
'--skipInstall',
115115
'--skipPackageJson',

‎e2e/nx-plugin-e2e/tests/nx-plugin.e2e.test.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,7 @@ describe('nx-plugin', () => {
242242
});
243243
});
244244

245-
it('should NOT add targets dynamically if plugin is not registered', async () => {
245+
it('should NOT add targets dynamically if plugin is NOT registered', async () => {
246246
const cwd = join(baseDir, 'plugin-not-registered');
247247
await materializeTree(tree, cwd);
248248

@@ -251,6 +251,5 @@ describe('nx-plugin', () => {
251251
expect(code).toBe(0);
252252

253253
expect(projectJson.targets).toStrictEqual({});
254-
expect(projectJson).toMatchSnapshot();
255254
});
256255
});

‎global-setup.e2e.ts

+11-3
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,26 @@ const localRegistryNxTarget = '@code-pushup/cli-source:local-registry';
88

99
export async function setup() {
1010
await globalSetup();
11+
await setupTestFolder('tmp/local-registry');
12+
await setupTestFolder('tmp/e2e');
13+
1114
try {
12-
await setupTestFolder('tmp/local-registry');
1315
await startLocalRegistry({ localRegistryTarget: localRegistryNxTarget });
16+
} catch (error) {
17+
console.error('Error starting local verdaccio registry:\n' + error.message);
18+
throw error;
19+
}
20+
21+
try {
1422
console.info('Installing packages');
1523
execFileSync(
1624
'npx',
1725
['nx', 'run-many', '--targets=npm-install', '--parallel=1'],
1826
{ env: process.env, stdio: 'inherit', shell: true },
1927
);
20-
await setupTestFolder('tmp/e2e');
2128
} catch (error) {
22-
console.info('setup error: ' + error.message);
29+
console.error('Error installing packages:\n' + error.message);
30+
throw error;
2331
}
2432
}
2533

‎packages/create-cli/.eslintrc.json

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
{
2+
"extends": ["../../.eslintrc.json"],
3+
"ignorePatterns": ["!**/*"],
4+
"overrides": [
5+
{
6+
"files": ["*.ts", "*.tsx"],
7+
"parserOptions": {
8+
"project": ["packages/create-cli/tsconfig.*?.json"]
9+
},
10+
"rules": {}
11+
},
12+
{
13+
"files": ["*.json"],
14+
"parser": "jsonc-eslint-parser",
15+
"rules": {
16+
"@nx/dependency-checks": [
17+
"error",
18+
{
19+
"ignoredDependencies": ["@code-pushup/nx-plugin"] // nx-plugin is run via CLI
20+
}
21+
]
22+
}
23+
}
24+
]
25+
}

‎packages/create-cli/README.md

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# @code-pushup/create-cli
2+
3+
[![npm](https://img.shields.io/npm/v/%40code-pushup%2Fcreate-cli.svg)](https://www.npmjs.com/package/@code-pushup/create-cli)
4+
[![downloads](https://img.shields.io/npm/dm/%40code-pushup%2Fcreate-cli)](https://npmtrends.com/@code-pushup/create-cli)
5+
[![dependencies](https://img.shields.io/librariesio/release/npm/%40code-pushup/create-cli)](https://www.npmjs.com/package/@code-pushup/create-cli?activeTab=dependencies)
6+
7+
A CLI tool to set up Code PushUp in your repository.
8+
9+
## Usage
10+
11+
To set up Code PushUp, run the following command:
12+
13+
```bash
14+
npx init @code-pushup/cli
15+
```
16+
17+
alternatives:
18+
19+
```bash
20+
npx @code-pushup/create-cli
21+
npm exec @code-pushup/create-cli
22+
```
23+
24+
It should generate the following output:
25+
26+
```bash
27+
> <> Generating @code-pushup/nx-plugin:init
28+
29+
> <> Generating @code-pushup/nx-plugin:configuration
30+
31+
CREATE code-pushup.config.ts
32+
```

‎packages/create-cli/package.json

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"name": "@code-pushup/create-cli",
3+
"version": "0.0.0",
4+
"license": "MIT",
5+
"bin": "index.js",
6+
"dependencies": {
7+
"@code-pushup/nx-plugin": "*",
8+
"@code-pushup/utils": "*"
9+
}
10+
}

0 commit comments

Comments
 (0)