Skip to content

Commit

Permalink
feat(ci): filter nx run-many by projects from nx show projects as fal…
Browse files Browse the repository at this point in the history
…lback
  • Loading branch information
matejchalk committed Dec 16, 2024
1 parent e221655 commit 97a603c
Show file tree
Hide file tree
Showing 11 changed files with 154 additions and 47 deletions.
15 changes: 13 additions & 2 deletions packages/ci/src/lib/monorepo/handlers/npm.unit.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import { vol } from 'memfs';
import type { PackageJson } from 'type-fest';
import { MEMFS_VOLUME } from '@code-pushup/test-utils';
import type { MonorepoHandlerOptions, ProjectConfig } from '../tools';
import type {
MonorepoHandlerOptions,
MonorepoHandlerProjectsContext,
ProjectConfig,
} from '../tools';
import { npmHandler } from './npm';

describe('npmHandler', () => {
Expand Down Expand Up @@ -169,8 +173,15 @@ describe('npmHandler', () => {
});

describe('createRunManyCommand', () => {
const projects: MonorepoHandlerProjectsContext = {
all: [
{ name: 'api', bin: 'npm --workspace=api run code-pushup --' },
{ name: 'ui', bin: 'npm --workspace=ui run code-pushup --' },
],
};

it('should create command to run npm script for all workspaces', () => {
expect(npmHandler.createRunManyCommand(options)).toBe(
expect(npmHandler.createRunManyCommand(options, projects)).toBe(
'npm run code-pushup --workspaces --if-present --',
);
});
Expand Down
9 changes: 5 additions & 4 deletions packages/ci/src/lib/monorepo/handlers/nx.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,15 +47,16 @@ export const nxHandler: MonorepoToolHandler = {
}));
},

createRunManyCommand(options, onlyProjects) {
createRunManyCommand(options, projects) {
const projectNames: string[] =
projects.only ?? projects.all.map(({ name }) => name);
return [
'npx',
'nx',
'run-many', // TODO: allow affected instead of run-many?
'run-many',
`--targets=${options.task}`,
// TODO: add options.nxRunManyFilter? (e.g. --exclude=...)
...(onlyProjects ? [`--projects=${onlyProjects.join(',')}`] : []),
`--parallel=${options.parallel}`,
`--projects=${projectNames.join(',')}`,
'--',
].join(' ');
},
Expand Down
43 changes: 33 additions & 10 deletions packages/ci/src/lib/monorepo/handlers/nx.unit.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import { vol } from 'memfs';
import { MEMFS_VOLUME } from '@code-pushup/test-utils';
import * as utils from '@code-pushup/utils';
import type { MonorepoHandlerOptions, ProjectConfig } from '../tools';
import type {
MonorepoHandlerOptions,
MonorepoHandlerProjectsContext,
ProjectConfig,
} from '../tools';
import { nxHandler } from './nx';

describe('nxHandler', () => {
Expand Down Expand Up @@ -113,27 +117,46 @@ describe('nxHandler', () => {
});

describe('createRunManyCommand', () => {
it('should run script for all projects sequentially by default', () => {
expect(nxHandler.createRunManyCommand(options)).toBe(
'npx nx run-many --targets=code-pushup --parallel=false --',
const projects: MonorepoHandlerProjectsContext = {
all: [
{ name: 'backend', bin: 'npx nx run backend:code-pushup --' },
{ name: 'frontend', bin: 'npx nx run frontend:code-pushup --' },
],
};

it('should run script for all listed projects sequentially by default', () => {
expect(nxHandler.createRunManyCommand(options, projects)).toBe(
'npx nx run-many --targets=code-pushup --parallel=false --projects=backend,frontend --',
);
});

it('should set parallel flag with default number of tasks', () => {
expect(
nxHandler.createRunManyCommand({ ...options, parallel: true }),
).toBe('npx nx run-many --targets=code-pushup --parallel=true --');
nxHandler.createRunManyCommand(
{ ...options, parallel: true },
projects,
),
).toBe(
'npx nx run-many --targets=code-pushup --parallel=true --projects=backend,frontend --',
);
});

it('should set parallel flag with custom number of tasks', () => {
expect(nxHandler.createRunManyCommand({ ...options, parallel: 5 })).toBe(
'npx nx run-many --targets=code-pushup --parallel=5 --',
expect(
nxHandler.createRunManyCommand({ ...options, parallel: 5 }, projects),
).toBe(
'npx nx run-many --targets=code-pushup --parallel=5 --projects=backend,frontend --',
);
});

it('should filter projects by list of project names', () => {
expect(nxHandler.createRunManyCommand(options, ['web', 'cms'])).toBe(
'npx nx run-many --targets=code-pushup --projects=web,cms --parallel=false --',
expect(
nxHandler.createRunManyCommand(options, {
...projects,
only: ['frontend'],
}),
).toBe(
'npx nx run-many --targets=code-pushup --parallel=false --projects=frontend --',
);
});
});
Expand Down
4 changes: 2 additions & 2 deletions packages/ci/src/lib/monorepo/handlers/pnpm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ export const pnpmHandler: MonorepoToolHandler = {
}));
},

createRunManyCommand(options, onlyProjects) {
createRunManyCommand(options, projects) {
const workspaceConcurrency: number =
options.parallel === true
? DEFAULT_WORKSPACE_CONCURRENCY
Expand All @@ -55,7 +55,7 @@ export const pnpmHandler: MonorepoToolHandler = {
'pnpm',
'--recursive',
`--workspace-concurrency=${workspaceConcurrency}`,
...(onlyProjects?.map(project => `--filter=${project}`) ?? []),
...(projects.only?.map(project => `--filter=${project}`) ?? []),
options.task,
].join(' ');
},
Expand Down
32 changes: 26 additions & 6 deletions packages/ci/src/lib/monorepo/handlers/pnpm.unit.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import { vol } from 'memfs';
import type { PackageJson } from 'type-fest';
import { MEMFS_VOLUME } from '@code-pushup/test-utils';
import type { MonorepoHandlerOptions, ProjectConfig } from '../tools';
import type {
MonorepoHandlerOptions,
MonorepoHandlerProjectsContext,
ProjectConfig,
} from '../tools';
import { pnpmHandler } from './pnpm';

describe('pnpmHandler', () => {
Expand Down Expand Up @@ -160,27 +164,43 @@ describe('pnpmHandler', () => {
});

describe('createRunManyCommand', () => {
const projects: MonorepoHandlerProjectsContext = {
all: [
{ name: 'backend', bin: 'pnpm --filter=backend run code-pushup' },
{ name: 'frontend', bin: 'pnpm --filter=frontend run code-pushup' },
{ name: 'shared', bin: 'pnpm --filter=shared run code-pushup' },
],
};

it('should run script for all workspace packages sequentially by default', () => {
expect(pnpmHandler.createRunManyCommand(options)).toBe(
expect(pnpmHandler.createRunManyCommand(options, projects)).toBe(
'pnpm --recursive --workspace-concurrency=1 code-pushup',
);
});

it('should set parallel flag with default number of jobs', () => {
expect(
pnpmHandler.createRunManyCommand({ ...options, parallel: true }),
pnpmHandler.createRunManyCommand(
{ ...options, parallel: true },
projects,
),
).toBe('pnpm --recursive --workspace-concurrency=4 code-pushup');
});

it('should set parallel flag with custom number of jobs', () => {
expect(
pnpmHandler.createRunManyCommand({ ...options, parallel: 5 }),
pnpmHandler.createRunManyCommand({ ...options, parallel: 5 }, projects),
).toBe('pnpm --recursive --workspace-concurrency=5 code-pushup');
});

it('should filter workspace packages by list of project names', () => {
expect(pnpmHandler.createRunManyCommand(options, ['core', 'utils'])).toBe(
'pnpm --recursive --workspace-concurrency=1 --filter=core --filter=utils code-pushup',
expect(
pnpmHandler.createRunManyCommand(options, {
...projects,
only: ['frontend', 'shared'],
}),
).toBe(
'pnpm --recursive --workspace-concurrency=1 --filter=frontend --filter=shared code-pushup',
);
});
});
Expand Down
4 changes: 2 additions & 2 deletions packages/ci/src/lib/monorepo/handlers/turbo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ export const turboHandler: MonorepoToolHandler = {
);
},

createRunManyCommand(options, onlyProjects) {
createRunManyCommand(options, projects) {
const concurrency: number =
options.parallel === true
? DEFAULT_CONCURRENCY
Expand All @@ -57,7 +57,7 @@ export const turboHandler: MonorepoToolHandler = {
'turbo',
'run',
options.task,
...(onlyProjects?.map(project => `--filter=${project}`) ?? []),
...(projects.only?.map(project => `--filter=${project}`) ?? []),
`--concurrency=${concurrency}`,
'--',
].join(' ');
Expand Down
35 changes: 29 additions & 6 deletions packages/ci/src/lib/monorepo/handlers/turbo.unit.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import { vol } from 'memfs';
import type { PackageJson } from 'type-fest';
import { MEMFS_VOLUME } from '@code-pushup/test-utils';
import type { MonorepoHandlerOptions, ProjectConfig } from '../tools';
import type {
MonorepoHandlerOptions,
MonorepoHandlerProjectsContext,
ProjectConfig,
} from '../tools';
import { turboHandler } from './turbo';

describe('turboHandler', () => {
Expand Down Expand Up @@ -158,27 +162,46 @@ describe('turboHandler', () => {
});

describe('createRunManyCommand', () => {
const projects: MonorepoHandlerProjectsContext = {
all: [
{ name: 'api', bin: 'npx turbo run code-pushup --filter=api --' },
{ name: 'cms', bin: 'npx turbo run code-pushup --filter=cms --' },
{ name: 'web', bin: 'npx turbo run code-pushup --filter=web --' },
],
};

it('should run script for all projects sequentially by default', () => {
expect(turboHandler.createRunManyCommand(options)).toBe(
expect(turboHandler.createRunManyCommand(options, projects)).toBe(
'npx turbo run code-pushup --concurrency=1 --',
);
});

it('should set parallel flag with default number of jobs', () => {
expect(
turboHandler.createRunManyCommand({ ...options, parallel: true }),
turboHandler.createRunManyCommand(
{ ...options, parallel: true },
projects,
),
).toBe('npx turbo run code-pushup --concurrency=10 --');
});

it('should set parallel flag with custom number of jobs', () => {
expect(
turboHandler.createRunManyCommand({ ...options, parallel: 5 }),
turboHandler.createRunManyCommand(
{ ...options, parallel: 5 },
projects,
),
).toBe('npx turbo run code-pushup --concurrency=5 --');
});

it('should filter projects by list of project names', () => {
expect(turboHandler.createRunManyCommand(options, ['web', 'cms'])).toBe(
'npx turbo run code-pushup --filter=web --filter=cms --concurrency=1 --',
expect(
turboHandler.createRunManyCommand(options, {
...projects,
only: ['cms', 'web'],
}),
).toBe(
'npx turbo run code-pushup --filter=cms --filter=web --concurrency=1 --',
);
});
});
Expand Down
4 changes: 2 additions & 2 deletions packages/ci/src/lib/monorepo/handlers/yarn.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export const yarnHandler: MonorepoToolHandler = {
}));
},

async createRunManyCommand(options, onlyProjects) {
async createRunManyCommand(options, projects) {
const { stdout } = await executeProcess({ command: 'yarn', args: ['-v'] });
const isV1 = stdout.startsWith('1.');

Expand All @@ -52,7 +52,7 @@ export const yarnHandler: MonorepoToolHandler = {
...(typeof options.parallel === 'number'
? [`--jobs=${options.parallel}`]
: []),
...(onlyProjects?.map(project => `--include=${project}`) ?? ['--all']),
...(projects.only?.map(project => `--include=${project}`) ?? ['--all']),
options.task,
].join(' ');
},
Expand Down
43 changes: 32 additions & 11 deletions packages/ci/src/lib/monorepo/handlers/yarn.unit.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@ import { vol } from 'memfs';
import type { PackageJson } from 'type-fest';
import { MEMFS_VOLUME } from '@code-pushup/test-utils';
import * as utils from '@code-pushup/utils';
import type { MonorepoHandlerOptions, ProjectConfig } from '../tools';
import type {
MonorepoHandlerOptions,
MonorepoHandlerProjectsContext,
ProjectConfig,
} from '../tools';
import { yarnHandler } from './yarn';

describe('yarnHandler', () => {
Expand Down Expand Up @@ -171,6 +175,14 @@ describe('yarnHandler', () => {
});

describe('createRunManyCommand', () => {
const projects: MonorepoHandlerProjectsContext = {
all: [
{ name: 'api', bin: 'yarn workspace api run code-pushup' },
{ name: 'cms', bin: 'yarn workspace cms run code-pushup' },
{ name: 'web', bin: 'yarn workspace web run code-pushup' },
],
};

// eslint-disable-next-line vitest/max-nested-describe
describe('classic Yarn (v1)', () => {
beforeEach(() => {
Expand All @@ -180,9 +192,9 @@ describe('yarnHandler', () => {
});

it('should run script for all workspaces sequentially', async () => {
await expect(yarnHandler.createRunManyCommand(options)).resolves.toBe(
'yarn workspaces run code-pushup',
);
await expect(
yarnHandler.createRunManyCommand(options, projects),
).resolves.toBe('yarn workspaces run code-pushup');
});
});

Expand All @@ -195,30 +207,39 @@ describe('yarnHandler', () => {
});

it('should run script for all workspaces sequentially by default', async () => {
await expect(yarnHandler.createRunManyCommand(options)).resolves.toBe(
'yarn workspaces foreach --all code-pushup',
);
await expect(
yarnHandler.createRunManyCommand(options, projects),
).resolves.toBe('yarn workspaces foreach --all code-pushup');
});

it('should set parallel flag with default number of jobs', async () => {
await expect(
yarnHandler.createRunManyCommand({ ...options, parallel: true }),
yarnHandler.createRunManyCommand(
{ ...options, parallel: true },
projects,
),
).resolves.toBe('yarn workspaces foreach --parallel --all code-pushup');
});

it('should set parallel flag with custom number of jobs', async () => {
await expect(
yarnHandler.createRunManyCommand({ ...options, parallel: 5 }),
yarnHandler.createRunManyCommand(
{ ...options, parallel: 5 },
projects,
),
).resolves.toBe(
'yarn workspaces foreach --parallel --jobs=5 --all code-pushup',
);
});

it('should filter workspaces by list of project names', async () => {
await expect(
yarnHandler.createRunManyCommand(options, ['core', 'utils']),
yarnHandler.createRunManyCommand(options, {
...projects,
only: ['api', 'cms'],
}),
).resolves.toBe(
'yarn workspaces foreach --include=core --include=utils code-pushup',
'yarn workspaces foreach --include=api --include=cms code-pushup',
);
});
});
Expand Down
Loading

0 comments on commit 97a603c

Please sign in to comment.