Skip to content

Commit

Permalink
feat(core): add ability to add metadata to projects
Browse files Browse the repository at this point in the history
  • Loading branch information
FrozenPandaz committed Mar 18, 2024
1 parent 3c72acd commit 6287f0f
Show file tree
Hide file tree
Showing 7 changed files with 349 additions and 30 deletions.
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[]>;
};
}

export interface TargetDependencyConfig {
Expand Down

0 comments on commit 6287f0f

Please sign in to comment.