Skip to content

Commit 9fe94d0

Browse files
committed
feat(core): add support for tags selection in affected and run-many commands
1 parent cb8bf52 commit 9fe94d0

File tree

13 files changed

+136
-20
lines changed

13 files changed

+136
-20
lines changed

docs/generated/cli/affected-apps.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,12 @@ Default: false
109109

110110
Rerun the tasks even when the results are available in the cache
111111

112+
### tags
113+
114+
Type: string
115+
116+
Tags to run (comma delimited)
117+
112118
### uncommitted
113119

114120
Type: boolean

docs/generated/cli/affected-graph.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,12 @@ Default: false
161161

162162
Rerun the tasks even when the results are available in the cache
163163

164+
### tags
165+
166+
Type: string
167+
168+
Tags to run (comma delimited)
169+
164170
### uncommitted
165171

166172
Type: boolean

docs/generated/cli/affected-libs.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,12 @@ Default: false
109109

110110
Rerun the tasks even when the results are available in the cache
111111

112+
### tags
113+
114+
Type: string
115+
116+
Tags to run (comma delimited)
117+
112118
### uncommitted
113119

114120
Type: boolean

docs/generated/cli/affected.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,12 @@ Default: false
129129

130130
Rerun the tasks even when the results are available in the cache
131131

132+
### tags
133+
134+
Type: string
135+
136+
Tags to run (comma delimited)
137+
132138
### target
133139

134140
Type: string

docs/generated/cli/format-check.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,12 @@ Default: false
9797

9898
Rerun the tasks even when the results are available in the cache
9999

100+
### tags
101+
102+
Type: string
103+
104+
Tags to run (comma delimited)
105+
100106
### uncommitted
101107

102108
Type: boolean

docs/generated/cli/format-write.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,12 @@ Default: false
9797

9898
Rerun the tasks even when the results are available in the cache
9999

100+
### tags
101+
102+
Type: string
103+
104+
Tags to run (comma delimited)
105+
100106
### uncommitted
101107

102108
Type: boolean

docs/generated/cli/print-affected.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,12 @@ Default: false
123123

124124
Rerun the tasks even when the results are available in the cache
125125

126+
### tags
127+
128+
Type: string
129+
130+
Tags to run (comma delimited)
131+
126132
### uncommitted
127133

128134
Type: boolean

docs/generated/cli/run-many.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,12 @@ Default: false
9999

100100
Rerun the tasks even when the results are available in the cache
101101

102+
### tags
103+
104+
Type: string
105+
106+
Tags to run (comma delimited)
107+
102108
### target
103109

104110
Type: string

packages/nx/src/command-line/affected.ts

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import { performance } from 'perf_hooks';
1414
import { createProjectGraphAsync } from '../project-graph/project-graph';
1515
import { withDeps } from '../project-graph/operators';
1616
import { ProjectGraph, ProjectGraphProjectNode } from '../config/project-graph';
17-
import { projectHasTarget } from '../utils/project-graph-utils';
17+
import { projectHasTarget, projectHasTag } from '../utils/project-graph-utils';
1818
import { filterAffected } from '../project-graph/affected/affected-project-graph';
1919
import { readEnvironment } from './read-environment';
2020

@@ -133,6 +133,9 @@ function projectsToRun(
133133
nxArgs
134134
)
135135
);
136+
if (!nxArgs.all && nxArgs.tags) {
137+
affectedGraph = filterByTag(affectedGraph, nxArgs);
138+
}
136139
if (!nxArgs.all && nxArgs.withDeps) {
137140
affectedGraph = withDeps(
138141
projectGraph,
@@ -150,6 +153,39 @@ function projectsToRun(
150153
return Object.values(affectedGraph.nodes) as ProjectGraphProjectNode[];
151154
}
152155

156+
function filterByTag(
157+
affectedGraph: ProjectGraph,
158+
nxArgs: NxArgs
159+
): ProjectGraph {
160+
const filteredProjects = allProjectsWithTag(
161+
Object.values(affectedGraph.nodes),
162+
nxArgs
163+
);
164+
const res = {
165+
nodes: filteredProjects.reduce(
166+
(nodes, project) => ({
167+
...nodes,
168+
[project.name]: project,
169+
}),
170+
{}
171+
),
172+
dependencies: affectedGraph.dependencies,
173+
} as ProjectGraph;
174+
return res;
175+
}
176+
177+
function allProjectsWithTag(
178+
projects: ProjectGraphProjectNode[],
179+
nxArgs: NxArgs
180+
) {
181+
return projects.filter((p) =>
182+
nxArgs.tags.reduce(
183+
(matched, tag) => matched || projectHasTag(p, tag),
184+
false
185+
)
186+
);
187+
}
188+
153189
function allProjectsWithTarget(
154190
projects: ProjectGraphProjectNode[],
155191
nxArgs: NxArgs

packages/nx/src/command-line/nx-commands.ts

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,11 @@ function withAffectedOptions(yargs: yargs.Argv): yargs.Argv {
359359
type: 'boolean',
360360
default: undefined,
361361
})
362+
.option('tags', {
363+
describe: 'Tags to run (comma delimited)',
364+
type: 'string',
365+
default: undefined,
366+
})
362367
.option('all', {
363368
describe: 'All projects',
364369
type: 'boolean',
@@ -416,10 +421,11 @@ function withAffectedOptions(yargs: yargs.Argv): yargs.Argv {
416421
describe: 'Print additional error stack trace on failure',
417422
})
418423
.conflicts({
419-
files: ['uncommitted', 'untracked', 'base', 'head', 'all'],
420-
untracked: ['uncommitted', 'files', 'base', 'head', 'all'],
421-
uncommitted: ['files', 'untracked', 'base', 'head', 'all'],
422-
all: ['files', 'untracked', 'uncommitted', 'base', 'head'],
424+
files: ['uncommitted', 'untracked', 'base', 'head', 'all', 'tags'],
425+
untracked: ['uncommitted', 'files', 'base', 'head', 'all', 'tags'],
426+
uncommitted: ['files', 'untracked', 'base', 'head', 'all', 'tags'],
427+
all: ['files', 'untracked', 'uncommitted', 'base', 'head', 'tags'],
428+
tags: ['files', 'untracked', 'uncommitted', 'base', 'head', 'all'],
423429
});
424430
}
425431

@@ -428,15 +434,21 @@ function withRunManyOptions(yargs: yargs.Argv): yargs.Argv {
428434
.option('projects', {
429435
describe: 'Projects to run (comma delimited)',
430436
type: 'string',
437+
default: undefined,
438+
})
439+
.option('tags', {
440+
describe: 'Tags to run (comma delimited)',
441+
type: 'string',
442+
default: undefined,
431443
})
432444
.option('all', {
433445
describe: 'Run the target on all projects in the workspace',
434446
type: 'boolean',
435447
default: undefined,
436448
})
437-
.check(({ all, projects }) => {
438-
if ((all && projects) || (!all && !projects))
439-
throw new Error('You must provide either --all or --projects');
449+
.check(({ all, projects, tags }) => {
450+
if (!all && !projects && !tags)
451+
throw new Error('You must provide either --all, --projects or --tags');
440452
return true;
441453
})
442454
.options('runner', {
@@ -471,7 +483,9 @@ function withRunManyOptions(yargs: yargs.Argv): yargs.Argv {
471483
describe: 'Print additional error stack trace on failure',
472484
})
473485
.conflicts({
474-
all: 'projects',
486+
all: ['projects', 'tags'],
487+
projects: ['all', 'tags'],
488+
tags: ['all', 'projects'],
475489
});
476490
}
477491

packages/nx/src/command-line/run-many.ts

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import * as yargs from 'yargs';
22
import { runCommand } from '../tasks-runner/run-command';
33
import type { NxArgs, RawNxArgs } from '../utils/command-line-utils';
44
import { splitArgsIntoNxArgsAndOverrides } from '../utils/command-line-utils';
5-
import { projectHasTarget } from '../utils/project-graph-utils';
5+
import { projectHasTarget, projectHasTag } from '../utils/project-graph-utils';
66
import { output } from '../utils/output';
77
import { connectToNxCloudUsingScan } from './connect-to-nx-cloud';
88
import { performance } from 'perf_hooks';
@@ -46,9 +46,13 @@ function projectsToRun(
4646
);
4747
}
4848
checkForInvalidProjects(nxArgs, allProjects);
49-
let selectedProjects = nxArgs.projects.map((name) =>
50-
allProjects.find((project) => project.name === name)
51-
);
49+
let selectedProjects = nxArgs.tags
50+
? nxArgs.tags.map((tag) =>
51+
allProjects.find((project) => project.data.tags.includes(tag))
52+
)
53+
: (nxArgs.projects ?? []).map((name) =>
54+
allProjects.find((project) => project.name === name)
55+
);
5256
return runnableForTarget(selectedProjects, nxArgs.target, true).filter(
5357
(proj) => !excludedProjects.has(proj.name)
5458
);
@@ -58,7 +62,7 @@ function checkForInvalidProjects(
5862
nxArgs: NxArgs,
5963
allProjects: ProjectGraphProjectNode[]
6064
) {
61-
const invalid = nxArgs.projects.filter(
65+
const invalid = (nxArgs.projects ?? []).filter(
6266
(name) => !allProjects.find((p) => p.name === name)
6367
);
6468
if (invalid.length !== 0) {

packages/nx/src/utils/command-line-utils.ts

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ const runOne: string[] = [
8484
'hide-cached-output',
8585
];
8686

87-
const runMany: string[] = [...runOne, 'projects', 'all'];
87+
const runMany: string[] = [...runOne, 'projects', 'tags', 'all'];
8888

8989
const runAffected: string[] = [
9090
...runOne,
@@ -96,6 +96,7 @@ const runAffected: string[] = [
9696
'files',
9797
'plain',
9898
'select',
99+
'tags',
99100
];
100101

101102
export interface RawNxArgs extends NxArgs {
@@ -129,6 +130,7 @@ export interface NxArgs {
129130
'hide-cached-output'?: boolean;
130131
hideCachedOutput?: boolean;
131132
scan?: boolean;
133+
tags?: string[];
132134
}
133135

134136
const ignoreArgs = ['$0', '_'];
@@ -163,9 +165,7 @@ export function splitArgsIntoNxArgsAndOverrides(
163165
});
164166

165167
if (mode === 'run-many') {
166-
if (!nxArgs.projects) {
167-
nxArgs.projects = [];
168-
} else {
168+
if (nxArgs.projects) {
169169
nxArgs.projects = (args.projects as string)
170170
.split(',')
171171
.map((p: string) => p.trim());
@@ -206,7 +206,7 @@ export function splitArgsIntoNxArgsAndOverrides(
206206
!nxArgs.untracked &&
207207
!nxArgs.base &&
208208
!nxArgs.head &&
209-
!nxArgs.all &&
209+
(!nxArgs.all || !nxArgs.tags) &&
210210
args._.length >= 3
211211
) {
212212
nxArgs.base = args._[1] as string;
@@ -246,7 +246,7 @@ export function splitArgsIntoNxArgsAndOverrides(
246246
!nxArgs.files &&
247247
!nxArgs.uncommitted &&
248248
!nxArgs.untracked &&
249-
!nxArgs.all
249+
(!nxArgs.all || !nxArgs.tags)
250250
) {
251251
output.note({
252252
title: `Affected criteria defaulted to --base=${output.bold(
@@ -255,6 +255,12 @@ export function splitArgsIntoNxArgsAndOverrides(
255255
});
256256
}
257257
}
258+
259+
if (nxArgs.tags) {
260+
nxArgs.tags = (args.tags as string)
261+
.split(',')
262+
.map((p: string) => p.trim());
263+
}
258264
}
259265

260266
if (!nxArgs.skipNxCache) {

packages/nx/src/utils/project-graph-utils.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,14 @@ export function projectHasTargetAndConfiguration(
2929
);
3030
}
3131

32+
export function projectHasTag(project: ProjectGraphProjectNode, tag: string) {
33+
return !!(
34+
project.data &&
35+
project.data.tags &&
36+
project.data.tags.includes(tag)
37+
);
38+
}
39+
3240
export function mergeNpmScriptsWithTargets(
3341
projectRoot: string,
3442
targets

0 commit comments

Comments
 (0)