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 14, 2024
1 parent c01b566 commit fee6d59
Show file tree
Hide file tree
Showing 7 changed files with 243 additions and 25 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
26 changes: 26 additions & 0 deletions packages/cypress/src/plugins/plugin.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,14 @@ describe('@nx/cypress/plugin', () => {
{
"projects": {
".": {
"metadata": {
"targetGroups": {
".:e2e-ci": null,
},
"technologies": [
"cypress",
],
},
"projectType": "application",
"targets": {
"e2e": {
Expand Down Expand Up @@ -128,6 +136,14 @@ describe('@nx/cypress/plugin', () => {
{
"projects": {
".": {
"metadata": {
"targetGroups": {
".:e2e-ci": null,
},
"technologies": [
"cypress",
],
},
"projectType": "application",
"targets": {
"component-test": {
Expand Down Expand Up @@ -186,6 +202,16 @@ describe('@nx/cypress/plugin', () => {
{
"projects": {
".": {
"metadata": {
"targetGroups": {
".:e2e-ci": [
"e2e-ci--src/test.cy.ts",
],
},
"technologies": [
"cypress",
],
},
"projectType": "application",
"targets": {
"e2e": {
Expand Down
53 changes: 32 additions & 21 deletions packages/cypress/src/plugins/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import {
CreateNodes,
CreateNodesContext,
detectPackageManager,
joinPathFragments,
normalizePath,
NxJsonConfiguration,
readJsonFile,
TargetConfiguration,
Expand All @@ -12,7 +14,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 +31,16 @@ export interface CypressPluginOptions {
const cachePath = join(projectGraphCacheDirectory, 'cypress.hash');
const targetsCache = existsSync(cachePath) ? readTargetsCache() : {};

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

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: CypressTargets) {
writeJsonFile(cachePath, targets);
}

Expand Down Expand Up @@ -75,7 +68,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 @@ -91,6 +84,12 @@ export const createNodes: CreateNodes<CypressPluginOptions> = [
[projectRoot]: {
projectType: 'application',
targets,
metadata: {
technologies: ['cypress'],
targetGroups: {
[`${projectRoot}:e2e-ci`]: ciTestingGroup,
},
},
},
},
};
Expand All @@ -104,9 +103,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 +144,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 +171,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 +219,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 Down Expand Up @@ -254,7 +261,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
Original file line number Diff line number Diff line change
Expand Up @@ -731,6 +731,90 @@ describe('project-configuration-utils', () => {
`);
});

describe('metadata', () => {
it('should be set if not previously defined', () => {
const rootMap = new RootMapBuilder()
.addProject({
root: 'libs/lib-a',
name: 'lib-a',
})
.getRootMap();
const sourceMap: ConfigurationSourceMaps = {
'libs/lib-a': {},
};
mergeProjectConfigurationIntoRootMap(
rootMap,
{
root: 'libs/lib-a',
name: 'lib-a',
metadata: {
technologies: ['technology'],
},
},
sourceMap,
['dummy', 'dummy.ts']
);

expect(rootMap.get('libs/lib-a').metadata).toEqual({
technologies: ['technology'],
});
expect(sourceMap['libs/lib-a']['metadata.technologies']).toEqual([
'dummy',
'dummy.ts',
]);
expect(sourceMap['libs/lib-a']['metadata.technologies.0']).toEqual([
'dummy',
'dummy.ts',
]);
});

it('should concat arrays', () => {
const rootMap = new RootMapBuilder()
.addProject({
root: 'libs/lib-a',
name: 'lib-a',
metadata: {
technologies: ['technology1'],
},
})
.getRootMap();
const sourceMap: ConfigurationSourceMaps = {
'libs/lib-a': {
'metadata.technologies': ['existing', 'existing.ts'],
'metadata.technologies.0': ['existing', 'existing.ts'],
},
};
mergeProjectConfigurationIntoRootMap(
rootMap,
{
root: 'libs/lib-a',
name: 'lib-a',
metadata: {
technologies: ['technology2'],
},
},
sourceMap,
['dummy', 'dummy.ts']
);

expect(rootMap.get('libs/lib-a').metadata).toEqual({
technologies: ['technology1', 'technology2'],
});
expect(sourceMap['libs/lib-a']['metadata.technologies']).toEqual([
'existing',
'existing.ts',
]);
expect(sourceMap['libs/lib-a']['metadata.technologies.0']).toEqual([
'existing',
'existing.ts',
]);
expect(sourceMap['libs/lib-a']['metadata.technologies.1']).toEqual([
'dummy',
'dummy.ts',
]);
});
});

describe('source map', () => {
it('should add new project info', () => {
const rootMap = new RootMapBuilder().getRootMap();
Expand Down
Loading

0 comments on commit fee6d59

Please sign in to comment.