fix(gradle): add migration script to check gradle plugin version (#31304)

<!-- Please make sure you have read the submission guidelines before
posting an PR -->
<!--
https://github.com/nrwl/nx/blob/master/CONTRIBUTING.md#-submitting-a-pr
-->

<!-- Please make sure that your commit message follows our format -->
<!-- Example: `fix(nx): must begin with lowercase` -->

<!-- If this is a particularly complex change or feature addition, you
can request a dedicated Nx release for this pull request branch. Mention
someone from the Nx team or the `@nrwl/nx-pipelines-reviewers` and they
will confirm if the PR warrants its own release for testing purposes,
and generate it for you if appropriate. -->

## Current Behavior
<!-- This is the behavior we have today -->
currently, when migrate @nx/gradle to latest, we don't check the
dev.nx.gradle.project-graph version in build file

## Expected Behavior
<!-- This is the behavior we should expect with the changes in this PR
-->
we should check the project-praph in the build file and make sure it is
correct version

## Related Issue(s)
<!-- Please link the issue being fixed so it gets closed when this is
merged. -->

Fixes #
This commit is contained in:
Emily Xiong 2025-05-26 13:59:28 -04:00 committed by GitHub
parent 5537df6411
commit 4a94841916
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 692 additions and 87 deletions

View File

@ -2225,6 +2225,16 @@
} }
}, },
"migrations": { "migrations": {
"/nx-api/gradle/migrations/change-plugin-version-0-1-0": {
"description": "Change dev.nx.gradle.project-graph to version 0.1.0 in build file",
"file": "generated/packages/gradle/migrations/change-plugin-version-0-1-0.json",
"hidden": false,
"name": "change-plugin-version-0-1-0",
"version": "21.1.2-beta.1",
"originalFilePath": "/packages/gradle",
"path": "/nx-api/gradle/migrations/change-plugin-version-0-1-0",
"type": "migration"
},
"/nx-api/gradle/migrations/change-ciTargetName-to-ciTestTargetName": { "/nx-api/gradle/migrations/change-ciTargetName-to-ciTestTargetName": {
"description": "Change @nx/gradle option from ciTargetName to ciTestTargetName", "description": "Change @nx/gradle option from ciTargetName to ciTestTargetName",
"file": "generated/packages/gradle/migrations/change-ciTargetName-to-ciTestTargetName.json", "file": "generated/packages/gradle/migrations/change-ciTargetName-to-ciTestTargetName.json",

View File

@ -2209,6 +2209,16 @@
} }
], ],
"migrations": [ "migrations": [
{
"description": "Change dev.nx.gradle.project-graph to version 0.1.0 in build file",
"file": "generated/packages/gradle/migrations/change-plugin-version-0-1-0.json",
"hidden": false,
"name": "change-plugin-version-0-1-0",
"version": "21.1.2-beta.1",
"originalFilePath": "/packages/gradle",
"path": "gradle/migrations/change-plugin-version-0-1-0",
"type": "migration"
},
{ {
"description": "Change @nx/gradle option from ciTargetName to ciTestTargetName", "description": "Change @nx/gradle option from ciTargetName to ciTestTargetName",
"file": "generated/packages/gradle/migrations/change-ciTargetName-to-ciTestTargetName.json", "file": "generated/packages/gradle/migrations/change-ciTargetName-to-ciTestTargetName.json",

View File

@ -0,0 +1,14 @@
{
"name": "change-plugin-version-0-1-0",
"version": "21.1.2-beta.1",
"cli": "nx",
"description": "Change dev.nx.gradle.project-graph to version 0.1.0 in build file",
"factory": "./src/migrations/21-1-2/change-plugin-version-0-1-0",
"implementation": "/packages/gradle/src/migrations/21-1-2/change-plugin-version-0-1-0.ts",
"aliases": [],
"hidden": false,
"path": "/packages/gradle",
"schema": null,
"type": "migration",
"examplesFile": "#### Change dev.nx.gradle.project-graph to version 0.1.0\n\nChange dev.nx.gradle.project-graph to version 0.1.0 in build file\n\n#### Sample Code Changes\n\n{% tabs %}\n{% tab label=\"Before\" %}\n\n```{% fileName=\"build.gradle\" %}\nplugins {\n\tid \"dev.nx.gradle.project-graph\" version \"0.0.5\"\n}\n```\n\n{% /tab %}\n{% tab label=\"After\" %}\n\n```{% fileName=\"build.gradle\" %}\nplugins {\n id \"dev.nx.gradle.project-graph\" version \"0.1.0\"\n}\n```\n\n{% /tab %}\n{% /tabs %}\n"
}

View File

@ -29,6 +29,12 @@
"cli": "nx", "cli": "nx",
"description": "Change @nx/gradle option from ciTargetName to ciTestTargetName", "description": "Change @nx/gradle option from ciTargetName to ciTestTargetName",
"factory": "./src/migrations/21-0-0/change-ciTargetName-to-ciTestTargetName" "factory": "./src/migrations/21-0-0/change-ciTargetName-to-ciTestTargetName"
},
"change-plugin-version-0-1-0": {
"version": "21.1.2-beta.1",
"cli": "nx",
"description": "Change dev.nx.gradle.project-graph to version 0.1.0 in build file",
"factory": "./src/migrations/21-1-2/change-plugin-version-0-1-0"
} }
}, },
"packageJsonUpdates": {} "packageJsonUpdates": {}

View File

@ -0,0 +1,272 @@
import { TempFs } from 'nx/src/internal-testing-utils/temp-fs';
import { Tree } from '@nx/devkit';
import { FsTree } from 'nx/src/generators/tree';
import {
addNxProjectGraphPlugin,
extractNxPluginVersion,
updateNxPluginVersion,
} from './gradle-project-graph-plugin-utils';
import { gradleProjectGraphPluginName } from '../../utils/versions';
import * as execGradle from '../../utils/exec-gradle';
jest.mock('../../utils/exec-gradle', () => ({
findGradlewFile: jest.fn(),
execGradleAsync: jest.fn(),
}));
const mockFindGradlewFile = execGradle.findGradlewFile as jest.Mock;
const mockExecGradleAsync = execGradle.execGradleAsync as jest.Mock;
describe('Gradle Project Graph Plugin Utils', () => {
describe('extractNxPluginVersion', () => {
beforeEach(() => {
jest.clearAllMocks();
});
it.each([
['id "dev.nx.gradle.project-graph" version "+"', '+'],
['id("dev.nx.gradle.project-graph") version("0.1.0")', '0.1.0'],
['id(\'dev.nx.gradle.project-graph\') version("0.1.0")', '0.1.0'],
["id('dev.nx.gradle.project-graph') version('0.1.0')", '0.1.0'],
])('should extract version from %s', async (input, expected) => {
const version = await extractNxPluginVersion('build.gradle.kts', input);
expect(version).toBe(expected);
});
it('should return version from buildEnvironment fallback if inline version is missing', async () => {
const gradleEnvOutput = `
classpath
\\--- dev.nx.gradle.project-graph:dev.nx.gradle.project-graph.gradle.plugin:0.2.3
\\--- dev.nx.gradle:project-graph:0.2.3
`;
mockFindGradlewFile.mockReturnValue('./gradlew');
mockExecGradleAsync.mockResolvedValue(gradleEnvOutput);
const version = await extractNxPluginVersion(
'build.gradle.kts',
'some unrelated content'
);
expect(version).toBe('0.2.3');
expect(mockFindGradlewFile).toHaveBeenCalled();
expect(mockExecGradleAsync).toHaveBeenCalled();
});
it('should return null when no version is found anywhere', async () => {
mockFindGradlewFile.mockImplementation(() => {
throw new Error('not found');
});
const version = await extractNxPluginVersion(
'build.gradle.kts',
'no version here'
);
expect(version).toBeNull();
});
});
describe('updateNxPluginVersion', () => {
it('should update version in Groovy DSL format', () => {
const input = 'id "dev.nx.gradle.project-graph" version "1.0.0"';
const expected = 'id "dev.nx.gradle.project-graph" version "2.0.0"';
expect(updateNxPluginVersion(input, '2.0.0')).toBe(expected);
});
it('should update version in Kotlin DSL format', () => {
const input = 'id("dev.nx.gradle.project-graph") version("1.0.0")';
const expected = 'id("dev.nx.gradle.project-graph") version("2.0.0")';
expect(updateNxPluginVersion(input, '2.0.0')).toBe(expected);
});
});
describe('addNxProjectGraphPlugin', () => {
let tempFs: TempFs;
let cwd: string;
let tree: Tree;
beforeEach(async () => {
tempFs = new TempFs('test');
cwd = process.cwd();
process.chdir(tempFs.tempDir);
tree = new FsTree(tempFs.tempDir, false);
});
afterEach(() => {
jest.resetModules();
process.chdir(cwd);
});
describe('Groovy DSL (build.gradle)', () => {
it('should add plugin to existing plugins block', async () => {
await tempFs.createFiles({
'proj/settings.gradle': '',
'proj/build.gradle': `plugins {
id 'java'
}`,
});
await addNxProjectGraphPlugin(tree);
const content = tree.read('proj/build.gradle', 'utf-8');
expect(content).toMatch(
/plugins\s*{\s*id\s*['"]dev\.nx\.gradle\.project-graph['"]\s*version\s*['"][^'"]+['"]\s*id\s*['"]java['"]/
);
expect(content).toMatch(
/allprojects\s*{\s*apply\s*{\s*plugin\(['"]dev\.nx\.gradle\.project-graph['"]\)\s*}\s*}/
);
});
it('should use passed in expected version', async () => {
const expectedVersion = '2.0.0';
await tempFs.createFiles({
'proj/settings.gradle': '',
'proj/build.gradle': `plugins {
id 'java'
}`,
});
await addNxProjectGraphPlugin(tree, expectedVersion);
const content = tree.read('proj/build.gradle', 'utf-8');
expect(content).toContain(
`id "${gradleProjectGraphPluginName}" version "${expectedVersion}"`
);
expect(content).toMatch(
/allprojects\s*{\s*apply\s*{\s*plugin\(['"]dev\.nx\.gradle\.project-graph['"]\)\s*}\s*}/
);
});
it('should create plugins block if missing', async () => {
await tempFs.createFiles({
'proj/settings.gradle': '',
'proj/build.gradle': 'apply plugin: "java"',
});
await addNxProjectGraphPlugin(tree);
const content = tree.read('proj/build.gradle', 'utf-8');
expect(content).toMatch(
/^plugins\s*{\s*id\s*['"]dev\.nx\.gradle\.project-graph['"]\s*version\s*['"][^'"]+['"]\s*}\s*apply plugin:/
);
});
it('should update existing plugin version', async () => {
await tempFs.createFiles({
'proj/settings.gradle': '',
'proj/build.gradle': `plugins {
id "dev.nx.gradle.project-graph" version "1.0.0"
}`,
});
await addNxProjectGraphPlugin(tree);
const content = tree.read('proj/build.gradle', 'utf-8');
expect(content).not.toContain('version "1.0.0"');
expect(content).toContain('allprojects {');
});
});
describe('Kotlin DSL (build.gradle.kts)', () => {
it('should add plugin to existing plugins block', async () => {
await tempFs.createFiles({
'proj/settings.gradle.kts': '',
'proj/build.gradle.kts': `plugins {
id("java")
}`,
});
await addNxProjectGraphPlugin(tree);
const content = tree.read('proj/build.gradle.kts', 'utf-8');
expect(content).toMatch(
/plugins\s*{\s*id\(['"]dev\.nx\.gradle\.project-graph['"]\)\s*version\(['"][^'"]+['"]\)\s*id\(['"]java['"]\)/
);
expect(content).toMatch(
/allprojects\s*{\s*apply\s*{\s*plugin\(['"]dev\.nx\.gradle\.project-graph['"]\)\s*}\s*}/
);
});
it('should create plugins block if missing', async () => {
await tempFs.createFiles({
'proj/settings.gradle.kts': '',
'proj/build.gradle.kts': 'apply(plugin = "java")',
});
await addNxProjectGraphPlugin(tree);
const content = tree.read('proj/build.gradle.kts', 'utf-8');
expect(content).toMatch(
/^plugins\s*{\s*id\(['"]dev\.nx\.gradle\.project-graph['"]\)\s*version\(['"][^'"]+['"]\)\s*}\s*apply\(plugin =/
);
});
});
describe('Multiple projects', () => {
it('should handle multiple build.gradle files', async () => {
await tempFs.createFiles({
'proj1/settings.gradle': '',
'proj1/build.gradle': 'apply plugin: "java"',
'proj2/settings.gradle': '',
'proj2/build.gradle': 'apply plugin: "java"',
});
await addNxProjectGraphPlugin(tree);
const proj1Content = tree.read('proj1/build.gradle', 'utf-8');
const proj2Content = tree.read('proj2/build.gradle', 'utf-8');
expect(proj1Content).toContain(`id "${gradleProjectGraphPluginName}"`);
expect(proj2Content).toContain(`id "${gradleProjectGraphPluginName}"`);
});
it('should handle mixed Groovy and Kotlin DSL projects', async () => {
await tempFs.createFiles({
'groovy/settings.gradle': '',
'groovy/build.gradle': 'apply plugin: "java"',
'kotlin/settings.gradle.kts': '',
'kotlin/build.gradle.kts': 'apply(plugin = "java")',
});
await addNxProjectGraphPlugin(tree);
const groovyContent = tree.read('groovy/build.gradle', 'utf-8');
const kotlinContent = tree.read('kotlin/build.gradle.kts', 'utf-8');
expect(groovyContent).toContain(`id "${gradleProjectGraphPluginName}"`);
expect(kotlinContent).toContain(
`id("${gradleProjectGraphPluginName}")`
);
});
});
describe('Edge cases', () => {
it('should handle empty build.gradle file', async () => {
await tempFs.createFiles({
'proj/settings.gradle': '',
'proj/build.gradle': '',
});
await addNxProjectGraphPlugin(tree);
const content = tree.read('proj/build.gradle', 'utf-8');
expect(content).toMatch(
/^plugins\s*{\s*id\s*['"]dev\.nx\.gradle\.project-graph['"]\s*version\s*['"][^'"]+['"]\s*}\s*allprojects/
);
});
it('should handle build.gradle with only comments', async () => {
await tempFs.createFiles({
'proj/settings.gradle': '',
'proj/build.gradle': '// Some comments\n// More comments',
});
await addNxProjectGraphPlugin(tree);
const content = tree.read('proj/build.gradle', 'utf-8');
expect(content).toMatch(
/^plugins\s*{\s*id\s*['"]dev\.nx\.gradle\.project-graph['"]\s*version\s*['"][^'"]+['"]\s*}\s*\/\/ Some comments/
);
});
});
});
});

View File

@ -0,0 +1,207 @@
import { globAsync, logger, Tree, workspaceRoot } from '@nx/devkit';
import {
gradleProjectGraphPluginName,
gradleProjectGraphVersion,
} from '../../utils/versions';
import { dirname, join } from 'path';
import { execGradleAsync, findGradlewFile } from '../../utils/exec-gradle';
/**
* Adds a `build.gradle(.kts)` file next to each `settings.gradle(.kts)` file found in the workspace.
* If the build.gradle file already exists, it reads its contents.
*/
export async function addBuildGradleFileNextToSettingsGradle(
tree: Tree
): Promise<{ filePath: string; content: string }[]> {
const settingsGradleFiles = await globAsync(tree, [
'**/settings.gradle',
'**/settings.gradle.kts',
]);
return settingsGradleFiles.map((settingsGradlePath) => {
return ensureBuildGradleFile(tree, settingsGradlePath);
});
}
/**
* Determines the appropriate build.gradle file path based on the settings file
* and ensures it exists in the tree. Returns the path and contents.
*/
function ensureBuildGradleFile(
tree: Tree,
settingsGradlePath: string
): { filePath: string; content: string } {
const isKotlinDsl = settingsGradlePath.endsWith('.kts');
const buildGradleFile = join(
dirname(settingsGradlePath),
isKotlinDsl ? 'build.gradle.kts' : 'build.gradle'
);
let content = '';
if (tree.exists(buildGradleFile)) {
content = tree.read(buildGradleFile, 'utf-8');
} else {
tree.write(buildGradleFile, content);
}
return { filePath: buildGradleFile, content };
}
// a regex to get the version in build file in format `id "dev.nx.gradle.project-graph" version "x"`
const regex =
/(id\s*\(?["']dev\.nx\.gradle\.project-graph["']\)?\s*version\s*\(?["'])([^"']+)(["']\)?)/;
/**
* Extract gradle plugin version from build.gradle file
*/
export async function extractNxPluginVersion(
gradleFilePath: string,
gradleContent: string
): Promise<string | null> {
const match = gradleContent.match(regex);
let version = match ? match[2] : null;
if (!version) {
try {
const gradlewFile = findGradlewFile(gradleFilePath, workspaceRoot);
const buildEnvironment = (
await execGradleAsync(join(workspaceRoot, gradlewFile), [
'buildEnvironment',
'--quiet',
])
).toString();
version = getPluginVersion(buildEnvironment);
} catch (e) {} // Silently ignore error, fallback remains null
}
return version;
}
function getPluginVersion(dependencyTree: string): string | null {
const lines = dependencyTree.split('\n');
for (const line of lines) {
// line is dev.nx.gradle.project-graph:dev.nx.gradle.project-graph.gradle.plugin:version
const match = line.match(
/dev\.nx\.gradle\.project-graph:dev\.nx\.gradle\.project-graph\.gradle\.plugin:([^\s\\]+)/
);
if (match) {
return match[1]; // returns the version part
}
}
return null; // not found
}
/**
* Updates the plugin version in the given Gradle file content.
*/
export function updateNxPluginVersion(
content: string,
newVersion: string
): string {
if (regex.test(content)) {
return content.replace(regex, `$1${newVersion}$3`);
} else {
logger.warn(
`Please update plugin dev.nx.gradle.project-graph to ${newVersion}`
);
}
return content;
}
/**
* Ensures all build.gradle(.kts) files use the expected version of dev.nx.gradle.project-graph.
*/
export async function addNxProjectGraphPlugin(
tree: Tree,
expectedVersion: string = gradleProjectGraphVersion
) {
const files = await addBuildGradleFileNextToSettingsGradle(tree);
files.forEach(({ filePath, content }) => {
addNxProjectGraphPluginToBuildGradle(
filePath,
content,
expectedVersion,
tree
);
});
}
/**
* Adds or updates the Nx Project Graph plugin in the build.gradle(.kts) file.
* Ensures the correct version and applies the plugin to all projects.
* Returns the updated build.gradle content.
*/
async function addNxProjectGraphPluginToBuildGradle(
gradleFilePath: string,
buildGradleContent: string,
expectedVersion: string = gradleProjectGraphVersion,
tree: Tree
): Promise<string> {
const isKotlinDsl = gradleFilePath.endsWith('.kts');
const nxProjectGraphReportPlugin = isKotlinDsl
? `id(\"${gradleProjectGraphPluginName}\") version(\"${expectedVersion}\")`
: `id \"${gradleProjectGraphPluginName}\" version \"${expectedVersion}\"`;
// Helper to add plugin to plugins block
function addPluginToPluginsBlock(content: string): string {
return content.replace(
/plugins\s*\{/,
`plugins {\n ${nxProjectGraphReportPlugin}`
);
}
// Helper to add plugins block if missing
function addPluginsBlock(content: string): string {
return `plugins {\n ${nxProjectGraphReportPlugin}\n}\n${content}`;
}
// Helper to add plugin application to allprojects
function addPluginToAllProjects(content: string): string {
const applyPlugin = isKotlinDsl
? `plugin(\"${gradleProjectGraphPluginName}\")`
: `plugin(\"${gradleProjectGraphPluginName}\")`;
return `${content}\nallprojects {\n apply {\n ${applyPlugin}\n }\n}`;
}
// 1. Ensure plugins block and correct plugin version
if (buildGradleContent.includes('plugins {')) {
if (buildGradleContent.includes(gradleProjectGraphPluginName)) {
// Update version if needed
const currentVersion = await extractNxPluginVersion(
gradleFilePath,
buildGradleContent
);
if (currentVersion && currentVersion !== expectedVersion) {
buildGradleContent = updateNxPluginVersion(
buildGradleContent,
expectedVersion
);
}
} else {
// Add plugin to plugins block
buildGradleContent = addPluginToPluginsBlock(buildGradleContent);
}
} else {
// Add plugins block if missing
buildGradleContent = addPluginsBlock(buildGradleContent);
}
// 2. Ensure plugin is applied to all projects
const applyPluginPattern = new RegExp(
`\\s*plugin\\(["']${gradleProjectGraphPluginName}["']\\)`
);
if (buildGradleContent.includes('allprojects {')) {
if (!applyPluginPattern.test(buildGradleContent)) {
logger.warn(
`Please add the ${gradleProjectGraphPluginName} plugin to your ${gradleFilePath}:\nallprojects {\n apply {\n plugin(\"${gradleProjectGraphPluginName}\")\n }\n}`
);
}
} else {
buildGradleContent = addPluginToAllProjects(buildGradleContent);
}
// 3. Write and return updated content
tree.write(gradleFilePath, buildGradleContent);
return buildGradleContent;
}

View File

@ -2,21 +2,15 @@ import {
addDependenciesToPackageJson, addDependenciesToPackageJson,
formatFiles, formatFiles,
GeneratorCallback, GeneratorCallback,
globAsync,
logger,
readNxJson, readNxJson,
runTasksInSerial, runTasksInSerial,
Tree, Tree,
updateNxJson, updateNxJson,
} from '@nx/devkit'; } from '@nx/devkit';
import { import { nxVersion } from '../../utils/versions';
gradleProjectGraphPluginName,
gradleProjectGraphVersion,
nxVersion,
} from '../../utils/versions';
import { InitGeneratorSchema } from './schema'; import { InitGeneratorSchema } from './schema';
import { hasGradlePlugin } from '../../utils/has-gradle-plugin'; import { hasGradlePlugin } from '../../utils/has-gradle-plugin';
import { dirname, join, basename } from 'path'; import { addNxProjectGraphPlugin } from './gradle-project-graph-plugin-utils';
export async function initGenerator(tree: Tree, options: InitGeneratorSchema) { export async function initGenerator(tree: Tree, options: InitGeneratorSchema) {
const tasks: GeneratorCallback[] = []; const tasks: GeneratorCallback[] = [];
@ -34,7 +28,7 @@ export async function initGenerator(tree: Tree, options: InitGeneratorSchema) {
) )
); );
} }
await addBuildGradleFileNextToSettingsGradle(tree); await addNxProjectGraphPlugin(tree);
addPlugin(tree); addPlugin(tree);
updateNxJsonConfiguration(tree); updateNxJsonConfiguration(tree);
@ -62,84 +56,6 @@ function addPlugin(tree: Tree) {
} }
} }
/**
* This function creates and populate build.gradle file next to the settings.gradle file.
*/
export async function addBuildGradleFileNextToSettingsGradle(tree: Tree) {
const settingsGradleFiles = await globAsync(tree, [
'**/settings.gradle?(.kts)',
]);
settingsGradleFiles.forEach((settingsGradleFile) => {
addNxProjectGraphPluginToBuildGradle(settingsGradleFile, tree);
});
}
/**
* - creates a build.gradle file next to the settings.gradle file if it does not exist.
* - adds the NxProjectGraphPlugin plugin to the build.gradle file if it does not exist.
*/
function addNxProjectGraphPluginToBuildGradle(
settingsGradleFile: string,
tree: Tree
) {
const filename = basename(settingsGradleFile);
let gradleFilePath = 'build.gradle';
if (filename.endsWith('.kts')) {
gradleFilePath = 'build.gradle.kts';
}
gradleFilePath = join(dirname(settingsGradleFile), gradleFilePath);
let buildGradleContent = '';
if (!tree.exists(gradleFilePath)) {
tree.write(gradleFilePath, buildGradleContent); // create a build.gradle file near settings.gradle file if it does not exist
} else {
buildGradleContent = tree.read(gradleFilePath).toString();
}
const nxProjectGraphReportPlugin = filename.endsWith('.kts')
? `id("${gradleProjectGraphPluginName}") version("${gradleProjectGraphVersion}")`
: `id "${gradleProjectGraphPluginName}" version "${gradleProjectGraphVersion}"`;
if (buildGradleContent.includes('plugins {')) {
if (!buildGradleContent.includes(gradleProjectGraphPluginName)) {
buildGradleContent = buildGradleContent.replace(
'plugins {',
`plugins {
${nxProjectGraphReportPlugin}`
);
}
} else {
buildGradleContent = `plugins {
${nxProjectGraphReportPlugin}
}\n\r${buildGradleContent}`;
}
const applyNxProjectGraphReportPlugin = `plugin("${gradleProjectGraphPluginName}")`;
if (buildGradleContent.includes('allprojects {')) {
if (
!buildGradleContent.includes(
`plugin("${gradleProjectGraphPluginName}")`
) &&
!buildGradleContent.includes(`plugin('${gradleProjectGraphPluginName}')`)
) {
logger.warn(
`Please add the ${gradleProjectGraphPluginName} plugin to your ${gradleFilePath}:
allprojects {
apply {
${applyNxProjectGraphReportPlugin}
}
}`
);
}
} else {
buildGradleContent = `${buildGradleContent}\n\rallprojects {
apply {
${applyNxProjectGraphReportPlugin}
}
}`;
}
tree.write(gradleFilePath, buildGradleContent);
}
export function updateNxJsonConfiguration(tree: Tree) { export function updateNxJsonConfiguration(tree: Tree) {
const nxJson = readNxJson(tree); const nxJson = readNxJson(tree);

View File

@ -0,0 +1,26 @@
#### Change dev.nx.gradle.project-graph to version 0.1.0
Change dev.nx.gradle.project-graph to version 0.1.0 in build file
#### Sample Code Changes
{% tabs %}
{% tab label="Before" %}
```{% fileName="build.gradle" %}
plugins {
id "dev.nx.gradle.project-graph" version "0.0.5"
}
```
{% /tab %}
{% tab label="After" %}
```{% fileName="build.gradle" %}
plugins {
id "dev.nx.gradle.project-graph" version "0.1.0"
}
```
{% /tab %}
{% /tabs %}

View File

@ -0,0 +1,128 @@
import { TempFs } from 'nx/src/internal-testing-utils/temp-fs';
import { Tree } from '@nx/devkit';
import { FsTree } from 'nx/src/generators/tree';
import update from './change-plugin-version-0-1-0';
import { gradleProjectGraphPluginName } from '../../utils/versions';
describe('change-plugin-version-0-1-0 migration', () => {
let tempFs: TempFs;
let cwd: string;
let tree: Tree;
beforeEach(async () => {
tempFs = new TempFs('test');
cwd = process.cwd();
process.chdir(tempFs.tempDir);
tree = new FsTree(tempFs.tempDir, false);
});
afterEach(() => {
jest.resetModules();
process.chdir(cwd);
});
it('should update plugin version to 0.1.0 in Groovy DSL', async () => {
await tempFs.createFiles({
'nx.json': JSON.stringify({
plugins: ['@nx/gradle'],
}),
'proj/settings.gradle': '',
'proj/build.gradle': `plugins {
id 'java'
id "${gradleProjectGraphPluginName}" version "0.0.1"
}`,
});
await update(tree);
const content = tree.read('proj/build.gradle', 'utf-8');
expect(content).toContain(
`id "${gradleProjectGraphPluginName}" version "0.1.0"`
);
expect(content).not.toContain('version "0.0.1"');
});
it('should update plugin version to 0.1.0 in Kotlin DSL', async () => {
await tempFs.createFiles({
'nx.json': JSON.stringify({
plugins: ['@nx/gradle'],
}),
'proj/settings.gradle.kts': '',
'proj/build.gradle.kts': `plugins {
id("java")
id("${gradleProjectGraphPluginName}") version("0.0.1")
}`,
});
await update(tree);
const content = tree.read('proj/build.gradle.kts', 'utf-8');
expect(content).toContain(
`id("${gradleProjectGraphPluginName}") version("0.1.0")`
);
expect(content).not.toContain('version("0.0.1")');
});
it('should not update if nx.json is missing', async () => {
await tempFs.createFiles({
'proj/settings.gradle': '',
'proj/build.gradle': `plugins {
id 'java'
id "${gradleProjectGraphPluginName}" version "0.0.1"
}`,
});
await update(tree);
const content = tree.read('proj/build.gradle', 'utf-8');
expect(content).toContain('version "0.0.1"');
expect(content).not.toContain('version "0.1.0"');
});
it('should not update if Gradle plugin is not present', async () => {
await tempFs.createFiles({
'nx.json': JSON.stringify({}),
'proj/settings.gradle': '',
'proj/build.gradle': `plugins {
id 'java'
}`,
});
await update(tree);
const content = tree.read('proj/build.gradle', 'utf-8');
expect(content).not.toContain(gradleProjectGraphPluginName);
});
it('should handle multiple build.gradle files', async () => {
await tempFs.createFiles({
'nx.json': JSON.stringify({
plugins: ['@nx/gradle'],
}),
'proj1/settings.gradle': '',
'proj1/build.gradle': `plugins {
id 'java'
id "${gradleProjectGraphPluginName}" version "0.0.1"
}`,
'proj2/settings.gradle': '',
'proj2/build.gradle': `plugins {
id 'java'
id "${gradleProjectGraphPluginName}" version "0.0.1"
}`,
});
await update(tree);
const proj1Content = tree.read('proj1/build.gradle', 'utf-8');
const proj2Content = tree.read('proj2/build.gradle', 'utf-8');
expect(proj1Content).toContain(
`id "${gradleProjectGraphPluginName}" version "0.1.0"`
);
expect(proj2Content).toContain(
`id "${gradleProjectGraphPluginName}" version "0.1.0"`
);
expect(proj1Content).not.toContain('version "0.0.1"');
expect(proj2Content).not.toContain('version "0.0.1"');
});
});

View File

@ -0,0 +1,16 @@
import { Tree, readNxJson } from '@nx/devkit';
import { hasGradlePlugin } from '../../utils/has-gradle-plugin';
import { addNxProjectGraphPlugin } from '../../generators/init/gradle-project-graph-plugin-utils';
/* Change the plugin version to 0.1.0
*/
export default async function update(tree: Tree) {
const nxJson = readNxJson(tree);
if (!nxJson) {
return;
}
if (!hasGradlePlugin(tree)) {
return;
}
await addNxProjectGraphPlugin(tree, '0.1.0');
}