feat(core): able to import gradle project (#27645)
<!-- 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 --> ## Expected Behavior <!-- This is the behavior we should expect with the changes in this PR --> ## Related Issue(s) <!-- Please link the issue being fixed so it gets closed when this is merged. --> Fixes #
This commit is contained in:
parent
5bbaffbda8
commit
61b3503619
175
e2e/gradle/src/gradle-import.test.ts
Normal file
175
e2e/gradle/src/gradle-import.test.ts
Normal file
@ -0,0 +1,175 @@
|
|||||||
|
import {
|
||||||
|
checkFilesExist,
|
||||||
|
cleanupProject,
|
||||||
|
getSelectedPackageManager,
|
||||||
|
newProject,
|
||||||
|
runCLI,
|
||||||
|
updateJson,
|
||||||
|
updateFile,
|
||||||
|
e2eCwd,
|
||||||
|
readJson,
|
||||||
|
} from '@nx/e2e/utils';
|
||||||
|
import { mkdirSync, rmdirSync, writeFileSync } from 'fs';
|
||||||
|
import { execSync } from 'node:child_process';
|
||||||
|
import { join } from 'path';
|
||||||
|
import { createGradleProject } from './utils/create-gradle-project';
|
||||||
|
import { createFileSync } from 'fs-extra';
|
||||||
|
|
||||||
|
describe('Nx Import Gradle', () => {
|
||||||
|
let proj: string;
|
||||||
|
const tempImportE2ERoot = join(e2eCwd, 'nx-import');
|
||||||
|
beforeAll(() => {
|
||||||
|
proj = newProject({
|
||||||
|
packages: ['@nx/js'],
|
||||||
|
unsetProjectNameAndRootFormat: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (getSelectedPackageManager() === 'pnpm') {
|
||||||
|
updateFile(
|
||||||
|
'pnpm-workspace.yaml',
|
||||||
|
`packages:
|
||||||
|
- 'projects/*'
|
||||||
|
`
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
updateJson('package.json', (json) => {
|
||||||
|
json.workspaces = ['projects/*'];
|
||||||
|
return json;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
rmdirSync(tempImportE2ERoot);
|
||||||
|
} catch {}
|
||||||
|
mkdirSync(tempImportE2ERoot, { recursive: true });
|
||||||
|
});
|
||||||
|
afterAll(() => cleanupProject());
|
||||||
|
|
||||||
|
it('should be able to import a kotlin gradle app', () => {
|
||||||
|
const tempGradleProjectName = 'created-gradle-app-kotlin';
|
||||||
|
const tempGraldeProjectPath = join(
|
||||||
|
tempImportE2ERoot,
|
||||||
|
tempGradleProjectName
|
||||||
|
);
|
||||||
|
try {
|
||||||
|
rmdirSync(tempGraldeProjectPath);
|
||||||
|
} catch {}
|
||||||
|
mkdirSync(tempGraldeProjectPath, { recursive: true });
|
||||||
|
createGradleProject(
|
||||||
|
tempGradleProjectName,
|
||||||
|
'kotlin',
|
||||||
|
tempGraldeProjectPath,
|
||||||
|
'gradleProjectKotlin',
|
||||||
|
'kotlin-'
|
||||||
|
);
|
||||||
|
// Add project.json files to the gradle project to avoid duplicate project names
|
||||||
|
createFileSync(join(tempGraldeProjectPath, 'project.json'));
|
||||||
|
writeFileSync(
|
||||||
|
join(tempGraldeProjectPath, 'project.json'),
|
||||||
|
`{"name": "${tempGradleProjectName}"}`
|
||||||
|
);
|
||||||
|
|
||||||
|
execSync(`git init`, {
|
||||||
|
cwd: tempGraldeProjectPath,
|
||||||
|
});
|
||||||
|
execSync(`git add .`, {
|
||||||
|
cwd: tempGraldeProjectPath,
|
||||||
|
});
|
||||||
|
execSync(`git commit -am "initial commit"`, {
|
||||||
|
cwd: tempGraldeProjectPath,
|
||||||
|
});
|
||||||
|
execSync(`git checkout -b main`, {
|
||||||
|
cwd: tempGraldeProjectPath,
|
||||||
|
});
|
||||||
|
|
||||||
|
const remote = tempGraldeProjectPath;
|
||||||
|
const ref = 'main';
|
||||||
|
const source = '.';
|
||||||
|
const directory = 'projects/gradle-app-kotlin';
|
||||||
|
|
||||||
|
runCLI(
|
||||||
|
`import ${remote} ${directory} --ref ${ref} --source ${source} --no-interactive`,
|
||||||
|
{
|
||||||
|
verbose: true,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
checkFilesExist(
|
||||||
|
`${directory}/settings.gradle.kts`,
|
||||||
|
`${directory}/build.gradle.kts`,
|
||||||
|
`${directory}/gradlew`,
|
||||||
|
`${directory}/gradlew.bat`
|
||||||
|
);
|
||||||
|
const nxJson = readJson('nx.json');
|
||||||
|
const gradlePlugin = nxJson.plugins.find(
|
||||||
|
(plugin) => plugin.plugin === '@nx/gradle'
|
||||||
|
);
|
||||||
|
expect(gradlePlugin).toBeDefined();
|
||||||
|
expect(() => {
|
||||||
|
runCLI(`show projects`);
|
||||||
|
runCLI('build kotlin-app');
|
||||||
|
}).not.toThrow();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be able to import a groovy gradle app', () => {
|
||||||
|
const tempGradleProjectName = 'created-gradle-app-groovy';
|
||||||
|
const tempGraldeProjectPath = join(
|
||||||
|
tempImportE2ERoot,
|
||||||
|
tempGradleProjectName
|
||||||
|
);
|
||||||
|
try {
|
||||||
|
rmdirSync(tempGraldeProjectPath);
|
||||||
|
} catch {}
|
||||||
|
mkdirSync(tempGraldeProjectPath, { recursive: true });
|
||||||
|
createGradleProject(
|
||||||
|
tempGradleProjectName,
|
||||||
|
'groovy',
|
||||||
|
tempGraldeProjectPath,
|
||||||
|
'gradleProjectGroovy',
|
||||||
|
'groovy-'
|
||||||
|
);
|
||||||
|
// Add project.json files to the gradle project to avoid duplicate project names
|
||||||
|
createFileSync(join(tempGraldeProjectPath, 'project.json'));
|
||||||
|
writeFileSync(
|
||||||
|
join(tempGraldeProjectPath, 'project.json'),
|
||||||
|
`{"name": "${tempGradleProjectName}"}`
|
||||||
|
);
|
||||||
|
|
||||||
|
execSync(`git init`, {
|
||||||
|
cwd: tempGraldeProjectPath,
|
||||||
|
});
|
||||||
|
execSync(`git add .`, {
|
||||||
|
cwd: tempGraldeProjectPath,
|
||||||
|
});
|
||||||
|
execSync(`git commit -am "initial commit"`, {
|
||||||
|
cwd: tempGraldeProjectPath,
|
||||||
|
});
|
||||||
|
execSync(`git checkout -b main`, {
|
||||||
|
cwd: tempGraldeProjectPath,
|
||||||
|
});
|
||||||
|
|
||||||
|
const remote = tempGraldeProjectPath;
|
||||||
|
const ref = 'main';
|
||||||
|
const source = '.';
|
||||||
|
const directory = 'projects/gradle-app-groovy';
|
||||||
|
|
||||||
|
runCLI(
|
||||||
|
`import ${remote} ${directory} --ref ${ref} --source ${source} --no-interactive`,
|
||||||
|
{
|
||||||
|
verbose: true,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
runCLI(`g @nx/gradle:init --no-interactive`);
|
||||||
|
|
||||||
|
checkFilesExist(
|
||||||
|
`${directory}/build.gradle`,
|
||||||
|
`${directory}/settings.gradle`,
|
||||||
|
`${directory}/gradlew`,
|
||||||
|
`${directory}/gradlew.bat`
|
||||||
|
);
|
||||||
|
expect(() => {
|
||||||
|
runCLI(`show projects`);
|
||||||
|
runCLI('build groovy-app');
|
||||||
|
}).not.toThrow();
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -2,17 +2,13 @@ import {
|
|||||||
checkFilesExist,
|
checkFilesExist,
|
||||||
cleanupProject,
|
cleanupProject,
|
||||||
createFile,
|
createFile,
|
||||||
e2eConsoleLogger,
|
|
||||||
isWindows,
|
|
||||||
newProject,
|
newProject,
|
||||||
runCLI,
|
runCLI,
|
||||||
runCommand,
|
|
||||||
tmpProjPath,
|
|
||||||
uniq,
|
uniq,
|
||||||
updateFile,
|
updateFile,
|
||||||
} from '@nx/e2e/utils';
|
} from '@nx/e2e/utils';
|
||||||
import { execSync } from 'child_process';
|
|
||||||
import { resolve } from 'path';
|
import { createGradleProject } from './utils/create-gradle-project';
|
||||||
|
|
||||||
describe('Gradle', () => {
|
describe('Gradle', () => {
|
||||||
describe.each([{ type: 'kotlin' }, { type: 'groovy' }])(
|
describe.each([{ type: 'kotlin' }, { type: 'groovy' }])(
|
||||||
@ -22,6 +18,7 @@ describe('Gradle', () => {
|
|||||||
beforeAll(() => {
|
beforeAll(() => {
|
||||||
newProject();
|
newProject();
|
||||||
createGradleProject(gradleProjectName, type);
|
createGradleProject(gradleProjectName, type);
|
||||||
|
runCLI(`add @nx/gradle`);
|
||||||
});
|
});
|
||||||
afterAll(() => cleanupProject());
|
afterAll(() => cleanupProject());
|
||||||
|
|
||||||
@ -101,33 +98,3 @@ dependencies {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
function createGradleProject(
|
|
||||||
projectName: string,
|
|
||||||
type: 'kotlin' | 'groovy' = 'kotlin'
|
|
||||||
) {
|
|
||||||
e2eConsoleLogger(`Using java version: ${execSync('java -version')}`);
|
|
||||||
const gradleCommand = isWindows()
|
|
||||||
? resolve(`${__dirname}/../gradlew.bat`)
|
|
||||||
: resolve(`${__dirname}/../gradlew`);
|
|
||||||
e2eConsoleLogger(
|
|
||||||
'Using gradle version: ' +
|
|
||||||
execSync(`${gradleCommand} --version`, {
|
|
||||||
cwd: tmpProjPath(),
|
|
||||||
})
|
|
||||||
);
|
|
||||||
e2eConsoleLogger(
|
|
||||||
execSync(`${gradleCommand} help --task :init`, {
|
|
||||||
cwd: tmpProjPath(),
|
|
||||||
}).toString()
|
|
||||||
);
|
|
||||||
e2eConsoleLogger(
|
|
||||||
runCommand(
|
|
||||||
`${gradleCommand} init --type ${type}-application --dsl ${type} --project-name ${projectName} --package gradleProject --no-incubating --split-project`,
|
|
||||||
{
|
|
||||||
cwd: tmpProjPath(),
|
|
||||||
}
|
|
||||||
)
|
|
||||||
);
|
|
||||||
runCLI(`add @nx/gradle`);
|
|
||||||
}
|
|
||||||
|
|||||||
59
e2e/gradle/src/utils/create-gradle-project.ts
Normal file
59
e2e/gradle/src/utils/create-gradle-project.ts
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
import {
|
||||||
|
e2eConsoleLogger,
|
||||||
|
isWindows,
|
||||||
|
runCommand,
|
||||||
|
tmpProjPath,
|
||||||
|
} from '@nx/e2e/utils';
|
||||||
|
import { execSync } from 'child_process';
|
||||||
|
import { createFileSync, writeFileSync } from 'fs-extra';
|
||||||
|
import { join, resolve } from 'path';
|
||||||
|
|
||||||
|
export function createGradleProject(
|
||||||
|
projectName: string,
|
||||||
|
type: 'kotlin' | 'groovy' = 'kotlin',
|
||||||
|
cwd: string = tmpProjPath(),
|
||||||
|
packageName: string = 'gradleProject',
|
||||||
|
addProjectJsonNamePrefix: string = ''
|
||||||
|
) {
|
||||||
|
e2eConsoleLogger(`Using java version: ${execSync('java -version')}`);
|
||||||
|
const gradleCommand = isWindows()
|
||||||
|
? resolve(`${__dirname}/../../gradlew.bat`)
|
||||||
|
: resolve(`${__dirname}/../../gradlew`);
|
||||||
|
e2eConsoleLogger(
|
||||||
|
'Using gradle version: ' +
|
||||||
|
execSync(`${gradleCommand} --version`, {
|
||||||
|
cwd,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
e2eConsoleLogger(
|
||||||
|
execSync(`${gradleCommand} help --task :init`, {
|
||||||
|
cwd,
|
||||||
|
}).toString()
|
||||||
|
);
|
||||||
|
e2eConsoleLogger(
|
||||||
|
runCommand(
|
||||||
|
`${gradleCommand} init --type ${type}-application --dsl ${type} --project-name ${projectName} --package ${packageName} --no-incubating --split-project`,
|
||||||
|
{
|
||||||
|
cwd,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (addProjectJsonNamePrefix) {
|
||||||
|
createFileSync(join(cwd, 'app/project.json'));
|
||||||
|
writeFileSync(
|
||||||
|
join(cwd, 'app/project.json'),
|
||||||
|
`{"name": "${addProjectJsonNamePrefix}app"}`
|
||||||
|
);
|
||||||
|
createFileSync(join(cwd, 'list/project.json'));
|
||||||
|
writeFileSync(
|
||||||
|
join(cwd, 'list/project.json'),
|
||||||
|
`{"name": "${addProjectJsonNamePrefix}list"}`
|
||||||
|
);
|
||||||
|
createFileSync(join(cwd, 'utilities/project.json'));
|
||||||
|
writeFileSync(
|
||||||
|
join(cwd, 'utilities/project.json'),
|
||||||
|
`{"name": "${addProjectJsonNamePrefix}utilities"}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "e2e-nx",
|
"name": "e2e-nx",
|
||||||
"$schema": "../../node_modules/nx/schemas/project-schema.json",
|
"$schema": "../../node_modules/nx/schemas/project-schema.json",
|
||||||
"sourceRoot": "e2e/nx-misc",
|
"sourceRoot": "e2e/nx",
|
||||||
"projectType": "application",
|
"projectType": "application",
|
||||||
"implicitDependencies": ["nx", "js"],
|
"implicitDependencies": ["nx", "js"],
|
||||||
"// targets": "to see all targets run: nx show project e2e-nx --web",
|
"// targets": "to see all targets run: nx show project e2e-nx --web",
|
||||||
|
|||||||
@ -9,7 +9,6 @@ import {
|
|||||||
Tree,
|
Tree,
|
||||||
updateNxJson,
|
updateNxJson,
|
||||||
} from '@nx/devkit';
|
} from '@nx/devkit';
|
||||||
import { execSync } from 'child_process';
|
|
||||||
import { nxVersion } from '../../utils/versions';
|
import { 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';
|
||||||
@ -18,13 +17,6 @@ import { dirname, join, basename } from 'path';
|
|||||||
export async function initGenerator(tree: Tree, options: InitGeneratorSchema) {
|
export async function initGenerator(tree: Tree, options: InitGeneratorSchema) {
|
||||||
const tasks: GeneratorCallback[] = [];
|
const tasks: GeneratorCallback[] = [];
|
||||||
|
|
||||||
if (!tree.exists('settings.gradle') && !tree.exists('settings.gradle.kts')) {
|
|
||||||
logger.warn(`Could not find 'settings.gradle' or 'settings.gradle.kts' file in your gradle workspace.
|
|
||||||
A Gradle build should contain a 'settings.gradle' or 'settings.gradle.kts' file in its root directory. It may also contain a 'build.gradle' or 'build.gradle.kts' file.
|
|
||||||
Running 'gradle init':`);
|
|
||||||
execSync('gradle init', { stdio: 'inherit' });
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!options.skipPackageJson && tree.exists('package.json')) {
|
if (!options.skipPackageJson && tree.exists('package.json')) {
|
||||||
tasks.push(
|
tasks.push(
|
||||||
addDependenciesToPackageJson(
|
addDependenciesToPackageJson(
|
||||||
|
|||||||
@ -9,11 +9,9 @@ import {
|
|||||||
import { readFileSync } from 'node:fs';
|
import { readFileSync } from 'node:fs';
|
||||||
import { basename, dirname } from 'node:path';
|
import { basename, dirname } from 'node:path';
|
||||||
|
|
||||||
import {
|
import { getCurrentGradleReport } from '../utils/get-gradle-report';
|
||||||
GRADLE_BUILD_FILES,
|
import { GRADLE_BUILD_FILES } from '../utils/split-config-files';
|
||||||
getCurrentGradleReport,
|
import { newLineSeparator } from '../utils/get-project-report-lines';
|
||||||
newLineSeparator,
|
|
||||||
} from '../utils/get-gradle-report';
|
|
||||||
|
|
||||||
export const createDependencies: CreateDependencies = async (
|
export const createDependencies: CreateDependencies = async (
|
||||||
_,
|
_,
|
||||||
|
|||||||
@ -116,6 +116,9 @@ describe('@nx/gradle/plugin', () => {
|
|||||||
"gradle",
|
"gradle",
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
"options": {
|
||||||
|
"cwd": ".",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -200,6 +203,9 @@ describe('@nx/gradle/plugin', () => {
|
|||||||
"gradle",
|
"gradle",
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
"options": {
|
||||||
|
"cwd": ".",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -310,6 +316,9 @@ describe('@nx/gradle/plugin', () => {
|
|||||||
"gradle",
|
"gradle",
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
"options": {
|
||||||
|
"cwd": ".",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
"test-ci": {
|
"test-ci": {
|
||||||
"cache": true,
|
"cache": true,
|
||||||
@ -379,6 +388,9 @@ describe('@nx/gradle/plugin', () => {
|
|||||||
"gradle",
|
"gradle",
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
"options": {
|
||||||
|
"cwd": ".",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
"test-ci--bTest": {
|
"test-ci--bTest": {
|
||||||
"cache": true,
|
"cache": true,
|
||||||
@ -406,6 +418,9 @@ describe('@nx/gradle/plugin', () => {
|
|||||||
"gradle",
|
"gradle",
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
"options": {
|
||||||
|
"cwd": ".",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
"test-ci--cTests": {
|
"test-ci--cTests": {
|
||||||
"cache": true,
|
"cache": true,
|
||||||
@ -433,6 +448,9 @@ describe('@nx/gradle/plugin', () => {
|
|||||||
"gradle",
|
"gradle",
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
"options": {
|
||||||
|
"cwd": ".",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@ -16,16 +16,18 @@ import { basename, dirname, join } from 'node:path';
|
|||||||
import { workspaceDataDirectory } from 'nx/src/utils/cache-directory';
|
import { workspaceDataDirectory } from 'nx/src/utils/cache-directory';
|
||||||
import { findProjectForPath } from 'nx/src/devkit-internals';
|
import { findProjectForPath } from 'nx/src/devkit-internals';
|
||||||
|
|
||||||
import { getGradleExecFile } from '../utils/exec-gradle';
|
|
||||||
import {
|
import {
|
||||||
populateGradleReport,
|
populateGradleReport,
|
||||||
getCurrentGradleReport,
|
getCurrentGradleReport,
|
||||||
GradleReport,
|
GradleReport,
|
||||||
gradleConfigGlob,
|
|
||||||
GRADLE_BUILD_FILES,
|
|
||||||
gradleConfigAndTestGlob,
|
|
||||||
} from '../utils/get-gradle-report';
|
} from '../utils/get-gradle-report';
|
||||||
import { hashObject } from 'nx/src/hasher/file-hasher';
|
import { hashObject } from 'nx/src/hasher/file-hasher';
|
||||||
|
import {
|
||||||
|
gradleConfigAndTestGlob,
|
||||||
|
gradleConfigGlob,
|
||||||
|
splitConfigFiles,
|
||||||
|
} from '../utils/split-config-files';
|
||||||
|
import { getGradleExecFile, findGraldewFile } from '../utils/exec-gradle';
|
||||||
|
|
||||||
const cacheableTaskType = new Set(['Build', 'Verification']);
|
const cacheableTaskType = new Set(['Build', 'Verification']);
|
||||||
const dependsOnMap = {
|
const dependsOnMap = {
|
||||||
@ -76,7 +78,8 @@ export function writeTargetsToCache(cachePath: string, results: GradleTargets) {
|
|||||||
export const createNodesV2: CreateNodesV2<GradlePluginOptions> = [
|
export const createNodesV2: CreateNodesV2<GradlePluginOptions> = [
|
||||||
gradleConfigAndTestGlob,
|
gradleConfigAndTestGlob,
|
||||||
async (files, options, context) => {
|
async (files, options, context) => {
|
||||||
const { configFiles, projectRoots, testFiles } = splitConfigFiles(files);
|
const { buildFiles, projectRoots, gradlewFiles, testFiles } =
|
||||||
|
splitConfigFiles(files);
|
||||||
const optionsHash = hashObject(options);
|
const optionsHash = hashObject(options);
|
||||||
const cachePath = join(
|
const cachePath = join(
|
||||||
workspaceDataDirectory,
|
workspaceDataDirectory,
|
||||||
@ -84,7 +87,10 @@ export const createNodesV2: CreateNodesV2<GradlePluginOptions> = [
|
|||||||
);
|
);
|
||||||
const targetsCache = readTargetsCache(cachePath);
|
const targetsCache = readTargetsCache(cachePath);
|
||||||
|
|
||||||
await populateGradleReport(context.workspaceRoot);
|
await populateGradleReport(
|
||||||
|
context.workspaceRoot,
|
||||||
|
gradlewFiles.map((f) => join(context.workspaceRoot, f))
|
||||||
|
);
|
||||||
const gradleReport = getCurrentGradleReport();
|
const gradleReport = getCurrentGradleReport();
|
||||||
const gradleProjectRootToTestFilesMap = getGradleProjectRootToTestFilesMap(
|
const gradleProjectRootToTestFilesMap = getGradleProjectRootToTestFilesMap(
|
||||||
testFiles,
|
testFiles,
|
||||||
@ -98,7 +104,7 @@ export const createNodesV2: CreateNodesV2<GradlePluginOptions> = [
|
|||||||
targetsCache,
|
targetsCache,
|
||||||
gradleProjectRootToTestFilesMap
|
gradleProjectRootToTestFilesMap
|
||||||
),
|
),
|
||||||
configFiles,
|
buildFiles,
|
||||||
options,
|
options,
|
||||||
context
|
context
|
||||||
);
|
);
|
||||||
@ -151,15 +157,16 @@ export const makeCreateNodesForGradleConfigFile =
|
|||||||
*/
|
*/
|
||||||
export const createNodes: CreateNodes<GradlePluginOptions> = [
|
export const createNodes: CreateNodes<GradlePluginOptions> = [
|
||||||
gradleConfigGlob,
|
gradleConfigGlob,
|
||||||
async (configFile, options, context) => {
|
async (buildFile, options, context) => {
|
||||||
logger.warn(
|
logger.warn(
|
||||||
'`createNodes` is deprecated. Update your plugin to utilize createNodesV2 instead. In Nx 20, this will change to the createNodesV2 API.'
|
'`createNodes` is deprecated. Update your plugin to utilize createNodesV2 instead. In Nx 20, this will change to the createNodesV2 API.'
|
||||||
);
|
);
|
||||||
await populateGradleReport(context.workspaceRoot);
|
const { gradlewFiles } = splitConfigFiles(context.configFiles);
|
||||||
|
await populateGradleReport(context.workspaceRoot, gradlewFiles);
|
||||||
const gradleReport = getCurrentGradleReport();
|
const gradleReport = getCurrentGradleReport();
|
||||||
const internalCreateNodes =
|
const internalCreateNodes =
|
||||||
makeCreateNodesForGradleConfigFile(gradleReport);
|
makeCreateNodesForGradleConfigFile(gradleReport);
|
||||||
return await internalCreateNodes(configFile, options, context);
|
return await internalCreateNodes(buildFile, options, context);
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
@ -234,13 +241,16 @@ async function createGradleTargets(
|
|||||||
context: CreateNodesContext,
|
context: CreateNodesContext,
|
||||||
outputDirs: Map<string, string>,
|
outputDirs: Map<string, string>,
|
||||||
gradleProject: string,
|
gradleProject: string,
|
||||||
gradleFilePath: string,
|
gradleBuildFilePath: string,
|
||||||
testFiles: string[] = []
|
testFiles: string[] = []
|
||||||
): Promise<{
|
): Promise<{
|
||||||
targetGroups: Record<string, string[]>;
|
targetGroups: Record<string, string[]>;
|
||||||
targets: Record<string, TargetConfiguration>;
|
targets: Record<string, TargetConfiguration>;
|
||||||
}> {
|
}> {
|
||||||
const inputsMap = createInputsMap(context);
|
const inputsMap = createInputsMap(context);
|
||||||
|
const gradlewFileDirectory = dirname(
|
||||||
|
findGraldewFile(gradleBuildFilePath, context.workspaceRoot)
|
||||||
|
);
|
||||||
|
|
||||||
const targets: Record<string, TargetConfiguration> = {};
|
const targets: Record<string, TargetConfiguration> = {};
|
||||||
const targetGroups: Record<string, string[]> = {};
|
const targetGroups: Record<string, string[]> = {};
|
||||||
@ -262,15 +272,20 @@ async function createGradleTargets(
|
|||||||
outputs,
|
outputs,
|
||||||
task.type,
|
task.type,
|
||||||
targets,
|
targets,
|
||||||
targetGroups
|
targetGroups,
|
||||||
|
gradlewFileDirectory
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const taskCommandToRun = `${gradleProject ? gradleProject + ':' : ''}${
|
const taskCommandToRun = `${gradleProject ? gradleProject + ':' : ''}${
|
||||||
task.name
|
task.name
|
||||||
}`;
|
}`;
|
||||||
|
|
||||||
targets[targetName] = {
|
targets[targetName] = {
|
||||||
command: `${getGradleExecFile()} ${taskCommandToRun}`,
|
command: `${getGradleExecFile()} ${taskCommandToRun}`,
|
||||||
|
options: {
|
||||||
|
cwd: gradlewFileDirectory,
|
||||||
|
},
|
||||||
cache: cacheableTaskType.has(task.type),
|
cache: cacheableTaskType.has(task.type),
|
||||||
inputs: inputsMap[task.name],
|
inputs: inputsMap[task.name],
|
||||||
dependsOn: dependsOnMap[task.name],
|
dependsOn: dependsOnMap[task.name],
|
||||||
@ -320,7 +335,8 @@ function getTestCiTargets(
|
|||||||
outputs: string[],
|
outputs: string[],
|
||||||
targetGroupName: string,
|
targetGroupName: string,
|
||||||
targets: Record<string, TargetConfiguration>,
|
targets: Record<string, TargetConfiguration>,
|
||||||
targetGroups: Record<string, string[]>
|
targetGroups: Record<string, string[]>,
|
||||||
|
gradlewFileDirectory: string
|
||||||
): void {
|
): void {
|
||||||
if (!testFiles || testFiles.length === 0 || !ciTargetName) {
|
if (!testFiles || testFiles.length === 0 || !ciTargetName) {
|
||||||
return;
|
return;
|
||||||
@ -338,6 +354,9 @@ function getTestCiTargets(
|
|||||||
|
|
||||||
targets[targetName] = {
|
targets[targetName] = {
|
||||||
command: `${getGradleExecFile()} ${taskCommandToRun} --tests ${testName}`,
|
command: `${getGradleExecFile()} ${taskCommandToRun} --tests ${testName}`,
|
||||||
|
options: {
|
||||||
|
cwd: gradlewFileDirectory,
|
||||||
|
},
|
||||||
cache: true,
|
cache: true,
|
||||||
inputs,
|
inputs,
|
||||||
dependsOn: dependsOnMap['test'],
|
dependsOn: dependsOnMap['test'],
|
||||||
@ -386,26 +405,6 @@ function getTestCiTargets(
|
|||||||
targetGroups[targetGroupName].push(ciTargetName);
|
targetGroups[targetGroupName].push(ciTargetName);
|
||||||
}
|
}
|
||||||
|
|
||||||
function splitConfigFiles(files: readonly string[]): {
|
|
||||||
configFiles: string[];
|
|
||||||
testFiles: string[];
|
|
||||||
projectRoots: string[];
|
|
||||||
} {
|
|
||||||
const configFiles = [];
|
|
||||||
const testFiles = [];
|
|
||||||
const projectRoots = new Set<string>();
|
|
||||||
files.forEach((file) => {
|
|
||||||
if (GRADLE_BUILD_FILES.has(basename(file))) {
|
|
||||||
configFiles.push(file);
|
|
||||||
projectRoots.add(dirname(file));
|
|
||||||
} else {
|
|
||||||
testFiles.push(file);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return { configFiles, testFiles, projectRoots: Array.from(projectRoots) };
|
|
||||||
}
|
|
||||||
|
|
||||||
function getGradleProjectRootToTestFilesMap(
|
function getGradleProjectRootToTestFilesMap(
|
||||||
testFiles: string[],
|
testFiles: string[],
|
||||||
projectRoots: string[]
|
projectRoots: string[]
|
||||||
|
|||||||
@ -0,0 +1,160 @@
|
|||||||
|
|
||||||
|
------------------------------------------------------------
|
||||||
|
Project ':app'
|
||||||
|
------------------------------------------------------------
|
||||||
|
|
||||||
|
allprojects: [project ':app']
|
||||||
|
ant: org.gradle.api.internal.project.DefaultAntBuilder@505598eb
|
||||||
|
antBuilderFactory: org.gradle.api.internal.project.DefaultAntBuilderFactory@259d836f
|
||||||
|
application: extension 'application'
|
||||||
|
applicationDefaultJvmArgs: []
|
||||||
|
applicationDistribution: org.gradle.api.internal.file.copy.DefaultCopySpec_Decorated@3978059a
|
||||||
|
applicationName: app
|
||||||
|
archivesBaseName: app
|
||||||
|
artifacts: org.gradle.api.internal.artifacts.dsl.DefaultArtifactHandler_Decorated@32167ebb
|
||||||
|
asDynamicObject: DynamicObject for project ':app'
|
||||||
|
assemble: task ':app:assemble'
|
||||||
|
assembleDist: task ':app:assembleDist'
|
||||||
|
autoTargetJvmDisabled: false
|
||||||
|
base: extension 'base'
|
||||||
|
baseClassLoaderScope: org.gradle.api.internal.initialization.DefaultClassLoaderScope@3c4c27d8
|
||||||
|
build: task ':app:build'
|
||||||
|
buildDependents: task ':app:buildDependents'
|
||||||
|
buildDir: /private/tmp/nx-e2e/nx/proj9912426/app/build
|
||||||
|
buildEnvironment: task ':app:buildEnvironment'
|
||||||
|
buildFile: /private/tmp/nx-e2e/nx/proj9912426/app/build.gradle
|
||||||
|
buildNeeded: task ':app:buildNeeded'
|
||||||
|
buildPath: :
|
||||||
|
buildScriptSource: org.gradle.groovy.scripts.TextResourceScriptSource@4ef82ad2
|
||||||
|
buildTreePath: :app
|
||||||
|
buildscript: org.gradle.api.internal.initialization.DefaultScriptHandler_Decorated@7b75e99
|
||||||
|
check: task ':app:check'
|
||||||
|
childProjects: {}
|
||||||
|
childProjectsUnchecked: {}
|
||||||
|
class: class org.gradle.api.internal.project.DefaultProject_Decorated
|
||||||
|
classLoaderScope: org.gradle.api.internal.initialization.DefaultClassLoaderScope@7e1acf20
|
||||||
|
classes: task ':app:classes'
|
||||||
|
clean: task ':app:clean'
|
||||||
|
compileGroovy: task ':app:compileGroovy'
|
||||||
|
compileJava: task ':app:compileJava'
|
||||||
|
compileTestGroovy: task ':app:compileTestGroovy'
|
||||||
|
compileTestJava: task ':app:compileTestJava'
|
||||||
|
components: SoftwareComponent container
|
||||||
|
configurationActions: org.gradle.configuration.project.DefaultProjectConfigurationActionContainer@7f7885fe
|
||||||
|
configurationTargetIdentifier: org.gradle.configuration.ConfigurationTargetIdentifier$1@70598e79
|
||||||
|
configurations: configuration container
|
||||||
|
convention: org.gradle.internal.extensibility.DefaultConvention@4d27557d
|
||||||
|
conventionMapping: org.gradle.internal.extensibility.ConventionAwareHelper@65ecf036
|
||||||
|
crossProjectModelAccess: org.gradle.api.internal.project.DefaultCrossProjectModelAccess@7665f252
|
||||||
|
defaultArtifacts: extension 'defaultArtifacts'
|
||||||
|
defaultTasks: []
|
||||||
|
deferredProjectConfiguration: org.gradle.api.internal.project.DeferredProjectConfiguration@5e80ce00
|
||||||
|
dependencies: org.gradle.api.internal.artifacts.dsl.dependencies.DefaultDependencyHandler_Decorated@6216b9ef
|
||||||
|
dependencyFactory: org.gradle.api.internal.artifacts.DefaultDependencyFactory@15ed846d
|
||||||
|
dependencyInsight: task ':app:dependencyInsight'
|
||||||
|
dependencyLocking: org.gradle.internal.locking.DefaultDependencyLockingHandler_Decorated@1702aba6
|
||||||
|
dependencyMetaDataProvider: org.gradle.internal.service.scopes.ProjectScopeServices$ProjectBackedModuleMetaDataProvider@4f2a8788
|
||||||
|
dependencyReport: task ':app:dependencyReport'
|
||||||
|
dependentComponents: task ':app:dependentComponents'
|
||||||
|
depth: 1
|
||||||
|
description: null
|
||||||
|
detachedState: false
|
||||||
|
displayName: project ':app'
|
||||||
|
distTar: task ':app:distTar'
|
||||||
|
distZip: task ':app:distZip'
|
||||||
|
distributions: Distribution container
|
||||||
|
distsDirName: distributions
|
||||||
|
distsDirectory: extension 'base' property 'distsDirectory'
|
||||||
|
docsDir: /private/tmp/nx-e2e/nx/proj9912426/app/build/docs
|
||||||
|
docsDirName: docs
|
||||||
|
executableDir: bin
|
||||||
|
ext: org.gradle.internal.extensibility.DefaultExtraPropertiesExtension@18249643
|
||||||
|
extensions: org.gradle.internal.extensibility.DefaultConvention@4d27557d
|
||||||
|
fileOperations: org.gradle.api.internal.file.DefaultFileOperations@6193a7c6
|
||||||
|
fileResolver: org.gradle.api.internal.file.BaseDirFileResolver@634e7fc9
|
||||||
|
gradle: build 'my-gradle-project5165026'
|
||||||
|
groovyRuntime: extension 'groovyRuntime'
|
||||||
|
groovydoc: task ':app:groovydoc'
|
||||||
|
group: my-gradle-project5165026
|
||||||
|
help: task ':app:help'
|
||||||
|
htmlDependencyReport: task ':app:htmlDependencyReport'
|
||||||
|
identityPath: :app
|
||||||
|
inheritedScope: org.gradle.internal.extensibility.ExtensibleDynamicObject$InheritedDynamicObject@7843a2ef
|
||||||
|
installDist: task ':app:installDist'
|
||||||
|
internalStatus: property(java.lang.Object, fixed(class java.lang.String, integration))
|
||||||
|
jar: task ':app:jar'
|
||||||
|
java: extension 'java'
|
||||||
|
javaToolchains: extension 'javaToolchains'
|
||||||
|
javadoc: task ':app:javadoc'
|
||||||
|
layout: org.gradle.api.internal.file.DefaultProjectLayout@38b897f6
|
||||||
|
libsDirName: libs
|
||||||
|
libsDirectory: extension 'base' property 'libsDirectory'
|
||||||
|
listenerBuildOperationDecorator: org.gradle.configuration.internal.DefaultListenerBuildOperationDecorator@58c7b14b
|
||||||
|
logger: org.gradle.internal.logging.slf4j.OutputEventListenerBackedLogger@2fb55781
|
||||||
|
logging: org.gradle.internal.logging.services.DefaultLoggingManager@2818071f
|
||||||
|
mainClassName: null
|
||||||
|
model: project ':app'
|
||||||
|
modelIdentityDisplayName: null
|
||||||
|
modelRegistry: org.gradle.model.internal.registry.DefaultModelRegistry@4d299c29
|
||||||
|
name: app
|
||||||
|
normalization: org.gradle.normalization.internal.DefaultInputNormalizationHandler_Decorated@4460a043
|
||||||
|
objects: org.gradle.api.internal.model.DefaultObjectFactory@381b881e
|
||||||
|
outgoingVariants: task ':app:outgoingVariants'
|
||||||
|
owner: project ':app'
|
||||||
|
parent: root project 'my-gradle-project5165026'
|
||||||
|
parentIdentifier: root project 'my-gradle-project5165026'
|
||||||
|
path: :app
|
||||||
|
pluginContext: false
|
||||||
|
pluginManager: org.gradle.api.internal.plugins.DefaultPluginManager_Decorated@505350fd
|
||||||
|
plugins: [org.gradle.api.plugins.ReportingBasePlugin$Inject@363d344c, org.gradle.api.plugins.ProjectReportsPlugin$Inject@4ecb0bf4, org.gradle.api.plugins.HelpTasksPlugin$Inject@55c1f1c, org.gradle.buildinit.plugins.BuildInitPlugin$Inject@5154243b, org.gradle.buildinit.plugins.WrapperPlugin$Inject@4186a206, org.gradle.language.base.plugins.LifecycleBasePlugin$Inject@63b97a85, org.gradle.api.plugins.BasePlugin$Inject@46c915ee, org.gradle.api.plugins.JvmEcosystemPlugin$Inject@26901290, org.gradle.api.plugins.JvmToolchainsPlugin$Inject@1047a16b, org.gradle.api.plugins.JavaBasePlugin$Inject@219fc174, org.gradle.api.plugins.GroovyBasePlugin$Inject@cc0c00e, org.gradle.testing.base.plugins.TestSuiteBasePlugin$Inject@afcdb52, org.gradle.api.plugins.JvmTestSuitePlugin$Inject@4f2802e1, org.gradle.api.plugins.JavaPlugin$Inject@457c77b1, org.gradle.api.plugins.GroovyPlugin$Inject@6bea0b65, BuildlogicGroovyCommonConventionsPlugin@340f0f12, org.gradle.api.distribution.plugins.DistributionPlugin$Inject@41c5c0a5, org.gradle.api.plugins.ApplicationPlugin$Inject@4e797fdb, BuildlogicGroovyApplicationConventionsPlugin@502595f2]
|
||||||
|
processOperations: org.gradle.process.internal.DefaultExecActionFactory$DecoratingExecActionFactory@511a460a
|
||||||
|
processResources: task ':app:processResources'
|
||||||
|
processTestResources: task ':app:processTestResources'
|
||||||
|
project: project ':app'
|
||||||
|
projectConfigurator: org.gradle.api.internal.project.BuildOperationCrossProjectConfigurator@21331883
|
||||||
|
projectDir: /private/tmp/nx-e2e/nx/proj9912426/app
|
||||||
|
projectEvaluationBroadcaster: ProjectEvaluationListener broadcast
|
||||||
|
projectEvaluator: org.gradle.configuration.project.LifecycleProjectEvaluator@f6c3829
|
||||||
|
projectPath: :app
|
||||||
|
projectReport: task ':app:projectReport'
|
||||||
|
projectReportDir: /private/tmp/nx-e2e/nx/proj9912426/app/build/reports/project
|
||||||
|
projectReportDirName: project
|
||||||
|
projects: [project ':app']
|
||||||
|
properties: {...}
|
||||||
|
propertyReport: task ':app:propertyReport'
|
||||||
|
providers: org.gradle.api.internal.provider.DefaultProviderFactory_Decorated@1eb7e486
|
||||||
|
publicType: org.gradle.api.plugins.ProjectReportsPluginConvention
|
||||||
|
reporting: extension 'reporting'
|
||||||
|
repositories: repository container
|
||||||
|
resolvableConfigurations: task ':app:resolvableConfigurations'
|
||||||
|
resources: org.gradle.api.internal.resources.DefaultResourceHandler@103986d2
|
||||||
|
rootDir: /private/tmp/nx-e2e/nx/proj9912426
|
||||||
|
rootProject: root project 'my-gradle-project5165026'
|
||||||
|
rootScript: false
|
||||||
|
run: task ':app:run'
|
||||||
|
script: false
|
||||||
|
scriptHandlerFactory: org.gradle.api.internal.initialization.DefaultScriptHandlerFactory@191cd667
|
||||||
|
scriptPluginFactory: org.gradle.configuration.ScriptPluginFactorySelector@775f081d
|
||||||
|
serviceRegistryFactory: org.gradle.internal.service.scopes.BuildScopeServiceRegistryFactory@566d51a4
|
||||||
|
services: Project services
|
||||||
|
sourceCompatibility: 21
|
||||||
|
sourceSets: SourceSet container
|
||||||
|
standardOutputCapture: org.gradle.internal.logging.services.DefaultLoggingManager@2818071f
|
||||||
|
startScripts: task ':app:startScripts'
|
||||||
|
state: project state 'EXECUTED'
|
||||||
|
status: integration
|
||||||
|
subprojects: []
|
||||||
|
targetCompatibility: 21
|
||||||
|
taskDependencyFactory: org.gradle.api.internal.tasks.DefaultTaskDependencyFactory@7486b7b3
|
||||||
|
taskReport: task ':app:taskReport'
|
||||||
|
taskThatOwnsThisObject: null
|
||||||
|
tasks: task set
|
||||||
|
test: task ':app:test'
|
||||||
|
testClasses: task ':app:testClasses'
|
||||||
|
testReportDir: /private/tmp/nx-e2e/nx/proj9912426/app/build/reports/tests
|
||||||
|
testReportDirName: tests
|
||||||
|
testResultsDir: /private/tmp/nx-e2e/nx/proj9912426/app/build/test-results
|
||||||
|
testResultsDirName: test-results
|
||||||
|
testing: extension 'testing'
|
||||||
|
version: unspecified
|
||||||
|
versionCatalogs: extension 'versionCatalogs'
|
||||||
87
packages/gradle/src/utils/exec-gradle.spec.ts
Normal file
87
packages/gradle/src/utils/exec-gradle.spec.ts
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
import { TempFs } from 'nx/src/internal-testing-utils/temp-fs';
|
||||||
|
import { findGraldewFile } from './exec-gradle';
|
||||||
|
|
||||||
|
describe('exec gradle', () => {
|
||||||
|
describe('findGraldewFile', () => {
|
||||||
|
let tempFs: TempFs;
|
||||||
|
let cwd: string;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
tempFs = new TempFs('test');
|
||||||
|
cwd = process.cwd();
|
||||||
|
process.chdir(tempFs.tempDir);
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
jest.resetModules();
|
||||||
|
process.chdir(cwd);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should find gradlew with one gradlew file at root', async () => {
|
||||||
|
await tempFs.createFiles({
|
||||||
|
'proj/build.gradle': ``,
|
||||||
|
gradlew: '',
|
||||||
|
'nested/nested/proj/build.gradle': ``,
|
||||||
|
'nested/nested/proj/settings.gradle': ``,
|
||||||
|
'nested/nested/proj/src/test/java/test/rootTest.java': ``,
|
||||||
|
'nested/nested/proj/src/test/java/test/aTest.java': ``,
|
||||||
|
'nested/nested/proj/src/test/java/test/bTest.java': ``,
|
||||||
|
});
|
||||||
|
let gradlewFile = findGraldewFile('proj/build.gradle', tempFs.tempDir);
|
||||||
|
expect(gradlewFile).toEqual('gradlew');
|
||||||
|
gradlewFile = findGraldewFile(
|
||||||
|
'nested/nested/proj/build.gradle',
|
||||||
|
tempFs.tempDir
|
||||||
|
);
|
||||||
|
expect(gradlewFile).toEqual('gradlew');
|
||||||
|
gradlewFile = findGraldewFile(
|
||||||
|
'nested/nested/proj/settings.gradle',
|
||||||
|
tempFs.tempDir
|
||||||
|
);
|
||||||
|
expect(gradlewFile).toEqual('gradlew');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should find gradlew with multiple gradlew files with nested project structure', async () => {
|
||||||
|
await tempFs.createFiles({
|
||||||
|
'proj/build.gradle': ``,
|
||||||
|
'proj/gradlew': '',
|
||||||
|
'proj/settings.gradle': ``,
|
||||||
|
'nested/nested/proj/gradlew': '',
|
||||||
|
'nested/nested/proj/build.gradle': ``,
|
||||||
|
'nested/nested/proj/settings.gradle': ``,
|
||||||
|
'nested/nested/proj/src/test/java/test/rootTest.java': ``,
|
||||||
|
'nested/nested/proj/src/test/java/test/aTest.java': ``,
|
||||||
|
'nested/nested/proj/src/test/java/test/bTest.java': ``,
|
||||||
|
});
|
||||||
|
|
||||||
|
let gradlewFile = findGraldewFile('proj/build.gradle', tempFs.tempDir);
|
||||||
|
expect(gradlewFile).toEqual('proj/gradlew');
|
||||||
|
gradlewFile = findGraldewFile('proj/settings.gradle', tempFs.tempDir);
|
||||||
|
expect(gradlewFile).toEqual('proj/gradlew');
|
||||||
|
gradlewFile = findGraldewFile(
|
||||||
|
'nested/nested/proj/build.gradle',
|
||||||
|
tempFs.tempDir
|
||||||
|
);
|
||||||
|
expect(gradlewFile).toEqual('nested/nested/proj/gradlew');
|
||||||
|
gradlewFile = findGraldewFile(
|
||||||
|
'nested/nested/proj/settings.gradle',
|
||||||
|
tempFs.tempDir
|
||||||
|
);
|
||||||
|
expect(gradlewFile).toEqual('nested/nested/proj/gradlew');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw an error if no gradlw in workspace', async () => {
|
||||||
|
await tempFs.createFiles({
|
||||||
|
'proj/build.gradle': ``,
|
||||||
|
'nested/nested/proj/build.gradle': ``,
|
||||||
|
'nested/nested/proj/settings.gradle': ``,
|
||||||
|
'nested/nested/proj/src/test/java/test/rootTest.java': ``,
|
||||||
|
'nested/nested/proj/src/test/java/test/aTest.java': ``,
|
||||||
|
'nested/nested/proj/src/test/java/test/bTest.java': ``,
|
||||||
|
});
|
||||||
|
expect(() =>
|
||||||
|
findGraldewFile('proj/build.gradle', tempFs.tempDir)
|
||||||
|
).toThrow();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -1,36 +1,35 @@
|
|||||||
import { workspaceRoot } from '@nx/devkit';
|
import { AggregateCreateNodesError, workspaceRoot } from '@nx/devkit';
|
||||||
import { ExecFileOptions, execFile } from 'node:child_process';
|
import { ExecFileOptions, execFile } from 'node:child_process';
|
||||||
import { existsSync } from 'node:fs';
|
import { existsSync } from 'node:fs';
|
||||||
import { join } from 'node:path';
|
import { dirname, join } from 'node:path';
|
||||||
|
|
||||||
export function getGradleBinaryPath(): string {
|
|
||||||
const gradleFile = process.platform.startsWith('win')
|
|
||||||
? 'gradlew.bat'
|
|
||||||
: 'gradlew';
|
|
||||||
const gradleBinaryPath = join(workspaceRoot, gradleFile);
|
|
||||||
if (!existsSync(gradleBinaryPath)) {
|
|
||||||
throw new Error('Gradle is not setup. Run "gradle init"');
|
|
||||||
}
|
|
||||||
|
|
||||||
return gradleBinaryPath;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For gradle command, it needs to be run from the directory of the gradle binary
|
||||||
|
* @returns gradle binary file name
|
||||||
|
*/
|
||||||
export function getGradleExecFile(): string {
|
export function getGradleExecFile(): string {
|
||||||
return process.platform.startsWith('win') ? '.\\gradlew.bat' : './gradlew';
|
return process.platform.startsWith('win') ? '.\\gradlew.bat' : './gradlew';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function executes gradle with the given arguments
|
||||||
|
* @param gradleBinaryPath absolute path to gradle binary
|
||||||
|
* @param args args passed to gradle
|
||||||
|
* @param execOptions exec options
|
||||||
|
* @returns promise with the stdout buffer
|
||||||
|
*/
|
||||||
export function execGradleAsync(
|
export function execGradleAsync(
|
||||||
|
gradleBinaryPath: string,
|
||||||
args: ReadonlyArray<string>,
|
args: ReadonlyArray<string>,
|
||||||
execOptions: ExecFileOptions = {}
|
execOptions: ExecFileOptions = {}
|
||||||
): Promise<Buffer> {
|
): Promise<Buffer> {
|
||||||
const gradleBinaryPath = getGradleBinaryPath();
|
|
||||||
|
|
||||||
return new Promise<Buffer>((res, rej) => {
|
return new Promise<Buffer>((res, rej) => {
|
||||||
const cp = execFile(gradleBinaryPath, args, {
|
const cp = execFile(gradleBinaryPath, args, {
|
||||||
...execOptions,
|
cwd: dirname(gradleBinaryPath),
|
||||||
shell: true,
|
shell: true,
|
||||||
windowsHide: true,
|
windowsHide: true,
|
||||||
env: process.env,
|
env: process.env,
|
||||||
|
...execOptions,
|
||||||
});
|
});
|
||||||
|
|
||||||
let stdout = Buffer.from('');
|
let stdout = Buffer.from('');
|
||||||
@ -53,3 +52,46 @@ export function execGradleAsync(
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function recursively finds the nearest gradlew file in the workspace
|
||||||
|
* @param originalFileToSearch the original file to search for
|
||||||
|
* @param wr workspace root
|
||||||
|
* @param currentSearchPath the path to start searching for gradlew file
|
||||||
|
* @returns the relative path of the gradlew file to workspace root, throws an error if gradlew file is not found
|
||||||
|
* It will return gradlew.bat file on windows and gradlew file on other platforms
|
||||||
|
*/
|
||||||
|
export function findGraldewFile(
|
||||||
|
originalFileToSearch: string,
|
||||||
|
wr: string = workspaceRoot,
|
||||||
|
currentSearchPath?: string
|
||||||
|
): string {
|
||||||
|
currentSearchPath ??= originalFileToSearch;
|
||||||
|
const parent = dirname(currentSearchPath);
|
||||||
|
if (currentSearchPath === parent) {
|
||||||
|
throw new AggregateCreateNodesError(
|
||||||
|
[
|
||||||
|
[
|
||||||
|
originalFileToSearch,
|
||||||
|
new Error('No Gradlew file found. Run "gradle init"'),
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const gradlewPath = join(parent, 'gradlew');
|
||||||
|
const gradlewBatPath = join(parent, 'gradlew.bat');
|
||||||
|
|
||||||
|
if (process.platform.startsWith('win')) {
|
||||||
|
if (existsSync(join(wr, gradlewBatPath))) {
|
||||||
|
return gradlewBatPath;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (existsSync(join(wr, gradlewPath))) {
|
||||||
|
return gradlewPath;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return findGraldewFile(originalFileToSearch, wr, parent);
|
||||||
|
}
|
||||||
|
|||||||
@ -36,4 +36,13 @@ describe('processProjectReports', () => {
|
|||||||
'mylibrary',
|
'mylibrary',
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should process properties report for projects without child projects', () => {
|
||||||
|
const report = processProjectReports([
|
||||||
|
'> Task :propertyReport',
|
||||||
|
`See the report at: file://${__dirname}/__mocks__/gradle-properties-report-no-child-projects.txt`,
|
||||||
|
]);
|
||||||
|
expect(report.gradleProjectToProjectName.get('')).toEqual('app');
|
||||||
|
expect(report.gradleProjectToChildProjects.get('')).toEqual([]);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -3,23 +3,18 @@ import { join, relative } from 'node:path';
|
|||||||
|
|
||||||
import {
|
import {
|
||||||
AggregateCreateNodesError,
|
AggregateCreateNodesError,
|
||||||
logger,
|
|
||||||
normalizePath,
|
normalizePath,
|
||||||
workspaceRoot,
|
workspaceRoot,
|
||||||
} from '@nx/devkit';
|
} from '@nx/devkit';
|
||||||
import { combineGlobPatterns } from 'nx/src/utils/globs';
|
|
||||||
|
|
||||||
import { execGradleAsync } from './exec-gradle';
|
|
||||||
import { hashWithWorkspaceContext } from 'nx/src/utils/workspace-context';
|
import { hashWithWorkspaceContext } from 'nx/src/utils/workspace-context';
|
||||||
import { dirname } from 'path';
|
import { dirname } from 'path';
|
||||||
|
import { gradleConfigAndTestGlob } from './split-config-files';
|
||||||
export const fileSeparator = process.platform.startsWith('win')
|
import {
|
||||||
? 'file:///'
|
getProjectReportLines,
|
||||||
: 'file://';
|
fileSeparator,
|
||||||
|
newLineSeparator,
|
||||||
export const newLineSeparator = process.platform.startsWith('win')
|
} from './get-project-report-lines';
|
||||||
? '\r\n'
|
|
||||||
: '\n';
|
|
||||||
|
|
||||||
export interface GradleReport {
|
export interface GradleReport {
|
||||||
gradleFileToGradleProjectMap: Map<string, string>;
|
gradleFileToGradleProjectMap: Map<string, string>;
|
||||||
@ -34,37 +29,39 @@ export interface GradleReport {
|
|||||||
let gradleReportCache: GradleReport;
|
let gradleReportCache: GradleReport;
|
||||||
let gradleCurrentConfigHash: string;
|
let gradleCurrentConfigHash: string;
|
||||||
|
|
||||||
export const GRADLE_BUILD_FILES = new Set(['build.gradle', 'build.gradle.kts']);
|
|
||||||
export const GRADLE_TEST_FILES = [
|
|
||||||
'**/src/test/java/**/*Test.java',
|
|
||||||
'**/src/test/kotlin/**/*Test.kt',
|
|
||||||
'**/src/test/java/**/*Tests.java',
|
|
||||||
'**/src/test/kotlin/**/*Tests.kt',
|
|
||||||
];
|
|
||||||
|
|
||||||
export const gradleConfigGlob = combineGlobPatterns(
|
|
||||||
...Array.from(GRADLE_BUILD_FILES).map((file) => `**/${file}`)
|
|
||||||
);
|
|
||||||
|
|
||||||
export const gradleConfigAndTestGlob = combineGlobPatterns(
|
|
||||||
...Array.from(GRADLE_BUILD_FILES).map((file) => `**/${file}`),
|
|
||||||
...GRADLE_TEST_FILES
|
|
||||||
);
|
|
||||||
|
|
||||||
export function getCurrentGradleReport() {
|
export function getCurrentGradleReport() {
|
||||||
if (!gradleReportCache) {
|
if (!gradleReportCache) {
|
||||||
throw new Error(
|
throw new AggregateCreateNodesError(
|
||||||
'Expected cached gradle report. Please open an issue at https://github.com/nrwl/nx/issues/new/choose'
|
[
|
||||||
|
[
|
||||||
|
null,
|
||||||
|
new Error(
|
||||||
|
`Expected cached gradle report. Please open an issue at https://github.com/nrwl/nx/issues/new/choose`
|
||||||
|
),
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return gradleReportCache;
|
return gradleReportCache;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function populates the gradle report cache.
|
||||||
|
* For each gradlew file, it runs the `projectReportAll` task and processes the output.
|
||||||
|
* If `projectReportAll` fails, it runs the `projectReport` task instead.
|
||||||
|
* It will throw an error if both tasks fail.
|
||||||
|
* It will accumulate the output of all gradlew files.
|
||||||
|
* @param workspaceRoot
|
||||||
|
* @param gradlewFiles absolute paths to all gradlew files in the workspace
|
||||||
|
* @returns Promise<void>
|
||||||
|
*/
|
||||||
export async function populateGradleReport(
|
export async function populateGradleReport(
|
||||||
workspaceRoot: string
|
workspaceRoot: string,
|
||||||
|
gradlewFiles: string[]
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const gradleConfigHash = await hashWithWorkspaceContext(workspaceRoot, [
|
const gradleConfigHash = await hashWithWorkspaceContext(workspaceRoot, [
|
||||||
gradleConfigGlob,
|
gradleConfigAndTestGlob,
|
||||||
]);
|
]);
|
||||||
if (gradleReportCache && gradleConfigHash === gradleCurrentConfigHash) {
|
if (gradleReportCache && gradleConfigHash === gradleCurrentConfigHash) {
|
||||||
return;
|
return;
|
||||||
@ -73,37 +70,18 @@ export async function populateGradleReport(
|
|||||||
const gradleProjectReportStart = performance.mark(
|
const gradleProjectReportStart = performance.mark(
|
||||||
'gradleProjectReport:start'
|
'gradleProjectReport:start'
|
||||||
);
|
);
|
||||||
let projectReportLines;
|
|
||||||
try {
|
const projectReportLines = await gradlewFiles.reduce(
|
||||||
projectReportLines = await execGradleAsync(['projectReportAll'], {
|
async (
|
||||||
cwd: workspaceRoot,
|
projectReportLines: Promise<string[]>,
|
||||||
});
|
gradlewFile: string
|
||||||
} catch (e) {
|
): Promise<string[]> => {
|
||||||
try {
|
const allLines = await projectReportLines;
|
||||||
projectReportLines = await execGradleAsync(['projectReport'], {
|
const currentLines = await getProjectReportLines(gradlewFile);
|
||||||
cwd: workspaceRoot,
|
return [...allLines, ...currentLines];
|
||||||
});
|
},
|
||||||
logger.warn(
|
Promise.resolve([])
|
||||||
'Could not run `projectReportAll` task. Ran `projectReport` instead. Please run `nx generate @nx/gradle:init` to generate the necessary tasks.'
|
);
|
||||||
);
|
|
||||||
} catch (e) {
|
|
||||||
throw new AggregateCreateNodesError(
|
|
||||||
[
|
|
||||||
[
|
|
||||||
null,
|
|
||||||
new Error(
|
|
||||||
'Could not run `projectReportAll` or `projectReport` task. Please run `nx generate @nx/gradle:init` to generate the necessary tasks.'
|
|
||||||
),
|
|
||||||
],
|
|
||||||
],
|
|
||||||
[]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
projectReportLines = projectReportLines
|
|
||||||
.toString()
|
|
||||||
.split(newLineSeparator)
|
|
||||||
.filter((line) => line.trim() !== '');
|
|
||||||
|
|
||||||
const gradleProjectReportEnd = performance.mark('gradleProjectReport:end');
|
const gradleProjectReportEnd = performance.mark('gradleProjectReport:end');
|
||||||
performance.measure(
|
performance.measure(
|
||||||
@ -111,6 +89,7 @@ export async function populateGradleReport(
|
|||||||
gradleProjectReportStart.name,
|
gradleProjectReportStart.name,
|
||||||
gradleProjectReportEnd.name
|
gradleProjectReportEnd.name
|
||||||
);
|
);
|
||||||
|
gradleCurrentConfigHash = gradleConfigHash;
|
||||||
gradleReportCache = processProjectReports(projectReportLines);
|
gradleReportCache = processProjectReports(projectReportLines);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
65
packages/gradle/src/utils/get-project-report-lines.ts
Normal file
65
packages/gradle/src/utils/get-project-report-lines.ts
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
import { AggregateCreateNodesError, logger } from '@nx/devkit';
|
||||||
|
import { execGradleAsync } from './exec-gradle';
|
||||||
|
import { existsSync } from 'fs';
|
||||||
|
import { dirname, join } from 'path';
|
||||||
|
|
||||||
|
export const fileSeparator = process.platform.startsWith('win')
|
||||||
|
? 'file:///'
|
||||||
|
: 'file://';
|
||||||
|
|
||||||
|
export const newLineSeparator = process.platform.startsWith('win')
|
||||||
|
? '\r\n'
|
||||||
|
: '\n';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function executes the gradle projectReportAll task and returns the output as an array of lines.
|
||||||
|
* @param gradlewFile the absolute path to the gradlew file
|
||||||
|
* @returns project report lines
|
||||||
|
*/
|
||||||
|
export async function getProjectReportLines(
|
||||||
|
gradlewFile: string
|
||||||
|
): Promise<string[]> {
|
||||||
|
let projectReportBuffer: Buffer;
|
||||||
|
|
||||||
|
// if there is no build.gradle or build.gradle.kts file, we cannot run the projectReport nor projectReportAll task
|
||||||
|
if (
|
||||||
|
!existsSync(join(dirname(gradlewFile), 'build.gradle')) &&
|
||||||
|
!existsSync(join(dirname(gradlewFile), 'build.gradle.kts'))
|
||||||
|
) {
|
||||||
|
logger.warn(
|
||||||
|
`Could not find build file near ${gradlewFile}. Please run 'nx generate @nx/gradle:init' to generate the necessary tasks.`
|
||||||
|
);
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
projectReportBuffer = await execGradleAsync(gradlewFile, [
|
||||||
|
'projectReportAll',
|
||||||
|
]);
|
||||||
|
} catch (e) {
|
||||||
|
try {
|
||||||
|
projectReportBuffer = await execGradleAsync(gradlewFile, [
|
||||||
|
'projectReport',
|
||||||
|
]);
|
||||||
|
logger.warn(
|
||||||
|
`Could not run 'projectReportAll' task. Ran 'projectReport' instead. Please run 'nx generate @nx/gradle:init' to generate the necessary tasks.`
|
||||||
|
);
|
||||||
|
} catch (e) {
|
||||||
|
throw new AggregateCreateNodesError(
|
||||||
|
[
|
||||||
|
[
|
||||||
|
gradlewFile,
|
||||||
|
new Error(
|
||||||
|
`Could not run 'projectReportAll' or 'projectReport' task. Please run 'nx generate @nx/gradle:init' to generate the necessary tasks.`
|
||||||
|
),
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return projectReportBuffer
|
||||||
|
.toString()
|
||||||
|
.split(newLineSeparator)
|
||||||
|
.filter((line) => line.trim() !== '');
|
||||||
|
}
|
||||||
88
packages/gradle/src/utils/split-config-files.spec.ts
Normal file
88
packages/gradle/src/utils/split-config-files.spec.ts
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
import { TempFs } from 'nx/src/internal-testing-utils/temp-fs';
|
||||||
|
import { splitConfigFiles } from './split-config-files';
|
||||||
|
|
||||||
|
describe('split config files', () => {
|
||||||
|
let tempFs: TempFs;
|
||||||
|
let cwd: string;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
tempFs = new TempFs('test');
|
||||||
|
cwd = process.cwd();
|
||||||
|
process.chdir(tempFs.tempDir);
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
jest.resetModules();
|
||||||
|
process.chdir(cwd);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should split config files with one gradlew file', async () => {
|
||||||
|
await tempFs.createFiles({
|
||||||
|
'proj/build.gradle': ``,
|
||||||
|
gradlew: '',
|
||||||
|
'nested/nested/proj/build.gradle': ``,
|
||||||
|
'nested/nested/proj/settings.gradle': ``,
|
||||||
|
'nested/nested/proj/src/test/java/test/rootTest.java': ``,
|
||||||
|
'nested/nested/proj/src/test/java/test/aTest.java': ``,
|
||||||
|
'nested/nested/proj/src/test/java/test/bTest.java': ``,
|
||||||
|
});
|
||||||
|
const { buildFiles, gradlewFiles, testFiles, projectRoots } =
|
||||||
|
splitConfigFiles([
|
||||||
|
'proj/build.gradle',
|
||||||
|
'gradlew',
|
||||||
|
'nested/nested/proj/build.gradle',
|
||||||
|
'nested/nested/proj/src/test/java/test/rootTest.java',
|
||||||
|
'nested/nested/proj/src/test/java/test/aTest.java',
|
||||||
|
'nested/nested/proj/src/test/java/test/bTest.java',
|
||||||
|
]);
|
||||||
|
expect(buildFiles).toEqual([
|
||||||
|
'proj/build.gradle',
|
||||||
|
'nested/nested/proj/build.gradle',
|
||||||
|
]);
|
||||||
|
expect(gradlewFiles).toEqual(['gradlew']);
|
||||||
|
expect(testFiles).toEqual([
|
||||||
|
'nested/nested/proj/src/test/java/test/rootTest.java',
|
||||||
|
'nested/nested/proj/src/test/java/test/aTest.java',
|
||||||
|
'nested/nested/proj/src/test/java/test/bTest.java',
|
||||||
|
]);
|
||||||
|
expect(projectRoots).toEqual(['proj', 'nested/nested/proj']);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should split config files with multiple gradlew files', async () => {
|
||||||
|
await tempFs.createFiles({
|
||||||
|
'proj/build.gradle': ``,
|
||||||
|
'proj/gradlew': '',
|
||||||
|
'proj/settings.gradle': ``,
|
||||||
|
'nested/nested/proj/gradlew': '',
|
||||||
|
'nested/nested/proj/build.gradle': ``,
|
||||||
|
'nested/nested/proj/settings.gradle': ``,
|
||||||
|
'nested/nested/proj/src/test/java/test/rootTest.java': ``,
|
||||||
|
'nested/nested/proj/src/test/java/test/aTest.java': ``,
|
||||||
|
'nested/nested/proj/src/test/java/test/bTest.java': ``,
|
||||||
|
});
|
||||||
|
const { buildFiles, gradlewFiles, testFiles, projectRoots } =
|
||||||
|
splitConfigFiles([
|
||||||
|
'proj/build.gradle',
|
||||||
|
'proj/gradlew',
|
||||||
|
'nested/nested/proj/build.gradle',
|
||||||
|
'nested/nested/proj/gradlew',
|
||||||
|
'nested/nested/proj/src/test/java/test/rootTest.java',
|
||||||
|
'nested/nested/proj/src/test/java/test/aTest.java',
|
||||||
|
'nested/nested/proj/src/test/java/test/bTest.java',
|
||||||
|
]);
|
||||||
|
expect(buildFiles).toEqual([
|
||||||
|
'proj/build.gradle',
|
||||||
|
'nested/nested/proj/build.gradle',
|
||||||
|
]);
|
||||||
|
expect(gradlewFiles).toEqual([
|
||||||
|
'proj/gradlew',
|
||||||
|
'nested/nested/proj/gradlew',
|
||||||
|
]);
|
||||||
|
expect(testFiles).toEqual([
|
||||||
|
'nested/nested/proj/src/test/java/test/rootTest.java',
|
||||||
|
'nested/nested/proj/src/test/java/test/aTest.java',
|
||||||
|
'nested/nested/proj/src/test/java/test/bTest.java',
|
||||||
|
]);
|
||||||
|
expect(projectRoots).toEqual(['proj', 'nested/nested/proj']);
|
||||||
|
});
|
||||||
|
});
|
||||||
67
packages/gradle/src/utils/split-config-files.ts
Normal file
67
packages/gradle/src/utils/split-config-files.ts
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
import { combineGlobPatterns } from 'nx/src/utils/globs';
|
||||||
|
import { basename, dirname } from 'node:path';
|
||||||
|
|
||||||
|
export const GRADLE_BUILD_FILES = new Set(['build.gradle', 'build.gradle.kts']);
|
||||||
|
export const GRALDEW_FILES = new Set(['gradlew', 'gradlew.bat']);
|
||||||
|
export const GRADLE_TEST_FILES = [
|
||||||
|
'**/src/test/java/**/*Test.java',
|
||||||
|
'**/src/test/kotlin/**/*Test.kt',
|
||||||
|
'**/src/test/java/**/*Tests.java',
|
||||||
|
'**/src/test/kotlin/**/*Tests.kt',
|
||||||
|
];
|
||||||
|
|
||||||
|
export const gradleConfigGlob = combineGlobPatterns(
|
||||||
|
...Array.from(GRADLE_BUILD_FILES).map((file) => `**/${file}`)
|
||||||
|
);
|
||||||
|
|
||||||
|
export const gradleConfigAndTestGlob = combineGlobPatterns(
|
||||||
|
...Array.from(GRADLE_BUILD_FILES).map((file) => `**/${file}`),
|
||||||
|
...Array.from(GRALDEW_FILES).map((file) => `**/${file}`),
|
||||||
|
...GRADLE_TEST_FILES
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function split config files into build files, settings files, test files and project roots
|
||||||
|
* @param files list of files to split
|
||||||
|
* @returns object with buildFiles, gradlewFiles, testFiles and projectRoots
|
||||||
|
* For gradlewFiles, it will start with settings files and find the nearest gradlew file in the workspace
|
||||||
|
*/
|
||||||
|
export function splitConfigFiles(files: readonly string[]): {
|
||||||
|
buildFiles: string[];
|
||||||
|
gradlewFiles: string[];
|
||||||
|
testFiles: string[];
|
||||||
|
projectRoots: string[];
|
||||||
|
} {
|
||||||
|
const buildFiles = [];
|
||||||
|
const testFiles = [];
|
||||||
|
const gradlewFiles = [];
|
||||||
|
const projectRoots = new Set<string>();
|
||||||
|
|
||||||
|
files.forEach((file) => {
|
||||||
|
const filename = basename(file);
|
||||||
|
const fileDirectory = dirname(file);
|
||||||
|
if (GRADLE_BUILD_FILES.has(filename)) {
|
||||||
|
buildFiles.push(file);
|
||||||
|
projectRoots.add(fileDirectory);
|
||||||
|
} else if (GRALDEW_FILES.has(filename)) {
|
||||||
|
if (process.platform.startsWith('win')) {
|
||||||
|
if (filename === 'gradlew.bat') {
|
||||||
|
gradlewFiles.push(file);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (filename === 'gradlew') {
|
||||||
|
gradlewFiles.push(file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
testFiles.push(file);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
buildFiles,
|
||||||
|
testFiles,
|
||||||
|
gradlewFiles,
|
||||||
|
projectRoots: Array.from(projectRoots),
|
||||||
|
};
|
||||||
|
}
|
||||||
@ -220,7 +220,14 @@ export async function detectPlugins(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (existsSync('gradlew') || existsSync('gradlew.bat')) {
|
|
||||||
|
let gradlewFiles = ['gradlew', 'gradlew.bat'].concat(
|
||||||
|
await globWithWorkspaceContext(process.cwd(), [
|
||||||
|
'**/gradlew',
|
||||||
|
'**/gradlew.bat',
|
||||||
|
])
|
||||||
|
);
|
||||||
|
if (gradlewFiles.some((f) => existsSync(f))) {
|
||||||
detectedPlugins.add('@nx/gradle');
|
detectedPlugins.add('@nx/gradle');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user