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:
parent
5537df6411
commit
4a94841916
@ -2225,6 +2225,16 @@
|
||||
}
|
||||
},
|
||||
"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": {
|
||||
"description": "Change @nx/gradle option from ciTargetName to ciTestTargetName",
|
||||
"file": "generated/packages/gradle/migrations/change-ciTargetName-to-ciTestTargetName.json",
|
||||
|
||||
@ -2209,6 +2209,16 @@
|
||||
}
|
||||
],
|
||||
"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",
|
||||
"file": "generated/packages/gradle/migrations/change-ciTargetName-to-ciTestTargetName.json",
|
||||
|
||||
@ -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"
|
||||
}
|
||||
@ -29,6 +29,12 @@
|
||||
"cli": "nx",
|
||||
"description": "Change @nx/gradle option from 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": {}
|
||||
|
||||
@ -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/
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -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;
|
||||
}
|
||||
@ -2,21 +2,15 @@ import {
|
||||
addDependenciesToPackageJson,
|
||||
formatFiles,
|
||||
GeneratorCallback,
|
||||
globAsync,
|
||||
logger,
|
||||
readNxJson,
|
||||
runTasksInSerial,
|
||||
Tree,
|
||||
updateNxJson,
|
||||
} from '@nx/devkit';
|
||||
import {
|
||||
gradleProjectGraphPluginName,
|
||||
gradleProjectGraphVersion,
|
||||
nxVersion,
|
||||
} from '../../utils/versions';
|
||||
import { nxVersion } from '../../utils/versions';
|
||||
import { InitGeneratorSchema } from './schema';
|
||||
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) {
|
||||
const tasks: GeneratorCallback[] = [];
|
||||
@ -34,7 +28,7 @@ export async function initGenerator(tree: Tree, options: InitGeneratorSchema) {
|
||||
)
|
||||
);
|
||||
}
|
||||
await addBuildGradleFileNextToSettingsGradle(tree);
|
||||
await addNxProjectGraphPlugin(tree);
|
||||
addPlugin(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) {
|
||||
const nxJson = readNxJson(tree);
|
||||
|
||||
|
||||
@ -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 %}
|
||||
@ -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"');
|
||||
});
|
||||
});
|
||||
@ -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');
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user