Skip to content

Monorepo support in setup wizard #1245

@matejchalk

Description

@matejchalk

User story

In addition to standalone repos, our setup wizard should also support various monorepo setups. Popular tools like Nx, Turborepo, and Yarn/pnpm/npm workspaces should have first-class support. Users should be able to decide if they want all their monorepo projects to be combined into 1 report, or to collect separate reports per project.

Outputs

Standalone mode

Non-monorepo

// code-pushup.config.ts

import coveragePlugin from '@code-pushup/coverage-plugin';
import eslintPlugin from '@code-pushup/eslint-plugin';
import jsPackagesPlugin from '@code-pushup/js-packages-plugin';
import type { CoreConfig } from '@code-pushup/models';

const config: CoreConfig = {
  plugins: [
    await eslintPlugin(),
    await coveragePlugin({
      coverageToolCommand: 'npx jest --coverage --coverageReporters=lcov',
      reports: ['coverage/lcov.info'],
    }),
    await jsPackagesPlugin(),
  ],
  categories: [
    // ...
  ],
};

export default config;

Nx monorepo

// {workspaceRoot}/code-pushup.config.ts

import coveragePlugin, {
  getNxCoveragePaths,
} from '@code-pushup/coverage-plugin';
import eslintPlugin, {
  eslintConfigFromNxProjectAndDeps,
} from '@code-pushup/eslint-plugin';
import jsPackagesPlugin from '@code-pushup/js-packages-plugin';
import type { CoreConfig } from '@code-pushup/models';

const config: CoreConfig = {
  plugins: [
    await eslintPlugin(await eslintConfigFromAllNxProjects()),
    await coveragePlugin({
      coverageToolCommand: 'npx nx run-many --target=test --coverage',
      reports: await getNxCoveragePaths(),
    }),
    await jsPackagesPlugin(),
  ],
  categories: [
    // ...
  ],
};

export default config;

Monorepo mode

// {workspaceRoot}/code-pushup.preset.ts

import coveragePlugin from '@code-pushup/coverage-plugin';
import eslintPlugin from '@code-pushup/eslint-plugin';
import type { CoreConfig } from '@code-pushup/models';
import path from 'node:path';
import { fileURLToPath } from 'node:url';

/**
 * Creates Code PushUp config for an Nx project.
 * @param project Nx project name
 * @returns Code PushUp config object as a promise
 */
export async function createConfig(project: string): Promise<CoreConfig> {
  return {
    plugins: [
      await eslintPlugin({ patterns: '.' }),
      await coveragePlugin({
        reports: [path.join('coverage', 'lcov.info')],
        coverageToolCommand: {
          command: 'npx',
          args: ['nx', 'test', project, '--coverage'],
        },
      }),
    ],
  };
}
// {projectRoot}/code-pushup.config.ts

import { createConfig } from '../../code-pushup.preset.js';

export default await createConfig('{projectName}');
// {workspaceRoot}/code-pushup.config.ts

import jsPackagesPlugin from '@code-pushup/js-packages-plugin';
import type { CoreConfig } from '@code-pushup/models';

const config: CoreConfig = {
  plugins: [
    await jsPackagesPlugin(),
  ],
  categories: [
    // ...
  ],
};

export default config;

Implementation notes

The @code-pushup/ci package already implements similar monorepo handling logic (see monorepo folder). We can extract and reuse it.

Acceptance criteria

  • Users are prompted to choose between standalone or monorepo mode.
    • Alternatively, standalone/monorepo mode may be specified as a CLI argument.
    • The default value should be inferred from the user's repository. If we can detect one of our supported monorepo tools, then monorepo mode should be pre-selected. Standalone mode should be pre-selected otherwise.
  • All monorepo tools supported by @code-pushup/ci are also supported in the setup wizard.
  • If standalone mode is selected, then a single config file is generated.
  • If standalone mode is selected and Nx is detected, then the config file uses individual plugins' Nx helpers if available.
  • If monorepo mode is selected, then config files are generated for each project. Each of these configs imports a config factory from a shared preset file.
  • If monorepo mode is selected, then a code-pushup command is added to each project. If Nx is used with project.json files, then the code-pushup command is added as an Nx target (using nx:run-commands executor). Otherwise, code-pushup is added to scripts in the project's package.json.

Metadata

Metadata

Assignees

Labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions