Skip to content
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions e2e/release/jest.config.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/* eslint-disable */
export default {
testTimeout: 120000,
transform: {
'^.+\\.[tj]sx?$': ['ts-jest', { tsconfig: '<rootDir>/tsconfig.spec.json' }],
},
Expand Down
7 changes: 7 additions & 0 deletions e2e/release/src/conventional-commits-config.test.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
import { NxJsonConfiguration } from '@nx/devkit';
import {
cleanupProject,
detectPackageManager,
getPackageManagerCommand,
newProject,
readFile,
runCLI,
runCommandAsync,
uniq,
updateJson,
} from '@nx/e2e-utils';
import { setupWorkspaces } from './utils';

expect.addSnapshotSerializer({
serialize(str: string) {
Expand Down Expand Up @@ -86,6 +89,10 @@ describe('nx release conventional commits config', () => {
return nxJson;
});

setupWorkspaces(detectPackageManager(), pkg1, pkg2, pkg3, pkg4, pkg5, pkg6);
const pmc = getPackageManagerCommand();
await runCommandAsync(pmc.install);

await runCommandAsync(`git add .`);
await runCommandAsync(`git commit -m "chore: initial commit"`);
await runCommandAsync(`git tag -a ${pkg1}@0.0.1 -m "${pkg1}@0.0.1"`);
Expand Down
649 changes: 331 additions & 318 deletions e2e/release/src/independent-projects.test.ts

Large diffs are not rendered by default.

41 changes: 25 additions & 16 deletions e2e/release/src/preserve-matching-dependency-ranges.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,17 @@ import { NxJsonConfiguration } from '@nx/devkit';
import {
cleanupProject,
newProject,
readJson,
runCommandAsync,
runCLI,
tmpProjPath,
uniq,
updateJson,
getPackageManagerCommand,
detectPackageManager,
} from '@nx/e2e-utils';
import { execSync } from 'node:child_process';
import { join } from 'node:path';
import { setupWorkspaces } from './utils';

expect.addSnapshotSerializer({
serialize(str: string) {
Expand All @@ -33,6 +36,7 @@ expect.addSnapshotSerializer({
.replaceAll(/\d*B\s+README.md/g, 'XXB README.md')
.replaceAll(/Test @[\w\d]+/g, 'Test @{COMMIT_AUTHOR}')
.replaceAll(/(\w+) lock file/g, 'PM lock file')
.replaceAll('NX Updating PM lock file\n', '')
// Normalize the version title date.
.replaceAll(/\(\d{4}-\d{2}-\d{2}\)/g, '(YYYY-MM-DD)')
// We trim each line to reduce the chances of snapshot flakiness
Expand Down Expand Up @@ -62,7 +66,7 @@ describe('nx release preserve matching dependency ranges', () => {
/**
* Initialize each test with a fresh workspace
*/
const initializeProject = () => {
const initializeProject = async () => {
newProject({
packages: ['@nx/js'],
});
Expand All @@ -74,6 +78,8 @@ describe('nx release preserve matching dependency ranges', () => {
const pkg3 = uniq('my-pkg-3');
runCLI(`generate @nx/workspace:npm-package ${pkg3}`);

setupWorkspaces(detectPackageManager(), pkg1, pkg2, pkg3);

// Set up dependencies with various range types
updateJson(join(pkg1, 'package.json'), (packageJson) => {
packageJson.version = '1.0.0';
Expand Down Expand Up @@ -103,15 +109,18 @@ describe('nx release preserve matching dependency ranges', () => {
return packageJson;
});

const pmc = getPackageManagerCommand();
await runCommandAsync(pmc.install);

// workaround for NXC-143
runCLI('reset');

return { workspacePath: tmpProjPath(), pkg1, pkg2, pkg3 };
};

describe('when preserveMatchingDependencyRanges is set to false', () => {
it('should update all dependency ranges', () => {
const { workspacePath } = initializeProject();
it('should update all dependency ranges', async () => {
const { workspacePath } = await initializeProject();

updateJson<NxJsonConfiguration>('nx.json', (nxJson) => {
nxJson.release = {
Expand Down Expand Up @@ -184,8 +193,8 @@ describe('nx release preserve matching dependency ranges', () => {
});

describe('when preserveMatchingDependencyRanges is set to true', () => {
it('should preserve dependency ranges when new version satisfies them', () => {
const { workspacePath, pkg1, pkg3 } = initializeProject();
it('should preserve dependency ranges when new version satisfies them', async () => {
const { workspacePath, pkg1, pkg3 } = await initializeProject();
updateJson(join(pkg1, 'package.json'), (packageJson) => {
packageJson.dependencies[`@proj/${pkg3}`] = '^1.0.0';
return packageJson;
Expand Down Expand Up @@ -244,8 +253,8 @@ describe('nx release preserve matching dependency ranges', () => {
});

describe('when preserveMatchingDependencyRanges is set to specific dependency types', () => {
it('should only preserve ranges for specified dependency types', () => {
const { workspacePath } = initializeProject();
it('should only preserve ranges for specified dependency types', async () => {
const { workspacePath } = await initializeProject();

updateJson<NxJsonConfiguration>('nx.json', (nxJson) => {
nxJson.release = {
Expand Down Expand Up @@ -311,8 +320,8 @@ describe('nx release preserve matching dependency ranges', () => {
`);
});

it('should handle empty array (no preservation)', () => {
const { workspacePath } = initializeProject();
it('should handle empty array (no preservation)', async () => {
const { workspacePath } = await initializeProject();

updateJson<NxJsonConfiguration>('nx.json', (nxJson) => {
nxJson.release = {
Expand Down Expand Up @@ -386,8 +395,8 @@ describe('nx release preserve matching dependency ranges', () => {
});

describe('with patch versions', () => {
it('should preserve ranges when patch version satisfies them', () => {
const { workspacePath } = initializeProject();
it('should preserve ranges when patch version satisfies them', async () => {
const { workspacePath } = await initializeProject();

updateJson<NxJsonConfiguration>('nx.json', (nxJson) => {
nxJson.release = {
Expand Down Expand Up @@ -443,8 +452,8 @@ describe('nx release preserve matching dependency ranges', () => {
});

describe('with exact version dependencies', () => {
it('should always update exact version dependencies', () => {
const { workspacePath, pkg1, pkg2 } = initializeProject();
it('should always update exact version dependencies', async () => {
const { workspacePath, pkg1, pkg2 } = await initializeProject();

// Add exact version dependency
updateJson(join(pkg1, 'package.json'), (packageJson) => {
Expand Down Expand Up @@ -512,8 +521,8 @@ describe('nx release preserve matching dependency ranges', () => {
});

describe('with wildcard ranges', () => {
it('should preserve wildcard ranges', () => {
const { workspacePath, pkg1, pkg2, pkg3 } = initializeProject();
it('should preserve wildcard ranges', async () => {
const { workspacePath, pkg1, pkg2, pkg3 } = await initializeProject();

// Add wildcard dependency
updateJson(join(pkg1, 'package.json'), (packageJson) => {
Expand Down
49 changes: 49 additions & 0 deletions e2e/release/src/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import {
runCommandAsync,
createFile,
updateJson,
removeFile,
} from '@nx/e2e-utils';

export function setupWorkspaces(
packageManager: 'npm' | 'yarn' | 'pnpm' | 'bun',
...packages: string[]
) {
if (packageManager === 'npm' || packageManager === 'yarn') {
updateJson('package.json', (packageJson) => {
packageJson.workspaces = packages;
return packageJson;
});
} else if (packageManager === 'pnpm') {
createFile(
`pnpm-workspace.yaml`,
`packages:
${packages.map((p) => `- ${p}`).join('\n ')}
`
);
}
}

export async function prepareAndInstallDependencies(
packageManager: 'npm' | 'yarn' | 'pnpm' | 'bun',
installCommand: string
) {
if (packageManager === 'npm') {
removeFile('yarn.lock');
removeFile('pnpm-lock.yaml');
removeFile('pnpm-workspace.yaml');
} else if (packageManager === 'yarn') {
removeFile('package-lock.json');
removeFile('pnpm-lock.yaml');
removeFile('pnpm-workspace.yaml');
updateJson('package.json', (pkgJson) => {
delete pkgJson.packageManager;
return pkgJson;
});
await runCommandAsync(`yarn config set enableImmutableInstalls false`);
} else if (packageManager === 'pnpm') {
removeFile('package-lock.json');
removeFile('yarn.lock');
}
await runCommandAsync(installCommand);
}
1 change: 1 addition & 0 deletions e2e/release/tsconfig.spec.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"types": ["jest", "node"]
},
"include": [
"src/utils.ts",
"**/*.test.ts",
"**/*.spec.ts",
"**/*.spec.tsx",
Expand Down
1 change: 1 addition & 0 deletions packages/nx/src/config/workspace-json-project-json.ts
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@ export interface ProjectMetadata {
};
js?: {
packageName: string;
packageVersion?: string;
packageExports?: PackageJson['exports'];
packageMain?: string;
isInPackageManagerWorkspaces?: boolean;
Expand Down
5 changes: 4 additions & 1 deletion packages/nx/src/plugins/js/lock-file/npm-parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,10 @@ function getNodes(

const packageName = path.split('node_modules/').pop();
const version = findV3Version(snapshot, packageName);
createNode(packageName, version, path, nodes, keyMap, snapshot);
// symlinked packages in workspaces do not have versions
if (version) {
createNode(packageName, version, path, nodes, keyMap, snapshot);
}
});
} else {
Object.entries(data.dependencies).forEach(([packageName, snapshot]) => {
Expand Down
Loading
Loading