feat(create-cli): setup wizard architecture#1248
Conversation
|
View your CI Pipeline Execution ↗ for commit 3e6bc84
☁️ Nx Cloud last updated this comment at |
@code-pushup/ci
@code-pushup/cli
@code-pushup/create-cli
@code-pushup/core
@code-pushup/models
@code-pushup/nx-plugin
@code-pushup/axe-plugin
@code-pushup/coverage-plugin
@code-pushup/eslint-plugin
@code-pushup/js-packages-plugin
@code-pushup/jsdocs-plugin
@code-pushup/lighthouse-plugin
@code-pushup/typescript-plugin
@code-pushup/utils
commit: |
Code PushUp🤨 Code PushUp report has both improvements and regressions – compared current commit 880b65a with previous commit dd6e35e. 🕵️ See full comparison in Code PushUp portal 🔍 🏷️ Categories👍 2 groups improved, 👎 4 groups regressed, 👍 5 audits improved, 👎 8 audits regressed, 16 audits changed without impacting score🗃️ Groups
28 other groups are unchanged. 🛡️ Audits
649 other audits are unchanged. |
Code PushUp🥳 Code PushUp report has improved – compared current commit 880b65a with previous commit dd6e35e. 💼 Project
|
| 🏷️ Category | ⭐ Previous score | ⭐ Current score | 🔄 Score change |
|---|---|---|---|
| Code coverage | 🟢 96 | 🟢 98 | |
| Documentation | 🟡 64 | 🟡 64 |
4 other categories are unchanged.
👍 2 groups improved, 👍 3 audits improved, 2 audits changed without impacting score
🗃️ Groups
| 🔌 Plugin | 🗃️ Group | ⭐ Previous score | ⭐ Current score | 🔄 Score change |
|---|---|---|---|---|
| Code coverage | Code coverage metrics | 🟢 96 | 🟢 98 | |
| JSDocs coverage | Documentation coverage | 🟡 64 | 🟡 64 |
13 other groups are unchanged.
🛡️ Audits
| 🔌 Plugin | 🛡️ Audit | 📏 Previous value | 📏 Current value | 🔄 Value change |
|---|---|---|---|---|
| JSDocs coverage | Types coverage | 🟥 1 undocumented types | 🟥 12 undocumented types | |
| Code coverage | Branch coverage | 🟨 87.5 % | 🟩 93 % | |
| Code coverage | Line coverage | 🟩 97 % | 🟩 98.2 % | |
| JSDocs coverage | Functions coverage | 🟥 6 undocumented functions | 🟥 11 undocumented functions | |
| JSDocs coverage | Variables coverage | 🟥 5 undocumented variables | 🟥 4 undocumented variables |
438 other audits are unchanged.
💼 Project utils
🥳 Code PushUp report has improved.
🕵️ See full comparison in Code PushUp portal 🔍
| 🏷️ Category | ⭐ Previous score | ⭐ Current score | 🔄 Score change |
|---|---|---|---|
| Documentation | 🟡 60 | 🟡 60 |
5 other categories are unchanged.
👍 1 group improved
🗃️ Groups
| 🔌 Plugin | 🗃️ Group | ⭐ Previous score | ⭐ Current score | 🔄 Score change |
|---|---|---|---|---|
| JSDocs coverage | Documentation coverage | 🟡 60 | 🟡 60 |
14 other groups are unchanged.
🛡️ Audits
All of 444 audits are unchanged.
12 other projects are unchanged.
matejchalk
left a comment
There was a problem hiding this comment.
Looks really promising 🙂
|
|
||
| ```bash | ||
| npx init @code-pushup/cli | ||
| npx @code-pushup/create-cli |
There was a problem hiding this comment.
Let's use npm init @code-pushup/cli in our documentation examples. The npm init command is commonly used for these setup tools. The package was named @code-pushup/create-cli to be compatible with it.
| '@nx/dependency-checks': [ | ||
| 'error', | ||
| { ignoredDependencies: ['@code-pushup/nx-plugin'] }, // nx-plugin is run via CLI | ||
| { ignoredDependencies: ['@code-pushup/models'] }, | ||
| ], |
There was a problem hiding this comment.
I would add @code-pushup/models to package.json dependencies instead. It's not strictly necessary at present because there's only a type import, but adding a runtime import would break the installation without being caught by the linter.
| .parse(); | ||
|
|
||
| // TODO: #1244 — provide plugin bindings from registry | ||
| await runSetupWizard([], argv as CliArgs); |
There was a problem hiding this comment.
The argv type is actually inferred by yargs and is assignable to CliArgs, so the type-cast is unnecessary and could mask incompatibilities in the future.
| await runSetupWizard([], argv as CliArgs); | |
| await runSetupWizard([], argv); |
| logger.info('Setup complete.'); | ||
| logger.newline(); | ||
| logNextSteps([ | ||
| ['npx code-pushup collect', 'Run your first report'], |
There was a problem hiding this comment.
I haven't created a sub-issue for it yet, but I'd like to also add an optional step to configure uploads. This could be useful for users who are already self-hosting the Portal.
Therefore, I would prompt them to run the (implicit) autorun command, so that their report may also be uploaded.
| ['npx code-pushup collect', 'Run your first report'], | |
| ['npx code-pushup', 'Collect your first report'], |
| /** Virtual file system that buffers writes in memory until flushed to disk. */ | ||
| export type Tree = { | ||
| root: string; | ||
| exists: (filePath: string) => boolean; | ||
| read: (filePath: string) => string | null; | ||
| write: (filePath: string, content: string) => void; | ||
| listChanges: () => FileChange[]; | ||
| flush: () => Promise<void>; | ||
| }; |
There was a problem hiding this comment.
I'd prefer to use async I/O (node:fs/promises), unless there's a good reason not to. It's non-blocking, which can sometimes be an advantage - e.g., easy parallelization with Promise.all. And I think it's generally useful to have external and potentially slow operations "marked" with awaits.
| function logNextSteps(steps: [string, string][]): void { | ||
| const colWidth = Math.max(...steps.map(([label]) => label.length)); | ||
| logger.info('Next steps:'); | ||
| steps.forEach(([label, description]) => { | ||
| logger.info(` ${label.padEnd(colWidth + COLUMN_GAP)}${description}`); | ||
| }); | ||
| } |
There was a problem hiding this comment.
You could use formatAsciiTable with the { borderless: true } option, then it'll calculate the padding for you.
| const pending = new Map< | ||
| string, | ||
| { content: string; type: 'CREATE' | 'UPDATE' } | ||
| >(); |
There was a problem hiding this comment.
This is very much a nitpick and a matter of preference, but you could reference the FileChange type explicitly here.
| const pending = new Map< | |
| string, | |
| { content: string; type: 'CREATE' | 'UPDATE' } | |
| >(); | |
| const pending = new Map<FileChange['path'], Omit<FileChange, 'path'>>(); |
| function buildExportStatement(plugins: PluginCodegenResult[]): string { | ||
| const items = plugins.map(({ pluginInit }) => pluginInit).join(', '); | ||
| return `export default { plugins: [${items}] } satisfies CoreConfig;`; | ||
| } |
There was a problem hiding this comment.
Have you considered using StatementStructures? It seems a bit more robust than concatenating strings. The plugins could also register their init code as an AST.
| [ | ||
| "import type { CoreConfig } from '@code-pushup/models';", | ||
| 'export default { plugins: [] } satisfies CoreConfig;', | ||
| '', | ||
| ].join('\n'), |
There was a problem hiding this comment.
It would be more readable to have a separator line between the imports and the config export. 🙏
| expect(generateConfigSource(plugins)).toBe( | ||
| [ | ||
| "import type { CoreConfig } from '@code-pushup/models';", | ||
| "import eslintPlugin from '@code-pushup/eslint-plugin';", | ||
| "import coveragePlugin from '@code-pushup/coverage-plugin';", | ||
| "export default { plugins: [await eslintPlugin(), await coveragePlugin({ reports: [{ resultsPath: 'coverage/lcov.info', pathToProject: '' }] })] } satisfies CoreConfig;", | ||
| '', | ||
| ].join('\n'), | ||
| ); |
There was a problem hiding this comment.
This generates quite a long line. Does ts-morph not wrap long lines? If not, we could run prettier on the output.
Closes #1240
Break
create-cli's dependency onnx-pluginand rebuild the package around a modular setup wizard. Usests-morphfor AST-based config generation,@inquirer/promptsfor interactive input, and a virtualTreefor buffered file writes with dry-run support.