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

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions