Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(core): add ability to add metadata to projects #22299

Merged
merged 1 commit into from
Mar 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
14 changes: 14 additions & 0 deletions docs/generated/devkit/ProjectConfiguration.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ Project configuration

- [generators](../../devkit/documents/ProjectConfiguration#generators): Object
- [implicitDependencies](../../devkit/documents/ProjectConfiguration#implicitdependencies): string[]
- [metadata](../../devkit/documents/ProjectConfiguration#metadata): Object
- [name](../../devkit/documents/ProjectConfiguration#name): string
- [namedInputs](../../devkit/documents/ProjectConfiguration#namedinputs): Object
- [projectType](../../devkit/documents/ProjectConfiguration#projecttype): ProjectType
Expand Down Expand Up @@ -53,6 +54,19 @@ List of projects which are added as a dependency

---

### metadata

• `Optional` **metadata**: `Object`

#### Type declaration

| Name | Type |
| :-------------- | :------------------------------- |
| `targetGroups?` | `Record`\<`string`, `string`[]\> |
| `technologies?` | `string`[] |

---

### name

• `Optional` **name**: `string`
Expand Down
21 changes: 21 additions & 0 deletions packages/cypress/src/plugins/plugin.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,11 @@ describe('@nx/cypress/plugin', () => {
{
"projects": {
".": {
"metadata": {
"technologies": [
"cypress",
],
},
"projectType": "application",
"targets": {
"e2e": {
Expand Down Expand Up @@ -129,6 +134,11 @@ describe('@nx/cypress/plugin', () => {
{
"projects": {
".": {
"metadata": {
"technologies": [
"cypress",
],
},
"projectType": "application",
"targets": {
"component-test": {
Expand Down Expand Up @@ -187,6 +197,17 @@ describe('@nx/cypress/plugin', () => {
{
"projects": {
".": {
"metadata": {
"targetGroups": {
".:e2e-ci": [
"e2e-ci--src/test.cy.ts",
"e2e-ci",
],
},
"technologies": [
"cypress",
],
},
"projectType": "application",
"targets": {
"e2e": {
Expand Down
67 changes: 41 additions & 26 deletions packages/cypress/src/plugins/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ import {
CreateNodes,
CreateNodesContext,
detectPackageManager,
joinPathFragments,
normalizePath,
NxJsonConfiguration,
ProjectConfiguration,
readJsonFile,
TargetConfiguration,
writeJsonFile,
Expand All @@ -12,7 +15,6 @@ import { dirname, join, relative } from 'path';

import { getLockFileName } from '@nx/js';

import { CypressExecutorOptions } from '../executors/cypress/cypress.impl';
import { getNamedInputs } from '@nx/devkit/src/utils/get-named-inputs';
import { existsSync, readdirSync } from 'fs';
import { globWithWorkspaceContext } from 'nx/src/utils/workspace-context';
Expand All @@ -30,24 +32,13 @@ export interface CypressPluginOptions {
const cachePath = join(projectGraphCacheDirectory, 'cypress.hash');
const targetsCache = existsSync(cachePath) ? readTargetsCache() : {};

const calculatedTargets: Record<
string,
Record<string, TargetConfiguration>
> = {};
const calculatedTargets: Record<string, CypressTargets> = {};

function readTargetsCache(): Record<
string,
Record<string, TargetConfiguration<CypressExecutorOptions>>
> {
function readTargetsCache(): Record<string, CypressTargets> {
return readJsonFile(cachePath);
}

function writeTargetsToCache(
targets: Record<
string,
Record<string, TargetConfiguration<CypressExecutorOptions>>
>
) {
function writeTargetsToCache(targets: Record<string, CypressTargets>) {
writeJsonFile(cachePath, targets);
}

Expand Down Expand Up @@ -75,7 +66,7 @@ export const createNodes: CreateNodes<CypressPluginOptions> = [
getLockFileName(detectPackageManager(context.workspaceRoot)),
]);

const targets = targetsCache[hash]
const { targets, ciTestingGroup } = targetsCache[hash]
? targetsCache[hash]
: await buildCypressTargets(
configFilePath,
Expand All @@ -84,14 +75,25 @@ export const createNodes: CreateNodes<CypressPluginOptions> = [
context
);

calculatedTargets[hash] = targets;
calculatedTargets[hash] = { targets, ciTestingGroup };

const project: Omit<ProjectConfiguration, 'root'> = {
projectType: 'application',
targets,
metadata: {
technologies: ['cypress'],
},
};

if (ciTestingGroup) {
project.metadata.targetGroups = {
[`${projectRoot}:e2e-ci`]: ciTestingGroup,
};
}

return {
projects: {
[projectRoot]: {
projectType: 'application',
targets,
},
[projectRoot]: project,
},
};
},
Expand All @@ -104,9 +106,9 @@ function getOutputs(
): string[] {
function getOutput(path: string): string {
if (path.startsWith('..')) {
return join('{workspaceRoot}', join(projectRoot, path));
return joinPathFragments('{workspaceRoot}', projectRoot, path);
} else {
return join('{projectRoot}', path);
return joinPathFragments('{projectRoot}', path);
}
}

Expand Down Expand Up @@ -145,12 +147,17 @@ function getOutputs(
return outputs;
}

interface CypressTargets {
targets: Record<string, TargetConfiguration>;
ciTestingGroup: string[];
}

async function buildCypressTargets(
configFilePath: string,
projectRoot: string,
options: CypressPluginOptions,
context: CreateNodesContext
) {
): Promise<CypressTargets> {
const cypressConfig = await loadConfigFile(
join(context.workspaceRoot, configFilePath)
);
Expand All @@ -167,6 +174,7 @@ async function buildCypressTargets(
const namedInputs = getNamedInputs(projectRoot, context);

const targets: Record<string, TargetConfiguration> = {};
let ciTestingGroup: string[] = [];

if ('e2e' in cypressConfig) {
targets[options.targetName] = {
Expand Down Expand Up @@ -214,8 +222,10 @@ async function buildCypressTargets(
const outputs = getOutputs(projectRoot, cypressConfig, 'e2e');
const inputs = getInputs(namedInputs);
for (const file of specFiles) {
const relativeSpecFilePath = relative(projectRoot, file);
const relativeSpecFilePath = normalizePath(relative(projectRoot, file));
const targetName = options.ciTargetName + '--' + relativeSpecFilePath;

ciTestingGroup.push(targetName);
targets[targetName] = {
outputs,
inputs,
Expand All @@ -240,6 +250,7 @@ async function buildCypressTargets(
outputs,
dependsOn,
};
ciTestingGroup.push(options.ciTargetName);
}
}

Expand All @@ -254,7 +265,11 @@ async function buildCypressTargets(
};
}

return targets;
if (ciTestingGroup.length === 0) {
ciTestingGroup = null;
}

return { targets, ciTestingGroup };
}

function normalizeOptions(options: CypressPluginOptions): CypressPluginOptions {
Expand Down
1 change: 1 addition & 0 deletions packages/nx/src/adapter/compat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ export const allowedProjectExtensions = [
'projectType',
'release',
'includedScripts',
'metadata',
] as const;

// If we pass props on the workspace that angular doesn't know about,
Expand Down
4 changes: 4 additions & 0 deletions packages/nx/src/config/workspace-json-project-json.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,10 @@ export interface ProjectConfiguration {
'generator' | 'generatorOptions'
>;
};
metadata?: {
technologies?: string[];
targetGroups?: Record<string, string[]>;
};
leosvelperez marked this conversation as resolved.
Show resolved Hide resolved
}

export interface TargetDependencyConfig {
Expand Down