@nx/gradle
Version:
251 lines (250 loc) • 10.8 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.createNodes = exports.makeCreateNodesForGradleConfigFile = exports.createNodesV2 = void 0;
const devkit_1 = require("@nx/devkit");
const calculate_hash_for_create_nodes_1 = require("@nx/devkit/src/utils/calculate-hash-for-create-nodes");
const node_path_1 = require("node:path");
const cache_directory_1 = require("nx/src/utils/cache-directory");
const plugin_cache_utils_1 = require("nx/src/utils/plugin-cache-utils");
const devkit_internals_1 = require("nx/src/devkit-internals");
const get_gradle_report_1 = require("./utils/get-gradle-report");
const file_hasher_1 = require("nx/src/hasher/file-hasher");
const split_config_files_1 = require("../utils/split-config-files");
const exec_gradle_1 = require("../utils/exec-gradle");
const cacheableTaskType = new Set(['Build', 'Verification']);
const dependsOnMap = {
build: ['^build', 'classes', 'test'],
testClasses: ['classes'],
test: ['testClasses'],
classes: ['^classes'],
};
function normalizeOptions(options) {
options ??= {};
options.testTargetName ??= 'test';
options.classesTargetName ??= 'classes';
options.buildTargetName ??= 'build';
return options;
}
exports.createNodesV2 = [
split_config_files_1.gradleConfigAndTestGlob,
async (files, options, context) => {
const { buildFiles, projectRoots, gradlewFiles, testFiles } = (0, split_config_files_1.splitConfigFiles)(files);
const optionsHash = (0, file_hasher_1.hashObject)(options);
const cachePath = (0, node_path_1.join)(cache_directory_1.workspaceDataDirectory, `gradle-${optionsHash}.hash`);
const pluginCache = new plugin_cache_utils_1.PluginCache(cachePath);
await (0, get_gradle_report_1.populateGradleReport)(context.workspaceRoot, gradlewFiles.map((f) => (0, node_path_1.join)(context.workspaceRoot, f)));
const gradleReport = (0, get_gradle_report_1.getCurrentGradleReport)();
const gradleProjectRootToTestFilesMap = getGradleProjectRootToTestFilesMap(testFiles, projectRoots);
try {
return (0, devkit_1.createNodesFromFiles)((0, exports.makeCreateNodesForGradleConfigFile)(gradleReport, pluginCache, gradleProjectRootToTestFilesMap), buildFiles, options, context);
}
finally {
pluginCache.writeToDisk(cachePath);
}
},
];
const makeCreateNodesForGradleConfigFile = (gradleReport, pluginCache = new plugin_cache_utils_1.PluginCache(), gradleProjectRootToTestFilesMap = {}) => async (gradleFilePath, options, context) => {
const projectRoot = (0, node_path_1.dirname)(gradleFilePath);
options = normalizeOptions(options);
const hash = await (0, calculate_hash_for_create_nodes_1.calculateHashForCreateNodes)(projectRoot, options ?? {}, context);
if (!pluginCache.has(hash)) {
pluginCache.set(hash, await createGradleProject(gradleReport, gradleFilePath, options, context, gradleProjectRootToTestFilesMap[projectRoot]));
}
const project = pluginCache.get(hash);
if (!project) {
return {};
}
return {
projects: {
[projectRoot]: project,
},
};
};
exports.makeCreateNodesForGradleConfigFile = makeCreateNodesForGradleConfigFile;
/**
@deprecated This is replaced with {@link createNodesV2}. Update your plugin to export its own `createNodesV2` function that wraps this one instead.
This function will change to the v2 function in Nx 20.
*/
exports.createNodes = exports.createNodesV2;
async function createGradleProject(gradleReport, gradleFilePath, options, context, testFiles = []) {
try {
const { gradleProjectToTasksTypeMap, gradleProjectToTasksMap, gradleFileToOutputDirsMap, gradleFileToGradleProjectMap, gradleProjectToProjectName, } = gradleReport;
const gradleProject = gradleFileToGradleProjectMap.get(gradleFilePath);
const projectName = gradleProjectToProjectName.get(gradleProject);
if (!projectName) {
return;
}
const tasksTypeMap = gradleProjectToTasksTypeMap.get(gradleProject);
const tasksSet = gradleProjectToTasksMap.get(gradleProject);
let tasks = [];
tasksSet.forEach((taskName) => {
tasks.push({
type: tasksTypeMap?.get(taskName),
name: taskName,
});
});
if (options.includeSubprojectsTasks) {
tasksTypeMap.forEach((taskType, taskName) => {
if (!tasksSet.has(taskName)) {
tasks.push({
type: taskType,
name: taskName,
});
}
});
}
const outputDirs = gradleFileToOutputDirsMap.get(gradleFilePath);
const { targets, targetGroups } = await createGradleTargets(tasks, options, context, outputDirs, gradleProject, gradleFilePath, testFiles);
const project = {
name: projectName,
projectType: 'application',
targets,
metadata: {
targetGroups,
technologies: ['gradle'],
},
};
return project;
}
catch (e) {
console.error(e);
return undefined;
}
}
async function createGradleTargets(tasks, options, context, outputDirs, gradleProject, gradleBuildFilePath, testFiles = []) {
const inputsMap = createInputsMap(context);
const gradlewFileDirectory = (0, node_path_1.dirname)((0, exec_gradle_1.findGradlewFile)(gradleBuildFilePath, context.workspaceRoot));
const targets = {};
const targetGroups = {};
for (const task of tasks) {
const targetName = options?.[`${task.name}TargetName`] ?? task.name;
let outputs = [outputDirs.get(task.name)].filter(Boolean);
if (task.name === 'test') {
outputs = [
outputDirs.get('testReport'),
outputDirs.get('testResults'),
].filter(Boolean);
getTestCiTargets(testFiles, gradleProject, targetName, options.ciTargetName, inputsMap['test'], outputs, task.type, targets, targetGroups, gradlewFileDirectory);
}
const taskCommandToRun = `${gradleProject ? gradleProject + ':' : ''}${task.name}`;
targets[targetName] = {
command: `${(0, exec_gradle_1.getGradleExecFile)()} ${taskCommandToRun}`,
options: {
cwd: gradlewFileDirectory,
},
cache: cacheableTaskType.has(task.type),
inputs: inputsMap[task.name],
dependsOn: dependsOnMap[task.name],
metadata: {
technologies: ['gradle'],
help: {
command: `${(0, exec_gradle_1.getGradleExecFile)()} help --task ${taskCommandToRun}`,
example: {
options: {
args: ['--rerun'],
},
},
},
},
...(outputs && outputs.length ? { outputs } : {}),
};
if (task.type) {
if (!targetGroups[task.type]) {
targetGroups[task.type] = [];
}
targetGroups[task.type].push(targetName);
}
}
return { targetGroups, targets };
}
function createInputsMap(context) {
const namedInputs = context.nxJsonConfiguration.namedInputs;
return {
build: namedInputs?.production
? ['production', '^production']
: ['default', '^default'],
test: ['default', namedInputs?.production ? '^production' : '^default'],
classes: namedInputs?.production
? ['production', '^production']
: ['default', '^default'],
};
}
function getTestCiTargets(testFiles, gradleProject, testTargetName, ciTargetName, inputs, outputs, targetGroupName, targets, targetGroups, gradlewFileDirectory) {
if (!testFiles || testFiles.length === 0 || !ciTargetName) {
return;
}
const taskCommandToRun = `${gradleProject ? gradleProject + ':' : ''}test`;
if (!targetGroups[targetGroupName]) {
targetGroups[targetGroupName] = [];
}
const dependsOn = [];
testFiles.forEach((testFile) => {
const testName = (0, node_path_1.basename)(testFile).split('.')[0];
const targetName = ciTargetName + '--' + testName;
targets[targetName] = {
command: `${(0, exec_gradle_1.getGradleExecFile)()} ${taskCommandToRun} --tests ${testName}`,
options: {
cwd: gradlewFileDirectory,
},
cache: true,
inputs,
dependsOn: dependsOnMap['test'],
metadata: {
technologies: ['gradle'],
description: `Runs Gradle test ${testFile} in CI`,
help: {
command: `${(0, exec_gradle_1.getGradleExecFile)()} help --task ${taskCommandToRun}`,
example: {
options: {
args: ['--rerun'],
},
},
},
},
...(outputs && outputs.length > 0 ? { outputs } : {}),
};
targetGroups[targetGroupName].push(targetName);
dependsOn.push({
target: targetName,
params: 'forward',
});
});
targets[ciTargetName] = {
executor: 'nx:noop',
cache: true,
inputs,
dependsOn: dependsOn,
...(outputs && outputs.length > 0 ? { outputs } : {}),
metadata: {
technologies: ['gradle'],
description: 'Runs Gradle Tests in CI',
nonAtomizedTarget: testTargetName,
help: {
command: `${(0, exec_gradle_1.getGradleExecFile)()} help --task ${taskCommandToRun}`,
example: {
options: {
args: ['--rerun'],
},
},
},
},
};
targetGroups[targetGroupName].push(ciTargetName);
}
function getGradleProjectRootToTestFilesMap(testFiles, projectRoots) {
if (testFiles.length === 0 || projectRoots.length === 0) {
return;
}
const roots = new Map(projectRoots.map((root) => [root, root]));
const testFilesToGradleProjectMap = {};
testFiles.forEach((testFile) => {
const projectRoot = (0, devkit_internals_1.findProjectForPath)(testFile, roots);
if (projectRoot) {
if (!testFilesToGradleProjectMap[projectRoot]) {
testFilesToGradleProjectMap[projectRoot] = [];
}
testFilesToGradleProjectMap[projectRoot].push(testFile);
}
});
return testFilesToGradleProjectMap;
}