diff --git a/docs/generated/manifests/nx-api.json b/docs/generated/manifests/nx-api.json index 0eac813536..1de7b52a65 100644 --- a/docs/generated/manifests/nx-api.json +++ b/docs/generated/manifests/nx-api.json @@ -2105,7 +2105,7 @@ "source": "/packages/gradle/src", "executors": { "/nx-api/gradle/executors/gradle": { - "description": "The Gradlew executor is used to run Gradle tasks.", + "description": "Runs gradle tasks via the Gradle Tooling API or by invoking gradlew.", "file": "generated/packages/gradle/executors/gradle.json", "hidden": false, "name": "gradle", @@ -2135,6 +2135,16 @@ } }, "migrations": { + "/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", + "hidden": false, + "name": "change-ciTargetName-to-ciTestTargetName", + "version": "21.0.0-beta.13", + "originalFilePath": "/packages/gradle", + "path": "/nx-api/gradle/migrations/change-ciTargetName-to-ciTestTargetName", + "type": "migration" + }, "/nx-api/gradle/migrations/change-plugin-to-v1": { "description": "Change @nx/gradle plugin to version 1", "file": "generated/packages/gradle/migrations/change-plugin-to-v1.json", diff --git a/docs/generated/packages-metadata.json b/docs/generated/packages-metadata.json index 095953a7a2..4bbaa0e7f3 100644 --- a/docs/generated/packages-metadata.json +++ b/docs/generated/packages-metadata.json @@ -2089,7 +2089,7 @@ ], "executors": [ { - "description": "The Gradlew executor is used to run Gradle tasks.", + "description": "Runs gradle tasks via the Gradle Tooling API or by invoking gradlew.", "file": "generated/packages/gradle/executors/gradle.json", "hidden": false, "name": "gradle", @@ -2119,6 +2119,16 @@ } ], "migrations": [ + { + "description": "Change @nx/gradle option from ciTargetName to ciTestTargetName", + "file": "generated/packages/gradle/migrations/change-ciTargetName-to-ciTestTargetName.json", + "hidden": false, + "name": "change-ciTargetName-to-ciTestTargetName", + "version": "21.0.0-beta.13", + "originalFilePath": "/packages/gradle", + "path": "gradle/migrations/change-ciTargetName-to-ciTestTargetName", + "type": "migration" + }, { "description": "Change @nx/gradle plugin to version 1", "file": "generated/packages/gradle/migrations/change-plugin-to-v1.json", diff --git a/docs/generated/packages/gradle/executors/gradle.json b/docs/generated/packages/gradle/executors/gradle.json index 9464088f27..05df55053e 100644 --- a/docs/generated/packages/gradle/executors/gradle.json +++ b/docs/generated/packages/gradle/executors/gradle.json @@ -29,7 +29,7 @@ "required": ["taskName"], "presets": [] }, - "description": "The Gradlew executor is used to run Gradle tasks.", + "description": "Runs gradle tasks via the Gradle Tooling API or by invoking gradlew.", "aliases": [], "hidden": false, "path": "/packages/gradle/src/executors/gradle/schema.json", diff --git a/docs/generated/packages/gradle/migrations/change-ciTargetName-to-ciTestTargetName.json b/docs/generated/packages/gradle/migrations/change-ciTargetName-to-ciTestTargetName.json new file mode 100644 index 0000000000..c8be3a7604 --- /dev/null +++ b/docs/generated/packages/gradle/migrations/change-ciTargetName-to-ciTestTargetName.json @@ -0,0 +1,14 @@ +{ + "name": "change-ciTargetName-to-ciTestTargetName", + "version": "21.0.0-beta.13", + "cli": "nx", + "description": "Change @nx/gradle option from ciTargetName to ciTestTargetName", + "factory": "./src/migrations/21-0-0/change-ciTargetName-to-ciTestTargetName", + "implementation": "/packages/gradle/src/migrations/21-0-0/change-ciTargetName-to-ciTestTargetName.ts", + "aliases": [], + "hidden": false, + "path": "/packages/gradle", + "schema": null, + "type": "migration", + "examplesFile": "#### Change @nx/gradle plugin option ciTargetName to ciTestTargetName\n\nChange @nx/gradle plugin option ciTargetName to ciTestTargetName in nx.json\n\n#### Sample Code Changes\n\n{% tabs %}\n{% tab label=\"Before\" %}\n\n```json {% fileName=\"nx.json\" %}\n{\n \"plugins\": [\n \"plugin\": \"@nx/gradle\",\n \"options\": {\n \"ciTargetName\": \"ci\"\n }\n ]\n}\n```\n\n{% /tab %}\n{% tab label=\"After\" %}\n\n```json {% highlightLines=[5] fileName=\"nx.json\" %}\n{\n \"plugins\": [\n \"plugin\": \"@nx/gradle\",\n \"options\": {\n \"ciTestTargetName\": \"ci\"\n }\n ]\n}\n```\n\n{% /tab %}\n{% /tabs %}\n" +} diff --git a/e2e/gradle/src/gradle.test.ts b/e2e/gradle/src/gradle.test.ts index e11a2fc37f..688f82a1c6 100644 --- a/e2e/gradle/src/gradle.test.ts +++ b/e2e/gradle/src/gradle.test.ts @@ -30,7 +30,7 @@ describe('Gradle', () => { expect(projects).toContain('utilities'); expect(projects).toContain(gradleProjectName); - const buildOutput = runCLI('build app', { verbose: true }); + let buildOutput = runCLI('build app', { verbose: true }); expect(buildOutput).toContain(':list:classes'); expect(buildOutput).toContain(':utilities:classes'); @@ -39,6 +39,10 @@ describe('Gradle', () => { `list/build/libs/list.jar`, `utilities/build/libs/utilities.jar` ); + + buildOutput = runCLI('build app --batch', { verbose: true }); + expect(buildOutput).toContain(':list:classes'); + expect(buildOutput).toContain(':utilities:classes'); }); xit('should track dependencies for new app', () => { @@ -86,6 +90,11 @@ dependencies { expect(buildOutput).toContain(':utilities:classes'); checkFilesExist(`app2/build/libs/app2.jar`); + + buildOutput = runCLI('build app2 --batch', { verbose: true }); + expect(buildOutput).toContain(':app:classes'); + expect(buildOutput).toContain(':list:classes'); + expect(buildOutput).toContain(':utilities:classes'); }); it('should run atomized test target', () => { diff --git a/packages/gradle/executors.json b/packages/gradle/executors.json index 23af203201..d27986aa3e 100644 --- a/packages/gradle/executors.json +++ b/packages/gradle/executors.json @@ -4,7 +4,7 @@ "batchImplementation": "./src/executors/gradle/gradle-batch.impl", "implementation": "./src/executors/gradle/gradle.impl", "schema": "./src/executors/gradle/schema.json", - "description": "The Gradlew executor is used to run Gradle tasks." + "description": "Runs gradle tasks via the Gradle Tooling API or by invoking gradlew." } } } diff --git a/packages/gradle/migrations.json b/packages/gradle/migrations.json index 5088bd5347..a6f4a99f7f 100644 --- a/packages/gradle/migrations.json +++ b/packages/gradle/migrations.json @@ -23,6 +23,12 @@ "cli": "nx", "description": "Change @nx/gradle plugin to version 1", "factory": "./src/migrations/21-0-0/change-plugin-to-v1" + }, + "change-ciTargetName-to-ciTestTargetName": { + "version": "21.0.0-beta.13", + "cli": "nx", + "description": "Change @nx/gradle option from ciTargetName to ciTestTargetName", + "factory": "./src/migrations/21-0-0/change-ciTargetName-to-ciTestTargetName" } }, "packageJsonUpdates": {} diff --git a/packages/gradle/src/executors/gradle/gradle-batch.impl.ts b/packages/gradle/src/executors/gradle/gradle-batch.impl.ts index 5995b65359..f247a533a5 100644 --- a/packages/gradle/src/executors/gradle/gradle-batch.impl.ts +++ b/packages/gradle/src/executors/gradle/gradle-batch.impl.ts @@ -1,4 +1,4 @@ -import { ExecutorContext, output, TaskGraph } from '@nx/devkit'; +import { ExecutorContext, output, TaskGraph, workspaceRoot } from '@nx/devkit'; import { LARGE_BUFFER, RunCommandsOptions, @@ -8,6 +8,10 @@ import { gradleExecutorSchema } from './schema'; import { findGradlewFile } from '../../utils/exec-gradle'; import { dirname, join } from 'path'; import { execSync } from 'child_process'; +import { + createPseudoTerminal, + PseudoTerminal, +} from 'nx/src/tasks-runner/pseudo-terminal'; export const batchRunnerPath = join( __dirname, @@ -56,20 +60,42 @@ export default async function gradleBatch( return gradlewTasksToRun; }, {}); const gradlewBatchStart = performance.mark(`gradlew-batch:start`); - const batchResults = execSync( - `java -jar ${batchRunnerPath} --tasks='${JSON.stringify( - gradlewTasksToRun - )}' --workspaceRoot=${root} --args='${args - .join(' ') - .replaceAll("'", '"')}' ${ - process.env.NX_VERBOSE_LOGGING === 'true' ? '' : '--quiet' - }`, - { + + const usePseudoTerminal = + process.env.NX_NATIVE_COMMAND_RUNNER !== 'false' && + PseudoTerminal.isSupported(); + const command = `java -jar ${batchRunnerPath} --tasks='${JSON.stringify( + gradlewTasksToRun + )}' --workspaceRoot=${root} --args='${args + .join(' ') + .replaceAll("'", '"')}' ${ + process.env.NX_VERBOSE_LOGGING === 'true' ? '' : '--quiet' + }`; + let batchResults; + if (usePseudoTerminal) { + const terminal = createPseudoTerminal(); + await terminal.init(); + + const cp = terminal.runCommand(command, { + cwd: workspaceRoot, + jsEnv: process.env, + quiet: process.env.NX_VERBOSE_LOGGING !== 'true', + }); + const results = await cp.getResults(); + batchResults = results.terminalOutput; + + batchResults = batchResults.replace(command, ''); + const startIndex = batchResults.indexOf('{'); + const endIndex = batchResults.lastIndexOf('}'); + batchResults = batchResults.substring(startIndex, endIndex + 1); + } else { + batchResults = execSync(command, { + cwd: workspaceRoot, windowsHide: true, env: process.env, maxBuffer: LARGE_BUFFER, - } - ); + }).toString(); + } const gradlewBatchEnd = performance.mark(`gradlew-batch:end`); performance.measure( `gradlew-batch`, diff --git a/packages/gradle/src/migrations/21-0-0/change-ciTargetName-to-ciTestTargetName.md b/packages/gradle/src/migrations/21-0-0/change-ciTargetName-to-ciTestTargetName.md new file mode 100644 index 0000000000..f744f0f2bd --- /dev/null +++ b/packages/gradle/src/migrations/21-0-0/change-ciTargetName-to-ciTestTargetName.md @@ -0,0 +1,36 @@ +#### Change @nx/gradle plugin option ciTargetName to ciTestTargetName + +Change @nx/gradle plugin option ciTargetName to ciTestTargetName in nx.json + +#### Sample Code Changes + +{% tabs %} +{% tab label="Before" %} + +```json {% fileName="nx.json" %} +{ + "plugins": [ + "plugin": "@nx/gradle", + "options": { + "ciTargetName": "ci" + } + ] +} +``` + +{% /tab %} +{% tab label="After" %} + +```json {% highlightLines=[5] fileName="nx.json" %} +{ + "plugins": [ + "plugin": "@nx/gradle", + "options": { + "ciTestTargetName": "ci" + } + ] +} +``` + +{% /tab %} +{% /tabs %} diff --git a/packages/gradle/src/migrations/21-0-0/change-ciTargetName-to-ciTestTargetName.spec.ts b/packages/gradle/src/migrations/21-0-0/change-ciTargetName-to-ciTestTargetName.spec.ts new file mode 100644 index 0000000000..bfe055975a --- /dev/null +++ b/packages/gradle/src/migrations/21-0-0/change-ciTargetName-to-ciTestTargetName.spec.ts @@ -0,0 +1,94 @@ +import { Tree, readNxJson } from '@nx/devkit'; +import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing'; +import update from './change-ciTargetName-to-ciTestTargetName'; + +describe('change ciTargetName to ciTestTargetName', () => { + let tree: Tree; + + beforeAll(() => { + tree = createTreeWithEmptyWorkspace(); + }); + + it('should not add @nx/gradle plugin if it does not exist', async () => { + tree.write('nx.json', JSON.stringify({ namedInputs: {} })); + update(tree); + expect(readNxJson(tree)).toMatchInlineSnapshot(` + { + "namedInputs": {}, + } + `); + }); + + it('should not add options to @nx/gradle if it have any options', async () => { + tree.write('nx.json', JSON.stringify({ plugins: ['@nx/gradle'] })); + update(tree); + expect(readNxJson(tree)).toMatchInlineSnapshot(` + { + "plugins": [ + "@nx/gradle", + ], + } + `); + }); + + it('should not add options to @nx/gradle/plugin-v1', async () => { + tree.write( + 'nx.json', + JSON.stringify({ plugins: ['@nx/gradle/plugin-v1'] }) + ); + update(tree); + expect(readNxJson(tree)).toMatchInlineSnapshot(` + { + "plugins": [ + "@nx/gradle/plugin-v1", + ], + } + `); + }); + + it('should not change to @nx/gradle plugin if ciTargetName does not exist', async () => { + tree.write( + 'nx.json', + JSON.stringify({ + plugins: [ + { plugin: '@nx/gradle', options: { testTargetName: 'test' } }, + ], + }) + ); + update(tree); + expect(readNxJson(tree)).toMatchInlineSnapshot(` + { + "plugins": [ + { + "options": { + "testTargetName": "test", + }, + "plugin": "@nx/gradle", + }, + ], + } + `); + }); + + it('should change to @nx/gradle plugin ciTargetName', async () => { + tree.write( + 'nx.json', + JSON.stringify({ + plugins: [{ plugin: '@nx/gradle', options: { ciTargetName: 'test' } }], + }) + ); + update(tree); + expect(readNxJson(tree)).toMatchInlineSnapshot(` + { + "plugins": [ + { + "options": { + "ciTestTargetName": "test", + }, + "plugin": "@nx/gradle", + }, + ], + } + `); + }); +}); diff --git a/packages/gradle/src/migrations/21-0-0/change-ciTargetName-to-ciTestTargetName.ts b/packages/gradle/src/migrations/21-0-0/change-ciTargetName-to-ciTestTargetName.ts new file mode 100644 index 0000000000..a94f6250d1 --- /dev/null +++ b/packages/gradle/src/migrations/21-0-0/change-ciTargetName-to-ciTestTargetName.ts @@ -0,0 +1,32 @@ +import { Tree, readNxJson, updateNxJson } from '@nx/devkit'; +import { hasGradlePlugin } from '../../utils/has-gradle-plugin'; + +/* This function changes the @nx/gradle plugin option from ciTargetName to ciTestTargetName + */ +export default function update(tree: Tree) { + const nxJson = readNxJson(tree); + if (!nxJson) { + return; + } + if (!hasGradlePlugin(tree)) { + return; + } + let gradlePluginIndex = nxJson.plugins.findIndex((p) => + typeof p === 'string' ? p === '@nx/gradle' : p.plugin === '@nx/gradle' + ); + let gradlePlugin = nxJson.plugins[gradlePluginIndex]; + if ( + typeof gradlePlugin === 'object' && + gradlePlugin.plugin === '@nx/gradle' + ) { + const ciTargetName = (gradlePlugin.options as Record)?.[ + 'ciTargetName' + ]; + if (ciTargetName) { + delete (gradlePlugin.options as Record)?.['ciTargetName']; + (gradlePlugin.options as Record)['ciTestTargetName'] = + ciTargetName; + } + } + updateNxJson(tree, nxJson); +} diff --git a/packages/gradle/src/migrations/21-0-0/change-plugin-to-v1.spec.ts b/packages/gradle/src/migrations/21-0-0/change-plugin-to-v1.spec.ts index ebb455143d..12d5b6de79 100644 --- a/packages/gradle/src/migrations/21-0-0/change-plugin-to-v1.spec.ts +++ b/packages/gradle/src/migrations/21-0-0/change-plugin-to-v1.spec.ts @@ -31,7 +31,7 @@ describe('ChangePluginToV1', () => { `); }); - it('should add change to @nx/gradle plugin with options', async () => { + it('should change @nx/gradle plugin name with options', async () => { tree.write( 'nx.json', JSON.stringify({ diff --git a/packages/gradle/src/plugin/dependencies.ts b/packages/gradle/src/plugin/dependencies.ts index 9fb42992d7..fd9f2d4262 100644 --- a/packages/gradle/src/plugin/dependencies.ts +++ b/packages/gradle/src/plugin/dependencies.ts @@ -17,6 +17,7 @@ import { import { GradlePluginOptions } from './utils/gradle-plugin-options'; import { GRALDEW_FILES, splitConfigFiles } from '../utils/split-config-files'; import { globWithWorkspaceContext } from 'nx/src/utils/workspace-context'; +import { existsSync } from 'node:fs'; export const createDependencies: CreateDependencies< GradlePluginOptions @@ -52,7 +53,11 @@ export const createDependencies: CreateDependencies< Object.values(context.projects).find( (project) => target === project.root )?.name ?? dependencyFromPlugin.target; - if (!sourceProjectName || !targetProjectName) { + if ( + !sourceProjectName || + !targetProjectName || + !existsSync(dependencyFromPlugin.sourceFile) + ) { return; } const dependency: StaticDependency = {