feat(java): add gradle kotlin plugin (#29464)
- [x] change init to create `createNodes` instead - [x] unit tests - [x] test-ci - [x] test on windows - [x] help metadata - [x] external nodes TODO: - add publish executor? - publish to maven central? <!-- 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, it uses [project report plugin](https://docs.gradle.org/current/userguide/project_report_plugin.html). - pro: no need to maintain this plugin - con: this plugin gives limited information ## Expected Behavior <!-- This is the behavior we should expect with the changes in this PR --> change the project report plugin to @nxn/gradle/plugin-v1 now the @nx/gradle plugin will use project graph plugin (dev.nx.gradle.project-graph) created in this pr. this plugin will create json file that is exactly what nx project grpah expected. ## Related Issue(s) <!-- Please link the issue being fixed so it gets closed when this is merged. --> Fixes #
This commit is contained in:
parent
296f326b94
commit
b377c96d99
6
.github/workflows/ci.yml
vendored
6
.github/workflows/ci.yml
vendored
@ -65,6 +65,12 @@ jobs:
|
|||||||
- name: Install Rust
|
- name: Install Rust
|
||||||
uses: dtolnay/rust-toolchain@stable
|
uses: dtolnay/rust-toolchain@stable
|
||||||
|
|
||||||
|
- name: Setup Java
|
||||||
|
uses: actions/setup-java@v4
|
||||||
|
with:
|
||||||
|
distribution: temurin
|
||||||
|
java-version: 21
|
||||||
|
|
||||||
- name: Check Documentation
|
- name: Check Documentation
|
||||||
run: pnpm nx documentation
|
run: pnpm nx documentation
|
||||||
timeout-minutes: 20
|
timeout-minutes: 20
|
||||||
|
|||||||
5
.gitignore
vendored
5
.gitignore
vendored
@ -67,5 +67,8 @@ target
|
|||||||
|
|
||||||
vite.config.*.timestamp*
|
vite.config.*.timestamp*
|
||||||
|
|
||||||
|
storybook-static
|
||||||
|
|
||||||
storybook-static
|
# Ignore Gradle project-specific cache directory
|
||||||
|
.gradle
|
||||||
|
.kotlin
|
||||||
|
|||||||
@ -64,6 +64,13 @@ launch-templates:
|
|||||||
- name: Load Cargo Env
|
- name: Load Cargo Env
|
||||||
script: echo "PATH=$HOME/.cargo/bin:$PATH" >> $NX_CLOUD_ENV
|
script: echo "PATH=$HOME/.cargo/bin:$PATH" >> $NX_CLOUD_ENV
|
||||||
|
|
||||||
|
- name: Setup Java 21
|
||||||
|
script: |
|
||||||
|
sudo apt update
|
||||||
|
sudo apt install -y openjdk-21-jdk
|
||||||
|
sudo update-alternatives --set java /usr/lib/jvm/java-21-openjdk-amd64/bin/java
|
||||||
|
java -version
|
||||||
|
|
||||||
linux-extra-large:
|
linux-extra-large:
|
||||||
resource-class: 'docker_linux_amd64/extra_large'
|
resource-class: 'docker_linux_amd64/extra_large'
|
||||||
image: 'ubuntu22.04-node20.11-v10'
|
image: 'ubuntu22.04-node20.11-v10'
|
||||||
@ -128,3 +135,10 @@ launch-templates:
|
|||||||
|
|
||||||
- name: Load Cargo Env
|
- name: Load Cargo Env
|
||||||
script: echo "PATH=$HOME/.cargo/bin:$PATH" >> $NX_CLOUD_ENV
|
script: echo "PATH=$HOME/.cargo/bin:$PATH" >> $NX_CLOUD_ENV
|
||||||
|
|
||||||
|
- name: Setup Java 21
|
||||||
|
script: |
|
||||||
|
sudo apt update
|
||||||
|
sudo apt install -y openjdk-21-jdk
|
||||||
|
sudo update-alternatives --set java /usr/lib/jvm/java-21-openjdk-amd64/bin/java
|
||||||
|
java -version
|
||||||
|
|||||||
@ -13,6 +13,7 @@ packages/express/src/schematics/**/files/**/*.json
|
|||||||
packages/nest/src/schematics/**/files/**/*.json
|
packages/nest/src/schematics/**/files/**/*.json
|
||||||
packages/react/src/schematics/**/files/**/*.json
|
packages/react/src/schematics/**/files/**/*.json
|
||||||
packages/jest/src/schematics/**/files/**/*.json
|
packages/jest/src/schematics/**/files/**/*.json
|
||||||
|
packages/gradle/project-graph/build/**/*.*
|
||||||
packages/nx/src/plugins/js/lock-file/__fixtures__/**/*.*
|
packages/nx/src/plugins/js/lock-file/__fixtures__/**/*.*
|
||||||
packages/**/schematics/**/files/**/*.html
|
packages/**/schematics/**/files/**/*.html
|
||||||
packages/**/generators/**/files/**/*.html
|
packages/**/generators/**/files/**/*.html
|
||||||
|
|||||||
6
build.gradle.kts
Normal file
6
build.gradle.kts
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
plugins {
|
||||||
|
id("dev.nx.gradle.project-graph") version("0.0.2")
|
||||||
|
id("com.ncorti.ktfmt.gradle") version("+")
|
||||||
|
}
|
||||||
|
|
||||||
|
group = "dev.nx"
|
||||||
@ -2325,6 +2325,16 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"migrations": {
|
"migrations": {
|
||||||
|
"/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",
|
||||||
|
"hidden": false,
|
||||||
|
"name": "change-plugin-to-v1",
|
||||||
|
"version": "21.0.0-beta.5",
|
||||||
|
"originalFilePath": "/packages/gradle",
|
||||||
|
"path": "/nx-api/gradle/migrations/change-plugin-to-v1",
|
||||||
|
"type": "migration"
|
||||||
|
},
|
||||||
"/nx-api/gradle/migrations/add-include-subprojects-tasks": {
|
"/nx-api/gradle/migrations/add-include-subprojects-tasks": {
|
||||||
"description": "Add includeSubprojectsTasks to build.gradle file",
|
"description": "Add includeSubprojectsTasks to build.gradle file",
|
||||||
"file": "generated/packages/gradle/migrations/add-include-subprojects-tasks.json",
|
"file": "generated/packages/gradle/migrations/add-include-subprojects-tasks.json",
|
||||||
|
|||||||
@ -2309,6 +2309,16 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"migrations": [
|
"migrations": [
|
||||||
|
{
|
||||||
|
"description": "Change @nx/gradle plugin to version 1",
|
||||||
|
"file": "generated/packages/gradle/migrations/change-plugin-to-v1.json",
|
||||||
|
"hidden": false,
|
||||||
|
"name": "change-plugin-to-v1",
|
||||||
|
"version": "21.0.0-beta.5",
|
||||||
|
"originalFilePath": "/packages/gradle",
|
||||||
|
"path": "gradle/migrations/change-plugin-to-v1",
|
||||||
|
"type": "migration"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"description": "Add includeSubprojectsTasks to build.gradle file",
|
"description": "Add includeSubprojectsTasks to build.gradle file",
|
||||||
"file": "generated/packages/gradle/migrations/add-include-subprojects-tasks.json",
|
"file": "generated/packages/gradle/migrations/add-include-subprojects-tasks.json",
|
||||||
|
|||||||
@ -10,5 +10,5 @@
|
|||||||
"path": "/packages/gradle",
|
"path": "/packages/gradle",
|
||||||
"schema": null,
|
"schema": null,
|
||||||
"type": "migration",
|
"type": "migration",
|
||||||
"examplesFile": "#### Add includeSubprojectsTasks to build.gradle File\n\nAdd includeSubprojectsTasks to build.gradle file\n\n#### Sample Code Changes\n\nUpdate import paths for `withModuleFederation` and `withModuleFederationForSSR`.\n\n{% tabs %}\n{% tab label=\"Before\" %}\n\n```json {% fileName=\"nx.json\" %}\n{\n \"plugins\": [\"@nx/gradle\"]\n}\n```\n\n{% /tab %}\n{% tab label=\"After\" %}\n\n```json {% highlightLines=[5] fileName=\"nx.json\" %}\n{\n \"plugins\": [\n {\n \"options\": {\n \"includeSubprojectsTasks\": true\n },\n \"plugin\": \"@nx/gradle\"\n }\n ]\n}\n```\n\n{% /tab %}\n{% /tabs %}\n"
|
"examplesFile": "#### Add includeSubprojectsTasks to @nx/gradle Plugin Options\n\nAdd includeSubprojectsTasks to @nx/gradle plugin options in nx.json file\n\n#### Sample Code Changes\n\n{% tabs %}\n{% tab label=\"Before\" %}\n\n```json {% fileName=\"nx.json\" %}\n{\n \"plugins\": [\"@nx/gradle\"]\n}\n```\n\n{% /tab %}\n{% tab label=\"After\" %}\n\n```json {% highlightLines=[5] fileName=\"nx.json\" %}\n{\n \"plugins\": [\n {\n \"options\": {\n \"includeSubprojectsTasks\": true\n },\n \"plugin\": \"@nx/gradle\"\n }\n ]\n}\n```\n\n{% /tab %}\n{% /tabs %}\n"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"name": "change-plugin-to-v1",
|
||||||
|
"version": "21.0.0-beta.5",
|
||||||
|
"cli": "nx",
|
||||||
|
"description": "Change @nx/gradle plugin to version 1",
|
||||||
|
"factory": "./src/migrations/21-0-0/change-plugin-to-v1",
|
||||||
|
"implementation": "/packages/gradle/src/migrations/21-0-0/change-plugin-to-v1.ts",
|
||||||
|
"aliases": [],
|
||||||
|
"hidden": false,
|
||||||
|
"path": "/packages/gradle",
|
||||||
|
"schema": null,
|
||||||
|
"type": "migration",
|
||||||
|
"examplesFile": "#### Change @nx/gradle plugin to @nx/gradle/plugin-v1\n\nChange @nx/gradle plugin to version 1 in nx.json\n\n#### Sample Code Changes\n\n{% tabs %}\n{% tab label=\"Before\" %}\n\n```json {% fileName=\"nx.json\" %}\n{\n \"plugins\": [\"@nx/gradle\"]\n}\n```\n\n{% /tab %}\n{% tab label=\"After\" %}\n\n```json {% highlightLines=[5] fileName=\"nx.json\" %}\n{\n \"plugins\": [\"@nx/gradle/plugin-v1\"]\n}\n```\n\n{% /tab %}\n{% /tabs %}\n"
|
||||||
|
}
|
||||||
@ -375,10 +375,10 @@ jobs:
|
|||||||
# Uncomment this line to enable task distribution
|
# Uncomment this line to enable task distribution
|
||||||
# - run: npx nx-cloud start-ci-run --distribute-on="3 linux-medium-jvm" --stop-agents-after="build"
|
# - run: npx nx-cloud start-ci-run --distribute-on="3 linux-medium-jvm" --stop-agents-after="build"
|
||||||
|
|
||||||
- name: Set up JDK 17 for x64
|
- name: Set up JDK 21 for x64
|
||||||
uses: actions/setup-java@v4
|
uses: actions/setup-java@v4
|
||||||
with:
|
with:
|
||||||
java-version: '17'
|
java-version: '21'
|
||||||
distribution: 'temurin'
|
distribution: 'temurin'
|
||||||
architecture: x64
|
architecture: x64
|
||||||
|
|
||||||
|
|||||||
@ -1,2 +0,0 @@
|
|||||||
# This file was generated by the Gradle 'init' task.
|
|
||||||
# https://docs.gradle.org/current/userguide/platforms.html#sub::toml-dependencies-format
|
|
||||||
BIN
e2e/gradle/gradle/wrapper/gradle-wrapper.jar
vendored
BIN
e2e/gradle/gradle/wrapper/gradle-wrapper.jar
vendored
Binary file not shown.
@ -17,10 +17,9 @@ import { createGradleProject } from './utils/create-gradle-project';
|
|||||||
import { createFileSync } from 'fs-extra';
|
import { createFileSync } from 'fs-extra';
|
||||||
|
|
||||||
describe('Nx Import Gradle', () => {
|
describe('Nx Import Gradle', () => {
|
||||||
let proj: string;
|
|
||||||
const tempImportE2ERoot = join(e2eCwd, 'nx-import');
|
const tempImportE2ERoot = join(e2eCwd, 'nx-import');
|
||||||
beforeAll(() => {
|
beforeAll(() => {
|
||||||
proj = newProject({
|
newProject({
|
||||||
packages: ['@nx/js'],
|
packages: ['@nx/js'],
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -66,30 +65,7 @@ describe('Nx Import Gradle', () => {
|
|||||||
'gradleProjectKotlin',
|
'gradleProjectKotlin',
|
||||||
'kotlin-'
|
'kotlin-'
|
||||||
);
|
);
|
||||||
// Add project.json files to the gradle project to avoid duplicate project names
|
setupGradleProjectGit(tempGraldeProjectPath, tempGradleProjectName);
|
||||||
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,
|
|
||||||
});
|
|
||||||
|
|
||||||
try {
|
|
||||||
execSync(`git checkout -b main`, {
|
|
||||||
cwd: tempGraldeProjectPath,
|
|
||||||
});
|
|
||||||
} catch {
|
|
||||||
// This fails if git is already configured to have `main` branch, but that's OK
|
|
||||||
}
|
|
||||||
|
|
||||||
const remote = tempGraldeProjectPath;
|
const remote = tempGraldeProjectPath;
|
||||||
const ref = 'main';
|
const ref = 'main';
|
||||||
@ -140,30 +116,7 @@ describe('Nx Import Gradle', () => {
|
|||||||
'gradleProjectGroovy',
|
'gradleProjectGroovy',
|
||||||
'groovy-'
|
'groovy-'
|
||||||
);
|
);
|
||||||
// Add project.json files to the gradle project to avoid duplicate project names
|
setupGradleProjectGit(tempGraldeProjectPath, tempGradleProjectName);
|
||||||
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,
|
|
||||||
});
|
|
||||||
|
|
||||||
try {
|
|
||||||
execSync(`git checkout -b main`, {
|
|
||||||
cwd: tempGraldeProjectPath,
|
|
||||||
});
|
|
||||||
} catch {
|
|
||||||
// This fails if git is already configured to have `main` branch, but that's OK
|
|
||||||
}
|
|
||||||
|
|
||||||
const remote = tempGraldeProjectPath;
|
const remote = tempGraldeProjectPath;
|
||||||
const ref = 'main';
|
const ref = 'main';
|
||||||
@ -199,3 +152,40 @@ describe('Nx Import Gradle', () => {
|
|||||||
runCommand(`git commit -am 'import groovy project'`);
|
runCommand(`git commit -am 'import groovy project'`);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function setupGradleProjectGit(
|
||||||
|
tempGraldeProjectPath: string,
|
||||||
|
tempGradleProjectName: string
|
||||||
|
) {
|
||||||
|
// 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(`./gradlew --stop`, {
|
||||||
|
cwd: tempGraldeProjectPath,
|
||||||
|
});
|
||||||
|
execSync(`./gradlew clean`, {
|
||||||
|
cwd: tempGraldeProjectPath,
|
||||||
|
});
|
||||||
|
|
||||||
|
execSync(`git init`, {
|
||||||
|
cwd: tempGraldeProjectPath,
|
||||||
|
});
|
||||||
|
execSync(`git add .`, {
|
||||||
|
cwd: tempGraldeProjectPath,
|
||||||
|
});
|
||||||
|
execSync(`git commit -am "initial commit"`, {
|
||||||
|
cwd: tempGraldeProjectPath,
|
||||||
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
execSync(`git checkout -b main`, {
|
||||||
|
cwd: tempGraldeProjectPath,
|
||||||
|
});
|
||||||
|
} catch {
|
||||||
|
// This fails if git is already configured to have `main` branch, but that's OK
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
177
e2e/gradle/src/gradle-plugin-v1.test.ts
Normal file
177
e2e/gradle/src/gradle-plugin-v1.test.ts
Normal file
@ -0,0 +1,177 @@
|
|||||||
|
import {
|
||||||
|
checkFilesExist,
|
||||||
|
cleanupProject,
|
||||||
|
createFile,
|
||||||
|
fileExists,
|
||||||
|
newProject,
|
||||||
|
readFile,
|
||||||
|
runCLI,
|
||||||
|
uniq,
|
||||||
|
updateFile,
|
||||||
|
updateJson,
|
||||||
|
} from '@nx/e2e/utils';
|
||||||
|
import { basename, dirname, join } from 'path';
|
||||||
|
|
||||||
|
import { createGradleProject } from './utils/create-gradle-project';
|
||||||
|
|
||||||
|
describe('Gradle Plugin V1', () => {
|
||||||
|
describe.each([{ type: 'kotlin' }, { type: 'groovy' }])(
|
||||||
|
'$type',
|
||||||
|
({ type }: { type: 'kotlin' | 'groovy' }) => {
|
||||||
|
let gradleProjectName = uniq('my-gradle-project');
|
||||||
|
beforeAll(() => {
|
||||||
|
newProject();
|
||||||
|
createGradleProject(gradleProjectName, type);
|
||||||
|
runCLI(`add @nx/gradle`);
|
||||||
|
updateJson('nx.json', (json) => {
|
||||||
|
json.plugins.find((p) => p.plugin === '@nx/gradle').plugin =
|
||||||
|
'@nx/gradle/plugin-v1';
|
||||||
|
return json;
|
||||||
|
});
|
||||||
|
addProjectReportToBuildGradle(
|
||||||
|
`settings.gradle${type === 'kotlin' ? '.kts' : ''}`
|
||||||
|
);
|
||||||
|
});
|
||||||
|
afterAll(() => cleanupProject());
|
||||||
|
|
||||||
|
it('should build', () => {
|
||||||
|
const projects = runCLI(`show projects`);
|
||||||
|
expect(projects).toContain('app');
|
||||||
|
expect(projects).toContain('list');
|
||||||
|
expect(projects).toContain('utilities');
|
||||||
|
expect(projects).toContain(gradleProjectName);
|
||||||
|
|
||||||
|
const buildOutput = runCLI('build app', { verbose: true });
|
||||||
|
expect(buildOutput).toContain('nx run list:build');
|
||||||
|
expect(buildOutput).toContain(':list:classes');
|
||||||
|
expect(buildOutput).toContain('nx run utilities:build');
|
||||||
|
expect(buildOutput).toContain(':utilities:classes');
|
||||||
|
|
||||||
|
checkFilesExist(
|
||||||
|
`app/build/libs/app.jar`,
|
||||||
|
`list/build/libs/list.jar`,
|
||||||
|
`utilities/build/libs/utilities.jar`
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should track dependencies for new app', () => {
|
||||||
|
if (type === 'groovy') {
|
||||||
|
createFile(
|
||||||
|
`app2/build.gradle`,
|
||||||
|
`plugins {
|
||||||
|
id 'buildlogic.groovy-application-conventions'
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation project(':app')
|
||||||
|
}`
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
createFile(
|
||||||
|
`app2/build.gradle.kts`,
|
||||||
|
`plugins {
|
||||||
|
id("buildlogic.kotlin-application-conventions")
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation(project(":app"))
|
||||||
|
}`
|
||||||
|
);
|
||||||
|
updateFile(`app/build.gradle.kts`, (content) => {
|
||||||
|
content += `\r\ntasks.register("task1"){
|
||||||
|
println("REGISTER TASK1: This is executed during the configuration phase")
|
||||||
|
}`;
|
||||||
|
return content;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
updateFile(
|
||||||
|
`settings.gradle${type === 'kotlin' ? '.kts' : ''}`,
|
||||||
|
(content) => {
|
||||||
|
content += `\r\ninclude("app2")`;
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
let buildOutput = runCLI('build app2', { verbose: true });
|
||||||
|
// app2 depends on app
|
||||||
|
expect(buildOutput).toContain('nx run app:build');
|
||||||
|
expect(buildOutput).toContain(':app:classes');
|
||||||
|
expect(buildOutput).toContain('nx run list:build');
|
||||||
|
expect(buildOutput).toContain(':list:classes');
|
||||||
|
expect(buildOutput).toContain('nx run utilities:build');
|
||||||
|
expect(buildOutput).toContain(':utilities:classes');
|
||||||
|
|
||||||
|
checkFilesExist(
|
||||||
|
`app2/build/libs/app2.jar`,
|
||||||
|
`app/build/libs/app.jar`,
|
||||||
|
`list/build/libs/list.jar`,
|
||||||
|
`utilities/build/libs/utilities.jar`
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should run atomized test target', () => {
|
||||||
|
updateJson('nx.json', (json) => {
|
||||||
|
json.plugins.find((p) => p.plugin === '@nx/gradle/plugin-v1').options[
|
||||||
|
'ciTargetName'
|
||||||
|
] = 'test-ci';
|
||||||
|
return json;
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(() => {
|
||||||
|
runCLI('run app:test-ci--MessageUtilsTest', { verbose: true });
|
||||||
|
runCLI('run list:test-ci--LinkedListTest', { verbose: true });
|
||||||
|
}).not.toThrow();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
function addProjectReportToBuildGradle(settingsGradleFile: string) {
|
||||||
|
const filename = basename(settingsGradleFile);
|
||||||
|
let gradleFilePath = 'build.gradle';
|
||||||
|
if (filename.endsWith('.kts')) {
|
||||||
|
gradleFilePath = 'build.gradle.kts';
|
||||||
|
}
|
||||||
|
gradleFilePath = join(dirname(settingsGradleFile), gradleFilePath);
|
||||||
|
let buildGradleContent = '';
|
||||||
|
if (!fileExists(gradleFilePath)) {
|
||||||
|
createFile(gradleFilePath, buildGradleContent); // create a build.gradle file near settings.gradle file if it does not exist
|
||||||
|
} else {
|
||||||
|
buildGradleContent = readFile(gradleFilePath).toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
buildGradleContent += `\n\rallprojects {
|
||||||
|
apply {
|
||||||
|
plugin("project-report")
|
||||||
|
}
|
||||||
|
}`;
|
||||||
|
|
||||||
|
if (gradleFilePath.endsWith('.kts')) {
|
||||||
|
buildGradleContent += `\n\rtasks.register("projectReportAll") {
|
||||||
|
// All project reports of subprojects
|
||||||
|
allprojects.forEach {
|
||||||
|
dependsOn(it.tasks.get("projectReport"))
|
||||||
|
}
|
||||||
|
|
||||||
|
// All projectReportAll of included builds
|
||||||
|
gradle.includedBuilds.forEach {
|
||||||
|
dependsOn(it.task(":projectReportAll"))
|
||||||
|
}
|
||||||
|
}`;
|
||||||
|
} else {
|
||||||
|
buildGradleContent += `\n\rtasks.register("projectReportAll") {
|
||||||
|
// All project reports of subprojects
|
||||||
|
allprojects.forEach {
|
||||||
|
dependsOn(it.tasks.getAt("projectReport"))
|
||||||
|
}
|
||||||
|
|
||||||
|
// All projectReportAll of included builds
|
||||||
|
gradle.includedBuilds.forEach {
|
||||||
|
dependsOn(it.task(":projectReportAll"))
|
||||||
|
}
|
||||||
|
}`;
|
||||||
|
}
|
||||||
|
if (buildGradleContent) {
|
||||||
|
updateFile(gradleFilePath, buildGradleContent);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -6,6 +6,7 @@ import {
|
|||||||
runCLI,
|
runCLI,
|
||||||
uniq,
|
uniq,
|
||||||
updateFile,
|
updateFile,
|
||||||
|
updateJson,
|
||||||
} from '@nx/e2e/utils';
|
} from '@nx/e2e/utils';
|
||||||
|
|
||||||
import { createGradleProject } from './utils/create-gradle-project';
|
import { createGradleProject } from './utils/create-gradle-project';
|
||||||
@ -30,9 +31,9 @@ describe('Gradle', () => {
|
|||||||
expect(projects).toContain(gradleProjectName);
|
expect(projects).toContain(gradleProjectName);
|
||||||
|
|
||||||
const buildOutput = runCLI('build app', { verbose: true });
|
const buildOutput = runCLI('build app', { verbose: true });
|
||||||
expect(buildOutput).toContain('nx run list:build');
|
expect(buildOutput).toContain('nx run list:');
|
||||||
expect(buildOutput).toContain(':list:classes');
|
expect(buildOutput).toContain(':list:classes');
|
||||||
expect(buildOutput).toContain('nx run utilities:build');
|
expect(buildOutput).toContain('nx run utilities:');
|
||||||
expect(buildOutput).toContain(':utilities:classes');
|
expect(buildOutput).toContain(':utilities:classes');
|
||||||
|
|
||||||
checkFilesExist(
|
checkFilesExist(
|
||||||
@ -82,8 +83,28 @@ dependencies {
|
|||||||
|
|
||||||
let buildOutput = runCLI('build app2', { verbose: true });
|
let buildOutput = runCLI('build app2', { verbose: true });
|
||||||
// app2 depends on app
|
// app2 depends on app
|
||||||
expect(buildOutput).toContain('nx run app:build');
|
expect(buildOutput).toContain('nx run app:');
|
||||||
expect(buildOutput).toContain(':app:classes');
|
expect(buildOutput).toContain(':app:classes');
|
||||||
|
expect(buildOutput).toContain('nx run list:');
|
||||||
|
expect(buildOutput).toContain(':list:classes');
|
||||||
|
expect(buildOutput).toContain('nx run utilities:');
|
||||||
|
expect(buildOutput).toContain(':utilities:classes');
|
||||||
|
|
||||||
|
checkFilesExist(`app2/build/libs/app2.jar`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should run atomized test target', () => {
|
||||||
|
updateJson('nx.json', (json) => {
|
||||||
|
json.plugins.find((p) => p.plugin === '@nx/gradle').options[
|
||||||
|
'ciTargetName'
|
||||||
|
] = 'test-ci';
|
||||||
|
return json;
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(() => {
|
||||||
|
runCLI('run app:test-ci--MessageUtilsTest', { verbose: true });
|
||||||
|
runCLI('run list:test-ci--LinkedListTest', { verbose: true });
|
||||||
|
}).not.toThrow();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|||||||
@ -5,6 +5,7 @@ import {
|
|||||||
tmpProjPath,
|
tmpProjPath,
|
||||||
} from '@nx/e2e/utils';
|
} from '@nx/e2e/utils';
|
||||||
import { execSync } from 'child_process';
|
import { execSync } from 'child_process';
|
||||||
|
import { readFileSync } from 'fs';
|
||||||
import { createFileSync, writeFileSync } from 'fs-extra';
|
import { createFileSync, writeFileSync } from 'fs-extra';
|
||||||
import { join, resolve } from 'path';
|
import { join, resolve } from 'path';
|
||||||
|
|
||||||
@ -15,14 +16,10 @@ export function createGradleProject(
|
|||||||
packageName: string = 'gradleProject',
|
packageName: string = 'gradleProject',
|
||||||
addProjectJsonNamePrefix: string = ''
|
addProjectJsonNamePrefix: string = ''
|
||||||
) {
|
) {
|
||||||
e2eConsoleLogger(
|
e2eConsoleLogger(`Using java version: ${execSync('java -version')}`);
|
||||||
`Using java version: ${execSync('java -version')} ${execSync(
|
|
||||||
'echo $JAVA_HOME'
|
|
||||||
)}`
|
|
||||||
);
|
|
||||||
const gradleCommand = isWindows()
|
const gradleCommand = isWindows()
|
||||||
? resolve(`${__dirname}/../../gradlew.bat`)
|
? resolve(`${__dirname}/../../../../gradlew.bat`)
|
||||||
: resolve(`${__dirname}/../../gradlew`);
|
: resolve(`${__dirname}/../../../../gradlew`);
|
||||||
e2eConsoleLogger(
|
e2eConsoleLogger(
|
||||||
'Using gradle version: ' +
|
'Using gradle version: ' +
|
||||||
execSync(`${gradleCommand} --version`, {
|
execSync(`${gradleCommand} --version`, {
|
||||||
@ -36,13 +33,26 @@ export function createGradleProject(
|
|||||||
);
|
);
|
||||||
e2eConsoleLogger(
|
e2eConsoleLogger(
|
||||||
runCommand(
|
runCommand(
|
||||||
`${gradleCommand} init --type ${type}-application --dsl ${type} --project-name ${projectName} --package ${packageName} --no-incubating --split-project`,
|
`${gradleCommand} init --type ${type}-application --dsl ${type} --project-name ${projectName} --package ${packageName} --no-incubating --split-project --overwrite`,
|
||||||
{
|
{
|
||||||
cwd,
|
cwd,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
try {
|
||||||
|
e2eConsoleLogger(
|
||||||
|
runCommand(`${gradleCommand} --stop`, {
|
||||||
|
cwd,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
e2eConsoleLogger(
|
||||||
|
runCommand(`${gradleCommand} clean`, {
|
||||||
|
cwd,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
} catch (e) {}
|
||||||
|
|
||||||
if (addProjectJsonNamePrefix) {
|
if (addProjectJsonNamePrefix) {
|
||||||
createFileSync(join(cwd, 'app/project.json'));
|
createFileSync(join(cwd, 'app/project.json'));
|
||||||
writeFileSync(
|
writeFileSync(
|
||||||
@ -60,4 +70,35 @@ export function createGradleProject(
|
|||||||
`{"name": "${addProjectJsonNamePrefix}utilities"}`
|
`{"name": "${addProjectJsonNamePrefix}utilities"}`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
addLocalPluginManagement(
|
||||||
|
join(cwd, `settings.gradle${type === 'kotlin' ? '.kts' : ''}`)
|
||||||
|
);
|
||||||
|
addLocalPluginManagement(
|
||||||
|
join(cwd, `buildSrc/settings.gradle${type === 'kotlin' ? '.kts' : ''}`)
|
||||||
|
);
|
||||||
|
|
||||||
|
e2eConsoleLogger(
|
||||||
|
execSync(
|
||||||
|
`${gradleCommand} :project-graph:publishToMavenLocal -x :project-graph:signNxProjectGraphPluginPluginMarkerMavenPublication -x :project-graph:signPluginMavenPublication -x :project-graph:publishNxProjectGraphPluginPluginMarkerMavenPublicationToMavenLocal -x :project-graph:publishPluginMavenPublicationToMavenLocal`,
|
||||||
|
{
|
||||||
|
cwd: `${__dirname}/../../../..`,
|
||||||
|
}
|
||||||
|
).toString()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function addLocalPluginManagement(filePath: string) {
|
||||||
|
let content = readFileSync(filePath).toString();
|
||||||
|
content =
|
||||||
|
`pluginManagement {
|
||||||
|
repositories {
|
||||||
|
mavenLocal()
|
||||||
|
gradlePluginPortal()
|
||||||
|
mavenCentral()
|
||||||
|
// Add other repositories if needed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
` + content;
|
||||||
|
writeFileSync(filePath, content);
|
||||||
}
|
}
|
||||||
|
|||||||
8
gradle.properties
Normal file
8
gradle.properties
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
# This file was generated by the Gradle 'init' task.
|
||||||
|
# https://docs.gradle.org/current/userguide/build_environment.html#sec:gradle_configuration_properties
|
||||||
|
|
||||||
|
org.gradle.parallel=true
|
||||||
|
org.gradle.caching=true
|
||||||
|
# disable the configuration cache for this project https://docs.gradle.org/current/userguide/configuration_cache.html#config_cache:requirements:disallowed_types
|
||||||
|
# nxProjectGraph is not supported by the configuration cache
|
||||||
|
org.gradle.configuration-cache=false
|
||||||
11
gradle/libs.versions.toml
Normal file
11
gradle/libs.versions.toml
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
# This file was generated by the Gradle 'init' task.
|
||||||
|
# https://docs.gradle.org/current/userguide/platforms.html#sub::toml-dependencies-format
|
||||||
|
|
||||||
|
[plugins]
|
||||||
|
jvm = { id = "org.jetbrains.kotlin.jvm", version = "1.9.20" }
|
||||||
|
|
||||||
|
[versions]
|
||||||
|
kotlin-gradle-plugin = "2.0.21"
|
||||||
|
|
||||||
|
[libraries]
|
||||||
|
kotlin-gradle-plugin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin-gradle-plugin" }
|
||||||
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
Binary file not shown.
@ -1,6 +1,7 @@
|
|||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip
|
||||||
validateDistributionUrl=false
|
networkTimeout=10000
|
||||||
|
validateDistributionUrl=true
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
8
e2e/gradle/gradlew → gradlew
vendored
8
e2e/gradle/gradlew → gradlew
vendored
@ -15,6 +15,8 @@
|
|||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
#
|
#
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
#
|
||||||
|
|
||||||
##############################################################################
|
##############################################################################
|
||||||
#
|
#
|
||||||
@ -55,7 +57,7 @@
|
|||||||
# Darwin, MinGW, and NonStop.
|
# Darwin, MinGW, and NonStop.
|
||||||
#
|
#
|
||||||
# (3) This script is generated from the Groovy template
|
# (3) This script is generated from the Groovy template
|
||||||
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||||
# within the Gradle project.
|
# within the Gradle project.
|
||||||
#
|
#
|
||||||
# You can find Gradle at https://github.com/gradle/gradle/.
|
# You can find Gradle at https://github.com/gradle/gradle/.
|
||||||
@ -84,7 +86,7 @@ done
|
|||||||
# shellcheck disable=SC2034
|
# shellcheck disable=SC2034
|
||||||
APP_BASE_NAME=${0##*/}
|
APP_BASE_NAME=${0##*/}
|
||||||
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
|
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
|
||||||
APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
|
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit
|
||||||
|
|
||||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||||
MAX_FD=maximum
|
MAX_FD=maximum
|
||||||
@ -203,7 +205,7 @@ fi
|
|||||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||||
|
|
||||||
# Collect all arguments for the java command:
|
# Collect all arguments for the java command:
|
||||||
# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
|
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
|
||||||
# and any embedded shellness will be escaped.
|
# and any embedded shellness will be escaped.
|
||||||
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
|
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
|
||||||
# treated as '${Hostname}' itself on the command line.
|
# treated as '${Hostname}' itself on the command line.
|
||||||
22
e2e/gradle/gradlew.bat → gradlew.bat
vendored
22
e2e/gradle/gradlew.bat → gradlew.bat
vendored
@ -13,6 +13,8 @@
|
|||||||
@rem See the License for the specific language governing permissions and
|
@rem See the License for the specific language governing permissions and
|
||||||
@rem limitations under the License.
|
@rem limitations under the License.
|
||||||
@rem
|
@rem
|
||||||
|
@rem SPDX-License-Identifier: Apache-2.0
|
||||||
|
@rem
|
||||||
|
|
||||||
@if "%DEBUG%"=="" @echo off
|
@if "%DEBUG%"=="" @echo off
|
||||||
@rem ##########################################################################
|
@rem ##########################################################################
|
||||||
@ -43,11 +45,11 @@ set JAVA_EXE=java.exe
|
|||||||
%JAVA_EXE% -version >NUL 2>&1
|
%JAVA_EXE% -version >NUL 2>&1
|
||||||
if %ERRORLEVEL% equ 0 goto execute
|
if %ERRORLEVEL% equ 0 goto execute
|
||||||
|
|
||||||
echo.
|
echo. 1>&2
|
||||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
|
||||||
echo.
|
echo. 1>&2
|
||||||
echo Please set the JAVA_HOME variable in your environment to match the
|
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||||
echo location of your Java installation.
|
echo location of your Java installation. 1>&2
|
||||||
|
|
||||||
goto fail
|
goto fail
|
||||||
|
|
||||||
@ -57,11 +59,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
|||||||
|
|
||||||
if exist "%JAVA_EXE%" goto execute
|
if exist "%JAVA_EXE%" goto execute
|
||||||
|
|
||||||
echo.
|
echo. 1>&2
|
||||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
|
||||||
echo.
|
echo. 1>&2
|
||||||
echo Please set the JAVA_HOME variable in your environment to match the
|
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||||
echo location of your Java installation.
|
echo location of your Java installation. 1>&2
|
||||||
|
|
||||||
goto fail
|
goto fail
|
||||||
|
|
||||||
@ -369,6 +369,7 @@
|
|||||||
"core-js": "3.36.1",
|
"core-js": "3.36.1",
|
||||||
"enquirer": "~2.3.6",
|
"enquirer": "~2.3.6",
|
||||||
"fast-glob": "3.3.3",
|
"fast-glob": "3.3.3",
|
||||||
|
"form-data": "^4.0.2",
|
||||||
"framer-motion": "^11.3.0",
|
"framer-motion": "^11.3.0",
|
||||||
"front-matter": "^4.0.2",
|
"front-matter": "^4.0.2",
|
||||||
"glob": "7.1.4",
|
"glob": "7.1.4",
|
||||||
|
|||||||
@ -27,7 +27,12 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"files": ["./package.json"],
|
"files": [
|
||||||
|
"./package.json",
|
||||||
|
"./generators.json",
|
||||||
|
"./executors.json",
|
||||||
|
"./migrations.json"
|
||||||
|
],
|
||||||
"parser": "jsonc-eslint-parser",
|
"parser": "jsonc-eslint-parser",
|
||||||
"rules": {
|
"rules": {
|
||||||
"@nx/nx-plugin-checks": "error"
|
"@nx/nx-plugin-checks": "error"
|
||||||
|
|||||||
3
packages/gradle/executors.json
Normal file
3
packages/gradle/executors.json
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"executors": {}
|
||||||
|
}
|
||||||
@ -17,6 +17,12 @@
|
|||||||
"cli": "nx",
|
"cli": "nx",
|
||||||
"description": "Add includeSubprojectsTasks to build.gradle file",
|
"description": "Add includeSubprojectsTasks to build.gradle file",
|
||||||
"factory": "./src/migrations/20-2-0/add-include-subprojects-tasks"
|
"factory": "./src/migrations/20-2-0/add-include-subprojects-tasks"
|
||||||
|
},
|
||||||
|
"change-plugin-to-v1": {
|
||||||
|
"version": "21.0.0-beta.5",
|
||||||
|
"cli": "nx",
|
||||||
|
"description": "Change @nx/gradle plugin to version 1",
|
||||||
|
"factory": "./src/migrations/21-0-0/change-plugin-to-v1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"packageJsonUpdates": {}
|
"packageJsonUpdates": {}
|
||||||
|
|||||||
@ -26,6 +26,7 @@
|
|||||||
"generators": "./generators.json",
|
"generators": "./generators.json",
|
||||||
"exports": {
|
"exports": {
|
||||||
".": "./index.js",
|
".": "./index.js",
|
||||||
|
"./plugin-v1": "./plugin-v1.js",
|
||||||
"./package.json": "./package.json",
|
"./package.json": "./package.json",
|
||||||
"./migrations.json": "./migrations.json",
|
"./migrations.json": "./migrations.json",
|
||||||
"./generators.json": "./generators.json"
|
"./generators.json": "./generators.json"
|
||||||
@ -38,5 +39,6 @@
|
|||||||
},
|
},
|
||||||
"publishConfig": {
|
"publishConfig": {
|
||||||
"access": "public"
|
"access": "public"
|
||||||
}
|
},
|
||||||
|
"executors": "./executors.json"
|
||||||
}
|
}
|
||||||
|
|||||||
131
packages/gradle/plugin-v1.spec.ts
Normal file
131
packages/gradle/plugin-v1.spec.ts
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
import { CreateNodesContext } from '@nx/devkit';
|
||||||
|
import { TempFs } from '@nx/devkit/internal-testing-utils';
|
||||||
|
import { createNodesV2 } from './plugin-v1';
|
||||||
|
import { type GradleReport } from './src/plugin-v1/utils/get-gradle-report';
|
||||||
|
|
||||||
|
let gradleReport: GradleReport;
|
||||||
|
jest.mock('./src/plugin-v1/utils/get-gradle-report', () => {
|
||||||
|
return {
|
||||||
|
GRADLE_BUILD_FILES: new Set(['build.gradle', 'build.gradle.kts']),
|
||||||
|
populateGradleReport: jest.fn().mockImplementation(() => void 0),
|
||||||
|
getCurrentGradleReport: jest.fn().mockImplementation(() => gradleReport),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('@nx/gradle/plugin-v1', () => {
|
||||||
|
let createNodesFunction = createNodesV2[1];
|
||||||
|
let context: CreateNodesContext;
|
||||||
|
let tempFs: TempFs;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
tempFs = new TempFs('gradle-plugin');
|
||||||
|
gradleReport = {
|
||||||
|
gradleFileToGradleProjectMap: new Map<string, string>([
|
||||||
|
['proj/build.gradle', 'proj'],
|
||||||
|
]),
|
||||||
|
gradleProjectToDepsMap: new Map<string, Set<string>>(),
|
||||||
|
gradleFileToOutputDirsMap: new Map<string, Map<string, string>>([
|
||||||
|
['proj/build.gradle', new Map([['build', 'build']])],
|
||||||
|
]),
|
||||||
|
gradleProjectToTasksMap: new Map<string, Set<string>>([
|
||||||
|
['proj', new Set(['test'])],
|
||||||
|
]),
|
||||||
|
gradleProjectToTasksTypeMap: new Map<string, Map<string, string>>([
|
||||||
|
['proj', new Map([['test', 'Verification']])],
|
||||||
|
]),
|
||||||
|
gradleProjectToProjectName: new Map<string, string>([['proj', 'proj']]),
|
||||||
|
gradleProjectNameToProjectRootMap: new Map<string, string>([
|
||||||
|
['proj', 'proj'],
|
||||||
|
]),
|
||||||
|
gradleProjectToChildProjects: new Map<string, string[]>(),
|
||||||
|
};
|
||||||
|
context = {
|
||||||
|
nxJsonConfiguration: {
|
||||||
|
namedInputs: {
|
||||||
|
default: ['{projectRoot}/**/*'],
|
||||||
|
production: ['!{projectRoot}/**/*.spec.ts'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
workspaceRoot: tempFs.tempDir,
|
||||||
|
configFiles: [],
|
||||||
|
};
|
||||||
|
tempFs.createFileSync('package.json', JSON.stringify({ name: 'repo' }));
|
||||||
|
tempFs.createFileSync(
|
||||||
|
'my-app/project.json',
|
||||||
|
JSON.stringify({ name: 'my-app' })
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
jest.resetModules();
|
||||||
|
tempFs.cleanup();
|
||||||
|
tempFs = null;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create nodes', async () => {
|
||||||
|
tempFs.createFileSync('gradlew', '');
|
||||||
|
|
||||||
|
const nodes = await createNodesFunction(
|
||||||
|
['gradlew', 'proj/build.gradle'],
|
||||||
|
undefined,
|
||||||
|
context
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(nodes).toMatchInlineSnapshot(`
|
||||||
|
[
|
||||||
|
[
|
||||||
|
"proj/build.gradle",
|
||||||
|
{
|
||||||
|
"projects": {
|
||||||
|
"proj": {
|
||||||
|
"metadata": {
|
||||||
|
"targetGroups": {
|
||||||
|
"Verification": [
|
||||||
|
"test",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"technologies": [
|
||||||
|
"gradle",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"name": "proj",
|
||||||
|
"projectType": "application",
|
||||||
|
"targets": {
|
||||||
|
"test": {
|
||||||
|
"cache": true,
|
||||||
|
"command": "./gradlew proj:test",
|
||||||
|
"dependsOn": [
|
||||||
|
"testClasses",
|
||||||
|
],
|
||||||
|
"inputs": [
|
||||||
|
"default",
|
||||||
|
"^production",
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"help": {
|
||||||
|
"command": "./gradlew help --task proj:test",
|
||||||
|
"example": {
|
||||||
|
"options": {
|
||||||
|
"args": [
|
||||||
|
"--rerun",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"technologies": [
|
||||||
|
"gradle",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"cwd": ".",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
]
|
||||||
|
`);
|
||||||
|
});
|
||||||
|
});
|
||||||
2
packages/gradle/plugin-v1.ts
Normal file
2
packages/gradle/plugin-v1.ts
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
export { createDependencies } from './src/plugin-v1/dependencies';
|
||||||
|
export { createNodes, createNodesV2 } from './src/plugin-v1/nodes';
|
||||||
@ -1,14 +1,17 @@
|
|||||||
import { CreateNodesContext } from '@nx/devkit';
|
import { CreateNodesContext, readJsonFile } from '@nx/devkit';
|
||||||
import { TempFs } from '@nx/devkit/internal-testing-utils';
|
import { TempFs } from '@nx/devkit/internal-testing-utils';
|
||||||
import { createNodesV2 } from './plugin';
|
import { createNodesV2 } from './plugin';
|
||||||
import { type GradleReport } from './src/utils/get-gradle-report';
|
import { type ProjectGraphReport } from './src/plugin/utils/get-project-graph-from-gradle-plugin';
|
||||||
|
import { join } from 'path';
|
||||||
|
|
||||||
let gradleReport: GradleReport;
|
let gradleReport: ProjectGraphReport;
|
||||||
jest.mock('./src/utils/get-gradle-report', () => {
|
jest.mock('./src/plugin/utils/get-project-graph-from-gradle-plugin', () => {
|
||||||
return {
|
return {
|
||||||
GRADLE_BUILD_FILES: new Set(['build.gradle', 'build.gradle.kts']),
|
GRADLE_BUILD_FILES: new Set(['build.gradle', 'build.gradle.kts']),
|
||||||
populateGradleReport: jest.fn().mockImplementation(() => void 0),
|
populateProjectGraph: jest.fn().mockImplementation(() => void 0),
|
||||||
getCurrentGradleReport: jest.fn().mockImplementation(() => gradleReport),
|
getCurrentProjectGraphReport: jest
|
||||||
|
.fn()
|
||||||
|
.mockImplementation(() => gradleReport),
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -19,26 +22,9 @@ describe('@nx/gradle/plugin', () => {
|
|||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
tempFs = new TempFs('gradle-plugin');
|
tempFs = new TempFs('gradle-plugin');
|
||||||
gradleReport = {
|
gradleReport = readJsonFile(
|
||||||
gradleFileToGradleProjectMap: new Map<string, string>([
|
join(__dirname, 'src/plugin/utils/__mocks__/gradle_tutorial.json')
|
||||||
['proj/build.gradle', 'proj'],
|
);
|
||||||
]),
|
|
||||||
buildFileToDepsMap: new Map<string, Set<string>>(),
|
|
||||||
gradleFileToOutputDirsMap: new Map<string, Map<string, string>>([
|
|
||||||
['proj/build.gradle', new Map([['build', 'build']])],
|
|
||||||
]),
|
|
||||||
gradleProjectToTasksMap: new Map<string, Set<string>>([
|
|
||||||
['proj', new Set(['test'])],
|
|
||||||
]),
|
|
||||||
gradleProjectToTasksTypeMap: new Map<string, Map<string, string>>([
|
|
||||||
['proj', new Map([['test', 'Verification']])],
|
|
||||||
]),
|
|
||||||
gradleProjectToProjectName: new Map<string, string>([['proj', 'proj']]),
|
|
||||||
gradleProjectNameToProjectRootMap: new Map<string, string>([
|
|
||||||
['proj', 'proj'],
|
|
||||||
]),
|
|
||||||
gradleProjectToChildProjects: new Map<string, string[]>(),
|
|
||||||
};
|
|
||||||
context = {
|
context = {
|
||||||
nxJsonConfiguration: {
|
nxJsonConfiguration: {
|
||||||
namedInputs: {
|
namedInputs: {
|
||||||
@ -76,48 +62,33 @@ describe('@nx/gradle/plugin', () => {
|
|||||||
[
|
[
|
||||||
"proj/build.gradle",
|
"proj/build.gradle",
|
||||||
{
|
{
|
||||||
|
"externalNodes": {},
|
||||||
"projects": {
|
"projects": {
|
||||||
"proj": {
|
"proj": {
|
||||||
"metadata": {
|
"metadata": {
|
||||||
"targetGroups": {
|
"targetGroups": {
|
||||||
"Verification": [
|
"help": [
|
||||||
"test",
|
"buildEnvironment",
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
"technologies": [
|
"technologies": [
|
||||||
"gradle",
|
"gradle",
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
"name": "proj",
|
"name": "gradle-tutorial",
|
||||||
"projectType": "application",
|
"root": "proj",
|
||||||
"targets": {
|
"targets": {
|
||||||
"test": {
|
"buildEnvironment": {
|
||||||
"cache": true,
|
"cache": true,
|
||||||
"command": "./gradlew proj:test",
|
"command": "./gradlew :buildEnvironment",
|
||||||
"dependsOn": [
|
|
||||||
"testClasses",
|
|
||||||
],
|
|
||||||
"inputs": [
|
|
||||||
"default",
|
|
||||||
"^production",
|
|
||||||
],
|
|
||||||
"metadata": {
|
"metadata": {
|
||||||
"help": {
|
"description": "Displays all buildscript dependencies declared in root project 'gradle-tutorial'.",
|
||||||
"command": "./gradlew help --task proj:test",
|
|
||||||
"example": {
|
|
||||||
"options": {
|
|
||||||
"args": [
|
|
||||||
"--rerun",
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"technologies": [
|
"technologies": [
|
||||||
"gradle",
|
"gradle",
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
"options": {
|
"options": {
|
||||||
"cwd": ".",
|
"cwd": "proj",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@ -1,2 +1,2 @@
|
|||||||
export { createDependencies } from './src/plugin/dependencies';
|
export { createDependencies } from './src/plugin/dependencies';
|
||||||
export { createNodes, createNodesV2 } from './src/plugin/nodes';
|
export { createNodesV2 } from './src/plugin/nodes';
|
||||||
|
|||||||
3
packages/gradle/project-graph/.gitignore
vendored
Normal file
3
packages/gradle/project-graph/.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# Ignore Gradle project-specific cache directory
|
||||||
|
bin
|
||||||
|
build
|
||||||
56
packages/gradle/project-graph/README.md
Normal file
56
packages/gradle/project-graph/README.md
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
# dev.nx.gradle.project-graph
|
||||||
|
|
||||||
|
This gradle plugin contains
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
Kotlin
|
||||||
|
build.gradle.kts
|
||||||
|
|
||||||
|
```
|
||||||
|
plugins {
|
||||||
|
id("dev.nx.gradle.project-graph") version("+")
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Groovy
|
||||||
|
build.gradle
|
||||||
|
|
||||||
|
```
|
||||||
|
plugins {
|
||||||
|
id "dev.nx.gradle.project-graph" version "+"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./gradlew nxProjectGraph
|
||||||
|
```
|
||||||
|
|
||||||
|
In terminal, it should output something like:
|
||||||
|
|
||||||
|
```
|
||||||
|
> Task :nxProjectGraph
|
||||||
|
< your workspace >/build/nx/add-nx-to-gradle.json
|
||||||
|
```
|
||||||
|
|
||||||
|
To pass in a hash parameter:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./gradlew nxProjectGraph -Phash=12345
|
||||||
|
```
|
||||||
|
|
||||||
|
It generates a json file to be consumed by nx:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"nodes": {
|
||||||
|
"app": {
|
||||||
|
"targets": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"dependencies": [],
|
||||||
|
"externalNodes": {}
|
||||||
|
}
|
||||||
|
```
|
||||||
120
packages/gradle/project-graph/build.gradle.kts
Normal file
120
packages/gradle/project-graph/build.gradle.kts
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
plugins {
|
||||||
|
`java-gradle-plugin`
|
||||||
|
`maven-publish`
|
||||||
|
signing
|
||||||
|
id("com.ncorti.ktfmt.gradle") version "+"
|
||||||
|
id("dev.nx.gradle.project-graph") version "0.0.2"
|
||||||
|
id("org.jetbrains.kotlin.jvm") version "2.1.10"
|
||||||
|
id("com.gradle.plugin-publish") version "1.2.1"
|
||||||
|
}
|
||||||
|
|
||||||
|
group = "dev.nx.gradle"
|
||||||
|
|
||||||
|
version = "0.0.2"
|
||||||
|
|
||||||
|
repositories { mavenCentral() }
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation("com.google.code.gson:gson:2.10.1")
|
||||||
|
testImplementation(kotlin("test"))
|
||||||
|
testImplementation("org.mockito:mockito-core:5.8.0")
|
||||||
|
testImplementation("org.mockito.kotlin:mockito-kotlin:5.2.1")
|
||||||
|
testImplementation("org.junit.jupiter:junit-jupiter:5.10.1")
|
||||||
|
}
|
||||||
|
|
||||||
|
java {
|
||||||
|
withSourcesJar()
|
||||||
|
withJavadocJar()
|
||||||
|
}
|
||||||
|
|
||||||
|
gradlePlugin {
|
||||||
|
website = "https://nx.dev/"
|
||||||
|
vcsUrl = "https://github.com/nrwl/nx"
|
||||||
|
plugins {
|
||||||
|
create("nxProjectGraphPlugin") {
|
||||||
|
id = "dev.nx.gradle.project-graph"
|
||||||
|
implementationClass = "dev.nx.gradle.NxProjectGraphReportPlugin"
|
||||||
|
displayName = "The Nx Plugin for Gradle to generate Nx project graph"
|
||||||
|
description = "Generates a JSON file with nodes, dependencies, and external nodes for Nx"
|
||||||
|
tags = listOf("nx", "monorepo", "javascript", "typescript")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
afterEvaluate {
|
||||||
|
publishing {
|
||||||
|
publications.named("pluginMaven", MavenPublication::class) {
|
||||||
|
pom {
|
||||||
|
name.set("Nx Gradle Project Graph Plugin")
|
||||||
|
description.set(
|
||||||
|
"A plugin to generate a JSON file with nodes, dependencies, and external nodes for Nx")
|
||||||
|
url.set("https://github.com/nrwl/nx")
|
||||||
|
|
||||||
|
licenses { license { name.set("MIT") } }
|
||||||
|
|
||||||
|
developers {
|
||||||
|
developer {
|
||||||
|
id.set("nx")
|
||||||
|
name.set("Nx")
|
||||||
|
email.set("java-services@nrwl.io")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
scm {
|
||||||
|
connection.set("scm:git:git://github.com/nrwl/nx.git")
|
||||||
|
developerConnection.set("scm:git:ssh://github.com/nrwl/nx.git")
|
||||||
|
url.set("https://github.com/nrwl/nx")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
maven {
|
||||||
|
name = "localStaging"
|
||||||
|
url = uri(layout.buildDirectory.dir("staging"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
publishing {
|
||||||
|
publications.named("nxProjectGraphPluginPluginMarkerMaven", MavenPublication::class) {
|
||||||
|
pom {
|
||||||
|
name.set("Nx Gradle Project Graph Plugin")
|
||||||
|
description.set(
|
||||||
|
"A plugin to generate a JSON file with nodes, dependencies, and external nodes for Nx")
|
||||||
|
url.set("https://github.com/nrwl/nx")
|
||||||
|
|
||||||
|
licenses { license { name.set("MIT") } }
|
||||||
|
|
||||||
|
developers {
|
||||||
|
developer {
|
||||||
|
id.set("nx")
|
||||||
|
name.set("Nx")
|
||||||
|
email.set("java-services@nrwl.io")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
scm {
|
||||||
|
connection.set("scm:git:git://github.com/nrwl/nx.git")
|
||||||
|
developerConnection.set("scm:git:ssh://github.com/nrwl/nx.git")
|
||||||
|
url.set("https://github.com/nrwl/nx")
|
||||||
|
}
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
maven {
|
||||||
|
name = "localStaging"
|
||||||
|
url = uri(layout.buildDirectory.dir("staging"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
signing {
|
||||||
|
afterEvaluate {
|
||||||
|
sign(publishing.publications["pluginMaven"])
|
||||||
|
sign(publishing.publications["nxProjectGraphPluginPluginMarkerMaven"])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.test { useJUnitPlatform() }
|
||||||
43
packages/gradle/project-graph/project.json
Normal file
43
packages/gradle/project-graph/project.json
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
{
|
||||||
|
"name": "gradle-project-graph",
|
||||||
|
"$schema": "node_modules/nx/schemas/project-schema.json",
|
||||||
|
"targets": {
|
||||||
|
"test": {
|
||||||
|
"command": "./gradlew :project-graph:test",
|
||||||
|
"options": {
|
||||||
|
"args": []
|
||||||
|
},
|
||||||
|
"cache": true
|
||||||
|
},
|
||||||
|
"lint": {
|
||||||
|
"command": "./gradlew :project-graph:ktfmtCheck",
|
||||||
|
"cache": true
|
||||||
|
},
|
||||||
|
"format": {
|
||||||
|
"command": "./gradlew :project-graph:ktfmtFormat",
|
||||||
|
"cache": true
|
||||||
|
},
|
||||||
|
"publish-staging": {
|
||||||
|
"command": "./gradlew :project-graph:publish",
|
||||||
|
"cache": true,
|
||||||
|
"outputs": ["{projectRoot}/build/staging"]
|
||||||
|
},
|
||||||
|
"zip-staging": {
|
||||||
|
"command": "zip -r ../deployment.zip .",
|
||||||
|
"options": {
|
||||||
|
"cwd": "{projectRoot}/build/staging"
|
||||||
|
},
|
||||||
|
"inputs": ["{projectRoot}/build/staging"],
|
||||||
|
"outputs": ["{projectRoot}/build/deployment.zip"],
|
||||||
|
"dependsOn": ["publish-staging"]
|
||||||
|
},
|
||||||
|
"maven": {
|
||||||
|
"command": "npx ts-node publish-maven.ts --deploymentZipPath=build/deployment.zip",
|
||||||
|
"options": {
|
||||||
|
"cwd": "{projectRoot}"
|
||||||
|
},
|
||||||
|
"inputs": ["{projectRoot}/build/deployment.zip"],
|
||||||
|
"dependsOn": ["zip-staging"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
133
packages/gradle/project-graph/publish-maven.ts
Normal file
133
packages/gradle/project-graph/publish-maven.ts
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
import axios from 'axios';
|
||||||
|
import * as fs from 'fs';
|
||||||
|
import * as FormData from 'form-data';
|
||||||
|
|
||||||
|
function parseArgs() {
|
||||||
|
const args = process.argv.slice(2);
|
||||||
|
const result: Record<string, string> = {};
|
||||||
|
args.forEach((arg) => {
|
||||||
|
const [key, value] = arg.replace(/^--/, '').split('=');
|
||||||
|
result[key] = value;
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function publishToMavenApi(
|
||||||
|
username: string,
|
||||||
|
password: string,
|
||||||
|
deploymentZipPath = 'deployment.zip'
|
||||||
|
) {
|
||||||
|
const token = Buffer.from(`${username}:${password}`).toString('base64');
|
||||||
|
console.log(`📦 Publishing to Maven Central...`);
|
||||||
|
|
||||||
|
const url = 'https://central.sonatype.com/api/v1/publisher/upload';
|
||||||
|
const form = new FormData();
|
||||||
|
form.append('bundle', fs.createReadStream(deploymentZipPath));
|
||||||
|
|
||||||
|
let uploadId: string;
|
||||||
|
try {
|
||||||
|
const response = await axios.post(url, form, {
|
||||||
|
headers: {
|
||||||
|
Authorization: `Basic ${token}`,
|
||||||
|
...form.getHeaders(),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
uploadId = response.data.toString().trim();
|
||||||
|
console.log(`✅ Upload ID: ${uploadId}`);
|
||||||
|
} catch (err: any) {
|
||||||
|
console.error('🚫 Upload failed:', err.response?.data || err.message);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
let currentStatus = await getUploadStatus(uploadId, token);
|
||||||
|
if (['PENDING', 'VALIDATING', 'PUBLISHING'].includes(currentStatus)) {
|
||||||
|
currentStatus = await retryUntilValidatedOrPublished(
|
||||||
|
currentStatus,
|
||||||
|
uploadId,
|
||||||
|
token
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!['VALIDATED', 'PUBLISHED'].includes(currentStatus)) {
|
||||||
|
console.error(`🚫 Upload failed with final status: ${currentStatus}`);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`📦 Upload is ${currentStatus}, proceeding to deploy...`);
|
||||||
|
if (currentStatus === 'PUBLISHED') {
|
||||||
|
console.log('✅ Already published, skipping deployment.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const deployUrl = `https://central.sonatype.com/api/v1/publisher/deployment/${uploadId}`;
|
||||||
|
try {
|
||||||
|
const deployRes = await axios.post(deployUrl, null, {
|
||||||
|
headers: { Authorization: `Basic ${token}` },
|
||||||
|
});
|
||||||
|
console.log(`🚀 Deployment response: ${deployRes.data}`);
|
||||||
|
} catch (err: any) {
|
||||||
|
console.error('🚫 Deployment failed:', err.response?.data || err.message);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getUploadStatus(
|
||||||
|
uploadId: string,
|
||||||
|
token: string
|
||||||
|
): Promise<string> {
|
||||||
|
const url = `https://central.sonatype.com/api/v1/publisher/status?id=${uploadId}`;
|
||||||
|
try {
|
||||||
|
const response = await axios.post(url, null, {
|
||||||
|
headers: { Authorization: `Basic ${token}` },
|
||||||
|
});
|
||||||
|
const state = response.data.deploymentState;
|
||||||
|
console.log(`📡 Current deployment state: ${state}`);
|
||||||
|
return state;
|
||||||
|
} catch (err: any) {
|
||||||
|
console.error(
|
||||||
|
'🚫 Failed to get status:',
|
||||||
|
err.response?.data || err.message
|
||||||
|
);
|
||||||
|
return 'FAILED';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function retryUntilValidatedOrPublished(
|
||||||
|
currentStatus: string,
|
||||||
|
uploadId: string,
|
||||||
|
token: string,
|
||||||
|
retries = 10,
|
||||||
|
delay = 10_000
|
||||||
|
): Promise<string> {
|
||||||
|
for (let i = 0; i < retries; i++) {
|
||||||
|
console.log(`🔁 Checking status (attempt ${i + 1}/${retries})...`);
|
||||||
|
await sleep(delay);
|
||||||
|
currentStatus = await getUploadStatus(uploadId, token);
|
||||||
|
if (['VALIDATED', 'PUBLISHED', 'FAILED'].includes(currentStatus)) break;
|
||||||
|
}
|
||||||
|
return currentStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
function sleep(ms: number) {
|
||||||
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Entry
|
||||||
|
(async function main() {
|
||||||
|
let { username, password, deploymentZipPath } = parseArgs();
|
||||||
|
|
||||||
|
username = username || process.env.MAVEN_USERNAME;
|
||||||
|
password = password || process.env.MAVEN_PASSWORD;
|
||||||
|
|
||||||
|
if (!username || !password) {
|
||||||
|
console.error('❌ Missing MAVEN_USERNAME or MAVEN_PASSWORD');
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!deploymentZipPath) {
|
||||||
|
console.error('❌ Missing required --deploymentZipPath argument');
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
await publishToMavenApi(username, password, deploymentZipPath);
|
||||||
|
})();
|
||||||
16
packages/gradle/project-graph/settings.gradle.kts
Normal file
16
packages/gradle/project-graph/settings.gradle.kts
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
/*
|
||||||
|
* This file was generated by the Gradle 'init' task.
|
||||||
|
*
|
||||||
|
* The settings file is used to specify which projects to include in your build.
|
||||||
|
* For more detailed information on multi-project builds, please refer to https://docs.gradle.org/8.5/userguide/building_swift_projects.html in the Gradle documentation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
pluginManagement {
|
||||||
|
repositories {
|
||||||
|
mavenLocal()
|
||||||
|
mavenCentral()
|
||||||
|
gradlePluginPortal()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rootProject.name = "project-graph"
|
||||||
@ -0,0 +1,94 @@
|
|||||||
|
package dev.nx.gradle
|
||||||
|
|
||||||
|
import java.util.*
|
||||||
|
import org.gradle.api.Plugin
|
||||||
|
import org.gradle.api.Project
|
||||||
|
import org.gradle.api.tasks.TaskProvider
|
||||||
|
|
||||||
|
class NxProjectGraphReportPlugin : Plugin<Project> {
|
||||||
|
override fun apply(project: Project) {
|
||||||
|
project.logger.info("${Date()} Applying NxProjectGraphReportPlugin to ${project.name}")
|
||||||
|
|
||||||
|
val nxProjectReportTask: TaskProvider<NxProjectReportTask> =
|
||||||
|
project.tasks.register("nxProjectReport", NxProjectReportTask::class.java) { task ->
|
||||||
|
val hashProperty =
|
||||||
|
project.findProperty("hash")?.toString()
|
||||||
|
?: run {
|
||||||
|
project.logger.warn(
|
||||||
|
"No 'hash' property was provided for $project. Using default hash value: 'default-hash'")
|
||||||
|
"default-hash"
|
||||||
|
}
|
||||||
|
|
||||||
|
val cwdProperty =
|
||||||
|
project.findProperty("cwd")?.toString()
|
||||||
|
?: run {
|
||||||
|
project.logger.warn(
|
||||||
|
"No 'cwd' property was provided for $project. Using default hash value: ${System.getProperty("user.dir")}")
|
||||||
|
System.getProperty("user.dir")
|
||||||
|
}
|
||||||
|
|
||||||
|
val workspaceRootProperty =
|
||||||
|
project.findProperty("workspaceRoot")?.toString()
|
||||||
|
?: run {
|
||||||
|
project.logger.warn(
|
||||||
|
"No 'workspaceRoot' property was provided for $project. Using default hash value: ${System.getProperty("user.dir")}")
|
||||||
|
System.getProperty("user.dir")
|
||||||
|
}
|
||||||
|
|
||||||
|
val targetNameOverrides: Map<String, String> =
|
||||||
|
project.properties
|
||||||
|
.filterKeys { it.endsWith("TargetName") }
|
||||||
|
.mapValues { it.value.toString() }
|
||||||
|
task.projectName.set(project.name)
|
||||||
|
task.projectRef.set(project)
|
||||||
|
task.hash.set(hashProperty)
|
||||||
|
task.targetNameOverrides.set(targetNameOverrides)
|
||||||
|
task.cwd.set(cwdProperty)
|
||||||
|
task.workspaceRoot.set(workspaceRootProperty)
|
||||||
|
|
||||||
|
task.description = "Create Nx project report for ${project.name}"
|
||||||
|
task.group = "Reporting"
|
||||||
|
|
||||||
|
task.doFirst { it.logger.info("${Date()} Running nxProjectReport for ${project.name}") }
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure all included builds are processed only once using lazy evaluation
|
||||||
|
project.gradle.includedBuilds.distinct().forEach { includedBuild ->
|
||||||
|
nxProjectReportTask.configure { it.dependsOn(includedBuild.task(":nxProjectReport")) }
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure all subprojects are processed only once using lazy evaluation
|
||||||
|
project.subprojects.distinct().forEach { subProject ->
|
||||||
|
// Add a dependency on each subproject's nxProjectReport task
|
||||||
|
nxProjectReportTask.configure {
|
||||||
|
it.dependsOn(subProject.tasks.matching { it.name == "nxProjectReport" })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
project.tasks.register("nxProjectGraph").configure { task ->
|
||||||
|
task.dependsOn(nxProjectReportTask)
|
||||||
|
task.description = "Create Nx project graph for ${project.name}"
|
||||||
|
task.group = "Reporting"
|
||||||
|
|
||||||
|
val outputFileProvider = nxProjectReportTask.map { it.outputFile }
|
||||||
|
|
||||||
|
task.doFirst { it.logger.info("${Date()} Running nxProjectGraph for ${project.name}") }
|
||||||
|
|
||||||
|
task.doLast { println(outputFileProvider.get().path) }
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure all included builds are processed only once using lazy evaluation
|
||||||
|
project.gradle.includedBuilds.distinct().forEach { includedBuild ->
|
||||||
|
project.tasks.named("nxProjectGraph").configure {
|
||||||
|
it.dependsOn(includedBuild.task(":nxProjectGraph"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure all subprojects are processed only once using lazy evaluation
|
||||||
|
project.subprojects.distinct().forEach { subProject ->
|
||||||
|
project.tasks.named("nxProjectGraph").configure {
|
||||||
|
it.dependsOn(subProject.tasks.matching { it.name == "nxProjectGraph" })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,63 @@
|
|||||||
|
package dev.nx.gradle
|
||||||
|
|
||||||
|
import com.google.gson.Gson
|
||||||
|
import dev.nx.gradle.utils.createNodeForProject
|
||||||
|
import java.io.File
|
||||||
|
import java.util.*
|
||||||
|
import javax.inject.Inject
|
||||||
|
import org.gradle.api.DefaultTask
|
||||||
|
import org.gradle.api.Project
|
||||||
|
import org.gradle.api.file.ProjectLayout
|
||||||
|
import org.gradle.api.provider.MapProperty
|
||||||
|
import org.gradle.api.provider.Property
|
||||||
|
import org.gradle.api.tasks.*
|
||||||
|
|
||||||
|
@CacheableTask
|
||||||
|
abstract class NxProjectReportTask @Inject constructor(private val projectLayout: ProjectLayout) :
|
||||||
|
DefaultTask() {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val gson = Gson()
|
||||||
|
}
|
||||||
|
|
||||||
|
@get:Input abstract val projectName: Property<String>
|
||||||
|
|
||||||
|
@get:Input abstract val hash: Property<String>
|
||||||
|
|
||||||
|
@get:Input abstract val cwd: Property<String>
|
||||||
|
|
||||||
|
@get:Input abstract val workspaceRoot: Property<String>
|
||||||
|
|
||||||
|
@get:Input abstract val targetNameOverrides: MapProperty<String, String>
|
||||||
|
|
||||||
|
// Don't compute report at configuration time, move it to execution time
|
||||||
|
@get:Internal // Prevent Gradle from caching this reference
|
||||||
|
abstract val projectRef: Property<Project>
|
||||||
|
|
||||||
|
@get:OutputFile
|
||||||
|
val outputFile: File
|
||||||
|
get() = projectLayout.buildDirectory.file("nx/${projectName.get()}.json").get().asFile
|
||||||
|
|
||||||
|
@TaskAction
|
||||||
|
fun action() {
|
||||||
|
logger.info("${Date()} Apply task action NxProjectReportTask for ${projectName.get()}")
|
||||||
|
logger.info("${Date()} Hash input: ${hash.get()}")
|
||||||
|
logger.info("${Date()} Target Name Overrides ${targetNameOverrides.get()}")
|
||||||
|
val project = projectRef.get() // Get project reference at execution time
|
||||||
|
val report =
|
||||||
|
createNodeForProject(
|
||||||
|
project,
|
||||||
|
targetNameOverrides.get(),
|
||||||
|
workspaceRoot.get(),
|
||||||
|
cwd.get()) // Compute report at execution time
|
||||||
|
val reportJson = gson.toJson(report)
|
||||||
|
|
||||||
|
if (outputFile.exists() && outputFile.readText() == reportJson) {
|
||||||
|
logger.info("${Date()} No change in the node report for ${projectName.get()}")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.info("${Date()} Writing node report for ${projectName.get()}")
|
||||||
|
outputFile.writeText(reportJson)
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,6 @@
|
|||||||
|
package dev.nx.gradle.data
|
||||||
|
|
||||||
|
import java.io.Serializable
|
||||||
|
|
||||||
|
data class Dependency(val source: String, val target: String, var sourceFile: String) :
|
||||||
|
Serializable
|
||||||
@ -0,0 +1,10 @@
|
|||||||
|
package dev.nx.gradle.data
|
||||||
|
|
||||||
|
import java.io.Serializable
|
||||||
|
import org.gradle.api.tasks.Input
|
||||||
|
|
||||||
|
data class ExternalDepData(
|
||||||
|
@Input val version: String?,
|
||||||
|
@Input val packageName: String,
|
||||||
|
@Input val hash: String?
|
||||||
|
) : Serializable
|
||||||
@ -0,0 +1,11 @@
|
|||||||
|
package dev.nx.gradle.data
|
||||||
|
|
||||||
|
import java.io.Serializable
|
||||||
|
import org.gradle.api.tasks.Input
|
||||||
|
import org.gradle.api.tasks.Nested
|
||||||
|
|
||||||
|
data class ExternalNode(
|
||||||
|
@Input var type: String?,
|
||||||
|
@Input val name: String,
|
||||||
|
@Nested var data: ExternalDepData
|
||||||
|
) : Serializable
|
||||||
@ -0,0 +1,11 @@
|
|||||||
|
package dev.nx.gradle.data
|
||||||
|
|
||||||
|
import java.io.Serializable
|
||||||
|
import org.gradle.api.tasks.Input
|
||||||
|
import org.gradle.api.tasks.Nested
|
||||||
|
|
||||||
|
data class GradleNodeReport(
|
||||||
|
@Nested val nodes: Map<String, ProjectNode>,
|
||||||
|
@Input val dependencies: Set<Dependency>,
|
||||||
|
@Nested val externalNodes: Map<String, ExternalNode>
|
||||||
|
) : Serializable
|
||||||
@ -0,0 +1,17 @@
|
|||||||
|
package dev.nx.gradle.data
|
||||||
|
|
||||||
|
import java.io.Serializable
|
||||||
|
|
||||||
|
typealias NxTarget = MutableMap<String, Any?>
|
||||||
|
|
||||||
|
typealias NxTargets = MutableMap<String, NxTarget>
|
||||||
|
|
||||||
|
typealias TargetGroup = MutableList<String>
|
||||||
|
|
||||||
|
typealias TargetGroups = MutableMap<String, TargetGroup>
|
||||||
|
|
||||||
|
data class GradleTargets(
|
||||||
|
val targets: NxTargets,
|
||||||
|
val targetGroups: TargetGroups,
|
||||||
|
var externalNodes: MutableMap<String, ExternalNode>
|
||||||
|
) : Serializable
|
||||||
@ -0,0 +1,9 @@
|
|||||||
|
package dev.nx.gradle.data
|
||||||
|
|
||||||
|
import java.io.Serializable
|
||||||
|
|
||||||
|
data class NodeMetadata(
|
||||||
|
val targetGroups: TargetGroups,
|
||||||
|
val technologies: List<String>,
|
||||||
|
val description: String?
|
||||||
|
) : Serializable
|
||||||
@ -0,0 +1,10 @@
|
|||||||
|
package dev.nx.gradle.data
|
||||||
|
|
||||||
|
import java.io.Serializable
|
||||||
|
import org.gradle.api.tasks.Input
|
||||||
|
|
||||||
|
data class ProjectNode(
|
||||||
|
@Input val targets: NxTargets,
|
||||||
|
@Input val metadata: NodeMetadata,
|
||||||
|
@Input val name: String
|
||||||
|
) : Serializable
|
||||||
@ -0,0 +1,143 @@
|
|||||||
|
package dev.nx.gradle.utils
|
||||||
|
|
||||||
|
import dev.nx.gradle.data.*
|
||||||
|
import java.io.File
|
||||||
|
import org.gradle.api.Task
|
||||||
|
import org.gradle.api.file.FileCollection
|
||||||
|
|
||||||
|
const val testCiTargetGroup = "verification"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add atomized ci test targets Going to loop through each test files and create a target for each
|
||||||
|
* It is going to modify targets and targetGroups in place
|
||||||
|
*/
|
||||||
|
fun addTestCiTargets(
|
||||||
|
testFiles: FileCollection,
|
||||||
|
projectBuildPath: String,
|
||||||
|
testTask: Task,
|
||||||
|
targets: NxTargets,
|
||||||
|
targetGroups: TargetGroups,
|
||||||
|
projectRoot: String,
|
||||||
|
workspaceRoot: String,
|
||||||
|
ciTargetName: String
|
||||||
|
) {
|
||||||
|
ensureTargetGroupExists(targetGroups, testCiTargetGroup)
|
||||||
|
|
||||||
|
val gradlewCommand = getGradlewCommand()
|
||||||
|
val ciDependsOn = mutableListOf<Map<String, String>>()
|
||||||
|
|
||||||
|
val filteredTestFiles = testFiles.filter { isTestFile(it, workspaceRoot) }
|
||||||
|
|
||||||
|
filteredTestFiles.forEach { testFile ->
|
||||||
|
val className = getTestClassNameIfAnnotated(testFile) ?: return@forEach
|
||||||
|
|
||||||
|
val testCiTarget =
|
||||||
|
buildTestCiTarget(
|
||||||
|
gradlewCommand = gradlewCommand,
|
||||||
|
projectBuildPath = projectBuildPath,
|
||||||
|
testClassName = className,
|
||||||
|
testFile = testFile,
|
||||||
|
testTask = testTask,
|
||||||
|
projectRoot = projectRoot,
|
||||||
|
workspaceRoot = workspaceRoot)
|
||||||
|
|
||||||
|
val targetName = "$ciTargetName--$className"
|
||||||
|
targets[targetName] = testCiTarget
|
||||||
|
targetGroups[testCiTargetGroup]?.add(targetName)
|
||||||
|
|
||||||
|
ciDependsOn.add(mapOf("target" to targetName, "projects" to "self", "params" to "forward"))
|
||||||
|
}
|
||||||
|
|
||||||
|
testTask.logger.info("$testTask ci tasks: $ciDependsOn")
|
||||||
|
|
||||||
|
if (ciDependsOn.isNotEmpty()) {
|
||||||
|
ensureParentCiTarget(
|
||||||
|
targets = targets,
|
||||||
|
targetGroups = targetGroups,
|
||||||
|
ciTargetName = ciTargetName,
|
||||||
|
projectBuildPath = projectBuildPath,
|
||||||
|
dependsOn = ciDependsOn)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getTestClassNameIfAnnotated(file: File): String? {
|
||||||
|
if (!file.exists()) return null
|
||||||
|
|
||||||
|
val content = file.readText()
|
||||||
|
if (!content.contains("@Test")) return null
|
||||||
|
|
||||||
|
val classRegex = Regex("""class\s+([A-Za-z_][A-Za-z0-9_]*)""")
|
||||||
|
val match = classRegex.find(content)
|
||||||
|
return match?.groupValues?.get(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ensureTargetGroupExists(targetGroups: TargetGroups, group: String) {
|
||||||
|
if (!targetGroups.containsKey(group)) {
|
||||||
|
targetGroups[group] = mutableListOf()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun isTestFile(file: File, workspaceRoot: String): Boolean {
|
||||||
|
val fileName = file.name.substringBefore(".")
|
||||||
|
val regex = "^(?!abstract).*?(Test)(s)?\\d*".toRegex(RegexOption.IGNORE_CASE)
|
||||||
|
return file.path.startsWith(workspaceRoot) && regex.matches(fileName)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun buildTestCiTarget(
|
||||||
|
gradlewCommand: String,
|
||||||
|
projectBuildPath: String,
|
||||||
|
testClassName: String,
|
||||||
|
testFile: File,
|
||||||
|
testTask: Task,
|
||||||
|
projectRoot: String,
|
||||||
|
workspaceRoot: String
|
||||||
|
): MutableMap<String, Any?> {
|
||||||
|
val target =
|
||||||
|
mutableMapOf<String, Any?>(
|
||||||
|
"command" to "$gradlewCommand ${projectBuildPath}:test --tests $testClassName",
|
||||||
|
"metadata" to
|
||||||
|
getMetadata("Runs Gradle test $testClassName in CI", projectBuildPath, "test"),
|
||||||
|
"cache" to true,
|
||||||
|
"inputs" to arrayOf(replaceRootInPath(testFile.path, projectRoot, workspaceRoot)))
|
||||||
|
|
||||||
|
getDependsOnForTask(testTask, null)
|
||||||
|
?.takeIf { it.isNotEmpty() }
|
||||||
|
?.let {
|
||||||
|
testTask.logger.info("$testTask: processed ${it.size} dependsOn")
|
||||||
|
target["dependsOn"] = it
|
||||||
|
}
|
||||||
|
|
||||||
|
getOutputsForTask(testTask, projectRoot, workspaceRoot)
|
||||||
|
?.takeIf { it.isNotEmpty() }
|
||||||
|
?.let {
|
||||||
|
testTask.logger.info("$testTask: processed ${it.size} outputs")
|
||||||
|
target["outputs"] = it
|
||||||
|
}
|
||||||
|
|
||||||
|
return target
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun ensureParentCiTarget(
|
||||||
|
targets: NxTargets,
|
||||||
|
targetGroups: TargetGroups,
|
||||||
|
ciTargetName: String,
|
||||||
|
projectBuildPath: String,
|
||||||
|
dependsOn: List<Map<String, String>>
|
||||||
|
) {
|
||||||
|
val ciTarget =
|
||||||
|
targets.getOrPut(ciTargetName) {
|
||||||
|
mutableMapOf<String, Any?>().apply {
|
||||||
|
put("executor", "nx:noop")
|
||||||
|
put("metadata", getMetadata("Runs Gradle Tests in CI", projectBuildPath, "test", "test"))
|
||||||
|
put("dependsOn", mutableListOf<Map<String, String>>())
|
||||||
|
put("cache", true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val dependsOnList = ciTarget.getOrPut("dependsOn") { mutableListOf<Any?>() } as MutableList<Any?>
|
||||||
|
dependsOnList.addAll(dependsOn)
|
||||||
|
|
||||||
|
if (targetGroups[testCiTargetGroup]?.contains(ciTargetName) != true) {
|
||||||
|
targetGroups[testCiTargetGroup]?.add(ciTargetName)
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,159 @@
|
|||||||
|
package dev.nx.gradle.utils
|
||||||
|
|
||||||
|
import dev.nx.gradle.data.*
|
||||||
|
import java.util.*
|
||||||
|
import org.gradle.api.Project
|
||||||
|
|
||||||
|
/** Loops through a project and populate dependencies and nodes for each target */
|
||||||
|
fun createNodeForProject(
|
||||||
|
project: Project,
|
||||||
|
targetNameOverrides: Map<String, String>,
|
||||||
|
workspaceRoot: String,
|
||||||
|
cwd: String
|
||||||
|
): GradleNodeReport {
|
||||||
|
val logger = project.logger
|
||||||
|
logger.info("${Date()} ${project.name} createNodeForProject: get nodes and dependencies")
|
||||||
|
|
||||||
|
// Initialize dependencies with an empty Set to prevent null issues
|
||||||
|
val dependencies: MutableSet<Dependency> =
|
||||||
|
try {
|
||||||
|
getDependenciesForProject(project)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
logger.info(
|
||||||
|
"${Date()} ${project.name} createNodeForProject: get dependencies error: ${e.message}")
|
||||||
|
mutableSetOf()
|
||||||
|
}
|
||||||
|
logger.info("${Date()} ${project.name} createNodeForProject: got dependencies")
|
||||||
|
|
||||||
|
// Initialize nodes and externalNodes with empty maps to prevent null issues
|
||||||
|
var nodes: Map<String, ProjectNode>
|
||||||
|
var externalNodes: Map<String, ExternalNode>
|
||||||
|
|
||||||
|
try {
|
||||||
|
val gradleTargets: GradleTargets =
|
||||||
|
processTargetsForProject(project, dependencies, targetNameOverrides, workspaceRoot, cwd)
|
||||||
|
val projectRoot = project.projectDir.path
|
||||||
|
val projectNode =
|
||||||
|
ProjectNode(
|
||||||
|
targets = gradleTargets.targets,
|
||||||
|
metadata =
|
||||||
|
NodeMetadata(gradleTargets.targetGroups, listOf("gradle"), project.description),
|
||||||
|
name = project.name)
|
||||||
|
nodes = mapOf(projectRoot to projectNode)
|
||||||
|
externalNodes = gradleTargets.externalNodes
|
||||||
|
logger.info(
|
||||||
|
"${Date()} ${project.name} createNodeForProject: get nodes and external nodes for $projectRoot")
|
||||||
|
} catch (e: Exception) {
|
||||||
|
logger.info("${project.name}: get nodes error: ${e.message}")
|
||||||
|
nodes = emptyMap()
|
||||||
|
externalNodes = emptyMap()
|
||||||
|
}
|
||||||
|
return GradleNodeReport(nodes, dependencies, externalNodes)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process targets for project
|
||||||
|
*
|
||||||
|
* @return targets and targetGroups
|
||||||
|
*/
|
||||||
|
fun processTargetsForProject(
|
||||||
|
project: Project,
|
||||||
|
dependencies: MutableSet<Dependency>,
|
||||||
|
targetNameOverrides: Map<String, String>,
|
||||||
|
workspaceRoot: String,
|
||||||
|
cwd: String
|
||||||
|
): GradleTargets {
|
||||||
|
val targets: NxTargets = mutableMapOf<String, MutableMap<String, Any?>>()
|
||||||
|
val targetGroups: TargetGroups = mutableMapOf<String, MutableList<String>>()
|
||||||
|
val externalNodes = mutableMapOf<String, ExternalNode>()
|
||||||
|
val projectRoot = project.projectDir.path
|
||||||
|
project.logger.info("Using workspace root $workspaceRoot")
|
||||||
|
|
||||||
|
var projectBuildPath: String =
|
||||||
|
project
|
||||||
|
.buildTreePath // get the build path of project e.g. :app, :utils:number-utils, :buildSrc
|
||||||
|
if (projectBuildPath.endsWith(":")) { // root project is ":", manually remove last :
|
||||||
|
projectBuildPath = projectBuildPath.dropLast(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
val logger = project.logger
|
||||||
|
|
||||||
|
logger.info("${Date()} ${project}: process targets")
|
||||||
|
|
||||||
|
var gradleProject = project.buildTreePath
|
||||||
|
if (!gradleProject.endsWith(":")) {
|
||||||
|
gradleProject += ":"
|
||||||
|
}
|
||||||
|
|
||||||
|
project.tasks.forEach { task ->
|
||||||
|
try {
|
||||||
|
logger.info("${Date()} ${project.name}: Processing $task")
|
||||||
|
val taskName = targetNameOverrides.getOrDefault(task.name + "TargetName", task.name)
|
||||||
|
// add task to target groups
|
||||||
|
val group: String? = task.group
|
||||||
|
if (!group.isNullOrBlank()) {
|
||||||
|
if (targetGroups.contains(group)) {
|
||||||
|
targetGroups[group]?.add(task.name)
|
||||||
|
} else {
|
||||||
|
targetGroups[group] = mutableListOf(task.name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val target =
|
||||||
|
processTask(
|
||||||
|
task,
|
||||||
|
projectBuildPath,
|
||||||
|
projectRoot,
|
||||||
|
workspaceRoot,
|
||||||
|
cwd,
|
||||||
|
externalNodes,
|
||||||
|
dependencies,
|
||||||
|
targetNameOverrides)
|
||||||
|
targets[taskName] = target
|
||||||
|
|
||||||
|
val ciTargetName = targetNameOverrides.getOrDefault("ciTargetName", null)
|
||||||
|
ciTargetName?.let {
|
||||||
|
if (task.name.startsWith("compileTest")) {
|
||||||
|
val testTask = project.getTasksByName("test", false)
|
||||||
|
if (testTask.isNotEmpty()) {
|
||||||
|
addTestCiTargets(
|
||||||
|
task.inputs.sourceFiles,
|
||||||
|
projectBuildPath,
|
||||||
|
testTask.first(),
|
||||||
|
targets,
|
||||||
|
targetGroups,
|
||||||
|
projectRoot,
|
||||||
|
workspaceRoot,
|
||||||
|
it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the `$ciTargetName-check` target when processing the "check" task
|
||||||
|
if (task.name == "check") {
|
||||||
|
val replacedDependencies =
|
||||||
|
(target["dependsOn"] as? List<*>)?.map { dep ->
|
||||||
|
if (dep.toString() == targetNameOverrides.getOrDefault("testTargetName", "test"))
|
||||||
|
ciTargetName
|
||||||
|
else dep.toString()
|
||||||
|
} ?: emptyList()
|
||||||
|
|
||||||
|
// Copy the original target and override "dependsOn"
|
||||||
|
val newTarget = target.toMutableMap()
|
||||||
|
newTarget["dependsOn"] = replacedDependencies
|
||||||
|
|
||||||
|
val ciCheckTargetName = "$ciTargetName-check"
|
||||||
|
targets[ciCheckTargetName] = newTarget
|
||||||
|
|
||||||
|
ensureTargetGroupExists(targetGroups, testCiTargetGroup)
|
||||||
|
targetGroups[testCiTargetGroup]?.add(ciCheckTargetName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
logger.info("${Date()} ${project.name}: Processed $task")
|
||||||
|
} catch (e: Exception) {
|
||||||
|
logger.info("${task}: process task error $e")
|
||||||
|
logger.debug("Stack trace:", e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return GradleTargets(targets, targetGroups, externalNodes)
|
||||||
|
}
|
||||||
@ -0,0 +1,348 @@
|
|||||||
|
package dev.nx.gradle.utils
|
||||||
|
|
||||||
|
import dev.nx.gradle.data.*
|
||||||
|
import org.gradle.api.Named
|
||||||
|
import org.gradle.api.NamedDomainObjectProvider
|
||||||
|
import org.gradle.api.Task
|
||||||
|
import org.gradle.api.tasks.TaskProvider
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process a task and convert it into target Going to populate:
|
||||||
|
* - cache
|
||||||
|
* - inputs
|
||||||
|
* - outputs
|
||||||
|
* - command
|
||||||
|
* - metadata
|
||||||
|
* - options with cwd and args
|
||||||
|
*/
|
||||||
|
fun processTask(
|
||||||
|
task: Task,
|
||||||
|
projectBuildPath: String,
|
||||||
|
projectRoot: String,
|
||||||
|
workspaceRoot: String,
|
||||||
|
cwd: String,
|
||||||
|
externalNodes: MutableMap<String, ExternalNode>,
|
||||||
|
dependencies: MutableSet<Dependency>,
|
||||||
|
targetNameOverrides: Map<String, String>
|
||||||
|
): MutableMap<String, Any?> {
|
||||||
|
val logger = task.logger
|
||||||
|
logger.info("NxProjectReportTask: process $task for $projectRoot")
|
||||||
|
val target = mutableMapOf<String, Any?>()
|
||||||
|
target["cache"] = true // set cache to be always true
|
||||||
|
|
||||||
|
// process inputs
|
||||||
|
val inputs = getInputsForTask(task, projectRoot, workspaceRoot, externalNodes)
|
||||||
|
if (!inputs.isNullOrEmpty()) {
|
||||||
|
logger.info("${task}: processed ${inputs.size} inputs")
|
||||||
|
target["inputs"] = inputs
|
||||||
|
}
|
||||||
|
|
||||||
|
// process outputs
|
||||||
|
val outputs = getOutputsForTask(task, projectRoot, workspaceRoot)
|
||||||
|
if (!outputs.isNullOrEmpty()) {
|
||||||
|
logger.info("${task}: processed ${outputs.size} outputs")
|
||||||
|
target["outputs"] = outputs
|
||||||
|
}
|
||||||
|
|
||||||
|
// process dependsOn
|
||||||
|
val dependsOn = getDependsOnForTask(task, dependencies, targetNameOverrides)
|
||||||
|
if (!dependsOn.isNullOrEmpty()) {
|
||||||
|
logger.info("${task}: processed ${dependsOn.size} dependsOn")
|
||||||
|
target["dependsOn"] = dependsOn
|
||||||
|
}
|
||||||
|
|
||||||
|
val gradlewCommand = getGradlewCommand()
|
||||||
|
target["command"] = "$gradlewCommand ${projectBuildPath}:${task.name}"
|
||||||
|
|
||||||
|
val metadata = getMetadata(task.description ?: "Run ${task.name}", projectBuildPath, task.name)
|
||||||
|
target["metadata"] = metadata
|
||||||
|
|
||||||
|
target["options"] = mapOf("cwd" to cwd)
|
||||||
|
|
||||||
|
return target
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getGradlewCommand(): String {
|
||||||
|
val gradlewCommand: String
|
||||||
|
val operatingSystem = System.getProperty("os.name").lowercase()
|
||||||
|
gradlewCommand =
|
||||||
|
if (operatingSystem.contains("win")) {
|
||||||
|
".\\gradlew.bat"
|
||||||
|
} else {
|
||||||
|
"./gradlew"
|
||||||
|
}
|
||||||
|
return gradlewCommand
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse task and get inputs for this task
|
||||||
|
*
|
||||||
|
* @param task task to process
|
||||||
|
* @return a list of inputs including external dependencies, null if empty or an error occurred
|
||||||
|
*/
|
||||||
|
fun getInputsForTask(
|
||||||
|
task: Task,
|
||||||
|
projectRoot: String,
|
||||||
|
workspaceRoot: String,
|
||||||
|
externalNodes: MutableMap<String, ExternalNode>?
|
||||||
|
): MutableList<Any>? {
|
||||||
|
return try {
|
||||||
|
val mappedInputsIncludeExternal: MutableList<Any> = mutableListOf()
|
||||||
|
val inputs = task.inputs
|
||||||
|
val externalDependencies = mutableListOf<String>()
|
||||||
|
inputs.sourceFiles.forEach { file ->
|
||||||
|
val path: String = file.path
|
||||||
|
// replace the absolute path to contain {projectRoot} or {workspaceRoot}
|
||||||
|
val pathWithReplacedRoot = replaceRootInPath(path, projectRoot, workspaceRoot)
|
||||||
|
if (pathWithReplacedRoot != null) { // if the path is inside workspace
|
||||||
|
mappedInputsIncludeExternal.add((pathWithReplacedRoot))
|
||||||
|
}
|
||||||
|
// if the path is outside of workspace
|
||||||
|
if (pathWithReplacedRoot == null &&
|
||||||
|
externalNodes != null) { // add it to external dependencies
|
||||||
|
try {
|
||||||
|
val externalDep = getExternalDepFromInputFile(path, externalNodes, task.logger)
|
||||||
|
externalDep?.let { externalDependencies.add(it) }
|
||||||
|
} catch (e: Exception) {
|
||||||
|
task.logger.info("${task}: get external dependency error $e")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (externalDependencies.isNotEmpty()) {
|
||||||
|
mappedInputsIncludeExternal.add(mutableMapOf("externalDependencies" to externalDependencies))
|
||||||
|
}
|
||||||
|
if (mappedInputsIncludeExternal.isNotEmpty()) {
|
||||||
|
return mappedInputsIncludeExternal
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
} catch (e: Exception) {
|
||||||
|
// Log the error but don't fail the build
|
||||||
|
task.logger.info("Error getting outputs for ${task.path}: ${e.message}")
|
||||||
|
task.logger.debug("Stack trace:", e)
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get outputs for task
|
||||||
|
*
|
||||||
|
* @param task task to process
|
||||||
|
* @return list of outputs file, will not include if output file is outside workspace, null if empty
|
||||||
|
* or an error occurred
|
||||||
|
*/
|
||||||
|
fun getOutputsForTask(task: Task, projectRoot: String, workspaceRoot: String): List<String>? {
|
||||||
|
return try {
|
||||||
|
val outputs = task.outputs.files
|
||||||
|
if (!outputs.isEmpty) {
|
||||||
|
return outputs.mapNotNull { file ->
|
||||||
|
val path: String = file.path
|
||||||
|
replaceRootInPath(path, projectRoot, workspaceRoot)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
null
|
||||||
|
} catch (e: Exception) {
|
||||||
|
// Log the error but don't fail the build
|
||||||
|
task.logger.info("Error getting outputs for ${task.path}: ${e.message}")
|
||||||
|
task.logger.debug("Stack trace:", e)
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get dependsOn for task, handling configuration timing safely. Rewrites dependency task names
|
||||||
|
* based on targetNameOverrides (e.g., test -> ci).
|
||||||
|
*
|
||||||
|
* @param task task to process
|
||||||
|
* @param dependencies optional set to collect inter-project Dependency objects
|
||||||
|
* @param targetNameOverrides optional map of overrides (e.g., test -> ci)
|
||||||
|
* @return list of dependsOn task names (possibly replaced), or null if none found or error occurred
|
||||||
|
*/
|
||||||
|
fun getDependsOnForTask(
|
||||||
|
task: Task,
|
||||||
|
dependencies: MutableSet<Dependency>?,
|
||||||
|
targetNameOverrides: Map<String, String> = emptyMap()
|
||||||
|
): List<String>? {
|
||||||
|
|
||||||
|
fun mapTasksToNames(tasks: Collection<Task>): List<String> {
|
||||||
|
return tasks.map { depTask ->
|
||||||
|
val depProject = depTask.project
|
||||||
|
val taskProject = task.project
|
||||||
|
|
||||||
|
if (task.name != "buildDependents" && depProject != taskProject && dependencies != null) {
|
||||||
|
dependencies.add(
|
||||||
|
Dependency(
|
||||||
|
taskProject.projectDir.path,
|
||||||
|
depProject.projectDir.path,
|
||||||
|
taskProject.buildFile.path))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if this task name needs to be overridden
|
||||||
|
val taskName = targetNameOverrides.getOrDefault(depTask.name + "TargetName", depTask.name)
|
||||||
|
val overriddenTaskName =
|
||||||
|
if (depProject == taskProject) {
|
||||||
|
taskName
|
||||||
|
} else {
|
||||||
|
"${depProject.name}:${taskName}"
|
||||||
|
}
|
||||||
|
|
||||||
|
overriddenTaskName
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return try {
|
||||||
|
val dependsOnEntries = task.dependsOn
|
||||||
|
|
||||||
|
// Prefer task.dependsOn
|
||||||
|
if (dependsOnEntries.isNotEmpty()) {
|
||||||
|
val resolvedTasks =
|
||||||
|
dependsOnEntries.flatMap { dep ->
|
||||||
|
when (dep) {
|
||||||
|
is Task -> listOf(dep)
|
||||||
|
|
||||||
|
is TaskProvider<*>,
|
||||||
|
is NamedDomainObjectProvider<*> -> {
|
||||||
|
val providerName = (dep as Named).name
|
||||||
|
val foundTask = task.project.tasks.findByName(providerName)
|
||||||
|
if (foundTask != null) {
|
||||||
|
listOf(foundTask)
|
||||||
|
} else {
|
||||||
|
task.logger.info(
|
||||||
|
"${dep::class.simpleName} '$providerName' did not resolve to a task in project ${task.project.name}")
|
||||||
|
emptyList()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
is String -> {
|
||||||
|
val foundTask = task.project.tasks.findByPath(dep)
|
||||||
|
if (foundTask != null) {
|
||||||
|
listOf(foundTask)
|
||||||
|
} else {
|
||||||
|
task.logger.info(
|
||||||
|
"Task string '$dep' could not be resolved in project ${task.project.name}")
|
||||||
|
emptyList()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> {
|
||||||
|
task.logger.info(
|
||||||
|
"Unhandled dependency type ${dep::class.java} for task ${task.path}")
|
||||||
|
emptyList()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (resolvedTasks.isNotEmpty()) {
|
||||||
|
return mapTasksToNames(resolvedTasks)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fallback: taskDependencies.getDependencies(task)
|
||||||
|
val fallbackDeps =
|
||||||
|
try {
|
||||||
|
task.taskDependencies.getDependencies(null)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
task.logger.info("Error calling getDependencies for ${task.path}: ${e.message}")
|
||||||
|
task.logger.debug("Stack trace:", e)
|
||||||
|
emptySet<Task>()
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fallbackDeps.isNotEmpty()) {
|
||||||
|
return mapTasksToNames(fallbackDeps)
|
||||||
|
}
|
||||||
|
|
||||||
|
null
|
||||||
|
} catch (e: Exception) {
|
||||||
|
task.logger.info("Unexpected error getting dependencies for ${task.path}: ${e.message}")
|
||||||
|
task.logger.debug("Stack trace:", e)
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get metadata for task
|
||||||
|
*
|
||||||
|
* @param description
|
||||||
|
*/
|
||||||
|
fun getMetadata(
|
||||||
|
description: String?,
|
||||||
|
projectBuildPath: String,
|
||||||
|
taskName: String,
|
||||||
|
nonAtomizedTarget: String? = null
|
||||||
|
): Map<String, Any?> {
|
||||||
|
val gradlewCommand = getGradlewCommand()
|
||||||
|
return mapOf(
|
||||||
|
"description" to description,
|
||||||
|
"technologies" to arrayOf("gradle"),
|
||||||
|
"help" to mapOf("command" to "$gradlewCommand help --task ${projectBuildPath}:${taskName}"),
|
||||||
|
"nonAtomizedTarget" to nonAtomizedTarget)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a file path like:
|
||||||
|
* org.apache.commons/commons-lang3/3.13.0/b7263237aa89c1f99b327197c41d0669707a462e/commons-lang3-3.13.0.jar
|
||||||
|
*
|
||||||
|
* Into an external dependency with key: "gradle:commons-lang3-3.13.0" with value: { "type":
|
||||||
|
* "gradle", "name": "commons-lang3", "data": { "version": "3.13.0", "packageName":
|
||||||
|
* "org.apache.commons.commons-lang3", "hash": "b7263237aa89c1f99b327197c41d0669707a462e",} }
|
||||||
|
*
|
||||||
|
* @param inputFile Path to the dependency jar.
|
||||||
|
* @param externalNodes Map to populate with the resulting ExternalNode.
|
||||||
|
* @return The external dependency key (e.g., gradle:commons-lang3-3.13.0), or null if parsing
|
||||||
|
* fails.
|
||||||
|
*/
|
||||||
|
fun getExternalDepFromInputFile(
|
||||||
|
inputFile: String,
|
||||||
|
externalNodes: MutableMap<String, ExternalNode>,
|
||||||
|
logger: org.gradle.api.logging.Logger
|
||||||
|
): String? {
|
||||||
|
try {
|
||||||
|
val segments = inputFile.split("/")
|
||||||
|
|
||||||
|
// Expecting at least 5 segments to safely extract group, package, version, hash, filename
|
||||||
|
if (segments.size < 5) {
|
||||||
|
logger.warn("Invalid input path: '$inputFile'. Expected at least 5 segments.")
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
val fileName = segments.last()
|
||||||
|
|
||||||
|
// Remove any file extension (after the last dot), if present
|
||||||
|
val nameKey = fileName.substringBeforeLast(".", fileName)
|
||||||
|
|
||||||
|
val hash = segments[segments.size - 2]
|
||||||
|
val version = segments[segments.size - 3]
|
||||||
|
val packageName = segments[segments.size - 4]
|
||||||
|
val packageGroup = segments[segments.size - 5]
|
||||||
|
|
||||||
|
val fullPackageName = "$packageGroup.$packageName"
|
||||||
|
|
||||||
|
val data = ExternalDepData(version, fullPackageName, hash)
|
||||||
|
val externalKey = "gradle:$nameKey"
|
||||||
|
val node = ExternalNode("gradle", externalKey, data)
|
||||||
|
|
||||||
|
externalNodes[externalKey] = node
|
||||||
|
|
||||||
|
return externalKey
|
||||||
|
} catch (e: Exception) {
|
||||||
|
logger.warn("Failed to parse inputFile '$inputFile': ${e.message}")
|
||||||
|
logger.debug("Stack trace:", e)
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Going to replace the projectRoot with {projectRoot} and workspaceRoot with {workspaceRoot}
|
||||||
|
*
|
||||||
|
* @return mapped path if inside workspace, null if outside workspace
|
||||||
|
*/
|
||||||
|
fun replaceRootInPath(p: String, projectRoot: String, workspaceRoot: String): String? {
|
||||||
|
var path = p
|
||||||
|
if (path.startsWith(projectRoot)) {
|
||||||
|
path = path.replace(projectRoot, "{projectRoot}")
|
||||||
|
return path
|
||||||
|
} else if (path.startsWith(workspaceRoot)) {
|
||||||
|
path = path.replace(workspaceRoot, "{workspaceRoot}")
|
||||||
|
return path
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
@ -0,0 +1,30 @@
|
|||||||
|
package dev.nx.gradle.utils
|
||||||
|
|
||||||
|
import dev.nx.gradle.data.Dependency
|
||||||
|
import org.gradle.api.Project
|
||||||
|
|
||||||
|
private val dependencyCache = mutableMapOf<Project, Set<Dependency>>()
|
||||||
|
|
||||||
|
fun getDependenciesForProject(project: Project): MutableSet<Dependency> {
|
||||||
|
return dependencyCache
|
||||||
|
.getOrPut(project) { buildDependenciesForProject(project) }
|
||||||
|
.toMutableSet() // Return a new mutable copy to prevent modifying the cached set
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun buildDependenciesForProject(project: Project): Set<Dependency> {
|
||||||
|
val dependencies = mutableSetOf<Dependency>()
|
||||||
|
|
||||||
|
// Include subprojects manually
|
||||||
|
project.subprojects.forEach { childProject ->
|
||||||
|
dependencies.add(
|
||||||
|
Dependency(project.projectDir.path, childProject.projectDir.path, project.buildFile.path))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Include included builds manually
|
||||||
|
project.gradle.includedBuilds.forEach { includedBuild ->
|
||||||
|
dependencies.add(
|
||||||
|
Dependency(project.projectDir.path, includedBuild.projectDir.path, project.buildFile.path))
|
||||||
|
}
|
||||||
|
|
||||||
|
return dependencies
|
||||||
|
}
|
||||||
@ -0,0 +1,81 @@
|
|||||||
|
package dev.nx.gradle.utils
|
||||||
|
|
||||||
|
import dev.nx.gradle.data.*
|
||||||
|
import java.io.File
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
import kotlin.test.assertTrue
|
||||||
|
import org.gradle.api.Project
|
||||||
|
import org.gradle.api.Task
|
||||||
|
import org.gradle.testfixtures.ProjectBuilder
|
||||||
|
import org.junit.jupiter.api.BeforeEach
|
||||||
|
import org.junit.jupiter.api.Test
|
||||||
|
|
||||||
|
class AddTestCiTargetsTest {
|
||||||
|
|
||||||
|
private lateinit var project: Project
|
||||||
|
private lateinit var testTask: Task
|
||||||
|
private lateinit var workspaceRoot: File
|
||||||
|
private lateinit var projectRoot: File
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
fun setup() {
|
||||||
|
workspaceRoot = createTempDir("workspace")
|
||||||
|
projectRoot = File(workspaceRoot, "project-a").apply { mkdirs() }
|
||||||
|
|
||||||
|
project = ProjectBuilder.builder().withProjectDir(projectRoot).build()
|
||||||
|
testTask = project.task("test")
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `should generate test CI targets and group correctly`() {
|
||||||
|
val testFile1 =
|
||||||
|
File(projectRoot, "src/test/kotlin/MyFirstTest.kt").apply {
|
||||||
|
parentFile.mkdirs()
|
||||||
|
writeText("@Test class MyFirstTest")
|
||||||
|
}
|
||||||
|
|
||||||
|
val testFile2 =
|
||||||
|
File(projectRoot, "src/test/kotlin/AnotherTest.kt").apply {
|
||||||
|
parentFile.mkdirs()
|
||||||
|
writeText("@Test class AnotherTest")
|
||||||
|
}
|
||||||
|
|
||||||
|
val testFiles = project.files(testFile1, testFile2)
|
||||||
|
|
||||||
|
val targets = mutableMapOf<String, MutableMap<String, Any?>>()
|
||||||
|
val targetGroups = mutableMapOf<String, MutableList<String>>()
|
||||||
|
val ciTargetName = "ci"
|
||||||
|
|
||||||
|
addTestCiTargets(
|
||||||
|
testFiles = testFiles,
|
||||||
|
projectBuildPath = ":project-a",
|
||||||
|
testTask = testTask,
|
||||||
|
targets = targets,
|
||||||
|
targetGroups = targetGroups,
|
||||||
|
projectRoot = projectRoot.absolutePath,
|
||||||
|
workspaceRoot = workspaceRoot.absolutePath,
|
||||||
|
ciTargetName = ciTargetName)
|
||||||
|
|
||||||
|
// Assert each test file created a CI target
|
||||||
|
assertTrue(targets.containsKey("ci--MyFirstTest"))
|
||||||
|
assertTrue(targets.containsKey("ci--AnotherTest"))
|
||||||
|
|
||||||
|
// Assert test group contains individual targets and parent ci task
|
||||||
|
val group = targetGroups[testCiTargetGroup]
|
||||||
|
assertTrue(group != null)
|
||||||
|
assertTrue(group!!.contains("ci--MyFirstTest"))
|
||||||
|
assertTrue(group.contains("ci--AnotherTest"))
|
||||||
|
assertTrue(group.contains("ci"))
|
||||||
|
|
||||||
|
// Assert parent CI task includes dependsOn
|
||||||
|
val parentCi = targets["ci"]
|
||||||
|
val dependsOn = parentCi?.get("dependsOn") as? List<*>
|
||||||
|
assertEquals(2, dependsOn!!.size)
|
||||||
|
|
||||||
|
val firstTarget = targets["ci--MyFirstTest"]!!
|
||||||
|
assertTrue(firstTarget["command"].toString().contains("--tests MyFirstTest"))
|
||||||
|
assertEquals(true, firstTarget["cache"])
|
||||||
|
assertTrue((firstTarget["inputs"] as Array<*>)[0].toString().contains("{projectRoot}"))
|
||||||
|
assertEquals("nx:noop", parentCi["executor"])
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,54 @@
|
|||||||
|
package dev.nx.gradle.utils
|
||||||
|
|
||||||
|
import dev.nx.gradle.data.*
|
||||||
|
import kotlin.test.*
|
||||||
|
import org.gradle.testfixtures.ProjectBuilder
|
||||||
|
|
||||||
|
class CreateNodeForProjectTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `should return GradleNodeReport with targets and metadata`() {
|
||||||
|
// Arrange
|
||||||
|
val workspaceRoot = createTempDir("workspace").absolutePath
|
||||||
|
val projectDir = createTempDir("project")
|
||||||
|
val project = ProjectBuilder.builder().withProjectDir(projectDir).build()
|
||||||
|
|
||||||
|
// Create a couple of dummy tasks
|
||||||
|
project.task("compileJava").apply {
|
||||||
|
group = "build"
|
||||||
|
description = "Compiles Java sources"
|
||||||
|
}
|
||||||
|
|
||||||
|
project.task("test").apply {
|
||||||
|
group = "verification"
|
||||||
|
description = "Runs the tests"
|
||||||
|
}
|
||||||
|
|
||||||
|
val targetNameOverrides = mapOf<String, String>()
|
||||||
|
|
||||||
|
// Act
|
||||||
|
val result =
|
||||||
|
createNodeForProject(
|
||||||
|
project = project,
|
||||||
|
targetNameOverrides = targetNameOverrides,
|
||||||
|
workspaceRoot = workspaceRoot,
|
||||||
|
cwd = "{projectRoot}")
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
val projectRoot = project.projectDir.absolutePath
|
||||||
|
assertTrue(result.nodes.containsKey(projectRoot), "Expected node for project root")
|
||||||
|
|
||||||
|
val projectNode = result.nodes[projectRoot]
|
||||||
|
assertNotNull(projectNode, "ProjectNode should not be null")
|
||||||
|
|
||||||
|
// Check target metadata
|
||||||
|
assertEquals(project.name, projectNode.name)
|
||||||
|
assertNotNull(projectNode.targets["compileJava"], "Expected compileJava target")
|
||||||
|
assertNotNull(projectNode.targets["test"], "Expected test target")
|
||||||
|
assertEquals("build", projectNode.metadata.targetGroups.keys.firstOrNull())
|
||||||
|
|
||||||
|
// Dependencies and external nodes should default to empty
|
||||||
|
assertTrue(result.dependencies.isEmpty(), "Expected no dependencies")
|
||||||
|
assertTrue(result.externalNodes.isEmpty(), "Expected no external nodes")
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,96 @@
|
|||||||
|
package dev.nx.gradle.utils
|
||||||
|
|
||||||
|
import dev.nx.gradle.data.Dependency
|
||||||
|
import dev.nx.gradle.data.ExternalNode
|
||||||
|
import org.gradle.testfixtures.ProjectBuilder
|
||||||
|
import org.junit.jupiter.api.Assertions.*
|
||||||
|
import org.junit.jupiter.api.Test
|
||||||
|
import org.mockito.kotlin.*
|
||||||
|
|
||||||
|
class ProcessTaskUtilsTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `test replaceRootInPath`() {
|
||||||
|
val path = "/home/user/workspace/project/src/main/java"
|
||||||
|
val projectRoot = "/home/user/workspace/project"
|
||||||
|
val workspaceRoot = "/home/user/workspace"
|
||||||
|
|
||||||
|
assertEquals("{projectRoot}/src/main/java", replaceRootInPath(path, projectRoot, workspaceRoot))
|
||||||
|
assertEquals(
|
||||||
|
"{workspaceRoot}/project/src/main/java",
|
||||||
|
replaceRootInPath(path, "/other/path", workspaceRoot))
|
||||||
|
assertNull(replaceRootInPath("/external/other", projectRoot, workspaceRoot))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `test getGradlewCommand`() {
|
||||||
|
val command = getGradlewCommand()
|
||||||
|
assertTrue(command.contains("gradlew"))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `test getMetadata`() {
|
||||||
|
val metadata = getMetadata("Compile Java", ":project", "compileJava")
|
||||||
|
assertEquals("Compile Java", metadata["description"])
|
||||||
|
assertEquals("gradle", (metadata["technologies"] as Array<*>)[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `test getExternalDepFromInputFile valid path`() {
|
||||||
|
val externalNodes = mutableMapOf<String, ExternalNode>()
|
||||||
|
val path = "org/apache/commons/commons-lang3/3.13.0/hash/commons-lang3-3.13.0.jar"
|
||||||
|
|
||||||
|
val key = getExternalDepFromInputFile(path, externalNodes, mock())
|
||||||
|
|
||||||
|
assertEquals("gradle:commons-lang3-3.13.0", key)
|
||||||
|
assertTrue(externalNodes.containsKey("gradle:commons-lang3-3.13.0"))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `test getExternalDepFromInputFile invalid path`() {
|
||||||
|
val externalNodes = mutableMapOf<String, ExternalNode>()
|
||||||
|
val key = getExternalDepFromInputFile("invalid/path.jar", externalNodes, mock())
|
||||||
|
|
||||||
|
assertNull(key)
|
||||||
|
assertTrue(externalNodes.isEmpty())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `test getDependsOnForTask with direct dependsOn`() {
|
||||||
|
val project = ProjectBuilder.builder().build()
|
||||||
|
val taskA = project.tasks.register("taskA").get()
|
||||||
|
val taskB = project.tasks.register("taskB").get()
|
||||||
|
|
||||||
|
taskA.dependsOn(taskB)
|
||||||
|
|
||||||
|
val dependencies = mutableSetOf<Dependency>()
|
||||||
|
val dependsOn = getDependsOnForTask(taskA, dependencies)
|
||||||
|
|
||||||
|
assertNotNull(dependsOn)
|
||||||
|
assertTrue(dependsOn!!.contains("taskB"))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `test processTask basic properties`() {
|
||||||
|
val project = ProjectBuilder.builder().build()
|
||||||
|
val task = project.tasks.register("compileJava").get()
|
||||||
|
task.group = "build"
|
||||||
|
task.description = "Compiles Java source files"
|
||||||
|
|
||||||
|
val result =
|
||||||
|
processTask(
|
||||||
|
task,
|
||||||
|
projectBuildPath = ":project",
|
||||||
|
projectRoot = project.projectDir.path,
|
||||||
|
workspaceRoot = project.rootDir.path,
|
||||||
|
cwd = ".",
|
||||||
|
externalNodes = mutableMapOf(),
|
||||||
|
dependencies = mutableSetOf(),
|
||||||
|
targetNameOverrides = emptyMap())
|
||||||
|
|
||||||
|
assertEquals(true, result["cache"])
|
||||||
|
assertTrue((result["command"] as String).contains("gradlew"))
|
||||||
|
assertNotNull(result["metadata"])
|
||||||
|
assertNotNull(result["options"])
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -13,7 +13,7 @@ jobs:
|
|||||||
_JAVA_OPTIONS: '-Xmx3g'
|
_JAVA_OPTIONS: '-Xmx3g'
|
||||||
GRADLE_OPTS: '-Dorg.gradle.daemon=false -Dorg.gradle.workers.max=2'
|
GRADLE_OPTS: '-Dorg.gradle.daemon=false -Dorg.gradle.workers.max=2'
|
||||||
docker:
|
docker:
|
||||||
- image: cimg/openjdk:17.0-node
|
- image: cimg/openjdk:21.0-node
|
||||||
steps:
|
steps:
|
||||||
- checkout
|
- checkout
|
||||||
|
|
||||||
@ -66,15 +66,15 @@ jobs:
|
|||||||
# Uncomment this line to enable task distribution
|
# Uncomment this line to enable task distribution
|
||||||
# - run: npx nx-cloud start-ci-run --distribute-on="3 linux-medium-jvm" --stop-agents-after="build"
|
# - run: npx nx-cloud start-ci-run --distribute-on="3 linux-medium-jvm" --stop-agents-after="build"
|
||||||
|
|
||||||
- name: Set up JDK 17 for x64
|
- name: Set up JDK 21 for x64
|
||||||
uses: actions/setup-java@v4
|
uses: actions/setup-java@v4
|
||||||
with:
|
with:
|
||||||
java-version: '17'
|
java-version: '21'
|
||||||
distribution: 'temurin'
|
distribution: 'temurin'
|
||||||
architecture: x64
|
architecture: x64
|
||||||
|
|
||||||
- name: Setup Gradle
|
- name: Setup Gradle
|
||||||
uses: gradle/gradle-build-action@v2
|
uses: gradle/gradle-build-action@v4
|
||||||
|
|
||||||
- uses: nrwl/nx-set-shas@v4
|
- uses: nrwl/nx-set-shas@v4
|
||||||
|
|
||||||
@ -96,7 +96,7 @@ jobs:
|
|||||||
_JAVA_OPTIONS: '-Xmx3g'
|
_JAVA_OPTIONS: '-Xmx3g'
|
||||||
GRADLE_OPTS: '-Dorg.gradle.daemon=false -Dorg.gradle.workers.max=2'
|
GRADLE_OPTS: '-Dorg.gradle.daemon=false -Dorg.gradle.workers.max=2'
|
||||||
docker:
|
docker:
|
||||||
- image: cimg/openjdk:17.0-node
|
- image: cimg/openjdk:21.0-node
|
||||||
steps:
|
steps:
|
||||||
- checkout
|
- checkout
|
||||||
|
|
||||||
@ -149,15 +149,15 @@ jobs:
|
|||||||
# Connect your workspace by running "nx connect" and uncomment this line to enable task distribution
|
# Connect your workspace by running "nx connect" and uncomment this line to enable task distribution
|
||||||
# - run: npx nx-cloud start-ci-run --distribute-on="3 linux-medium-jvm" --stop-agents-after="build"
|
# - run: npx nx-cloud start-ci-run --distribute-on="3 linux-medium-jvm" --stop-agents-after="build"
|
||||||
|
|
||||||
- name: Set up JDK 17 for x64
|
- name: Set up JDK 21 for x64
|
||||||
uses: actions/setup-java@v4
|
uses: actions/setup-java@v4
|
||||||
with:
|
with:
|
||||||
java-version: '17'
|
java-version: '21'
|
||||||
distribution: 'temurin'
|
distribution: 'temurin'
|
||||||
architecture: x64
|
architecture: x64
|
||||||
|
|
||||||
- name: Setup Gradle
|
- name: Setup Gradle
|
||||||
uses: gradle/gradle-build-action@v2
|
uses: gradle/gradle-build-action@v4
|
||||||
|
|
||||||
- uses: nrwl/nx-set-shas@v4
|
- uses: nrwl/nx-set-shas@v4
|
||||||
|
|
||||||
|
|||||||
@ -10,7 +10,7 @@ jobs:
|
|||||||
_JAVA_OPTIONS: "-Xmx3g"
|
_JAVA_OPTIONS: "-Xmx3g"
|
||||||
GRADLE_OPTS: "-Dorg.gradle.daemon=false -Dorg.gradle.workers.max=2"
|
GRADLE_OPTS: "-Dorg.gradle.daemon=false -Dorg.gradle.workers.max=2"
|
||||||
docker:
|
docker:
|
||||||
- image: cimg/openjdk:17.0-node
|
- image: cimg/openjdk:21.0-node
|
||||||
steps:
|
steps:
|
||||||
- checkout
|
- checkout
|
||||||
|
|
||||||
|
|||||||
@ -25,15 +25,15 @@ jobs:
|
|||||||
<% if (connectedToCloud) { %># Uncomment this line to enable task distribution<% } else { %># Connect your workspace by running "nx connect" and uncomment this line to enable task distribution<% } %>
|
<% if (connectedToCloud) { %># Uncomment this line to enable task distribution<% } else { %># Connect your workspace by running "nx connect" and uncomment this line to enable task distribution<% } %>
|
||||||
# - run: <%= packageManagerPrefix %> nx-cloud start-ci-run --distribute-on="3 linux-medium-jvm" --stop-agents-after="build"
|
# - run: <%= packageManagerPrefix %> nx-cloud start-ci-run --distribute-on="3 linux-medium-jvm" --stop-agents-after="build"
|
||||||
|
|
||||||
- name: Set up JDK 17 for x64
|
- name: Set up JDK 21 for x64
|
||||||
uses: actions/setup-java@v4
|
uses: actions/setup-java@v4
|
||||||
with:
|
with:
|
||||||
java-version: '17'
|
java-version: '21'
|
||||||
distribution: 'temurin'
|
distribution: 'temurin'
|
||||||
architecture: x64
|
architecture: x64
|
||||||
|
|
||||||
- name: Setup Gradle
|
- name: Setup Gradle
|
||||||
uses: gradle/gradle-build-action@v2
|
uses: gradle/gradle-build-action@v4
|
||||||
|
|
||||||
- uses: nrwl/nx-set-shas@v4
|
- uses: nrwl/nx-set-shas@v4
|
||||||
|
|
||||||
|
|||||||
@ -24,7 +24,6 @@ describe('@nx/gradle:init', () => {
|
|||||||
"options": {
|
"options": {
|
||||||
"buildTargetName": "build",
|
"buildTargetName": "build",
|
||||||
"classesTargetName": "classes",
|
"classesTargetName": "classes",
|
||||||
"includeSubprojectsTasks": false,
|
|
||||||
"testTargetName": "test",
|
"testTargetName": "test",
|
||||||
},
|
},
|
||||||
"plugin": "@nx/gradle",
|
"plugin": "@nx/gradle",
|
||||||
@ -49,7 +48,6 @@ describe('@nx/gradle:init', () => {
|
|||||||
"options": {
|
"options": {
|
||||||
"buildTargetName": "build",
|
"buildTargetName": "build",
|
||||||
"classesTargetName": "classes",
|
"classesTargetName": "classes",
|
||||||
"includeSubprojectsTasks": false,
|
|
||||||
"testTargetName": "test",
|
"testTargetName": "test",
|
||||||
},
|
},
|
||||||
"plugin": "@nx/gradle",
|
"plugin": "@nx/gradle",
|
||||||
|
|||||||
@ -9,7 +9,11 @@ import {
|
|||||||
Tree,
|
Tree,
|
||||||
updateNxJson,
|
updateNxJson,
|
||||||
} from '@nx/devkit';
|
} from '@nx/devkit';
|
||||||
import { nxVersion } from '../../utils/versions';
|
import {
|
||||||
|
gradleProjectGraphPluginName,
|
||||||
|
gradleProjectGraphVersion,
|
||||||
|
nxVersion,
|
||||||
|
} from '../../utils/versions';
|
||||||
import { InitGeneratorSchema } from './schema';
|
import { InitGeneratorSchema } from './schema';
|
||||||
import { hasGradlePlugin } from '../../utils/has-gradle-plugin';
|
import { hasGradlePlugin } from '../../utils/has-gradle-plugin';
|
||||||
import { dirname, join, basename } from 'path';
|
import { dirname, join, basename } from 'path';
|
||||||
@ -52,7 +56,6 @@ function addPlugin(tree: Tree) {
|
|||||||
testTargetName: 'test',
|
testTargetName: 'test',
|
||||||
classesTargetName: 'classes',
|
classesTargetName: 'classes',
|
||||||
buildTargetName: 'build',
|
buildTargetName: 'build',
|
||||||
includeSubprojectsTasks: false,
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
updateNxJson(tree, nxJson);
|
updateNxJson(tree, nxJson);
|
||||||
@ -67,16 +70,18 @@ export async function addBuildGradleFileNextToSettingsGradle(tree: Tree) {
|
|||||||
'**/settings.gradle?(.kts)',
|
'**/settings.gradle?(.kts)',
|
||||||
]);
|
]);
|
||||||
settingsGradleFiles.forEach((settingsGradleFile) => {
|
settingsGradleFiles.forEach((settingsGradleFile) => {
|
||||||
addProjectReportToBuildGradle(settingsGradleFile, tree);
|
addNxProjectGraphPluginToBuildGradle(settingsGradleFile, tree);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* - creates a build.gradle file next to the settings.gradle file if it does not exist.
|
* - creates a build.gradle file next to the settings.gradle file if it does not exist.
|
||||||
* - adds the project-report plugin to the build.gradle file if it does not exist.
|
* - adds the NxProjectGraphPlugin plugin to the build.gradle file if it does not exist.
|
||||||
* - adds a task to generate project reports for all subprojects and included builds.
|
|
||||||
*/
|
*/
|
||||||
function addProjectReportToBuildGradle(settingsGradleFile: string, tree: Tree) {
|
function addNxProjectGraphPluginToBuildGradle(
|
||||||
|
settingsGradleFile: string,
|
||||||
|
tree: Tree
|
||||||
|
) {
|
||||||
const filename = basename(settingsGradleFile);
|
const filename = basename(settingsGradleFile);
|
||||||
let gradleFilePath = 'build.gradle';
|
let gradleFilePath = 'build.gradle';
|
||||||
if (filename.endsWith('.kts')) {
|
if (filename.endsWith('.kts')) {
|
||||||
@ -90,53 +95,49 @@ function addProjectReportToBuildGradle(settingsGradleFile: string, tree: Tree) {
|
|||||||
buildGradleContent = tree.read(gradleFilePath).toString();
|
buildGradleContent = tree.read(gradleFilePath).toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (buildGradleContent.includes('allprojects')) {
|
const nxProjectGraphReportPlugin = filename.endsWith('.kts')
|
||||||
if (!buildGradleContent.includes('"project-report"')) {
|
? `id("${gradleProjectGraphPluginName}") version("${gradleProjectGraphVersion}")`
|
||||||
logger.warn(`Please add the project-report plugin to your ${gradleFilePath}:
|
: `id "${gradleProjectGraphPluginName}" version "${gradleProjectGraphVersion}"`;
|
||||||
allprojects {
|
if (buildGradleContent.includes('plugins {')) {
|
||||||
apply {
|
if (!buildGradleContent.includes(gradleProjectGraphPluginName)) {
|
||||||
plugin("project-report")
|
buildGradleContent = buildGradleContent.replace(
|
||||||
}
|
'plugins {',
|
||||||
}`);
|
`plugins {
|
||||||
|
${nxProjectGraphReportPlugin}`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
buildGradleContent += `\n\rallprojects {
|
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 {
|
apply {
|
||||||
plugin("project-report")
|
${applyNxProjectGraphReportPlugin}
|
||||||
}
|
}
|
||||||
}`;
|
}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
buildGradleContent = `${buildGradleContent}\n\rallprojects {
|
||||||
|
apply {
|
||||||
|
${applyNxProjectGraphReportPlugin}
|
||||||
|
}
|
||||||
|
}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!buildGradleContent.includes(`tasks.register("projectReportAll")`)) {
|
tree.write(gradleFilePath, buildGradleContent);
|
||||||
if (gradleFilePath.endsWith('.kts')) {
|
|
||||||
buildGradleContent += `\n\rtasks.register("projectReportAll") {
|
|
||||||
// All project reports of subprojects
|
|
||||||
allprojects.forEach {
|
|
||||||
dependsOn(it.tasks.get("projectReport"))
|
|
||||||
}
|
|
||||||
|
|
||||||
// All projectReportAll of included builds
|
|
||||||
gradle.includedBuilds.forEach {
|
|
||||||
dependsOn(it.task(":projectReportAll"))
|
|
||||||
}
|
|
||||||
}`;
|
|
||||||
} else {
|
|
||||||
buildGradleContent += `\n\rtasks.register("projectReportAll") {
|
|
||||||
// All project reports of subprojects
|
|
||||||
allprojects.forEach {
|
|
||||||
dependsOn(it.tasks.getAt("projectReport"))
|
|
||||||
}
|
|
||||||
|
|
||||||
// All projectReportAll of included builds
|
|
||||||
gradle.includedBuilds.forEach {
|
|
||||||
dependsOn(it.task(":projectReportAll"))
|
|
||||||
}
|
|
||||||
}`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (buildGradleContent) {
|
|
||||||
tree.write(gradleFilePath, buildGradleContent);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function updateNxJsonConfiguration(tree: Tree) {
|
export function updateNxJsonConfiguration(tree: Tree) {
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import { Tree } from '@nx/devkit';
|
import { globAsync, logger, Tree } from '@nx/devkit';
|
||||||
import { addBuildGradleFileNextToSettingsGradle } from '../../generators/init/init';
|
import { basename, dirname, join } from 'node:path';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This migration adds task `projectReportAll` to build.gradle files
|
* This migration adds task `projectReportAll` to build.gradle files
|
||||||
@ -7,3 +7,83 @@ import { addBuildGradleFileNextToSettingsGradle } from '../../generators/init/in
|
|||||||
export default async function update(tree: Tree) {
|
export default async function update(tree: Tree) {
|
||||||
await addBuildGradleFileNextToSettingsGradle(tree);
|
await addBuildGradleFileNextToSettingsGradle(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) => {
|
||||||
|
addProjectReportToBuildGradle(settingsGradleFile, tree);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* - creates a build.gradle file next to the settings.gradle file if it does not exist.
|
||||||
|
* - adds the project-report plugin to the build.gradle file if it does not exist.
|
||||||
|
* - adds a task to generate project reports for all subprojects and included builds.
|
||||||
|
*/
|
||||||
|
function addProjectReportToBuildGradle(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();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buildGradleContent.includes('allprojects')) {
|
||||||
|
if (!buildGradleContent.includes('"project-report"')) {
|
||||||
|
logger.warn(`Please add the project-report plugin to your ${gradleFilePath}:
|
||||||
|
allprojects {
|
||||||
|
apply {
|
||||||
|
plugin("project-report")
|
||||||
|
}
|
||||||
|
}`);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
buildGradleContent += `\n\rallprojects {
|
||||||
|
apply {
|
||||||
|
plugin("project-report")
|
||||||
|
}
|
||||||
|
}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!buildGradleContent.includes(`tasks.register("projectReportAll")`)) {
|
||||||
|
if (gradleFilePath.endsWith('.kts')) {
|
||||||
|
buildGradleContent += `\n\rtasks.register("projectReportAll") {
|
||||||
|
// All project reports of subprojects
|
||||||
|
allprojects.forEach {
|
||||||
|
dependsOn(it.tasks.get("projectReport"))
|
||||||
|
}
|
||||||
|
|
||||||
|
// All projectReportAll of included builds
|
||||||
|
gradle.includedBuilds.forEach {
|
||||||
|
dependsOn(it.task(":projectReportAll"))
|
||||||
|
}
|
||||||
|
}`;
|
||||||
|
} else {
|
||||||
|
buildGradleContent += `\n\rtasks.register("projectReportAll") {
|
||||||
|
// All project reports of subprojects
|
||||||
|
allprojects.forEach {
|
||||||
|
dependsOn(it.tasks.getAt("projectReport"))
|
||||||
|
}
|
||||||
|
|
||||||
|
// All projectReportAll of included builds
|
||||||
|
gradle.includedBuilds.forEach {
|
||||||
|
dependsOn(it.task(":projectReportAll"))
|
||||||
|
}
|
||||||
|
}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (buildGradleContent) {
|
||||||
|
tree.write(gradleFilePath, buildGradleContent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -1,11 +1,9 @@
|
|||||||
#### Add includeSubprojectsTasks to build.gradle File
|
#### Add includeSubprojectsTasks to @nx/gradle Plugin Options
|
||||||
|
|
||||||
Add includeSubprojectsTasks to build.gradle file
|
Add includeSubprojectsTasks to @nx/gradle plugin options in nx.json file
|
||||||
|
|
||||||
#### Sample Code Changes
|
#### Sample Code Changes
|
||||||
|
|
||||||
Update import paths for `withModuleFederation` and `withModuleFederationForSSR`.
|
|
||||||
|
|
||||||
{% tabs %}
|
{% tabs %}
|
||||||
{% tab label="Before" %}
|
{% tab label="Before" %}
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import { Tree, readNxJson, updateNxJson } from '@nx/devkit';
|
import { Tree, readNxJson, updateNxJson } from '@nx/devkit';
|
||||||
import { hasGradlePlugin } from '../../utils/has-gradle-plugin';
|
import { hasGradlePlugin } from '../../utils/has-gradle-plugin';
|
||||||
import { GradlePluginOptions } from '../../plugin/nodes';
|
import { GradlePluginOptions } from '../../plugin-v1/nodes';
|
||||||
|
|
||||||
// This function add options includeSubprojectsTasks as true in nx.json for gradle plugin
|
// This function add options includeSubprojectsTasks as true in nx.json for gradle plugin
|
||||||
export default function update(tree: Tree) {
|
export default function update(tree: Tree) {
|
||||||
|
|||||||
26
packages/gradle/src/migrations/21-0-0/change-plugin-to-v1.md
Normal file
26
packages/gradle/src/migrations/21-0-0/change-plugin-to-v1.md
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
#### Change @nx/gradle plugin to @nx/gradle/plugin-v1
|
||||||
|
|
||||||
|
Change @nx/gradle plugin to version 1 in nx.json
|
||||||
|
|
||||||
|
#### Sample Code Changes
|
||||||
|
|
||||||
|
{% tabs %}
|
||||||
|
{% tab label="Before" %}
|
||||||
|
|
||||||
|
```json {% fileName="nx.json" %}
|
||||||
|
{
|
||||||
|
"plugins": ["@nx/gradle"]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
{% /tab %}
|
||||||
|
{% tab label="After" %}
|
||||||
|
|
||||||
|
```json {% highlightLines=[5] fileName="nx.json" %}
|
||||||
|
{
|
||||||
|
"plugins": ["@nx/gradle/plugin-v1"]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
{% /tab %}
|
||||||
|
{% /tabs %}
|
||||||
@ -0,0 +1,57 @@
|
|||||||
|
import { Tree, readNxJson } from '@nx/devkit';
|
||||||
|
import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing';
|
||||||
|
import update from './change-plugin-to-v1';
|
||||||
|
|
||||||
|
describe('ChangePluginToV1', () => {
|
||||||
|
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 change @nx/gradle to @nx/gradle/plugin-v1 plugin', async () => {
|
||||||
|
tree.write('nx.json', JSON.stringify({ plugins: ['@nx/gradle'] }));
|
||||||
|
update(tree);
|
||||||
|
expect(readNxJson(tree)).toMatchInlineSnapshot(`
|
||||||
|
{
|
||||||
|
"plugins": [
|
||||||
|
"@nx/gradle/plugin-v1",
|
||||||
|
],
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should add change to @nx/gradle plugin with options', 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/plugin-v1",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
});
|
||||||
|
});
|
||||||
25
packages/gradle/src/migrations/21-0-0/change-plugin-to-v1.ts
Normal file
25
packages/gradle/src/migrations/21-0-0/change-plugin-to-v1.ts
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
import { Tree, readNxJson, updateNxJson } from '@nx/devkit';
|
||||||
|
import { hasGradlePlugin } from '../../utils/has-gradle-plugin';
|
||||||
|
|
||||||
|
/* This function changes the plugin to v1
|
||||||
|
* Replace @nx/gradle with @nx/gradle/plugin-v1
|
||||||
|
*/
|
||||||
|
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 === 'string') {
|
||||||
|
nxJson.plugins[gradlePluginIndex] = '@nx/gradle/plugin-v1';
|
||||||
|
} else {
|
||||||
|
gradlePlugin.plugin = '@nx/gradle/plugin-v1';
|
||||||
|
}
|
||||||
|
updateNxJson(tree, nxJson);
|
||||||
|
}
|
||||||
96
packages/gradle/src/plugin-v1/dependencies.ts
Normal file
96
packages/gradle/src/plugin-v1/dependencies.ts
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
import {
|
||||||
|
CreateDependencies,
|
||||||
|
CreateDependenciesContext,
|
||||||
|
DependencyType,
|
||||||
|
FileMap,
|
||||||
|
RawProjectGraphDependency,
|
||||||
|
validateDependency,
|
||||||
|
} from '@nx/devkit';
|
||||||
|
import { basename, dirname } from 'node:path';
|
||||||
|
|
||||||
|
import { getCurrentGradleReport } from './utils/get-gradle-report';
|
||||||
|
import { GRADLE_BUILD_FILES } from '../utils/split-config-files';
|
||||||
|
|
||||||
|
export const createDependencies: CreateDependencies = async (
|
||||||
|
_,
|
||||||
|
context: CreateDependenciesContext
|
||||||
|
) => {
|
||||||
|
const gradleFiles: string[] = findGradleFiles(context.filesToProcess);
|
||||||
|
if (gradleFiles.length === 0) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
const gradleDependenciesStart = performance.mark('gradleDependencies:start');
|
||||||
|
const {
|
||||||
|
gradleFileToGradleProjectMap,
|
||||||
|
gradleProjectNameToProjectRootMap,
|
||||||
|
gradleProjectToDepsMap,
|
||||||
|
gradleProjectToChildProjects,
|
||||||
|
} = getCurrentGradleReport();
|
||||||
|
const dependencies: Set<RawProjectGraphDependency> = new Set();
|
||||||
|
|
||||||
|
for (const gradleFile of gradleFiles) {
|
||||||
|
const gradleProject = gradleFileToGradleProjectMap.get(gradleFile);
|
||||||
|
const projectName = Object.values(context.projects).find(
|
||||||
|
(project) => project.root === dirname(gradleFile)
|
||||||
|
)?.name;
|
||||||
|
const dependedProjects: Set<string> =
|
||||||
|
gradleProjectToDepsMap.get(gradleProject);
|
||||||
|
|
||||||
|
if (projectName && dependedProjects?.size) {
|
||||||
|
dependedProjects?.forEach((dependedProject) => {
|
||||||
|
const targetProjectRoot = gradleProjectNameToProjectRootMap.get(
|
||||||
|
dependedProject
|
||||||
|
) as string;
|
||||||
|
const targetProjectName = Object.values(context.projects).find(
|
||||||
|
(project) => project.root === targetProjectRoot
|
||||||
|
)?.name;
|
||||||
|
if (targetProjectName) {
|
||||||
|
const dependency: RawProjectGraphDependency = {
|
||||||
|
source: projectName as string,
|
||||||
|
target: targetProjectName as string,
|
||||||
|
type: DependencyType.static,
|
||||||
|
sourceFile: gradleFile,
|
||||||
|
};
|
||||||
|
validateDependency(dependency, context);
|
||||||
|
dependencies.add(dependency);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
gradleProjectToChildProjects.get(gradleProject)?.forEach((childProject) => {
|
||||||
|
if (childProject) {
|
||||||
|
const dependency: RawProjectGraphDependency = {
|
||||||
|
source: projectName as string,
|
||||||
|
target: childProject,
|
||||||
|
type: DependencyType.static,
|
||||||
|
sourceFile: gradleFile,
|
||||||
|
};
|
||||||
|
validateDependency(dependency, context);
|
||||||
|
dependencies.add(dependency);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const gradleDependenciesEnd = performance.mark('gradleDependencies:end');
|
||||||
|
performance.measure(
|
||||||
|
'gradleDependencies',
|
||||||
|
gradleDependenciesStart.name,
|
||||||
|
gradleDependenciesEnd.name
|
||||||
|
);
|
||||||
|
|
||||||
|
return Array.from(dependencies);
|
||||||
|
};
|
||||||
|
|
||||||
|
function findGradleFiles(fileMap: FileMap): string[] {
|
||||||
|
const gradleFiles: string[] = [];
|
||||||
|
|
||||||
|
for (const [_, files] of Object.entries(fileMap.projectFileMap)) {
|
||||||
|
for (const file of files) {
|
||||||
|
if (GRADLE_BUILD_FILES.has(basename(file.file))) {
|
||||||
|
gradleFiles.push(file.file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return gradleFiles;
|
||||||
|
}
|
||||||
587
packages/gradle/src/plugin-v1/nodes.spec.ts
Normal file
587
packages/gradle/src/plugin-v1/nodes.spec.ts
Normal file
@ -0,0 +1,587 @@
|
|||||||
|
import { CreateNodesContext } from '@nx/devkit';
|
||||||
|
|
||||||
|
import { TempFs } from 'nx/src/internal-testing-utils/temp-fs';
|
||||||
|
import { type GradleReport } from './utils/get-gradle-report';
|
||||||
|
|
||||||
|
let gradleReport: GradleReport;
|
||||||
|
jest.mock('./utils/get-gradle-report', () => {
|
||||||
|
return {
|
||||||
|
GRADLE_BUILD_FILES: new Set(['build.gradle', 'build.gradle.kts']),
|
||||||
|
populateGradleReport: jest.fn().mockImplementation(() => void 0),
|
||||||
|
getCurrentGradleReport: jest.fn().mockImplementation(() => gradleReport),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
import { createNodesV2 } from './nodes';
|
||||||
|
|
||||||
|
describe('@nx/gradle/plugin-v1/nodes', () => {
|
||||||
|
let createNodesFunction = createNodesV2[1];
|
||||||
|
let context: CreateNodesContext;
|
||||||
|
let tempFs: TempFs;
|
||||||
|
let cwd: string;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
tempFs = new TempFs('test');
|
||||||
|
gradleReport = {
|
||||||
|
gradleFileToGradleProjectMap: new Map<string, string>([
|
||||||
|
['proj/build.gradle', 'proj'],
|
||||||
|
]),
|
||||||
|
gradleProjectToDepsMap: new Map<string, Set<string>>(),
|
||||||
|
gradleFileToOutputDirsMap: new Map<string, Map<string, string>>([
|
||||||
|
['proj/build.gradle', new Map([['build', 'build']])],
|
||||||
|
]),
|
||||||
|
gradleProjectToTasksMap: new Map<string, Set<string>>([
|
||||||
|
['proj', new Set(['test'])],
|
||||||
|
]),
|
||||||
|
gradleProjectToTasksTypeMap: new Map<string, Map<string, string>>([
|
||||||
|
[
|
||||||
|
'proj',
|
||||||
|
new Map([
|
||||||
|
['test', 'Verification'],
|
||||||
|
['build', 'Build'],
|
||||||
|
]),
|
||||||
|
],
|
||||||
|
]),
|
||||||
|
gradleProjectToProjectName: new Map<string, string>([['proj', 'proj']]),
|
||||||
|
gradleProjectNameToProjectRootMap: new Map<string, string>([
|
||||||
|
['proj', 'proj'],
|
||||||
|
]),
|
||||||
|
gradleProjectToChildProjects: new Map<string, string[]>(),
|
||||||
|
};
|
||||||
|
cwd = process.cwd();
|
||||||
|
process.chdir(tempFs.tempDir);
|
||||||
|
context = {
|
||||||
|
nxJsonConfiguration: {
|
||||||
|
namedInputs: {
|
||||||
|
default: ['{projectRoot}/**/*'],
|
||||||
|
production: ['!{projectRoot}/**/*.spec.ts'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
workspaceRoot: tempFs.tempDir,
|
||||||
|
configFiles: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
await tempFs.createFiles({
|
||||||
|
'proj/build.gradle': ``,
|
||||||
|
gradlew: '',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
jest.resetModules();
|
||||||
|
process.chdir(cwd);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create nodes based on gradle', async () => {
|
||||||
|
const results = await createNodesFunction(
|
||||||
|
['proj/build.gradle'],
|
||||||
|
{
|
||||||
|
buildTargetName: 'build',
|
||||||
|
},
|
||||||
|
context
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(results).toMatchInlineSnapshot(`
|
||||||
|
[
|
||||||
|
[
|
||||||
|
"proj/build.gradle",
|
||||||
|
{
|
||||||
|
"projects": {
|
||||||
|
"proj": {
|
||||||
|
"metadata": {
|
||||||
|
"targetGroups": {
|
||||||
|
"Verification": [
|
||||||
|
"test",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"technologies": [
|
||||||
|
"gradle",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"name": "proj",
|
||||||
|
"projectType": "application",
|
||||||
|
"targets": {
|
||||||
|
"test": {
|
||||||
|
"cache": true,
|
||||||
|
"command": "./gradlew proj:test",
|
||||||
|
"dependsOn": [
|
||||||
|
"testClasses",
|
||||||
|
],
|
||||||
|
"inputs": [
|
||||||
|
"default",
|
||||||
|
"^production",
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"help": {
|
||||||
|
"command": "./gradlew help --task proj:test",
|
||||||
|
"example": {
|
||||||
|
"options": {
|
||||||
|
"args": [
|
||||||
|
"--rerun",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"technologies": [
|
||||||
|
"gradle",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"cwd": ".",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
]
|
||||||
|
`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create nodes include subprojects tasks', async () => {
|
||||||
|
const results = await createNodesFunction(
|
||||||
|
['proj/build.gradle'],
|
||||||
|
{
|
||||||
|
buildTargetName: 'build',
|
||||||
|
includeSubprojectsTasks: true,
|
||||||
|
},
|
||||||
|
context
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(results).toMatchInlineSnapshot(`
|
||||||
|
[
|
||||||
|
[
|
||||||
|
"proj/build.gradle",
|
||||||
|
{
|
||||||
|
"projects": {
|
||||||
|
"proj": {
|
||||||
|
"metadata": {
|
||||||
|
"targetGroups": {
|
||||||
|
"Build": [
|
||||||
|
"build",
|
||||||
|
],
|
||||||
|
"Verification": [
|
||||||
|
"test",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"technologies": [
|
||||||
|
"gradle",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"name": "proj",
|
||||||
|
"projectType": "application",
|
||||||
|
"targets": {
|
||||||
|
"build": {
|
||||||
|
"cache": true,
|
||||||
|
"command": "./gradlew proj:build",
|
||||||
|
"dependsOn": [
|
||||||
|
"^build",
|
||||||
|
"classes",
|
||||||
|
"test",
|
||||||
|
],
|
||||||
|
"inputs": [
|
||||||
|
"production",
|
||||||
|
"^production",
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"help": {
|
||||||
|
"command": "./gradlew help --task proj:build",
|
||||||
|
"example": {
|
||||||
|
"options": {
|
||||||
|
"args": [
|
||||||
|
"--rerun",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"technologies": [
|
||||||
|
"gradle",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"cwd": ".",
|
||||||
|
},
|
||||||
|
"outputs": [
|
||||||
|
"build",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"test": {
|
||||||
|
"cache": true,
|
||||||
|
"command": "./gradlew proj:test",
|
||||||
|
"dependsOn": [
|
||||||
|
"testClasses",
|
||||||
|
],
|
||||||
|
"inputs": [
|
||||||
|
"default",
|
||||||
|
"^production",
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"help": {
|
||||||
|
"command": "./gradlew help --task proj:test",
|
||||||
|
"example": {
|
||||||
|
"options": {
|
||||||
|
"args": [
|
||||||
|
"--rerun",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"technologies": [
|
||||||
|
"gradle",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"cwd": ".",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
]
|
||||||
|
`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create nodes based on gradle for nested project root', async () => {
|
||||||
|
gradleReport = {
|
||||||
|
gradleFileToGradleProjectMap: new Map<string, string>([
|
||||||
|
['nested/nested/proj/build.gradle', 'proj'],
|
||||||
|
]),
|
||||||
|
gradleProjectToDepsMap: new Map<string, Set<string>>(),
|
||||||
|
gradleFileToOutputDirsMap: new Map<string, Map<string, string>>([
|
||||||
|
['nested/nested/proj/build.gradle', new Map([['build', 'build']])],
|
||||||
|
]),
|
||||||
|
gradleProjectToTasksMap: new Map<string, Set<string>>([
|
||||||
|
['proj', new Set(['test'])],
|
||||||
|
]),
|
||||||
|
gradleProjectToTasksTypeMap: new Map<string, Map<string, string>>([
|
||||||
|
['proj', new Map([['test', 'Verification']])],
|
||||||
|
]),
|
||||||
|
gradleProjectToProjectName: new Map<string, string>([['proj', 'proj']]),
|
||||||
|
gradleProjectNameToProjectRootMap: new Map<string, string>([
|
||||||
|
['proj', 'proj'],
|
||||||
|
]),
|
||||||
|
gradleProjectToChildProjects: new Map<string, string[]>(),
|
||||||
|
};
|
||||||
|
await tempFs.createFiles({
|
||||||
|
'nested/nested/proj/build.gradle': ``,
|
||||||
|
});
|
||||||
|
|
||||||
|
const results = await createNodesFunction(
|
||||||
|
['nested/nested/proj/build.gradle'],
|
||||||
|
{
|
||||||
|
buildTargetName: 'build',
|
||||||
|
},
|
||||||
|
context
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(results).toMatchInlineSnapshot(`
|
||||||
|
[
|
||||||
|
[
|
||||||
|
"nested/nested/proj/build.gradle",
|
||||||
|
{
|
||||||
|
"projects": {
|
||||||
|
"nested/nested/proj": {
|
||||||
|
"metadata": {
|
||||||
|
"targetGroups": {
|
||||||
|
"Verification": [
|
||||||
|
"test",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"technologies": [
|
||||||
|
"gradle",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"name": "proj",
|
||||||
|
"projectType": "application",
|
||||||
|
"targets": {
|
||||||
|
"test": {
|
||||||
|
"cache": true,
|
||||||
|
"command": "./gradlew proj:test",
|
||||||
|
"dependsOn": [
|
||||||
|
"testClasses",
|
||||||
|
],
|
||||||
|
"inputs": [
|
||||||
|
"default",
|
||||||
|
"^production",
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"help": {
|
||||||
|
"command": "./gradlew help --task proj:test",
|
||||||
|
"example": {
|
||||||
|
"options": {
|
||||||
|
"args": [
|
||||||
|
"--rerun",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"technologies": [
|
||||||
|
"gradle",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"cwd": ".",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
]
|
||||||
|
`);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('with atomized tests targets', () => {
|
||||||
|
beforeEach(async () => {
|
||||||
|
gradleReport = {
|
||||||
|
gradleFileToGradleProjectMap: new Map<string, string>([
|
||||||
|
['nested/nested/proj/build.gradle', 'proj'],
|
||||||
|
]),
|
||||||
|
gradleProjectToDepsMap: new Map<string, Set<string>>(),
|
||||||
|
gradleFileToOutputDirsMap: new Map<string, Map<string, string>>([
|
||||||
|
['nested/nested/proj/build.gradle', new Map([['build', 'build']])],
|
||||||
|
]),
|
||||||
|
gradleProjectToTasksMap: new Map<string, Set<string>>([
|
||||||
|
['proj', new Set(['test'])],
|
||||||
|
]),
|
||||||
|
gradleProjectToTasksTypeMap: new Map<string, Map<string, string>>([
|
||||||
|
['proj', new Map([['test', 'Test']])],
|
||||||
|
]),
|
||||||
|
gradleProjectToProjectName: new Map<string, string>([['proj', 'proj']]),
|
||||||
|
gradleProjectNameToProjectRootMap: new Map<string, string>([
|
||||||
|
['proj', 'proj'],
|
||||||
|
]),
|
||||||
|
gradleProjectToChildProjects: new Map<string, string[]>(),
|
||||||
|
};
|
||||||
|
await tempFs.createFiles({
|
||||||
|
'nested/nested/proj/build.gradle': ``,
|
||||||
|
});
|
||||||
|
await tempFs.createFiles({
|
||||||
|
'proj/src/test/java/test/rootTest.java': ``,
|
||||||
|
});
|
||||||
|
await tempFs.createFiles({
|
||||||
|
'nested/nested/proj/src/test/java/test/aTest.java': ``,
|
||||||
|
});
|
||||||
|
await tempFs.createFiles({
|
||||||
|
'nested/nested/proj/src/test/java/test/bTest.java': ``,
|
||||||
|
});
|
||||||
|
await tempFs.createFiles({
|
||||||
|
'nested/nested/proj/src/test/java/test/cTests.java': ``,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create nodes with atomized tests targets based on gradle for nested project root', async () => {
|
||||||
|
const results = await createNodesFunction(
|
||||||
|
[
|
||||||
|
'nested/nested/proj/build.gradle',
|
||||||
|
'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',
|
||||||
|
'nested/nested/proj/src/test/java/test/cTests.java',
|
||||||
|
],
|
||||||
|
{
|
||||||
|
buildTargetName: 'build',
|
||||||
|
ciTargetName: 'test-ci',
|
||||||
|
},
|
||||||
|
context
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(results).toMatchInlineSnapshot(`
|
||||||
|
[
|
||||||
|
[
|
||||||
|
"nested/nested/proj/build.gradle",
|
||||||
|
{
|
||||||
|
"projects": {
|
||||||
|
"nested/nested/proj": {
|
||||||
|
"metadata": {
|
||||||
|
"targetGroups": {
|
||||||
|
"Test": [
|
||||||
|
"test-ci--aTest",
|
||||||
|
"test-ci--bTest",
|
||||||
|
"test-ci--cTests",
|
||||||
|
"test-ci",
|
||||||
|
"test",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"technologies": [
|
||||||
|
"gradle",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"name": "proj",
|
||||||
|
"projectType": "application",
|
||||||
|
"targets": {
|
||||||
|
"test": {
|
||||||
|
"cache": false,
|
||||||
|
"command": "./gradlew proj:test",
|
||||||
|
"dependsOn": [
|
||||||
|
"testClasses",
|
||||||
|
],
|
||||||
|
"inputs": [
|
||||||
|
"default",
|
||||||
|
"^production",
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"help": {
|
||||||
|
"command": "./gradlew help --task proj:test",
|
||||||
|
"example": {
|
||||||
|
"options": {
|
||||||
|
"args": [
|
||||||
|
"--rerun",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"technologies": [
|
||||||
|
"gradle",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"cwd": ".",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"test-ci": {
|
||||||
|
"cache": true,
|
||||||
|
"dependsOn": [
|
||||||
|
{
|
||||||
|
"params": "forward",
|
||||||
|
"projects": "self",
|
||||||
|
"target": "test-ci--aTest",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"params": "forward",
|
||||||
|
"projects": "self",
|
||||||
|
"target": "test-ci--bTest",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"params": "forward",
|
||||||
|
"projects": "self",
|
||||||
|
"target": "test-ci--cTests",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"executor": "nx:noop",
|
||||||
|
"inputs": [
|
||||||
|
"default",
|
||||||
|
"^production",
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"description": "Runs Gradle Tests in CI",
|
||||||
|
"help": {
|
||||||
|
"command": "./gradlew help --task proj:test",
|
||||||
|
"example": {
|
||||||
|
"options": {
|
||||||
|
"args": [
|
||||||
|
"--rerun",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"nonAtomizedTarget": "test",
|
||||||
|
"technologies": [
|
||||||
|
"gradle",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"test-ci--aTest": {
|
||||||
|
"cache": true,
|
||||||
|
"command": "./gradlew proj:test --tests aTest",
|
||||||
|
"dependsOn": [
|
||||||
|
"testClasses",
|
||||||
|
],
|
||||||
|
"inputs": [
|
||||||
|
"default",
|
||||||
|
"^production",
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"description": "Runs Gradle test nested/nested/proj/src/test/java/test/aTest.java in CI",
|
||||||
|
"help": {
|
||||||
|
"command": "./gradlew help --task proj:test",
|
||||||
|
"example": {
|
||||||
|
"options": {
|
||||||
|
"args": [
|
||||||
|
"--rerun",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"technologies": [
|
||||||
|
"gradle",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"cwd": ".",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"test-ci--bTest": {
|
||||||
|
"cache": true,
|
||||||
|
"command": "./gradlew proj:test --tests bTest",
|
||||||
|
"dependsOn": [
|
||||||
|
"testClasses",
|
||||||
|
],
|
||||||
|
"inputs": [
|
||||||
|
"default",
|
||||||
|
"^production",
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"description": "Runs Gradle test nested/nested/proj/src/test/java/test/bTest.java in CI",
|
||||||
|
"help": {
|
||||||
|
"command": "./gradlew help --task proj:test",
|
||||||
|
"example": {
|
||||||
|
"options": {
|
||||||
|
"args": [
|
||||||
|
"--rerun",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"technologies": [
|
||||||
|
"gradle",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"cwd": ".",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"test-ci--cTests": {
|
||||||
|
"cache": true,
|
||||||
|
"command": "./gradlew proj:test --tests cTests",
|
||||||
|
"dependsOn": [
|
||||||
|
"testClasses",
|
||||||
|
],
|
||||||
|
"inputs": [
|
||||||
|
"default",
|
||||||
|
"^production",
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"description": "Runs Gradle test nested/nested/proj/src/test/java/test/cTests.java in CI",
|
||||||
|
"help": {
|
||||||
|
"command": "./gradlew help --task proj:test",
|
||||||
|
"example": {
|
||||||
|
"options": {
|
||||||
|
"args": [
|
||||||
|
"--rerun",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"technologies": [
|
||||||
|
"gradle",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"cwd": ".",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
]
|
||||||
|
`);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
435
packages/gradle/src/plugin-v1/nodes.ts
Normal file
435
packages/gradle/src/plugin-v1/nodes.ts
Normal file
@ -0,0 +1,435 @@
|
|||||||
|
import {
|
||||||
|
CreateNodes,
|
||||||
|
CreateNodesV2,
|
||||||
|
CreateNodesContext,
|
||||||
|
ProjectConfiguration,
|
||||||
|
TargetConfiguration,
|
||||||
|
createNodesFromFiles,
|
||||||
|
readJsonFile,
|
||||||
|
writeJsonFile,
|
||||||
|
CreateNodesFunction,
|
||||||
|
logger,
|
||||||
|
} from '@nx/devkit';
|
||||||
|
import { calculateHashForCreateNodes } from '@nx/devkit/src/utils/calculate-hash-for-create-nodes';
|
||||||
|
import { existsSync } from 'node:fs';
|
||||||
|
import { basename, dirname, join } from 'node:path';
|
||||||
|
import { workspaceDataDirectory } from 'nx/src/utils/cache-directory';
|
||||||
|
import { findProjectForPath } from 'nx/src/devkit-internals';
|
||||||
|
|
||||||
|
import {
|
||||||
|
populateGradleReport,
|
||||||
|
getCurrentGradleReport,
|
||||||
|
GradleReport,
|
||||||
|
} from './utils/get-gradle-report';
|
||||||
|
import { hashObject } from 'nx/src/hasher/file-hasher';
|
||||||
|
import {
|
||||||
|
gradleConfigAndTestGlob,
|
||||||
|
gradleConfigGlob,
|
||||||
|
splitConfigFiles,
|
||||||
|
} from '../utils/split-config-files';
|
||||||
|
import { getGradleExecFile, findGradlewFile } from '../utils/exec-gradle';
|
||||||
|
|
||||||
|
const cacheableTaskType = new Set(['Build', 'Verification']);
|
||||||
|
const dependsOnMap = {
|
||||||
|
build: ['^build', 'classes', 'test'],
|
||||||
|
testClasses: ['classes'],
|
||||||
|
test: ['testClasses'],
|
||||||
|
classes: ['^classes'],
|
||||||
|
};
|
||||||
|
|
||||||
|
interface GradleTask {
|
||||||
|
type: string;
|
||||||
|
name: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GradlePluginOptions {
|
||||||
|
includeSubprojectsTasks?: boolean; // default is false, show all gradle tasks in the project
|
||||||
|
ciTargetName?: string;
|
||||||
|
testTargetName?: string;
|
||||||
|
classesTargetName?: string;
|
||||||
|
buildTargetName?: string;
|
||||||
|
[taskTargetName: string]: string | undefined | boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
function normalizeOptions(options: GradlePluginOptions): GradlePluginOptions {
|
||||||
|
options ??= {};
|
||||||
|
options.testTargetName ??= 'test';
|
||||||
|
options.classesTargetName ??= 'classes';
|
||||||
|
options.buildTargetName ??= 'build';
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
|
||||||
|
type GradleTargets = Record<string, Partial<ProjectConfiguration>>;
|
||||||
|
|
||||||
|
function readTargetsCache(cachePath: string): GradleTargets {
|
||||||
|
return existsSync(cachePath) ? readJsonFile(cachePath) : {};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function writeTargetsToCache(cachePath: string, results: GradleTargets) {
|
||||||
|
writeJsonFile(cachePath, results);
|
||||||
|
}
|
||||||
|
|
||||||
|
export const createNodesV2: CreateNodesV2<GradlePluginOptions> = [
|
||||||
|
gradleConfigAndTestGlob,
|
||||||
|
async (files, options, context) => {
|
||||||
|
const { buildFiles, projectRoots, gradlewFiles, testFiles } =
|
||||||
|
splitConfigFiles(files);
|
||||||
|
const optionsHash = hashObject(options);
|
||||||
|
const cachePath = join(
|
||||||
|
workspaceDataDirectory,
|
||||||
|
`gradle-${optionsHash}.hash`
|
||||||
|
);
|
||||||
|
const targetsCache = readTargetsCache(cachePath);
|
||||||
|
|
||||||
|
await populateGradleReport(
|
||||||
|
context.workspaceRoot,
|
||||||
|
gradlewFiles.map((f) => join(context.workspaceRoot, f))
|
||||||
|
);
|
||||||
|
const gradleReport = getCurrentGradleReport();
|
||||||
|
const gradleProjectRootToTestFilesMap = getGradleProjectRootToTestFilesMap(
|
||||||
|
testFiles,
|
||||||
|
projectRoots
|
||||||
|
);
|
||||||
|
|
||||||
|
try {
|
||||||
|
return createNodesFromFiles(
|
||||||
|
makeCreateNodesForGradleConfigFile(
|
||||||
|
gradleReport,
|
||||||
|
targetsCache,
|
||||||
|
gradleProjectRootToTestFilesMap
|
||||||
|
),
|
||||||
|
buildFiles,
|
||||||
|
options,
|
||||||
|
context
|
||||||
|
);
|
||||||
|
} finally {
|
||||||
|
writeTargetsToCache(cachePath, targetsCache);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export const makeCreateNodesForGradleConfigFile =
|
||||||
|
(
|
||||||
|
gradleReport: GradleReport,
|
||||||
|
targetsCache: GradleTargets = {},
|
||||||
|
gradleProjectRootToTestFilesMap: Record<string, string[]> = {}
|
||||||
|
): CreateNodesFunction =>
|
||||||
|
async (
|
||||||
|
gradleFilePath,
|
||||||
|
options: GradlePluginOptions | undefined,
|
||||||
|
context: CreateNodesContext
|
||||||
|
) => {
|
||||||
|
const projectRoot = dirname(gradleFilePath);
|
||||||
|
options = normalizeOptions(options);
|
||||||
|
|
||||||
|
const hash = await calculateHashForCreateNodes(
|
||||||
|
projectRoot,
|
||||||
|
options ?? {},
|
||||||
|
context
|
||||||
|
);
|
||||||
|
targetsCache[hash] ??= await createGradleProject(
|
||||||
|
gradleReport,
|
||||||
|
gradleFilePath,
|
||||||
|
options,
|
||||||
|
context,
|
||||||
|
gradleProjectRootToTestFilesMap[projectRoot]
|
||||||
|
);
|
||||||
|
const project = targetsCache[hash];
|
||||||
|
if (!project) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
projects: {
|
||||||
|
[projectRoot]: project,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
@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.
|
||||||
|
*/
|
||||||
|
export const createNodes: CreateNodes<GradlePluginOptions> = [
|
||||||
|
gradleConfigGlob,
|
||||||
|
async (buildFile, options, context) => {
|
||||||
|
logger.warn(
|
||||||
|
'`createNodes` is deprecated. Update your plugin to utilize createNodesV2 instead. In Nx 20, this will change to the createNodesV2 API.'
|
||||||
|
);
|
||||||
|
const { gradlewFiles } = splitConfigFiles(context.configFiles);
|
||||||
|
await populateGradleReport(context.workspaceRoot, gradlewFiles);
|
||||||
|
const gradleReport = getCurrentGradleReport();
|
||||||
|
const internalCreateNodes =
|
||||||
|
makeCreateNodesForGradleConfigFile(gradleReport);
|
||||||
|
return await internalCreateNodes(buildFile, options, context);
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
async function createGradleProject(
|
||||||
|
gradleReport: GradleReport,
|
||||||
|
gradleFilePath: string,
|
||||||
|
options: GradlePluginOptions | undefined,
|
||||||
|
context: CreateNodesContext,
|
||||||
|
testFiles = []
|
||||||
|
) {
|
||||||
|
try {
|
||||||
|
const {
|
||||||
|
gradleProjectToTasksTypeMap,
|
||||||
|
gradleProjectToTasksMap,
|
||||||
|
gradleFileToOutputDirsMap,
|
||||||
|
gradleFileToGradleProjectMap,
|
||||||
|
gradleProjectToProjectName,
|
||||||
|
} = gradleReport;
|
||||||
|
|
||||||
|
const gradleProject = gradleFileToGradleProjectMap.get(
|
||||||
|
gradleFilePath
|
||||||
|
) as string;
|
||||||
|
const projectName = gradleProjectToProjectName.get(gradleProject);
|
||||||
|
if (!projectName) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const tasksTypeMap: Map<string, string> = gradleProjectToTasksTypeMap.get(
|
||||||
|
gradleProject
|
||||||
|
) as Map<string, string>;
|
||||||
|
const tasksSet = gradleProjectToTasksMap.get(gradleProject) as Set<string>;
|
||||||
|
let tasks: GradleTask[] = [];
|
||||||
|
tasksSet.forEach((taskName) => {
|
||||||
|
tasks.push({
|
||||||
|
type: tasksTypeMap?.get(taskName) as string,
|
||||||
|
name: taskName,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
if (options.includeSubprojectsTasks) {
|
||||||
|
tasksTypeMap.forEach((taskType, taskName) => {
|
||||||
|
if (!tasksSet.has(taskName)) {
|
||||||
|
tasks.push({
|
||||||
|
type: taskType,
|
||||||
|
name: taskName,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const outputDirs = gradleFileToOutputDirsMap.get(gradleFilePath) as Map<
|
||||||
|
string,
|
||||||
|
string
|
||||||
|
>;
|
||||||
|
|
||||||
|
const { targets, targetGroups } = await createGradleTargets(
|
||||||
|
tasks,
|
||||||
|
options,
|
||||||
|
context,
|
||||||
|
outputDirs,
|
||||||
|
gradleProject,
|
||||||
|
gradleFilePath,
|
||||||
|
testFiles
|
||||||
|
);
|
||||||
|
const project: Partial<ProjectConfiguration> = {
|
||||||
|
name: projectName,
|
||||||
|
projectType: 'application',
|
||||||
|
targets,
|
||||||
|
metadata: {
|
||||||
|
targetGroups,
|
||||||
|
technologies: ['gradle'],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
return project;
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function createGradleTargets(
|
||||||
|
tasks: GradleTask[],
|
||||||
|
options: GradlePluginOptions | undefined,
|
||||||
|
context: CreateNodesContext,
|
||||||
|
outputDirs: Map<string, string>,
|
||||||
|
gradleProject: string,
|
||||||
|
gradleBuildFilePath: string,
|
||||||
|
testFiles: string[] = []
|
||||||
|
): Promise<{
|
||||||
|
targetGroups: Record<string, string[]>;
|
||||||
|
targets: Record<string, TargetConfiguration>;
|
||||||
|
}> {
|
||||||
|
const inputsMap = createInputsMap(context);
|
||||||
|
const gradlewFileDirectory = dirname(
|
||||||
|
findGradlewFile(gradleBuildFilePath, context.workspaceRoot)
|
||||||
|
);
|
||||||
|
|
||||||
|
const targets: Record<string, TargetConfiguration> = {};
|
||||||
|
const targetGroups: Record<string, string[]> = {};
|
||||||
|
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 as string,
|
||||||
|
options.ciTargetName,
|
||||||
|
inputsMap['test'],
|
||||||
|
outputs,
|
||||||
|
task.type,
|
||||||
|
targets,
|
||||||
|
targetGroups,
|
||||||
|
gradlewFileDirectory
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const taskCommandToRun = `${gradleProject ? gradleProject + ':' : ''}${
|
||||||
|
task.name
|
||||||
|
}`;
|
||||||
|
|
||||||
|
targets[targetName as string] = {
|
||||||
|
command: `${getGradleExecFile()} ${taskCommandToRun}`,
|
||||||
|
options: {
|
||||||
|
cwd: gradlewFileDirectory,
|
||||||
|
},
|
||||||
|
cache: cacheableTaskType.has(task.type),
|
||||||
|
inputs: inputsMap[task.name],
|
||||||
|
dependsOn: dependsOnMap[task.name],
|
||||||
|
metadata: {
|
||||||
|
technologies: ['gradle'],
|
||||||
|
help: {
|
||||||
|
command: `${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 as string);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return { targetGroups, targets };
|
||||||
|
}
|
||||||
|
|
||||||
|
function createInputsMap(
|
||||||
|
context: CreateNodesContext
|
||||||
|
): Record<string, TargetConfiguration['inputs']> {
|
||||||
|
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: string[],
|
||||||
|
gradleProject: string,
|
||||||
|
testTargetName: string,
|
||||||
|
ciTargetName: string,
|
||||||
|
inputs: TargetConfiguration['inputs'],
|
||||||
|
outputs: string[],
|
||||||
|
targetGroupName: string,
|
||||||
|
targets: Record<string, TargetConfiguration>,
|
||||||
|
targetGroups: Record<string, string[]>,
|
||||||
|
gradlewFileDirectory: string
|
||||||
|
): void {
|
||||||
|
if (!testFiles || testFiles.length === 0 || !ciTargetName) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const taskCommandToRun = `${gradleProject ? gradleProject + ':' : ''}test`;
|
||||||
|
|
||||||
|
if (!targetGroups[targetGroupName]) {
|
||||||
|
targetGroups[targetGroupName] = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
const dependsOn: TargetConfiguration['dependsOn'] = [];
|
||||||
|
testFiles.forEach((testFile) => {
|
||||||
|
const testName = basename(testFile).split('.')[0];
|
||||||
|
const targetName = ciTargetName + '--' + testName;
|
||||||
|
|
||||||
|
targets[targetName] = {
|
||||||
|
command: `${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: `${getGradleExecFile()} help --task ${taskCommandToRun}`,
|
||||||
|
example: {
|
||||||
|
options: {
|
||||||
|
args: ['--rerun'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
...(outputs && outputs.length > 0 ? { outputs } : {}),
|
||||||
|
};
|
||||||
|
targetGroups[targetGroupName].push(targetName);
|
||||||
|
dependsOn.push({
|
||||||
|
target: targetName,
|
||||||
|
projects: 'self',
|
||||||
|
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: `${getGradleExecFile()} help --task ${taskCommandToRun}`,
|
||||||
|
example: {
|
||||||
|
options: {
|
||||||
|
args: ['--rerun'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
targetGroups[targetGroupName].push(ciTargetName);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getGradleProjectRootToTestFilesMap(
|
||||||
|
testFiles: string[],
|
||||||
|
projectRoots: string[]
|
||||||
|
): Record<string, string[]> | undefined {
|
||||||
|
if (testFiles.length === 0 || projectRoots.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const roots = new Map(projectRoots.map((root) => [root, root]));
|
||||||
|
const testFilesToGradleProjectMap: Record<string, string[]> = {};
|
||||||
|
testFiles.forEach((testFile) => {
|
||||||
|
const projectRoot = findProjectForPath(testFile, roots);
|
||||||
|
if (projectRoot) {
|
||||||
|
if (!testFilesToGradleProjectMap[projectRoot]) {
|
||||||
|
testFilesToGradleProjectMap[projectRoot] = [];
|
||||||
|
}
|
||||||
|
testFilesToGradleProjectMap[projectRoot].push(testFile);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return testFilesToGradleProjectMap;
|
||||||
|
}
|
||||||
@ -1,8 +1,5 @@
|
|||||||
> Task :dependencyReport
|
> Task :dependencyReport
|
||||||
See the report at: file:///tmp/build/reports/project/dependencies.txt
|
See the report at: file://__dirname__/__mocks__/gradle-dependencies.txt
|
||||||
|
|
||||||
> Task :htmlDependencyReport
|
|
||||||
See the report at: file:///tmp/build/reports/project/dependencies/index.html
|
|
||||||
|
|
||||||
> Task :propertyReport
|
> Task :propertyReport
|
||||||
See the report at: file:///tmp/build/reports/project/properties.txt
|
See the report at: file:///tmp/build/reports/project/properties.txt
|
||||||
@ -11,10 +8,7 @@ See the report at: file:///tmp/build/reports/project/properties.txt
|
|||||||
See the report at: file:///tmp/build/reports/project/tasks.txt
|
See the report at: file:///tmp/build/reports/project/tasks.txt
|
||||||
|
|
||||||
> Task :app:dependencyReport
|
> Task :app:dependencyReport
|
||||||
See the report at: file:///tmp/app/build/reports/project/dependencies.txt
|
See the report at: file://__dirname__/__mocks__/gradle-dependencies.txt
|
||||||
|
|
||||||
> Task :app:htmlDependencyReport
|
|
||||||
See the report at: file:///tmp/app/build/reports/project/dependencies/index.html
|
|
||||||
|
|
||||||
> Task :app:propertyReport
|
> Task :app:propertyReport
|
||||||
See the report at: file:///tmp/app/build/reports/project/properties.txt
|
See the report at: file:///tmp/app/build/reports/project/properties.txt
|
||||||
@ -25,10 +19,7 @@ NAMED TASK1: This is executed during the configuration phase
|
|||||||
See the report at: file:///tmp/app/build/reports/project/tasks.txt
|
See the report at: file:///tmp/app/build/reports/project/tasks.txt
|
||||||
|
|
||||||
> Task :list:dependencyReport
|
> Task :list:dependencyReport
|
||||||
See the report at: file:///tmp/list/build/reports/project/dependencies.txt
|
See the report at: file://__dirname__/__mocks__/gradle-dependencies.txt
|
||||||
|
|
||||||
> Task :list:htmlDependencyReport
|
|
||||||
See the report at: file:///tmp/list/build/reports/project/dependencies/index.html
|
|
||||||
|
|
||||||
> Task :list:propertyReport
|
> Task :list:propertyReport
|
||||||
See the report at: file:///tmp/list/build/reports/project/properties.txt
|
See the report at: file:///tmp/list/build/reports/project/properties.txt
|
||||||
@ -37,10 +28,7 @@ See the report at: file:///tmp/list/build/reports/project/properties.txt
|
|||||||
See the report at: file:///tmp/list/build/reports/project/tasks.txt
|
See the report at: file:///tmp/list/build/reports/project/tasks.txt
|
||||||
|
|
||||||
> Task :utilities:dependencyReport
|
> Task :utilities:dependencyReport
|
||||||
See the report at: file:///tmp/utilities/build/reports/project/dependencies.txt
|
See the report at: file://__dirname__/__mocks__/gradle-dependencies.txt
|
||||||
|
|
||||||
> Task :utilities:htmlDependencyReport
|
|
||||||
See the report at: file:///tmp/utilities/build/reports/project/dependencies/index.html
|
|
||||||
|
|
||||||
> Task :utilities:propertyReport
|
> Task :utilities:propertyReport
|
||||||
See the report at: file:///tmp/utilities/build/reports/project/properties.txt
|
See the report at: file:///tmp/utilities/build/reports/project/properties.txt
|
||||||
@ -1,5 +1,5 @@
|
|||||||
> Task :dependencyReport
|
> Task :dependencyReport
|
||||||
See the report at: file:///tmp/build/reports/project/dependencies.txt
|
See the report at: file://__dirname__/__mocks__/gradle-dependencies.txt
|
||||||
|
|
||||||
> Task :htmlDependencyReport
|
> Task :htmlDependencyReport
|
||||||
See the report at: file:///tmp/build/reports/project/dependencies/index.html
|
See the report at: file:///tmp/build/reports/project/dependencies/index.html
|
||||||
@ -11,10 +11,7 @@ See the report at: file:///tmp/build/reports/project/properties.txt
|
|||||||
See the report at: file:///tmp/build/reports/project/tasks.txt
|
See the report at: file:///tmp/build/reports/project/tasks.txt
|
||||||
|
|
||||||
> Task :app:dependencyReport
|
> Task :app:dependencyReport
|
||||||
See the report at: file:///tmp/app/build/reports/project/dependencies.txt
|
See the report at: file://__dirname__/__mocks__/gradle-dependencies.txt
|
||||||
|
|
||||||
> Task :app:htmlDependencyReport
|
|
||||||
See the report at: file:///tmp/app/build/reports/project/dependencies/index.html
|
|
||||||
|
|
||||||
> Task :app:propertyReport
|
> Task :app:propertyReport
|
||||||
See the report at: file:///tmp/app/build/reports/project/properties.txt
|
See the report at: file:///tmp/app/build/reports/project/properties.txt
|
||||||
@ -23,7 +20,7 @@ See the report at: file:///tmp/app/build/reports/project/properties.txt
|
|||||||
See the report at: file:///tmp/app/build/reports/project/tasks.txt
|
See the report at: file:///tmp/app/build/reports/project/tasks.txt
|
||||||
|
|
||||||
> Task :list:dependencyReport
|
> Task :list:dependencyReport
|
||||||
See the report at: file:///tmp/list/build/reports/project/dependencies.txt
|
See the report at: file://__dirname__/__mocks__/gradle-dependencies.txt
|
||||||
|
|
||||||
> Task :list:htmlDependencyReport
|
> Task :list:htmlDependencyReport
|
||||||
See the report at: file:///tmp/list/build/reports/project/dependencies/index.html
|
See the report at: file:///tmp/list/build/reports/project/dependencies/index.html
|
||||||
@ -35,10 +32,7 @@ See the report at: file:///tmp/list/build/reports/project/properties.txt
|
|||||||
See the report at: file:///tmp/list/build/reports/project/tasks.txt
|
See the report at: file:///tmp/list/build/reports/project/tasks.txt
|
||||||
|
|
||||||
> Task :utilities:dependencyReport
|
> Task :utilities:dependencyReport
|
||||||
See the report at: file:///tmp/utilities/build/reports/project/dependencies.txt
|
See the report at: file://__dirname__/__mocks__/gradle-dependencies.txt
|
||||||
|
|
||||||
> Task :utilities:htmlDependencyReport
|
|
||||||
See the report at: file:///tmp/utilities/build/reports/project/dependencies/index.html
|
|
||||||
|
|
||||||
> Task :utilities:propertyReport
|
> Task :utilities:propertyReport
|
||||||
See the report at: file:///tmp/utilities/build/reports/project/properties.txt
|
See the report at: file:///tmp/utilities/build/reports/project/properties.txt
|
||||||
@ -1,31 +1,103 @@
|
|||||||
import { readFileSync } from 'fs';
|
import { readFileSync } from 'fs';
|
||||||
|
import { fileSync } from 'tmp';
|
||||||
import { join } from 'path';
|
import { join } from 'path';
|
||||||
import {
|
import {
|
||||||
processGradleDependencies,
|
processGradleDependencies,
|
||||||
processProjectReports,
|
processProjectReports,
|
||||||
|
writeGradleReportToCache,
|
||||||
} from './get-gradle-report';
|
} from './get-gradle-report';
|
||||||
|
|
||||||
describe('processProjectReports', () => {
|
describe('processProjectReports', () => {
|
||||||
|
const tmpFile = fileSync();
|
||||||
|
|
||||||
it('should process project reports', () => {
|
it('should process project reports', () => {
|
||||||
const projectReportLines = readFileSync(
|
const projectReportLines = readFileSync(
|
||||||
join(__dirname, '__mocks__/gradle-project-report.txt'),
|
join(__dirname, '__mocks__/gradle-project-report.txt'),
|
||||||
'utf-8'
|
'utf-8'
|
||||||
).split('\n');
|
)
|
||||||
|
.replaceAll('__dirname__', __dirname)
|
||||||
|
.split('\n');
|
||||||
const report = processProjectReports(projectReportLines);
|
const report = processProjectReports(projectReportLines);
|
||||||
expect(
|
expect(
|
||||||
Object.keys(Object.fromEntries(report.gradleProjectToTasksTypeMap))
|
Object.keys(Object.fromEntries(report.gradleProjectToTasksTypeMap))
|
||||||
).toEqual(['', ':app', ':list', ':utilities']);
|
).toEqual(['', ':app', ':list', ':utilities']);
|
||||||
|
|
||||||
|
writeGradleReportToCache(tmpFile.name, report);
|
||||||
|
expect(readFileSync(tmpFile.name).toString()).toMatchInlineSnapshot(`
|
||||||
|
"{
|
||||||
|
"gradleFileToGradleProjectMap": {},
|
||||||
|
"gradleProjectToDepsMap": {
|
||||||
|
"": [
|
||||||
|
":utilities"
|
||||||
|
],
|
||||||
|
":app": [
|
||||||
|
":utilities"
|
||||||
|
],
|
||||||
|
":list": [
|
||||||
|
":utilities"
|
||||||
|
],
|
||||||
|
":utilities": [
|
||||||
|
":utilities"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"gradleFileToOutputDirsMap": {},
|
||||||
|
"gradleProjectToTasksTypeMap": {
|
||||||
|
"": {},
|
||||||
|
":app": {},
|
||||||
|
":list": {},
|
||||||
|
":utilities": {}
|
||||||
|
},
|
||||||
|
"gradleProjectToTasksMap": {},
|
||||||
|
"gradleProjectToProjectName": {},
|
||||||
|
"gradleProjectNameToProjectRootMap": {},
|
||||||
|
"gradleProjectToChildProjects": {}
|
||||||
|
}"
|
||||||
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should process project reports with println', () => {
|
it('should process project reports with println', () => {
|
||||||
const projectReportLines = readFileSync(
|
const projectReportLines = readFileSync(
|
||||||
join(__dirname, '__mocks__/gradle-project-report-println.txt'),
|
join(__dirname, '__mocks__/gradle-project-report-println.txt'),
|
||||||
'utf-8'
|
'utf-8'
|
||||||
).split('\n');
|
)
|
||||||
|
.replaceAll('__dirname__', __dirname)
|
||||||
|
.split('\n');
|
||||||
const report = processProjectReports(projectReportLines);
|
const report = processProjectReports(projectReportLines);
|
||||||
expect(
|
expect(
|
||||||
Object.keys(Object.fromEntries(report.gradleProjectToTasksTypeMap))
|
Object.keys(Object.fromEntries(report.gradleProjectToTasksTypeMap))
|
||||||
).toEqual(['', ':app', ':list', ':utilities']);
|
).toEqual(['', ':app', ':list', ':utilities']);
|
||||||
|
|
||||||
|
writeGradleReportToCache(tmpFile.name, report);
|
||||||
|
expect(readFileSync(tmpFile.name).toString()).toMatchInlineSnapshot(`
|
||||||
|
"{
|
||||||
|
"gradleFileToGradleProjectMap": {},
|
||||||
|
"gradleProjectToDepsMap": {
|
||||||
|
"": [
|
||||||
|
":utilities"
|
||||||
|
],
|
||||||
|
":app": [
|
||||||
|
":utilities"
|
||||||
|
],
|
||||||
|
":list": [
|
||||||
|
":utilities"
|
||||||
|
],
|
||||||
|
":utilities": [
|
||||||
|
":utilities"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"gradleFileToOutputDirsMap": {},
|
||||||
|
"gradleProjectToTasksTypeMap": {
|
||||||
|
"": {},
|
||||||
|
":app": {},
|
||||||
|
":list": {},
|
||||||
|
":utilities": {}
|
||||||
|
},
|
||||||
|
"gradleProjectToTasksMap": {},
|
||||||
|
"gradleProjectToProjectName": {},
|
||||||
|
"gradleProjectNameToProjectRootMap": {},
|
||||||
|
"gradleProjectToChildProjects": {}
|
||||||
|
}"
|
||||||
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should process properties report with child projects', () => {
|
it('should process properties report with child projects', () => {
|
||||||
@ -11,18 +11,15 @@ import {
|
|||||||
|
|
||||||
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';
|
import { gradleConfigAndTestGlob } from '../../utils/split-config-files';
|
||||||
import {
|
import { getProjectReportLines } from './get-project-report-lines';
|
||||||
getProjectReportLines,
|
|
||||||
fileSeparator,
|
|
||||||
newLineSeparator,
|
|
||||||
} from './get-project-report-lines';
|
|
||||||
import { workspaceDataDirectory } from 'nx/src/utils/cache-directory';
|
import { workspaceDataDirectory } from 'nx/src/utils/cache-directory';
|
||||||
|
import { fileSeparator, newLineSeparator } from '../../utils/exec-gradle';
|
||||||
|
|
||||||
export interface GradleReport {
|
export interface GradleReport {
|
||||||
gradleFileToGradleProjectMap: Map<string, string>;
|
gradleFileToGradleProjectMap: Map<string, string>;
|
||||||
buildFileToDepsMap: Map<string, Set<string>>;
|
|
||||||
gradleFileToOutputDirsMap: Map<string, Map<string, string>>;
|
gradleFileToOutputDirsMap: Map<string, Map<string, string>>;
|
||||||
|
gradleProjectToDepsMap: Map<string, Set<string>>;
|
||||||
gradleProjectToTasksTypeMap: Map<string, Map<string, string>>;
|
gradleProjectToTasksTypeMap: Map<string, Map<string, string>>;
|
||||||
gradleProjectToTasksMap: Map<string, Set<string>>;
|
gradleProjectToTasksMap: Map<string, Set<string>>;
|
||||||
gradleProjectToProjectName: Map<string, string>;
|
gradleProjectToProjectName: Map<string, string>;
|
||||||
@ -33,7 +30,7 @@ export interface GradleReport {
|
|||||||
export interface GradleReportJSON {
|
export interface GradleReportJSON {
|
||||||
hash: string;
|
hash: string;
|
||||||
gradleFileToGradleProjectMap: Record<string, string>;
|
gradleFileToGradleProjectMap: Record<string, string>;
|
||||||
buildFileToDepsMap: Record<string, Set<string>>;
|
gradleProjectToDepsMap: Record<string, Array<string>>;
|
||||||
gradleFileToOutputDirsMap: Record<string, Record<string, string>>;
|
gradleFileToOutputDirsMap: Record<string, Record<string, string>>;
|
||||||
gradleProjectToTasksTypeMap: Record<string, Record<string, string>>;
|
gradleProjectToTasksTypeMap: Record<string, Record<string, string>>;
|
||||||
gradleProjectToTasksMap: Record<string, Array<string>>;
|
gradleProjectToTasksMap: Record<string, Array<string>>;
|
||||||
@ -56,8 +53,10 @@ function readGradleReportCache(
|
|||||||
gradleFileToGradleProjectMap: new Map(
|
gradleFileToGradleProjectMap: new Map(
|
||||||
Object.entries(gradleReportJson['gradleFileToGradleProjectMap'])
|
Object.entries(gradleReportJson['gradleFileToGradleProjectMap'])
|
||||||
),
|
),
|
||||||
buildFileToDepsMap: new Map(
|
gradleProjectToDepsMap: new Map(
|
||||||
Object.entries(gradleReportJson['buildFileToDepsMap'])
|
Object.entries(gradleReportJson['gradleProjectToDepsMap']).map(
|
||||||
|
([key, value]) => [key, new Set(value)]
|
||||||
|
)
|
||||||
),
|
),
|
||||||
gradleFileToOutputDirsMap: new Map(
|
gradleFileToOutputDirsMap: new Map(
|
||||||
Object.entries(gradleReportJson['gradleFileToOutputDirsMap']).map(
|
Object.entries(gradleReportJson['gradleFileToOutputDirsMap']).map(
|
||||||
@ -96,7 +95,12 @@ export function writeGradleReportToCache(
|
|||||||
gradleFileToGradleProjectMap: Object.fromEntries(
|
gradleFileToGradleProjectMap: Object.fromEntries(
|
||||||
results.gradleFileToGradleProjectMap
|
results.gradleFileToGradleProjectMap
|
||||||
),
|
),
|
||||||
buildFileToDepsMap: Object.fromEntries(results.buildFileToDepsMap),
|
gradleProjectToDepsMap: Object.fromEntries(
|
||||||
|
Array.from(results.gradleProjectToDepsMap).map(([key, value]) => [
|
||||||
|
key,
|
||||||
|
Array.from(value),
|
||||||
|
])
|
||||||
|
),
|
||||||
gradleFileToOutputDirsMap: Object.fromEntries(
|
gradleFileToOutputDirsMap: Object.fromEntries(
|
||||||
Array.from(results.gradleFileToOutputDirsMap).map(([key, value]) => [
|
Array.from(results.gradleFileToOutputDirsMap).map(([key, value]) => [
|
||||||
key,
|
key,
|
||||||
@ -215,7 +219,7 @@ export function processProjectReports(
|
|||||||
* Map of Gradle File path to Gradle Project Name
|
* Map of Gradle File path to Gradle Project Name
|
||||||
*/
|
*/
|
||||||
const gradleFileToGradleProjectMap = new Map<string, string>();
|
const gradleFileToGradleProjectMap = new Map<string, string>();
|
||||||
const dependenciesMap = new Map<string, string>();
|
const gradleProjectToDepsMap = new Map<string, Set<string>>();
|
||||||
/**
|
/**
|
||||||
* Map of Gradle Build File to tasks type map
|
* Map of Gradle Build File to tasks type map
|
||||||
*/
|
*/
|
||||||
@ -223,10 +227,6 @@ export function processProjectReports(
|
|||||||
const gradleProjectToTasksMap = new Map<string, Set<string>>();
|
const gradleProjectToTasksMap = new Map<string, Set<string>>();
|
||||||
const gradleProjectToProjectName = new Map<string, string>();
|
const gradleProjectToProjectName = new Map<string, string>();
|
||||||
const gradleProjectNameToProjectRootMap = new Map<string, string>();
|
const gradleProjectNameToProjectRootMap = new Map<string, string>();
|
||||||
/**
|
|
||||||
* Map of buildFile to dependencies report path
|
|
||||||
*/
|
|
||||||
const buildFileToDepsMap = new Map<string, Set<string>>();
|
|
||||||
/**
|
/**
|
||||||
* Map fo possible output files of each gradle file
|
* Map fo possible output files of each gradle file
|
||||||
* e.g. {build.gradle.kts: { projectReportDir: '' testReportDir: '' }}
|
* e.g. {build.gradle.kts: { projectReportDir: '' testReportDir: '' }}
|
||||||
@ -253,7 +253,10 @@ export function processProjectReports(
|
|||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
const [_, file] = projectReportLines[index].split(fileSeparator);
|
const [_, file] = projectReportLines[index].split(fileSeparator);
|
||||||
dependenciesMap.set(gradleProject, file);
|
gradleProjectToDepsMap.set(
|
||||||
|
gradleProject,
|
||||||
|
processGradleDependencies(file)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
if (line.endsWith('propertyReport')) {
|
if (line.endsWith('propertyReport')) {
|
||||||
const gradleProject = line.substring(
|
const gradleProject = line.substring(
|
||||||
@ -320,13 +323,6 @@ export function processProjectReports(
|
|||||||
relative(workspaceRoot, absBuildFilePath)
|
relative(workspaceRoot, absBuildFilePath)
|
||||||
);
|
);
|
||||||
const buildDir = relative(workspaceRoot, absBuildDirPath);
|
const buildDir = relative(workspaceRoot, absBuildDirPath);
|
||||||
const depsFile = dependenciesMap.get(gradleProject);
|
|
||||||
if (depsFile) {
|
|
||||||
buildFileToDepsMap.set(
|
|
||||||
buildFile,
|
|
||||||
processGradleDependencies(depsFile)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
outputDirMap.set('build', `{workspaceRoot}/${buildDir}`);
|
outputDirMap.set('build', `{workspaceRoot}/${buildDir}`);
|
||||||
outputDirMap.set(
|
outputDirMap.set(
|
||||||
@ -389,9 +385,9 @@ export function processProjectReports(
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
gradleFileToGradleProjectMap,
|
gradleFileToGradleProjectMap,
|
||||||
buildFileToDepsMap,
|
|
||||||
gradleFileToOutputDirsMap,
|
gradleFileToOutputDirsMap,
|
||||||
gradleProjectToTasksTypeMap,
|
gradleProjectToTasksTypeMap,
|
||||||
|
gradleProjectToDepsMap,
|
||||||
gradleProjectToTasksMap,
|
gradleProjectToTasksMap,
|
||||||
gradleProjectToProjectName,
|
gradleProjectToProjectName,
|
||||||
gradleProjectNameToProjectRootMap,
|
gradleProjectNameToProjectRootMap,
|
||||||
@ -1,16 +1,7 @@
|
|||||||
import { AggregateCreateNodesError, logger, output } from '@nx/devkit';
|
import { AggregateCreateNodesError, logger, output } from '@nx/devkit';
|
||||||
import { execGradleAsync } from './exec-gradle';
|
import { execGradleAsync, newLineSeparator } from '../../utils/exec-gradle';
|
||||||
import { existsSync } from 'fs';
|
import { existsSync } from 'fs';
|
||||||
import { dirname, join } from 'path';
|
import { dirname, join } from 'path';
|
||||||
import { execSync } from 'child_process';
|
|
||||||
|
|
||||||
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.
|
* This function executes the gradle projectReportAll task and returns the output as an array of lines.
|
||||||
@ -21,8 +12,6 @@ export async function getProjectReportLines(
|
|||||||
gradlewFile: string
|
gradlewFile: string
|
||||||
): Promise<string[]> {
|
): Promise<string[]> {
|
||||||
let projectReportBuffer: Buffer;
|
let projectReportBuffer: Buffer;
|
||||||
|
|
||||||
// Attempt to run projectReport or projectReportAll task, regardless of build.gradle or build.gradle.kts location
|
|
||||||
try {
|
try {
|
||||||
projectReportBuffer = await execGradleAsync(gradlewFile, [
|
projectReportBuffer = await execGradleAsync(gradlewFile, [
|
||||||
'projectReportAll',
|
'projectReportAll',
|
||||||
849
packages/gradle/src/plugin/__snapshots__/nodes.spec.ts.snap
Normal file
849
packages/gradle/src/plugin/__snapshots__/nodes.spec.ts.snap
Normal file
@ -0,0 +1,849 @@
|
|||||||
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
|
exports[`@nx/gradle/plugin/nodes should create nodes based on gradle 1`] = `
|
||||||
|
[
|
||||||
|
[
|
||||||
|
"proj/build.gradle",
|
||||||
|
{
|
||||||
|
"externalNodes": {},
|
||||||
|
"projects": {
|
||||||
|
"proj": {
|
||||||
|
"metadata": {
|
||||||
|
"targetGroups": {
|
||||||
|
"help": [
|
||||||
|
"buildEnvironment",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"technologies": [
|
||||||
|
"gradle",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"name": "gradle-tutorial",
|
||||||
|
"root": "proj",
|
||||||
|
"targets": {
|
||||||
|
"buildEnvironment": {
|
||||||
|
"cache": true,
|
||||||
|
"command": "./gradlew :buildEnvironment",
|
||||||
|
"metadata": {
|
||||||
|
"description": "Displays all buildscript dependencies declared in root project 'gradle-tutorial'.",
|
||||||
|
"technologies": [
|
||||||
|
"gradle",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"cwd": "proj",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
]
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`@nx/gradle/plugin/nodes should create nodes based on gradle for nested project root 1`] = `
|
||||||
|
[
|
||||||
|
[
|
||||||
|
"nested/nested/proj/build.gradle",
|
||||||
|
{
|
||||||
|
"externalNodes": {},
|
||||||
|
"projects": {
|
||||||
|
"nested/nested/proj": {
|
||||||
|
"metadata": {
|
||||||
|
"targetGroups": {
|
||||||
|
"help": [
|
||||||
|
"buildEnvironment",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"technologies": [
|
||||||
|
"gradle",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"name": "my-composite",
|
||||||
|
"root": "nested/nested/proj",
|
||||||
|
"targets": {
|
||||||
|
"buildEnvironment": {
|
||||||
|
"cache": true,
|
||||||
|
"command": "./gradlew :buildEnvironment",
|
||||||
|
"metadata": {
|
||||||
|
"description": "Displays all buildscript dependencies declared in root project 'my-composite'.",
|
||||||
|
"technologies": [
|
||||||
|
"gradle",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"cwd": "nested/nested/proj",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
]
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`@nx/gradle/plugin/nodes should create nodes with atomized tests targets based on gradle if ciTargetName is specified 1`] = `
|
||||||
|
[
|
||||||
|
[
|
||||||
|
"proj/application/build.gradle",
|
||||||
|
{
|
||||||
|
"externalNodes": {},
|
||||||
|
"projects": {
|
||||||
|
"proj/application": {
|
||||||
|
"metadata": {
|
||||||
|
"targetGroups": {
|
||||||
|
"verification": [
|
||||||
|
"ci",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"technologies": [
|
||||||
|
"gradle",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"name": "application",
|
||||||
|
"root": "proj/application",
|
||||||
|
"targets": {
|
||||||
|
"ci": {
|
||||||
|
"cache": true,
|
||||||
|
"dependsOn": [
|
||||||
|
{
|
||||||
|
"params": "forward",
|
||||||
|
"projects": "self",
|
||||||
|
"target": "ci--DemoApplicationTest10",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"params": "forward",
|
||||||
|
"projects": "self",
|
||||||
|
"target": "ci--DemoApplicationTest7",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"params": "forward",
|
||||||
|
"projects": "self",
|
||||||
|
"target": "ci--DemoApplicationTest6",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"params": "forward",
|
||||||
|
"projects": "self",
|
||||||
|
"target": "ci--DemoApplicationTest3",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"params": "forward",
|
||||||
|
"projects": "self",
|
||||||
|
"target": "ci--DemoApplicationTest2",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"params": "forward",
|
||||||
|
"projects": "self",
|
||||||
|
"target": "ci--DemoApplicationTest9",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"params": "forward",
|
||||||
|
"projects": "self",
|
||||||
|
"target": "ci--DemoApplicationTest",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"params": "forward",
|
||||||
|
"projects": "self",
|
||||||
|
"target": "ci--DemoApplicationTest5",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"params": "forward",
|
||||||
|
"projects": "self",
|
||||||
|
"target": "ci--DemoApplicationTest4",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"params": "forward",
|
||||||
|
"projects": "self",
|
||||||
|
"target": "ci--DemoApplicationTest8",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"executor": "nx:noop",
|
||||||
|
"inputs": [
|
||||||
|
"{projectRoot}/src/test/java/com/example/multimodule/application/DemoApplicationTest10.java",
|
||||||
|
"{projectRoot}/src/test/java/com/example/multimodule/application/DemoApplicationTest7.java",
|
||||||
|
"{projectRoot}/src/test/java/com/example/multimodule/application/DemoApplicationTest6.java",
|
||||||
|
"{projectRoot}/src/test/java/com/example/multimodule/application/DemoApplicationTest3.java",
|
||||||
|
"{projectRoot}/src/test/java/com/example/multimodule/application/DemoApplicationTest2.java",
|
||||||
|
"{projectRoot}/src/test/java/com/example/multimodule/application/DemoApplicationTest9.java",
|
||||||
|
"{projectRoot}/src/test/java/com/example/multimodule/application/DemoApplicationTest.java",
|
||||||
|
"{projectRoot}/src/test/java/com/example/multimodule/application/DemoApplicationTest5.java",
|
||||||
|
"{projectRoot}/src/test/java/com/example/multimodule/application/DemoApplicationTest4.java",
|
||||||
|
"{projectRoot}/src/test/java/com/example/multimodule/application/DemoApplicationTest8.java",
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"description": "Runs Gradle Tests in CI",
|
||||||
|
"technologies": [
|
||||||
|
"gradle",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"cwd": "proj",
|
||||||
|
},
|
||||||
|
"outputs": [
|
||||||
|
"{projectRoot}/build/classes/java/test",
|
||||||
|
"{projectRoot}/build/generated/sources/annotationProcessor/java/test",
|
||||||
|
"{projectRoot}/build/generated/sources/headers/java/test",
|
||||||
|
"{projectRoot}/build/tmp/compileTestJava/previous-compilation-data.bin",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"ci--DemoApplicationTest": {
|
||||||
|
"cache": true,
|
||||||
|
"command": "./gradlew :application:test --tests DemoApplicationTest",
|
||||||
|
"dependsOn": [
|
||||||
|
"application:classes",
|
||||||
|
"application:compileJava",
|
||||||
|
"library:jar",
|
||||||
|
],
|
||||||
|
"inputs": [
|
||||||
|
"{projectRoot}/src/test/java/com/example/multimodule/application/DemoApplicationTest.java",
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"description": "Runs Gradle test proj/application/src/test/java/com/example/multimodule/application/DemoApplicationTest.java in CI",
|
||||||
|
"technologies": [
|
||||||
|
"gradle",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"cwd": "proj",
|
||||||
|
},
|
||||||
|
"outputs": [
|
||||||
|
"{projectRoot}/build/classes/java/test",
|
||||||
|
"{projectRoot}/build/generated/sources/annotationProcessor/java/test",
|
||||||
|
"{projectRoot}/build/generated/sources/headers/java/test",
|
||||||
|
"{projectRoot}/build/tmp/compileTestJava/previous-compilation-data.bin",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"ci--DemoApplicationTest10": {
|
||||||
|
"cache": true,
|
||||||
|
"command": "./gradlew :application:test --tests DemoApplicationTest10",
|
||||||
|
"dependsOn": [
|
||||||
|
"application:classes",
|
||||||
|
"application:compileJava",
|
||||||
|
"library:jar",
|
||||||
|
],
|
||||||
|
"inputs": [
|
||||||
|
"{projectRoot}/src/test/java/com/example/multimodule/application/DemoApplicationTest10.java",
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"description": "Runs Gradle test proj/application/src/test/java/com/example/multimodule/application/DemoApplicationTest10.java in CI",
|
||||||
|
"technologies": [
|
||||||
|
"gradle",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"cwd": "proj",
|
||||||
|
},
|
||||||
|
"outputs": [
|
||||||
|
"{projectRoot}/build/classes/java/test",
|
||||||
|
"{projectRoot}/build/generated/sources/annotationProcessor/java/test",
|
||||||
|
"{projectRoot}/build/generated/sources/headers/java/test",
|
||||||
|
"{projectRoot}/build/tmp/compileTestJava/previous-compilation-data.bin",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"ci--DemoApplicationTest2": {
|
||||||
|
"cache": true,
|
||||||
|
"command": "./gradlew :application:test --tests DemoApplicationTest2",
|
||||||
|
"dependsOn": [
|
||||||
|
"application:classes",
|
||||||
|
"application:compileJava",
|
||||||
|
"library:jar",
|
||||||
|
],
|
||||||
|
"inputs": [
|
||||||
|
"{projectRoot}/src/test/java/com/example/multimodule/application/DemoApplicationTest2.java",
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"description": "Runs Gradle test proj/application/src/test/java/com/example/multimodule/application/DemoApplicationTest2.java in CI",
|
||||||
|
"technologies": [
|
||||||
|
"gradle",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"cwd": "proj",
|
||||||
|
},
|
||||||
|
"outputs": [
|
||||||
|
"{projectRoot}/build/classes/java/test",
|
||||||
|
"{projectRoot}/build/generated/sources/annotationProcessor/java/test",
|
||||||
|
"{projectRoot}/build/generated/sources/headers/java/test",
|
||||||
|
"{projectRoot}/build/tmp/compileTestJava/previous-compilation-data.bin",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"ci--DemoApplicationTest3": {
|
||||||
|
"cache": true,
|
||||||
|
"command": "./gradlew :application:test --tests DemoApplicationTest3",
|
||||||
|
"dependsOn": [
|
||||||
|
"application:classes",
|
||||||
|
"application:compileJava",
|
||||||
|
"library:jar",
|
||||||
|
],
|
||||||
|
"inputs": [
|
||||||
|
"{projectRoot}/src/test/java/com/example/multimodule/application/DemoApplicationTest3.java",
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"description": "Runs Gradle test proj/application/src/test/java/com/example/multimodule/application/DemoApplicationTest3.java in CI",
|
||||||
|
"technologies": [
|
||||||
|
"gradle",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"cwd": "proj",
|
||||||
|
},
|
||||||
|
"outputs": [
|
||||||
|
"{projectRoot}/build/classes/java/test",
|
||||||
|
"{projectRoot}/build/generated/sources/annotationProcessor/java/test",
|
||||||
|
"{projectRoot}/build/generated/sources/headers/java/test",
|
||||||
|
"{projectRoot}/build/tmp/compileTestJava/previous-compilation-data.bin",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"ci--DemoApplicationTest4": {
|
||||||
|
"cache": true,
|
||||||
|
"command": "./gradlew :application:test --tests DemoApplicationTest4",
|
||||||
|
"dependsOn": [
|
||||||
|
"application:classes",
|
||||||
|
"application:compileJava",
|
||||||
|
"library:jar",
|
||||||
|
],
|
||||||
|
"inputs": [
|
||||||
|
"{projectRoot}/src/test/java/com/example/multimodule/application/DemoApplicationTest4.java",
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"description": "Runs Gradle test proj/application/src/test/java/com/example/multimodule/application/DemoApplicationTest4.java in CI",
|
||||||
|
"technologies": [
|
||||||
|
"gradle",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"cwd": "proj",
|
||||||
|
},
|
||||||
|
"outputs": [
|
||||||
|
"{projectRoot}/build/classes/java/test",
|
||||||
|
"{projectRoot}/build/generated/sources/annotationProcessor/java/test",
|
||||||
|
"{projectRoot}/build/generated/sources/headers/java/test",
|
||||||
|
"{projectRoot}/build/tmp/compileTestJava/previous-compilation-data.bin",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"ci--DemoApplicationTest5": {
|
||||||
|
"cache": true,
|
||||||
|
"command": "./gradlew :application:test --tests DemoApplicationTest5",
|
||||||
|
"dependsOn": [
|
||||||
|
"application:classes",
|
||||||
|
"application:compileJava",
|
||||||
|
"library:jar",
|
||||||
|
],
|
||||||
|
"inputs": [
|
||||||
|
"{projectRoot}/src/test/java/com/example/multimodule/application/DemoApplicationTest5.java",
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"description": "Runs Gradle test proj/application/src/test/java/com/example/multimodule/application/DemoApplicationTest5.java in CI",
|
||||||
|
"technologies": [
|
||||||
|
"gradle",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"cwd": "proj",
|
||||||
|
},
|
||||||
|
"outputs": [
|
||||||
|
"{projectRoot}/build/classes/java/test",
|
||||||
|
"{projectRoot}/build/generated/sources/annotationProcessor/java/test",
|
||||||
|
"{projectRoot}/build/generated/sources/headers/java/test",
|
||||||
|
"{projectRoot}/build/tmp/compileTestJava/previous-compilation-data.bin",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"ci--DemoApplicationTest6": {
|
||||||
|
"cache": true,
|
||||||
|
"command": "./gradlew :application:test --tests DemoApplicationTest6",
|
||||||
|
"dependsOn": [
|
||||||
|
"application:classes",
|
||||||
|
"application:compileJava",
|
||||||
|
"library:jar",
|
||||||
|
],
|
||||||
|
"inputs": [
|
||||||
|
"{projectRoot}/src/test/java/com/example/multimodule/application/DemoApplicationTest6.java",
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"description": "Runs Gradle test proj/application/src/test/java/com/example/multimodule/application/DemoApplicationTest6.java in CI",
|
||||||
|
"technologies": [
|
||||||
|
"gradle",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"cwd": "proj",
|
||||||
|
},
|
||||||
|
"outputs": [
|
||||||
|
"{projectRoot}/build/classes/java/test",
|
||||||
|
"{projectRoot}/build/generated/sources/annotationProcessor/java/test",
|
||||||
|
"{projectRoot}/build/generated/sources/headers/java/test",
|
||||||
|
"{projectRoot}/build/tmp/compileTestJava/previous-compilation-data.bin",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"ci--DemoApplicationTest7": {
|
||||||
|
"cache": true,
|
||||||
|
"command": "./gradlew :application:test --tests DemoApplicationTest7",
|
||||||
|
"dependsOn": [
|
||||||
|
"application:classes",
|
||||||
|
"application:compileJava",
|
||||||
|
"library:jar",
|
||||||
|
],
|
||||||
|
"inputs": [
|
||||||
|
"{projectRoot}/src/test/java/com/example/multimodule/application/DemoApplicationTest7.java",
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"description": "Runs Gradle test proj/application/src/test/java/com/example/multimodule/application/DemoApplicationTest7.java in CI",
|
||||||
|
"technologies": [
|
||||||
|
"gradle",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"cwd": "proj",
|
||||||
|
},
|
||||||
|
"outputs": [
|
||||||
|
"{projectRoot}/build/classes/java/test",
|
||||||
|
"{projectRoot}/build/generated/sources/annotationProcessor/java/test",
|
||||||
|
"{projectRoot}/build/generated/sources/headers/java/test",
|
||||||
|
"{projectRoot}/build/tmp/compileTestJava/previous-compilation-data.bin",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"ci--DemoApplicationTest8": {
|
||||||
|
"cache": true,
|
||||||
|
"command": "./gradlew :application:test --tests DemoApplicationTest8",
|
||||||
|
"dependsOn": [
|
||||||
|
"application:classes",
|
||||||
|
"application:compileJava",
|
||||||
|
"library:jar",
|
||||||
|
],
|
||||||
|
"inputs": [
|
||||||
|
"{projectRoot}/src/test/java/com/example/multimodule/application/DemoApplicationTest8.java",
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"description": "Runs Gradle test proj/application/src/test/java/com/example/multimodule/application/DemoApplicationTest8.java in CI",
|
||||||
|
"technologies": [
|
||||||
|
"gradle",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"cwd": "proj",
|
||||||
|
},
|
||||||
|
"outputs": [
|
||||||
|
"{projectRoot}/build/classes/java/test",
|
||||||
|
"{projectRoot}/build/generated/sources/annotationProcessor/java/test",
|
||||||
|
"{projectRoot}/build/generated/sources/headers/java/test",
|
||||||
|
"{projectRoot}/build/tmp/compileTestJava/previous-compilation-data.bin",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"ci--DemoApplicationTest9": {
|
||||||
|
"cache": true,
|
||||||
|
"command": "./gradlew :application:test --tests DemoApplicationTest9",
|
||||||
|
"dependsOn": [
|
||||||
|
"application:classes",
|
||||||
|
"application:compileJava",
|
||||||
|
"library:jar",
|
||||||
|
],
|
||||||
|
"inputs": [
|
||||||
|
"{projectRoot}/src/test/java/com/example/multimodule/application/DemoApplicationTest9.java",
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"description": "Runs Gradle test proj/application/src/test/java/com/example/multimodule/application/DemoApplicationTest9.java in CI",
|
||||||
|
"technologies": [
|
||||||
|
"gradle",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"cwd": "proj",
|
||||||
|
},
|
||||||
|
"outputs": [
|
||||||
|
"{projectRoot}/build/classes/java/test",
|
||||||
|
"{projectRoot}/build/generated/sources/annotationProcessor/java/test",
|
||||||
|
"{projectRoot}/build/generated/sources/headers/java/test",
|
||||||
|
"{projectRoot}/build/tmp/compileTestJava/previous-compilation-data.bin",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
]
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`@nx/gradle/plugin/nodes should not create nodes with atomized tests targets based on gradle if ciTargetName is not specified 1`] = `
|
||||||
|
[
|
||||||
|
[
|
||||||
|
"proj/application/build.gradle",
|
||||||
|
{
|
||||||
|
"externalNodes": {},
|
||||||
|
"projects": {
|
||||||
|
"proj/application": {
|
||||||
|
"metadata": {
|
||||||
|
"targetGroups": {
|
||||||
|
"verification": [
|
||||||
|
"ci",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"technologies": [
|
||||||
|
"gradle",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"name": "application",
|
||||||
|
"root": "proj/application",
|
||||||
|
"targets": {
|
||||||
|
"ci": {
|
||||||
|
"cache": true,
|
||||||
|
"dependsOn": [
|
||||||
|
{
|
||||||
|
"params": "forward",
|
||||||
|
"projects": "self",
|
||||||
|
"target": "ci--DemoApplicationTest10",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"params": "forward",
|
||||||
|
"projects": "self",
|
||||||
|
"target": "ci--DemoApplicationTest7",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"params": "forward",
|
||||||
|
"projects": "self",
|
||||||
|
"target": "ci--DemoApplicationTest6",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"params": "forward",
|
||||||
|
"projects": "self",
|
||||||
|
"target": "ci--DemoApplicationTest3",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"params": "forward",
|
||||||
|
"projects": "self",
|
||||||
|
"target": "ci--DemoApplicationTest2",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"params": "forward",
|
||||||
|
"projects": "self",
|
||||||
|
"target": "ci--DemoApplicationTest9",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"params": "forward",
|
||||||
|
"projects": "self",
|
||||||
|
"target": "ci--DemoApplicationTest",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"params": "forward",
|
||||||
|
"projects": "self",
|
||||||
|
"target": "ci--DemoApplicationTest5",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"params": "forward",
|
||||||
|
"projects": "self",
|
||||||
|
"target": "ci--DemoApplicationTest4",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"params": "forward",
|
||||||
|
"projects": "self",
|
||||||
|
"target": "ci--DemoApplicationTest8",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"executor": "nx:noop",
|
||||||
|
"inputs": [
|
||||||
|
"{projectRoot}/src/test/java/com/example/multimodule/application/DemoApplicationTest10.java",
|
||||||
|
"{projectRoot}/src/test/java/com/example/multimodule/application/DemoApplicationTest7.java",
|
||||||
|
"{projectRoot}/src/test/java/com/example/multimodule/application/DemoApplicationTest6.java",
|
||||||
|
"{projectRoot}/src/test/java/com/example/multimodule/application/DemoApplicationTest3.java",
|
||||||
|
"{projectRoot}/src/test/java/com/example/multimodule/application/DemoApplicationTest2.java",
|
||||||
|
"{projectRoot}/src/test/java/com/example/multimodule/application/DemoApplicationTest9.java",
|
||||||
|
"{projectRoot}/src/test/java/com/example/multimodule/application/DemoApplicationTest.java",
|
||||||
|
"{projectRoot}/src/test/java/com/example/multimodule/application/DemoApplicationTest5.java",
|
||||||
|
"{projectRoot}/src/test/java/com/example/multimodule/application/DemoApplicationTest4.java",
|
||||||
|
"{projectRoot}/src/test/java/com/example/multimodule/application/DemoApplicationTest8.java",
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"description": "Runs Gradle Tests in CI",
|
||||||
|
"technologies": [
|
||||||
|
"gradle",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"cwd": "proj",
|
||||||
|
},
|
||||||
|
"outputs": [
|
||||||
|
"{projectRoot}/build/classes/java/test",
|
||||||
|
"{projectRoot}/build/generated/sources/annotationProcessor/java/test",
|
||||||
|
"{projectRoot}/build/generated/sources/headers/java/test",
|
||||||
|
"{projectRoot}/build/tmp/compileTestJava/previous-compilation-data.bin",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"ci--DemoApplicationTest": {
|
||||||
|
"cache": true,
|
||||||
|
"command": "./gradlew :application:test --tests DemoApplicationTest",
|
||||||
|
"dependsOn": [
|
||||||
|
"application:classes",
|
||||||
|
"application:compileJava",
|
||||||
|
"library:jar",
|
||||||
|
],
|
||||||
|
"inputs": [
|
||||||
|
"{projectRoot}/src/test/java/com/example/multimodule/application/DemoApplicationTest.java",
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"description": "Runs Gradle test proj/application/src/test/java/com/example/multimodule/application/DemoApplicationTest.java in CI",
|
||||||
|
"technologies": [
|
||||||
|
"gradle",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"cwd": "proj",
|
||||||
|
},
|
||||||
|
"outputs": [
|
||||||
|
"{projectRoot}/build/classes/java/test",
|
||||||
|
"{projectRoot}/build/generated/sources/annotationProcessor/java/test",
|
||||||
|
"{projectRoot}/build/generated/sources/headers/java/test",
|
||||||
|
"{projectRoot}/build/tmp/compileTestJava/previous-compilation-data.bin",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"ci--DemoApplicationTest10": {
|
||||||
|
"cache": true,
|
||||||
|
"command": "./gradlew :application:test --tests DemoApplicationTest10",
|
||||||
|
"dependsOn": [
|
||||||
|
"application:classes",
|
||||||
|
"application:compileJava",
|
||||||
|
"library:jar",
|
||||||
|
],
|
||||||
|
"inputs": [
|
||||||
|
"{projectRoot}/src/test/java/com/example/multimodule/application/DemoApplicationTest10.java",
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"description": "Runs Gradle test proj/application/src/test/java/com/example/multimodule/application/DemoApplicationTest10.java in CI",
|
||||||
|
"technologies": [
|
||||||
|
"gradle",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"cwd": "proj",
|
||||||
|
},
|
||||||
|
"outputs": [
|
||||||
|
"{projectRoot}/build/classes/java/test",
|
||||||
|
"{projectRoot}/build/generated/sources/annotationProcessor/java/test",
|
||||||
|
"{projectRoot}/build/generated/sources/headers/java/test",
|
||||||
|
"{projectRoot}/build/tmp/compileTestJava/previous-compilation-data.bin",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"ci--DemoApplicationTest2": {
|
||||||
|
"cache": true,
|
||||||
|
"command": "./gradlew :application:test --tests DemoApplicationTest2",
|
||||||
|
"dependsOn": [
|
||||||
|
"application:classes",
|
||||||
|
"application:compileJava",
|
||||||
|
"library:jar",
|
||||||
|
],
|
||||||
|
"inputs": [
|
||||||
|
"{projectRoot}/src/test/java/com/example/multimodule/application/DemoApplicationTest2.java",
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"description": "Runs Gradle test proj/application/src/test/java/com/example/multimodule/application/DemoApplicationTest2.java in CI",
|
||||||
|
"technologies": [
|
||||||
|
"gradle",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"cwd": "proj",
|
||||||
|
},
|
||||||
|
"outputs": [
|
||||||
|
"{projectRoot}/build/classes/java/test",
|
||||||
|
"{projectRoot}/build/generated/sources/annotationProcessor/java/test",
|
||||||
|
"{projectRoot}/build/generated/sources/headers/java/test",
|
||||||
|
"{projectRoot}/build/tmp/compileTestJava/previous-compilation-data.bin",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"ci--DemoApplicationTest3": {
|
||||||
|
"cache": true,
|
||||||
|
"command": "./gradlew :application:test --tests DemoApplicationTest3",
|
||||||
|
"dependsOn": [
|
||||||
|
"application:classes",
|
||||||
|
"application:compileJava",
|
||||||
|
"library:jar",
|
||||||
|
],
|
||||||
|
"inputs": [
|
||||||
|
"{projectRoot}/src/test/java/com/example/multimodule/application/DemoApplicationTest3.java",
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"description": "Runs Gradle test proj/application/src/test/java/com/example/multimodule/application/DemoApplicationTest3.java in CI",
|
||||||
|
"technologies": [
|
||||||
|
"gradle",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"cwd": "proj",
|
||||||
|
},
|
||||||
|
"outputs": [
|
||||||
|
"{projectRoot}/build/classes/java/test",
|
||||||
|
"{projectRoot}/build/generated/sources/annotationProcessor/java/test",
|
||||||
|
"{projectRoot}/build/generated/sources/headers/java/test",
|
||||||
|
"{projectRoot}/build/tmp/compileTestJava/previous-compilation-data.bin",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"ci--DemoApplicationTest4": {
|
||||||
|
"cache": true,
|
||||||
|
"command": "./gradlew :application:test --tests DemoApplicationTest4",
|
||||||
|
"dependsOn": [
|
||||||
|
"application:classes",
|
||||||
|
"application:compileJava",
|
||||||
|
"library:jar",
|
||||||
|
],
|
||||||
|
"inputs": [
|
||||||
|
"{projectRoot}/src/test/java/com/example/multimodule/application/DemoApplicationTest4.java",
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"description": "Runs Gradle test proj/application/src/test/java/com/example/multimodule/application/DemoApplicationTest4.java in CI",
|
||||||
|
"technologies": [
|
||||||
|
"gradle",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"cwd": "proj",
|
||||||
|
},
|
||||||
|
"outputs": [
|
||||||
|
"{projectRoot}/build/classes/java/test",
|
||||||
|
"{projectRoot}/build/generated/sources/annotationProcessor/java/test",
|
||||||
|
"{projectRoot}/build/generated/sources/headers/java/test",
|
||||||
|
"{projectRoot}/build/tmp/compileTestJava/previous-compilation-data.bin",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"ci--DemoApplicationTest5": {
|
||||||
|
"cache": true,
|
||||||
|
"command": "./gradlew :application:test --tests DemoApplicationTest5",
|
||||||
|
"dependsOn": [
|
||||||
|
"application:classes",
|
||||||
|
"application:compileJava",
|
||||||
|
"library:jar",
|
||||||
|
],
|
||||||
|
"inputs": [
|
||||||
|
"{projectRoot}/src/test/java/com/example/multimodule/application/DemoApplicationTest5.java",
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"description": "Runs Gradle test proj/application/src/test/java/com/example/multimodule/application/DemoApplicationTest5.java in CI",
|
||||||
|
"technologies": [
|
||||||
|
"gradle",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"cwd": "proj",
|
||||||
|
},
|
||||||
|
"outputs": [
|
||||||
|
"{projectRoot}/build/classes/java/test",
|
||||||
|
"{projectRoot}/build/generated/sources/annotationProcessor/java/test",
|
||||||
|
"{projectRoot}/build/generated/sources/headers/java/test",
|
||||||
|
"{projectRoot}/build/tmp/compileTestJava/previous-compilation-data.bin",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"ci--DemoApplicationTest6": {
|
||||||
|
"cache": true,
|
||||||
|
"command": "./gradlew :application:test --tests DemoApplicationTest6",
|
||||||
|
"dependsOn": [
|
||||||
|
"application:classes",
|
||||||
|
"application:compileJava",
|
||||||
|
"library:jar",
|
||||||
|
],
|
||||||
|
"inputs": [
|
||||||
|
"{projectRoot}/src/test/java/com/example/multimodule/application/DemoApplicationTest6.java",
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"description": "Runs Gradle test proj/application/src/test/java/com/example/multimodule/application/DemoApplicationTest6.java in CI",
|
||||||
|
"technologies": [
|
||||||
|
"gradle",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"cwd": "proj",
|
||||||
|
},
|
||||||
|
"outputs": [
|
||||||
|
"{projectRoot}/build/classes/java/test",
|
||||||
|
"{projectRoot}/build/generated/sources/annotationProcessor/java/test",
|
||||||
|
"{projectRoot}/build/generated/sources/headers/java/test",
|
||||||
|
"{projectRoot}/build/tmp/compileTestJava/previous-compilation-data.bin",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"ci--DemoApplicationTest7": {
|
||||||
|
"cache": true,
|
||||||
|
"command": "./gradlew :application:test --tests DemoApplicationTest7",
|
||||||
|
"dependsOn": [
|
||||||
|
"application:classes",
|
||||||
|
"application:compileJava",
|
||||||
|
"library:jar",
|
||||||
|
],
|
||||||
|
"inputs": [
|
||||||
|
"{projectRoot}/src/test/java/com/example/multimodule/application/DemoApplicationTest7.java",
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"description": "Runs Gradle test proj/application/src/test/java/com/example/multimodule/application/DemoApplicationTest7.java in CI",
|
||||||
|
"technologies": [
|
||||||
|
"gradle",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"cwd": "proj",
|
||||||
|
},
|
||||||
|
"outputs": [
|
||||||
|
"{projectRoot}/build/classes/java/test",
|
||||||
|
"{projectRoot}/build/generated/sources/annotationProcessor/java/test",
|
||||||
|
"{projectRoot}/build/generated/sources/headers/java/test",
|
||||||
|
"{projectRoot}/build/tmp/compileTestJava/previous-compilation-data.bin",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"ci--DemoApplicationTest8": {
|
||||||
|
"cache": true,
|
||||||
|
"command": "./gradlew :application:test --tests DemoApplicationTest8",
|
||||||
|
"dependsOn": [
|
||||||
|
"application:classes",
|
||||||
|
"application:compileJava",
|
||||||
|
"library:jar",
|
||||||
|
],
|
||||||
|
"inputs": [
|
||||||
|
"{projectRoot}/src/test/java/com/example/multimodule/application/DemoApplicationTest8.java",
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"description": "Runs Gradle test proj/application/src/test/java/com/example/multimodule/application/DemoApplicationTest8.java in CI",
|
||||||
|
"technologies": [
|
||||||
|
"gradle",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"cwd": "proj",
|
||||||
|
},
|
||||||
|
"outputs": [
|
||||||
|
"{projectRoot}/build/classes/java/test",
|
||||||
|
"{projectRoot}/build/generated/sources/annotationProcessor/java/test",
|
||||||
|
"{projectRoot}/build/generated/sources/headers/java/test",
|
||||||
|
"{projectRoot}/build/tmp/compileTestJava/previous-compilation-data.bin",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"ci--DemoApplicationTest9": {
|
||||||
|
"cache": true,
|
||||||
|
"command": "./gradlew :application:test --tests DemoApplicationTest9",
|
||||||
|
"dependsOn": [
|
||||||
|
"application:classes",
|
||||||
|
"application:compileJava",
|
||||||
|
"library:jar",
|
||||||
|
],
|
||||||
|
"inputs": [
|
||||||
|
"{projectRoot}/src/test/java/com/example/multimodule/application/DemoApplicationTest9.java",
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"description": "Runs Gradle test proj/application/src/test/java/com/example/multimodule/application/DemoApplicationTest9.java in CI",
|
||||||
|
"technologies": [
|
||||||
|
"gradle",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"cwd": "proj",
|
||||||
|
},
|
||||||
|
"outputs": [
|
||||||
|
"{projectRoot}/build/classes/java/test",
|
||||||
|
"{projectRoot}/build/generated/sources/annotationProcessor/java/test",
|
||||||
|
"{projectRoot}/build/generated/sources/headers/java/test",
|
||||||
|
"{projectRoot}/build/tmp/compileTestJava/previous-compilation-data.bin",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
]
|
||||||
|
`;
|
||||||
@ -2,94 +2,71 @@ import {
|
|||||||
CreateDependencies,
|
CreateDependencies,
|
||||||
CreateDependenciesContext,
|
CreateDependenciesContext,
|
||||||
DependencyType,
|
DependencyType,
|
||||||
FileMap,
|
logger,
|
||||||
RawProjectGraphDependency,
|
normalizePath,
|
||||||
|
StaticDependency,
|
||||||
validateDependency,
|
validateDependency,
|
||||||
|
workspaceRoot,
|
||||||
} from '@nx/devkit';
|
} from '@nx/devkit';
|
||||||
import { basename, dirname } from 'node:path';
|
import { relative } from 'node:path';
|
||||||
|
|
||||||
import { getCurrentGradleReport } from '../utils/get-gradle-report';
|
import {
|
||||||
import { GRADLE_BUILD_FILES } from '../utils/split-config-files';
|
getCurrentProjectGraphReport,
|
||||||
|
populateProjectGraph,
|
||||||
|
} from './utils/get-project-graph-from-gradle-plugin';
|
||||||
|
import { GradlePluginOptions } from './utils/gradle-plugin-options';
|
||||||
|
import { GRALDEW_FILES, splitConfigFiles } from '../utils/split-config-files';
|
||||||
|
import { globWithWorkspaceContext } from 'nx/src/utils/workspace-context';
|
||||||
|
|
||||||
export const createDependencies: CreateDependencies = async (
|
export const createDependencies: CreateDependencies<
|
||||||
_,
|
GradlePluginOptions
|
||||||
|
> = async (
|
||||||
|
options: GradlePluginOptions,
|
||||||
context: CreateDependenciesContext
|
context: CreateDependenciesContext
|
||||||
) => {
|
) => {
|
||||||
const gradleFiles: string[] = findGradleFiles(context.filesToProcess);
|
const files = await globWithWorkspaceContext(
|
||||||
if (gradleFiles.length === 0) {
|
workspaceRoot,
|
||||||
return [];
|
Array.from(GRALDEW_FILES)
|
||||||
}
|
|
||||||
|
|
||||||
const gradleDependenciesStart = performance.mark('gradleDependencies:start');
|
|
||||||
const {
|
|
||||||
gradleFileToGradleProjectMap,
|
|
||||||
gradleProjectNameToProjectRootMap,
|
|
||||||
buildFileToDepsMap,
|
|
||||||
gradleProjectToChildProjects,
|
|
||||||
} = getCurrentGradleReport();
|
|
||||||
const dependencies: Set<RawProjectGraphDependency> = new Set();
|
|
||||||
|
|
||||||
for (const gradleFile of gradleFiles) {
|
|
||||||
const gradleProject = gradleFileToGradleProjectMap.get(gradleFile);
|
|
||||||
const projectName = Object.values(context.projects).find(
|
|
||||||
(project) => project.root === dirname(gradleFile)
|
|
||||||
)?.name;
|
|
||||||
const dependedProjects: Set<string> = buildFileToDepsMap.get(gradleFile);
|
|
||||||
|
|
||||||
if (projectName && dependedProjects?.size) {
|
|
||||||
dependedProjects?.forEach((dependedProject) => {
|
|
||||||
const targetProjectRoot = gradleProjectNameToProjectRootMap.get(
|
|
||||||
dependedProject
|
|
||||||
) as string;
|
|
||||||
const targetProjectName = Object.values(context.projects).find(
|
|
||||||
(project) => project.root === targetProjectRoot
|
|
||||||
)?.name;
|
|
||||||
if (targetProjectName) {
|
|
||||||
const dependency: RawProjectGraphDependency = {
|
|
||||||
source: projectName as string,
|
|
||||||
target: targetProjectName as string,
|
|
||||||
type: DependencyType.static,
|
|
||||||
sourceFile: gradleFile,
|
|
||||||
};
|
|
||||||
validateDependency(dependency, context);
|
|
||||||
dependencies.add(dependency);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
gradleProjectToChildProjects.get(gradleProject)?.forEach((childProject) => {
|
|
||||||
if (childProject) {
|
|
||||||
const dependency: RawProjectGraphDependency = {
|
|
||||||
source: projectName as string,
|
|
||||||
target: childProject,
|
|
||||||
type: DependencyType.static,
|
|
||||||
sourceFile: gradleFile,
|
|
||||||
};
|
|
||||||
validateDependency(dependency, context);
|
|
||||||
dependencies.add(dependency);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const gradleDependenciesEnd = performance.mark('gradleDependencies:end');
|
|
||||||
performance.measure(
|
|
||||||
'gradleDependencies',
|
|
||||||
gradleDependenciesStart.name,
|
|
||||||
gradleDependenciesEnd.name
|
|
||||||
);
|
);
|
||||||
|
const { gradlewFiles } = splitConfigFiles(files);
|
||||||
|
await populateProjectGraph(context.workspaceRoot, gradlewFiles, options);
|
||||||
|
const { dependencies: dependenciesFromReport } =
|
||||||
|
getCurrentProjectGraphReport();
|
||||||
|
|
||||||
return Array.from(dependencies);
|
const dependencies: Array<StaticDependency> = [];
|
||||||
};
|
dependenciesFromReport.forEach((dependencyFromPlugin: StaticDependency) => {
|
||||||
|
try {
|
||||||
function findGradleFiles(fileMap: FileMap): string[] {
|
const source =
|
||||||
const gradleFiles: string[] = [];
|
relative(workspaceRoot, dependencyFromPlugin.source) || '.';
|
||||||
|
const sourceProjectName =
|
||||||
for (const [_, files] of Object.entries(fileMap.projectFileMap)) {
|
Object.values(context.projects).find(
|
||||||
for (const file of files) {
|
(project) => source === project.root
|
||||||
if (GRADLE_BUILD_FILES.has(basename(file.file))) {
|
)?.name ?? dependencyFromPlugin.source;
|
||||||
gradleFiles.push(file.file);
|
const target =
|
||||||
|
relative(workspaceRoot, dependencyFromPlugin.target) || '.';
|
||||||
|
const targetProjectName =
|
||||||
|
Object.values(context.projects).find(
|
||||||
|
(project) => target === project.root
|
||||||
|
)?.name ?? dependencyFromPlugin.target;
|
||||||
|
if (!sourceProjectName || !targetProjectName) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
const dependency: StaticDependency = {
|
||||||
|
source: sourceProjectName,
|
||||||
|
target: targetProjectName,
|
||||||
|
type: DependencyType.static,
|
||||||
|
sourceFile: normalizePath(
|
||||||
|
relative(workspaceRoot, dependencyFromPlugin.sourceFile)
|
||||||
|
),
|
||||||
|
};
|
||||||
|
validateDependency(dependency, context);
|
||||||
|
dependencies.push(dependency);
|
||||||
|
} catch {
|
||||||
|
logger.warn(
|
||||||
|
`Unable to parse dependency from gradle plugin: ${dependencyFromPlugin.source} -> ${dependencyFromPlugin.target}`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
|
||||||
return gradleFiles;
|
return dependencies;
|
||||||
}
|
};
|
||||||
|
|||||||
@ -1,20 +1,22 @@
|
|||||||
import { CreateNodesContext } from '@nx/devkit';
|
import { CreateNodesContext, readJsonFile } from '@nx/devkit';
|
||||||
|
import { join } from 'path';
|
||||||
import { TempFs } from 'nx/src/internal-testing-utils/temp-fs';
|
import { TempFs } from 'nx/src/internal-testing-utils/temp-fs';
|
||||||
import { type GradleReport } from '../utils/get-gradle-report';
|
import { type ProjectGraphReport } from './utils/get-project-graph-from-gradle-plugin';
|
||||||
|
|
||||||
let gradleReport: GradleReport;
|
let gradleReport: ProjectGraphReport;
|
||||||
jest.mock('../utils/get-gradle-report', () => {
|
jest.mock('./utils/get-project-graph-from-gradle-plugin', () => {
|
||||||
return {
|
return {
|
||||||
GRADLE_BUILD_FILES: new Set(['build.gradle', 'build.gradle.kts']),
|
GRADLE_BUILD_FILES: new Set(['build.gradle', 'build.gradle.kts']),
|
||||||
populateGradleReport: jest.fn().mockImplementation(() => void 0),
|
populateProjectGraph: jest.fn().mockImplementation(() => void 0),
|
||||||
getCurrentGradleReport: jest.fn().mockImplementation(() => gradleReport),
|
getCurrentProjectGraphReport: jest
|
||||||
|
.fn()
|
||||||
|
.mockImplementation(() => gradleReport),
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
import { createNodesV2 } from './nodes';
|
import { createNodesV2 } from './nodes';
|
||||||
|
|
||||||
describe('@nx/gradle/plugin', () => {
|
describe('@nx/gradle/plugin/nodes', () => {
|
||||||
let createNodesFunction = createNodesV2[1];
|
let createNodesFunction = createNodesV2[1];
|
||||||
let context: CreateNodesContext;
|
let context: CreateNodesContext;
|
||||||
let tempFs: TempFs;
|
let tempFs: TempFs;
|
||||||
@ -22,32 +24,9 @@ describe('@nx/gradle/plugin', () => {
|
|||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
tempFs = new TempFs('test');
|
tempFs = new TempFs('test');
|
||||||
gradleReport = {
|
gradleReport = readJsonFile(
|
||||||
gradleFileToGradleProjectMap: new Map<string, string>([
|
join(__dirname, 'utils/__mocks__/gradle_tutorial.json')
|
||||||
['proj/build.gradle', 'proj'],
|
);
|
||||||
]),
|
|
||||||
buildFileToDepsMap: new Map<string, Set<string>>(),
|
|
||||||
gradleFileToOutputDirsMap: new Map<string, Map<string, string>>([
|
|
||||||
['proj/build.gradle', new Map([['build', 'build']])],
|
|
||||||
]),
|
|
||||||
gradleProjectToTasksMap: new Map<string, Set<string>>([
|
|
||||||
['proj', new Set(['test'])],
|
|
||||||
]),
|
|
||||||
gradleProjectToTasksTypeMap: new Map<string, Map<string, string>>([
|
|
||||||
[
|
|
||||||
'proj',
|
|
||||||
new Map([
|
|
||||||
['test', 'Verification'],
|
|
||||||
['build', 'Build'],
|
|
||||||
]),
|
|
||||||
],
|
|
||||||
]),
|
|
||||||
gradleProjectToProjectName: new Map<string, string>([['proj', 'proj']]),
|
|
||||||
gradleProjectNameToProjectRootMap: new Map<string, string>([
|
|
||||||
['proj', 'proj'],
|
|
||||||
]),
|
|
||||||
gradleProjectToChildProjects: new Map<string, string[]>(),
|
|
||||||
};
|
|
||||||
cwd = process.cwd();
|
cwd = process.cwd();
|
||||||
process.chdir(tempFs.tempDir);
|
process.chdir(tempFs.tempDir);
|
||||||
context = {
|
context = {
|
||||||
@ -81,190 +60,13 @@ describe('@nx/gradle/plugin', () => {
|
|||||||
context
|
context
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(results).toMatchInlineSnapshot(`
|
expect(results).toMatchSnapshot();
|
||||||
[
|
|
||||||
[
|
|
||||||
"proj/build.gradle",
|
|
||||||
{
|
|
||||||
"projects": {
|
|
||||||
"proj": {
|
|
||||||
"metadata": {
|
|
||||||
"targetGroups": {
|
|
||||||
"Verification": [
|
|
||||||
"test",
|
|
||||||
],
|
|
||||||
},
|
|
||||||
"technologies": [
|
|
||||||
"gradle",
|
|
||||||
],
|
|
||||||
},
|
|
||||||
"name": "proj",
|
|
||||||
"projectType": "application",
|
|
||||||
"targets": {
|
|
||||||
"test": {
|
|
||||||
"cache": true,
|
|
||||||
"command": "./gradlew proj:test",
|
|
||||||
"dependsOn": [
|
|
||||||
"testClasses",
|
|
||||||
],
|
|
||||||
"inputs": [
|
|
||||||
"default",
|
|
||||||
"^production",
|
|
||||||
],
|
|
||||||
"metadata": {
|
|
||||||
"help": {
|
|
||||||
"command": "./gradlew help --task proj:test",
|
|
||||||
"example": {
|
|
||||||
"options": {
|
|
||||||
"args": [
|
|
||||||
"--rerun",
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"technologies": [
|
|
||||||
"gradle",
|
|
||||||
],
|
|
||||||
},
|
|
||||||
"options": {
|
|
||||||
"cwd": ".",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
]
|
|
||||||
`);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should create nodes include subprojects tasks', async () => {
|
|
||||||
const results = await createNodesFunction(
|
|
||||||
['proj/build.gradle'],
|
|
||||||
{
|
|
||||||
buildTargetName: 'build',
|
|
||||||
includeSubprojectsTasks: true,
|
|
||||||
},
|
|
||||||
context
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(results).toMatchInlineSnapshot(`
|
|
||||||
[
|
|
||||||
[
|
|
||||||
"proj/build.gradle",
|
|
||||||
{
|
|
||||||
"projects": {
|
|
||||||
"proj": {
|
|
||||||
"metadata": {
|
|
||||||
"targetGroups": {
|
|
||||||
"Build": [
|
|
||||||
"build",
|
|
||||||
],
|
|
||||||
"Verification": [
|
|
||||||
"test",
|
|
||||||
],
|
|
||||||
},
|
|
||||||
"technologies": [
|
|
||||||
"gradle",
|
|
||||||
],
|
|
||||||
},
|
|
||||||
"name": "proj",
|
|
||||||
"projectType": "application",
|
|
||||||
"targets": {
|
|
||||||
"build": {
|
|
||||||
"cache": true,
|
|
||||||
"command": "./gradlew proj:build",
|
|
||||||
"dependsOn": [
|
|
||||||
"^build",
|
|
||||||
"classes",
|
|
||||||
"test",
|
|
||||||
],
|
|
||||||
"inputs": [
|
|
||||||
"production",
|
|
||||||
"^production",
|
|
||||||
],
|
|
||||||
"metadata": {
|
|
||||||
"help": {
|
|
||||||
"command": "./gradlew help --task proj:build",
|
|
||||||
"example": {
|
|
||||||
"options": {
|
|
||||||
"args": [
|
|
||||||
"--rerun",
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"technologies": [
|
|
||||||
"gradle",
|
|
||||||
],
|
|
||||||
},
|
|
||||||
"options": {
|
|
||||||
"cwd": ".",
|
|
||||||
},
|
|
||||||
"outputs": [
|
|
||||||
"build",
|
|
||||||
],
|
|
||||||
},
|
|
||||||
"test": {
|
|
||||||
"cache": true,
|
|
||||||
"command": "./gradlew proj:test",
|
|
||||||
"dependsOn": [
|
|
||||||
"testClasses",
|
|
||||||
],
|
|
||||||
"inputs": [
|
|
||||||
"default",
|
|
||||||
"^production",
|
|
||||||
],
|
|
||||||
"metadata": {
|
|
||||||
"help": {
|
|
||||||
"command": "./gradlew help --task proj:test",
|
|
||||||
"example": {
|
|
||||||
"options": {
|
|
||||||
"args": [
|
|
||||||
"--rerun",
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"technologies": [
|
|
||||||
"gradle",
|
|
||||||
],
|
|
||||||
},
|
|
||||||
"options": {
|
|
||||||
"cwd": ".",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
]
|
|
||||||
`);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should create nodes based on gradle for nested project root', async () => {
|
it('should create nodes based on gradle for nested project root', async () => {
|
||||||
gradleReport = {
|
gradleReport = readJsonFile(
|
||||||
gradleFileToGradleProjectMap: new Map<string, string>([
|
join(__dirname, '/utils/__mocks__/gradle_composite.json')
|
||||||
['nested/nested/proj/build.gradle', 'proj'],
|
);
|
||||||
]),
|
|
||||||
buildFileToDepsMap: new Map<string, Set<string>>(),
|
|
||||||
gradleFileToOutputDirsMap: new Map<string, Map<string, string>>([
|
|
||||||
['nested/nested/proj/build.gradle', new Map([['build', 'build']])],
|
|
||||||
]),
|
|
||||||
gradleProjectToTasksMap: new Map<string, Set<string>>([
|
|
||||||
['proj', new Set(['test'])],
|
|
||||||
]),
|
|
||||||
gradleProjectToTasksTypeMap: new Map<string, Map<string, string>>([
|
|
||||||
['proj', new Map([['test', 'Verification']])],
|
|
||||||
]),
|
|
||||||
gradleProjectToProjectName: new Map<string, string>([['proj', 'proj']]),
|
|
||||||
gradleProjectNameToProjectRootMap: new Map<string, string>([
|
|
||||||
['proj', 'proj'],
|
|
||||||
]),
|
|
||||||
gradleProjectToChildProjects: new Map<string, string[]>(),
|
|
||||||
};
|
|
||||||
await tempFs.createFiles({
|
await tempFs.createFiles({
|
||||||
'nested/nested/proj/build.gradle': ``,
|
'nested/nested/proj/build.gradle': ``,
|
||||||
});
|
});
|
||||||
@ -277,311 +79,30 @@ describe('@nx/gradle/plugin', () => {
|
|||||||
context
|
context
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(results).toMatchInlineSnapshot(`
|
expect(results).toMatchSnapshot();
|
||||||
[
|
|
||||||
[
|
|
||||||
"nested/nested/proj/build.gradle",
|
|
||||||
{
|
|
||||||
"projects": {
|
|
||||||
"nested/nested/proj": {
|
|
||||||
"metadata": {
|
|
||||||
"targetGroups": {
|
|
||||||
"Verification": [
|
|
||||||
"test",
|
|
||||||
],
|
|
||||||
},
|
|
||||||
"technologies": [
|
|
||||||
"gradle",
|
|
||||||
],
|
|
||||||
},
|
|
||||||
"name": "proj",
|
|
||||||
"projectType": "application",
|
|
||||||
"targets": {
|
|
||||||
"test": {
|
|
||||||
"cache": true,
|
|
||||||
"command": "./gradlew proj:test",
|
|
||||||
"dependsOn": [
|
|
||||||
"testClasses",
|
|
||||||
],
|
|
||||||
"inputs": [
|
|
||||||
"default",
|
|
||||||
"^production",
|
|
||||||
],
|
|
||||||
"metadata": {
|
|
||||||
"help": {
|
|
||||||
"command": "./gradlew help --task proj:test",
|
|
||||||
"example": {
|
|
||||||
"options": {
|
|
||||||
"args": [
|
|
||||||
"--rerun",
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"technologies": [
|
|
||||||
"gradle",
|
|
||||||
],
|
|
||||||
},
|
|
||||||
"options": {
|
|
||||||
"cwd": ".",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
]
|
|
||||||
`);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('with atomized tests targets', () => {
|
it('should create nodes with atomized tests targets based on gradle if ciTargetName is specified', async () => {
|
||||||
beforeEach(async () => {
|
const results = await createNodesFunction(
|
||||||
gradleReport = {
|
['proj/application/build.gradle'],
|
||||||
gradleFileToGradleProjectMap: new Map<string, string>([
|
{
|
||||||
['nested/nested/proj/build.gradle', 'proj'],
|
buildTargetName: 'build',
|
||||||
]),
|
ciTargetName: 'test-ci',
|
||||||
buildFileToDepsMap: new Map<string, Set<string>>(),
|
},
|
||||||
gradleFileToOutputDirsMap: new Map<string, Map<string, string>>([
|
context
|
||||||
['nested/nested/proj/build.gradle', new Map([['build', 'build']])],
|
);
|
||||||
]),
|
|
||||||
gradleProjectToTasksMap: new Map<string, Set<string>>([
|
|
||||||
['proj', new Set(['test'])],
|
|
||||||
]),
|
|
||||||
gradleProjectToTasksTypeMap: new Map<string, Map<string, string>>([
|
|
||||||
['proj', new Map([['test', 'Test']])],
|
|
||||||
]),
|
|
||||||
gradleProjectToProjectName: new Map<string, string>([['proj', 'proj']]),
|
|
||||||
gradleProjectNameToProjectRootMap: new Map<string, string>([
|
|
||||||
['proj', 'proj'],
|
|
||||||
]),
|
|
||||||
gradleProjectToChildProjects: new Map<string, string[]>(),
|
|
||||||
};
|
|
||||||
await tempFs.createFiles({
|
|
||||||
'nested/nested/proj/build.gradle': ``,
|
|
||||||
});
|
|
||||||
await tempFs.createFiles({
|
|
||||||
'proj/src/test/java/test/rootTest.java': ``,
|
|
||||||
});
|
|
||||||
await tempFs.createFiles({
|
|
||||||
'nested/nested/proj/src/test/java/test/aTest.java': ``,
|
|
||||||
});
|
|
||||||
await tempFs.createFiles({
|
|
||||||
'nested/nested/proj/src/test/java/test/bTest.java': ``,
|
|
||||||
});
|
|
||||||
await tempFs.createFiles({
|
|
||||||
'nested/nested/proj/src/test/java/test/cTests.java': ``,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should create nodes with atomized tests targets based on gradle for nested project root', async () => {
|
expect(results).toMatchSnapshot();
|
||||||
const results = await createNodesFunction(
|
});
|
||||||
[
|
|
||||||
'nested/nested/proj/build.gradle',
|
|
||||||
'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',
|
|
||||||
'nested/nested/proj/src/test/java/test/cTests.java',
|
|
||||||
],
|
|
||||||
{
|
|
||||||
buildTargetName: 'build',
|
|
||||||
ciTargetName: 'test-ci',
|
|
||||||
},
|
|
||||||
context
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(results).toMatchInlineSnapshot(`
|
it('should not create nodes with atomized tests targets based on gradle if ciTargetName is not specified', async () => {
|
||||||
[
|
const results = await createNodesFunction(
|
||||||
[
|
['proj/application/build.gradle'],
|
||||||
"nested/nested/proj/build.gradle",
|
{
|
||||||
{
|
buildTargetName: 'build',
|
||||||
"projects": {
|
},
|
||||||
"nested/nested/proj": {
|
context
|
||||||
"metadata": {
|
);
|
||||||
"targetGroups": {
|
expect(results).toMatchSnapshot();
|
||||||
"Test": [
|
|
||||||
"test-ci--aTest",
|
|
||||||
"test-ci--bTest",
|
|
||||||
"test-ci--cTests",
|
|
||||||
"test-ci",
|
|
||||||
"test",
|
|
||||||
],
|
|
||||||
},
|
|
||||||
"technologies": [
|
|
||||||
"gradle",
|
|
||||||
],
|
|
||||||
},
|
|
||||||
"name": "proj",
|
|
||||||
"projectType": "application",
|
|
||||||
"targets": {
|
|
||||||
"test": {
|
|
||||||
"cache": false,
|
|
||||||
"command": "./gradlew proj:test",
|
|
||||||
"dependsOn": [
|
|
||||||
"testClasses",
|
|
||||||
],
|
|
||||||
"inputs": [
|
|
||||||
"default",
|
|
||||||
"^production",
|
|
||||||
],
|
|
||||||
"metadata": {
|
|
||||||
"help": {
|
|
||||||
"command": "./gradlew help --task proj:test",
|
|
||||||
"example": {
|
|
||||||
"options": {
|
|
||||||
"args": [
|
|
||||||
"--rerun",
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"technologies": [
|
|
||||||
"gradle",
|
|
||||||
],
|
|
||||||
},
|
|
||||||
"options": {
|
|
||||||
"cwd": ".",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"test-ci": {
|
|
||||||
"cache": true,
|
|
||||||
"dependsOn": [
|
|
||||||
{
|
|
||||||
"params": "forward",
|
|
||||||
"projects": "self",
|
|
||||||
"target": "test-ci--aTest",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"params": "forward",
|
|
||||||
"projects": "self",
|
|
||||||
"target": "test-ci--bTest",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"params": "forward",
|
|
||||||
"projects": "self",
|
|
||||||
"target": "test-ci--cTests",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
"executor": "nx:noop",
|
|
||||||
"inputs": [
|
|
||||||
"default",
|
|
||||||
"^production",
|
|
||||||
],
|
|
||||||
"metadata": {
|
|
||||||
"description": "Runs Gradle Tests in CI",
|
|
||||||
"help": {
|
|
||||||
"command": "./gradlew help --task proj:test",
|
|
||||||
"example": {
|
|
||||||
"options": {
|
|
||||||
"args": [
|
|
||||||
"--rerun",
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"nonAtomizedTarget": "test",
|
|
||||||
"technologies": [
|
|
||||||
"gradle",
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"test-ci--aTest": {
|
|
||||||
"cache": true,
|
|
||||||
"command": "./gradlew proj:test --tests aTest",
|
|
||||||
"dependsOn": [
|
|
||||||
"testClasses",
|
|
||||||
],
|
|
||||||
"inputs": [
|
|
||||||
"default",
|
|
||||||
"^production",
|
|
||||||
],
|
|
||||||
"metadata": {
|
|
||||||
"description": "Runs Gradle test nested/nested/proj/src/test/java/test/aTest.java in CI",
|
|
||||||
"help": {
|
|
||||||
"command": "./gradlew help --task proj:test",
|
|
||||||
"example": {
|
|
||||||
"options": {
|
|
||||||
"args": [
|
|
||||||
"--rerun",
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"technologies": [
|
|
||||||
"gradle",
|
|
||||||
],
|
|
||||||
},
|
|
||||||
"options": {
|
|
||||||
"cwd": ".",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"test-ci--bTest": {
|
|
||||||
"cache": true,
|
|
||||||
"command": "./gradlew proj:test --tests bTest",
|
|
||||||
"dependsOn": [
|
|
||||||
"testClasses",
|
|
||||||
],
|
|
||||||
"inputs": [
|
|
||||||
"default",
|
|
||||||
"^production",
|
|
||||||
],
|
|
||||||
"metadata": {
|
|
||||||
"description": "Runs Gradle test nested/nested/proj/src/test/java/test/bTest.java in CI",
|
|
||||||
"help": {
|
|
||||||
"command": "./gradlew help --task proj:test",
|
|
||||||
"example": {
|
|
||||||
"options": {
|
|
||||||
"args": [
|
|
||||||
"--rerun",
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"technologies": [
|
|
||||||
"gradle",
|
|
||||||
],
|
|
||||||
},
|
|
||||||
"options": {
|
|
||||||
"cwd": ".",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"test-ci--cTests": {
|
|
||||||
"cache": true,
|
|
||||||
"command": "./gradlew proj:test --tests cTests",
|
|
||||||
"dependsOn": [
|
|
||||||
"testClasses",
|
|
||||||
],
|
|
||||||
"inputs": [
|
|
||||||
"default",
|
|
||||||
"^production",
|
|
||||||
],
|
|
||||||
"metadata": {
|
|
||||||
"description": "Runs Gradle test nested/nested/proj/src/test/java/test/cTests.java in CI",
|
|
||||||
"help": {
|
|
||||||
"command": "./gradlew help --task proj:test",
|
|
||||||
"example": {
|
|
||||||
"options": {
|
|
||||||
"args": [
|
|
||||||
"--rerun",
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"technologies": [
|
|
||||||
"gradle",
|
|
||||||
],
|
|
||||||
},
|
|
||||||
"options": {
|
|
||||||
"cwd": ".",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
]
|
|
||||||
`);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,67 +1,36 @@
|
|||||||
import {
|
import {
|
||||||
CreateNodes,
|
|
||||||
CreateNodesV2,
|
CreateNodesV2,
|
||||||
CreateNodesContext,
|
CreateNodesContext,
|
||||||
ProjectConfiguration,
|
ProjectConfiguration,
|
||||||
TargetConfiguration,
|
|
||||||
createNodesFromFiles,
|
createNodesFromFiles,
|
||||||
readJsonFile,
|
readJsonFile,
|
||||||
writeJsonFile,
|
writeJsonFile,
|
||||||
CreateNodesFunction,
|
CreateNodesFunction,
|
||||||
logger,
|
workspaceRoot,
|
||||||
|
ProjectGraphExternalNode,
|
||||||
} from '@nx/devkit';
|
} from '@nx/devkit';
|
||||||
import { calculateHashForCreateNodes } from '@nx/devkit/src/utils/calculate-hash-for-create-nodes';
|
import { calculateHashForCreateNodes } from '@nx/devkit/src/utils/calculate-hash-for-create-nodes';
|
||||||
import { existsSync } from 'node:fs';
|
import { existsSync } from 'node:fs';
|
||||||
import { basename, dirname, join } from 'node:path';
|
import { 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 {
|
|
||||||
populateGradleReport,
|
|
||||||
getCurrentGradleReport,
|
|
||||||
GradleReport,
|
|
||||||
} from '../utils/get-gradle-report';
|
|
||||||
import { hashObject } from 'nx/src/hasher/file-hasher';
|
import { hashObject } from 'nx/src/hasher/file-hasher';
|
||||||
import {
|
import {
|
||||||
gradleConfigAndTestGlob,
|
gradleConfigAndTestGlob,
|
||||||
gradleConfigGlob,
|
|
||||||
splitConfigFiles,
|
splitConfigFiles,
|
||||||
} from '../utils/split-config-files';
|
} from '../utils/split-config-files';
|
||||||
import { getGradleExecFile, findGraldewFile } from '../utils/exec-gradle';
|
import {
|
||||||
|
getCurrentProjectGraphReport,
|
||||||
const cacheableTaskType = new Set(['Build', 'Verification']);
|
populateProjectGraph,
|
||||||
const dependsOnMap = {
|
} from './utils/get-project-graph-from-gradle-plugin';
|
||||||
build: ['^build', 'classes', 'test'],
|
import {
|
||||||
testClasses: ['classes'],
|
GradlePluginOptions,
|
||||||
test: ['testClasses'],
|
normalizeOptions,
|
||||||
classes: ['^classes'],
|
} from './utils/gradle-plugin-options';
|
||||||
};
|
|
||||||
|
|
||||||
interface GradleTask {
|
|
||||||
type: string;
|
|
||||||
name: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface GradlePluginOptions {
|
|
||||||
includeSubprojectsTasks?: boolean; // default is false, show all gradle tasks in the project
|
|
||||||
ciTargetName?: string;
|
|
||||||
testTargetName?: string;
|
|
||||||
classesTargetName?: string;
|
|
||||||
buildTargetName?: string;
|
|
||||||
[taskTargetName: string]: string | undefined | boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
function normalizeOptions(options: GradlePluginOptions): GradlePluginOptions {
|
|
||||||
options ??= {};
|
|
||||||
options.testTargetName ??= 'test';
|
|
||||||
options.classesTargetName ??= 'classes';
|
|
||||||
options.buildTargetName ??= 'build';
|
|
||||||
return options;
|
|
||||||
}
|
|
||||||
|
|
||||||
type GradleTargets = Record<string, Partial<ProjectConfiguration>>;
|
type GradleTargets = Record<string, Partial<ProjectConfiguration>>;
|
||||||
|
|
||||||
function readTargetsCache(cachePath: string): GradleTargets {
|
function readProjectsCache(cachePath: string): GradleTargets {
|
||||||
return existsSync(cachePath) ? readJsonFile(cachePath) : {};
|
return existsSync(cachePath) ? readJsonFile(cachePath) : {};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,47 +41,39 @@ 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 { buildFiles, projectRoots, gradlewFiles, testFiles } =
|
const { buildFiles, gradlewFiles } = splitConfigFiles(files);
|
||||||
splitConfigFiles(files);
|
|
||||||
const optionsHash = hashObject(options);
|
const optionsHash = hashObject(options);
|
||||||
const cachePath = join(
|
const cachePath = join(
|
||||||
workspaceDataDirectory,
|
workspaceDataDirectory,
|
||||||
`gradle-${optionsHash}.hash`
|
`gradle-${optionsHash}.hash`
|
||||||
);
|
);
|
||||||
const targetsCache = readTargetsCache(cachePath);
|
const projectsCache = readProjectsCache(cachePath);
|
||||||
|
|
||||||
await populateGradleReport(
|
await populateProjectGraph(
|
||||||
context.workspaceRoot,
|
context.workspaceRoot,
|
||||||
gradlewFiles.map((f) => join(context.workspaceRoot, f))
|
gradlewFiles.map((f) => join(context.workspaceRoot, f)),
|
||||||
);
|
options
|
||||||
const gradleReport = getCurrentGradleReport();
|
|
||||||
const gradleProjectRootToTestFilesMap = getGradleProjectRootToTestFilesMap(
|
|
||||||
testFiles,
|
|
||||||
projectRoots
|
|
||||||
);
|
);
|
||||||
|
const { nodes, externalNodes } = getCurrentProjectGraphReport();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return createNodesFromFiles(
|
return createNodesFromFiles(
|
||||||
makeCreateNodesForGradleConfigFile(
|
makeCreateNodesForGradleConfigFile(nodes, projectsCache, externalNodes),
|
||||||
gradleReport,
|
|
||||||
targetsCache,
|
|
||||||
gradleProjectRootToTestFilesMap
|
|
||||||
),
|
|
||||||
buildFiles,
|
buildFiles,
|
||||||
options,
|
options,
|
||||||
context
|
context
|
||||||
);
|
);
|
||||||
} finally {
|
} finally {
|
||||||
writeTargetsToCache(cachePath, targetsCache);
|
writeTargetsToCache(cachePath, projectsCache);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
export const makeCreateNodesForGradleConfigFile =
|
export const makeCreateNodesForGradleConfigFile =
|
||||||
(
|
(
|
||||||
gradleReport: GradleReport,
|
projects: Record<string, Partial<ProjectConfiguration>>,
|
||||||
targetsCache: GradleTargets = {},
|
projectsCache: GradleTargets = {},
|
||||||
gradleProjectRootToTestFilesMap: Record<string, string[]> = {}
|
externalNodes: Record<string, ProjectGraphExternalNode> = {}
|
||||||
): CreateNodesFunction =>
|
): CreateNodesFunction =>
|
||||||
async (
|
async (
|
||||||
gradleFilePath,
|
gradleFilePath,
|
||||||
@ -127,309 +88,18 @@ export const makeCreateNodesForGradleConfigFile =
|
|||||||
options ?? {},
|
options ?? {},
|
||||||
context
|
context
|
||||||
);
|
);
|
||||||
targetsCache[hash] ??= await createGradleProject(
|
projectsCache[hash] ??=
|
||||||
gradleReport,
|
projects[projectRoot] ?? projects[join(workspaceRoot, projectRoot)];
|
||||||
gradleFilePath,
|
const project = projectsCache[hash];
|
||||||
options,
|
|
||||||
context,
|
|
||||||
gradleProjectRootToTestFilesMap[projectRoot]
|
|
||||||
);
|
|
||||||
const project = targetsCache[hash];
|
|
||||||
if (!project) {
|
if (!project) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
project.root = projectRoot;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
projects: {
|
projects: {
|
||||||
[projectRoot]: project,
|
[projectRoot]: project,
|
||||||
},
|
},
|
||||||
|
externalNodes: externalNodes,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
@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.
|
|
||||||
*/
|
|
||||||
export const createNodes: CreateNodes<GradlePluginOptions> = [
|
|
||||||
gradleConfigGlob,
|
|
||||||
async (buildFile, options, context) => {
|
|
||||||
logger.warn(
|
|
||||||
'`createNodes` is deprecated. Update your plugin to utilize createNodesV2 instead. In Nx 20, this will change to the createNodesV2 API.'
|
|
||||||
);
|
|
||||||
const { gradlewFiles } = splitConfigFiles(context.configFiles);
|
|
||||||
await populateGradleReport(context.workspaceRoot, gradlewFiles);
|
|
||||||
const gradleReport = getCurrentGradleReport();
|
|
||||||
const internalCreateNodes =
|
|
||||||
makeCreateNodesForGradleConfigFile(gradleReport);
|
|
||||||
return await internalCreateNodes(buildFile, options, context);
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
async function createGradleProject(
|
|
||||||
gradleReport: GradleReport,
|
|
||||||
gradleFilePath: string,
|
|
||||||
options: GradlePluginOptions | undefined,
|
|
||||||
context: CreateNodesContext,
|
|
||||||
testFiles = []
|
|
||||||
) {
|
|
||||||
try {
|
|
||||||
const {
|
|
||||||
gradleProjectToTasksTypeMap,
|
|
||||||
gradleProjectToTasksMap,
|
|
||||||
gradleFileToOutputDirsMap,
|
|
||||||
gradleFileToGradleProjectMap,
|
|
||||||
gradleProjectToProjectName,
|
|
||||||
} = gradleReport;
|
|
||||||
|
|
||||||
const gradleProject = gradleFileToGradleProjectMap.get(
|
|
||||||
gradleFilePath
|
|
||||||
) as string;
|
|
||||||
const projectName = gradleProjectToProjectName.get(gradleProject);
|
|
||||||
if (!projectName) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const tasksTypeMap: Map<string, string> = gradleProjectToTasksTypeMap.get(
|
|
||||||
gradleProject
|
|
||||||
) as Map<string, string>;
|
|
||||||
const tasksSet = gradleProjectToTasksMap.get(gradleProject) as Set<string>;
|
|
||||||
let tasks: GradleTask[] = [];
|
|
||||||
tasksSet.forEach((taskName) => {
|
|
||||||
tasks.push({
|
|
||||||
type: tasksTypeMap?.get(taskName) as string,
|
|
||||||
name: taskName,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
if (options.includeSubprojectsTasks) {
|
|
||||||
tasksTypeMap.forEach((taskType, taskName) => {
|
|
||||||
if (!tasksSet.has(taskName)) {
|
|
||||||
tasks.push({
|
|
||||||
type: taskType,
|
|
||||||
name: taskName,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const outputDirs = gradleFileToOutputDirsMap.get(gradleFilePath) as Map<
|
|
||||||
string,
|
|
||||||
string
|
|
||||||
>;
|
|
||||||
|
|
||||||
const { targets, targetGroups } = await createGradleTargets(
|
|
||||||
tasks,
|
|
||||||
options,
|
|
||||||
context,
|
|
||||||
outputDirs,
|
|
||||||
gradleProject,
|
|
||||||
gradleFilePath,
|
|
||||||
testFiles
|
|
||||||
);
|
|
||||||
const project: Partial<ProjectConfiguration> = {
|
|
||||||
name: projectName,
|
|
||||||
projectType: 'application',
|
|
||||||
targets,
|
|
||||||
metadata: {
|
|
||||||
targetGroups,
|
|
||||||
technologies: ['gradle'],
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
return project;
|
|
||||||
} catch (e) {
|
|
||||||
console.error(e);
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function createGradleTargets(
|
|
||||||
tasks: GradleTask[],
|
|
||||||
options: GradlePluginOptions | undefined,
|
|
||||||
context: CreateNodesContext,
|
|
||||||
outputDirs: Map<string, string>,
|
|
||||||
gradleProject: string,
|
|
||||||
gradleBuildFilePath: string,
|
|
||||||
testFiles: string[] = []
|
|
||||||
): Promise<{
|
|
||||||
targetGroups: Record<string, string[]>;
|
|
||||||
targets: Record<string, TargetConfiguration>;
|
|
||||||
}> {
|
|
||||||
const inputsMap = createInputsMap(context);
|
|
||||||
const gradlewFileDirectory = dirname(
|
|
||||||
findGraldewFile(gradleBuildFilePath, context.workspaceRoot)
|
|
||||||
);
|
|
||||||
|
|
||||||
const targets: Record<string, TargetConfiguration> = {};
|
|
||||||
const targetGroups: Record<string, string[]> = {};
|
|
||||||
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 as string,
|
|
||||||
options.ciTargetName,
|
|
||||||
inputsMap['test'],
|
|
||||||
outputs,
|
|
||||||
task.type,
|
|
||||||
targets,
|
|
||||||
targetGroups,
|
|
||||||
gradlewFileDirectory
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const taskCommandToRun = `${gradleProject ? gradleProject + ':' : ''}${
|
|
||||||
task.name
|
|
||||||
}`;
|
|
||||||
|
|
||||||
targets[targetName as string] = {
|
|
||||||
command: `${getGradleExecFile()} ${taskCommandToRun}`,
|
|
||||||
options: {
|
|
||||||
cwd: gradlewFileDirectory,
|
|
||||||
},
|
|
||||||
cache: cacheableTaskType.has(task.type),
|
|
||||||
inputs: inputsMap[task.name],
|
|
||||||
dependsOn: dependsOnMap[task.name],
|
|
||||||
metadata: {
|
|
||||||
technologies: ['gradle'],
|
|
||||||
help: {
|
|
||||||
command: `${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 as string);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return { targetGroups, targets };
|
|
||||||
}
|
|
||||||
|
|
||||||
function createInputsMap(
|
|
||||||
context: CreateNodesContext
|
|
||||||
): Record<string, TargetConfiguration['inputs']> {
|
|
||||||
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: string[],
|
|
||||||
gradleProject: string,
|
|
||||||
testTargetName: string,
|
|
||||||
ciTargetName: string,
|
|
||||||
inputs: TargetConfiguration['inputs'],
|
|
||||||
outputs: string[],
|
|
||||||
targetGroupName: string,
|
|
||||||
targets: Record<string, TargetConfiguration>,
|
|
||||||
targetGroups: Record<string, string[]>,
|
|
||||||
gradlewFileDirectory: string
|
|
||||||
): void {
|
|
||||||
if (!testFiles || testFiles.length === 0 || !ciTargetName) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const taskCommandToRun = `${gradleProject ? gradleProject + ':' : ''}test`;
|
|
||||||
|
|
||||||
if (!targetGroups[targetGroupName]) {
|
|
||||||
targetGroups[targetGroupName] = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
const dependsOn: TargetConfiguration['dependsOn'] = [];
|
|
||||||
testFiles.forEach((testFile) => {
|
|
||||||
const testName = basename(testFile).split('.')[0];
|
|
||||||
const targetName = ciTargetName + '--' + testName;
|
|
||||||
|
|
||||||
targets[targetName] = {
|
|
||||||
command: `${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: `${getGradleExecFile()} help --task ${taskCommandToRun}`,
|
|
||||||
example: {
|
|
||||||
options: {
|
|
||||||
args: ['--rerun'],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
...(outputs && outputs.length > 0 ? { outputs } : {}),
|
|
||||||
};
|
|
||||||
targetGroups[targetGroupName].push(targetName);
|
|
||||||
dependsOn.push({
|
|
||||||
target: targetName,
|
|
||||||
projects: 'self',
|
|
||||||
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: `${getGradleExecFile()} help --task ${taskCommandToRun}`,
|
|
||||||
example: {
|
|
||||||
options: {
|
|
||||||
args: ['--rerun'],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
targetGroups[targetGroupName].push(ciTargetName);
|
|
||||||
}
|
|
||||||
|
|
||||||
function getGradleProjectRootToTestFilesMap(
|
|
||||||
testFiles: string[],
|
|
||||||
projectRoots: string[]
|
|
||||||
): Record<string, string[]> | undefined {
|
|
||||||
if (testFiles.length === 0 || projectRoots.length === 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const roots = new Map(projectRoots.map((root) => [root, root]));
|
|
||||||
const testFilesToGradleProjectMap: Record<string, string[]> = {};
|
|
||||||
testFiles.forEach((testFile) => {
|
|
||||||
const projectRoot = findProjectForPath(testFile, roots);
|
|
||||||
if (projectRoot) {
|
|
||||||
if (!testFilesToGradleProjectMap[projectRoot]) {
|
|
||||||
testFilesToGradleProjectMap[projectRoot] = [];
|
|
||||||
}
|
|
||||||
testFilesToGradleProjectMap[projectRoot].push(testFile);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return testFilesToGradleProjectMap;
|
|
||||||
}
|
|
||||||
|
|||||||
@ -0,0 +1,38 @@
|
|||||||
|
{
|
||||||
|
"nodes": {
|
||||||
|
"nested/nested/proj": {
|
||||||
|
"targets": {
|
||||||
|
"buildEnvironment": {
|
||||||
|
"cache": true,
|
||||||
|
"metadata": {
|
||||||
|
"description": "Displays all buildscript dependencies declared in root project \u0027my-composite\u0027.",
|
||||||
|
"technologies": ["gradle"]
|
||||||
|
},
|
||||||
|
"command": "./gradlew :buildEnvironment",
|
||||||
|
"options": {
|
||||||
|
"cwd": "nested/nested/proj"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"metadata": {
|
||||||
|
"targetGroups": {
|
||||||
|
"help": ["buildEnvironment"]
|
||||||
|
},
|
||||||
|
"technologies": ["gradle"]
|
||||||
|
},
|
||||||
|
"name": "my-composite"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"dependencies": [
|
||||||
|
{
|
||||||
|
"source": "nested/nested/proj",
|
||||||
|
"target": "projectRoot/my-app",
|
||||||
|
"sourceFile": "projectRoot/build.gradle.kts"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"source": "nested/nested/proj",
|
||||||
|
"target": "projectRoot/my-utils",
|
||||||
|
"sourceFile": "projectRoot/build.gradle.kts"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
590
packages/gradle/src/plugin/utils/__mocks__/gradle_nx_list.json
Normal file
590
packages/gradle/src/plugin/utils/__mocks__/gradle_nx_list.json
Normal file
@ -0,0 +1,590 @@
|
|||||||
|
{
|
||||||
|
"targets": {
|
||||||
|
"assemble": {
|
||||||
|
"cache": true,
|
||||||
|
"parallelism": false,
|
||||||
|
"dependsOn": ["list:jar"],
|
||||||
|
"command": "./gradlew :list:assemble",
|
||||||
|
"metadata": {
|
||||||
|
"description": "Assembles the outputs of this project.",
|
||||||
|
"technologies": ["gradle"],
|
||||||
|
"help": { "command": "./gradlew help --task :list:assemble" }
|
||||||
|
},
|
||||||
|
"options": { "cwd": "." }
|
||||||
|
},
|
||||||
|
"build": {
|
||||||
|
"cache": true,
|
||||||
|
"parallelism": false,
|
||||||
|
"dependsOn": ["list:check", "list:assemble"],
|
||||||
|
"command": "./gradlew :list:build",
|
||||||
|
"metadata": {
|
||||||
|
"description": "Assembles and tests this project.",
|
||||||
|
"technologies": ["gradle"],
|
||||||
|
"help": { "command": "./gradlew help --task :list:build" }
|
||||||
|
},
|
||||||
|
"options": { "cwd": "." }
|
||||||
|
},
|
||||||
|
"buildDependents": {
|
||||||
|
"cache": true,
|
||||||
|
"parallelism": false,
|
||||||
|
"command": "./gradlew :list:buildDependents",
|
||||||
|
"metadata": {
|
||||||
|
"description": "Assembles and tests this project and all projects that depend on it.",
|
||||||
|
"technologies": ["gradle"],
|
||||||
|
"help": { "command": "./gradlew help --task :list:buildDependents" }
|
||||||
|
},
|
||||||
|
"options": { "cwd": "." }
|
||||||
|
},
|
||||||
|
"buildEnvironment": {
|
||||||
|
"cache": true,
|
||||||
|
"parallelism": false,
|
||||||
|
"command": "./gradlew :list:buildEnvironment",
|
||||||
|
"metadata": {
|
||||||
|
"description": "Displays all buildscript dependencies declared in project \u0027:list\u0027.",
|
||||||
|
"technologies": ["gradle"],
|
||||||
|
"help": {
|
||||||
|
"command": "./gradlew help --task :list:buildEnvironment"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"options": { "cwd": "." }
|
||||||
|
},
|
||||||
|
"buildNeeded": {
|
||||||
|
"cache": true,
|
||||||
|
"parallelism": false,
|
||||||
|
"dependsOn": ["list:build"],
|
||||||
|
"command": "./gradlew :list:buildNeeded",
|
||||||
|
"metadata": {
|
||||||
|
"description": "Assembles and tests this project and all projects it depends on.",
|
||||||
|
"technologies": ["gradle"],
|
||||||
|
"help": { "command": "./gradlew help --task :list:buildNeeded" }
|
||||||
|
},
|
||||||
|
"options": { "cwd": "." }
|
||||||
|
},
|
||||||
|
"check": {
|
||||||
|
"cache": true,
|
||||||
|
"parallelism": false,
|
||||||
|
"dependsOn": ["list:test"],
|
||||||
|
"command": "./gradlew :list:check",
|
||||||
|
"metadata": {
|
||||||
|
"description": "Runs all checks.",
|
||||||
|
"technologies": ["gradle"],
|
||||||
|
"help": { "command": "./gradlew help --task :list:check" }
|
||||||
|
},
|
||||||
|
"options": { "cwd": "." }
|
||||||
|
},
|
||||||
|
"classes": {
|
||||||
|
"cache": true,
|
||||||
|
"parallelism": false,
|
||||||
|
"dependsOn": ["list:compileJava", "list:processResources"],
|
||||||
|
"command": "./gradlew :list:classes",
|
||||||
|
"metadata": {
|
||||||
|
"description": "Assembles main classes.",
|
||||||
|
"technologies": ["gradle"],
|
||||||
|
"help": { "command": "./gradlew help --task :list:classes" }
|
||||||
|
},
|
||||||
|
"options": { "cwd": "." }
|
||||||
|
},
|
||||||
|
"clean": {
|
||||||
|
"cache": true,
|
||||||
|
"parallelism": false,
|
||||||
|
"command": "./gradlew :list:clean",
|
||||||
|
"metadata": {
|
||||||
|
"description": "Deletes the build directory.",
|
||||||
|
"technologies": ["gradle"],
|
||||||
|
"help": { "command": "./gradlew help --task :list:clean" }
|
||||||
|
},
|
||||||
|
"options": { "cwd": "." }
|
||||||
|
},
|
||||||
|
"compileJava": {
|
||||||
|
"cache": true,
|
||||||
|
"parallelism": false,
|
||||||
|
"inputs": [
|
||||||
|
"{projectRoot}/src/main/java/org/example/list/LinkedList.java"
|
||||||
|
],
|
||||||
|
"outputs": [
|
||||||
|
"{projectRoot}/build/classes/java/main",
|
||||||
|
"{projectRoot}/build/generated/sources/annotationProcessor/java/main",
|
||||||
|
"{projectRoot}/build/generated/sources/headers/java/main",
|
||||||
|
"{projectRoot}/build/tmp/compileJava/previous-compilation-data.bin"
|
||||||
|
],
|
||||||
|
"command": "./gradlew :list:compileJava",
|
||||||
|
"metadata": {
|
||||||
|
"description": "Compiles main Java source.",
|
||||||
|
"technologies": ["gradle"],
|
||||||
|
"help": { "command": "./gradlew help --task :list:compileJava" }
|
||||||
|
},
|
||||||
|
"options": { "cwd": "." }
|
||||||
|
},
|
||||||
|
"compileTestJava": {
|
||||||
|
"cache": true,
|
||||||
|
"parallelism": false,
|
||||||
|
"inputs": [
|
||||||
|
"{projectRoot}/src/test/java/org/example/list/LinkedListTest.java",
|
||||||
|
"{projectRoot}/src/test/java/org/example/list/LinkedList2Test.java"
|
||||||
|
],
|
||||||
|
"outputs": [
|
||||||
|
"{projectRoot}/build/classes/java/test",
|
||||||
|
"{projectRoot}/build/generated/sources/annotationProcessor/java/test",
|
||||||
|
"{projectRoot}/build/generated/sources/headers/java/test",
|
||||||
|
"{projectRoot}/build/tmp/compileTestJava/previous-compilation-data.bin"
|
||||||
|
],
|
||||||
|
"dependsOn": ["list:classes", "list:compileJava"],
|
||||||
|
"command": "./gradlew :list:compileTestJava",
|
||||||
|
"metadata": {
|
||||||
|
"description": "Compiles test Java source.",
|
||||||
|
"technologies": ["gradle"],
|
||||||
|
"help": { "command": "./gradlew help --task :list:compileTestJava" }
|
||||||
|
},
|
||||||
|
"options": { "cwd": "." }
|
||||||
|
},
|
||||||
|
"ci--LinkedListTest": {
|
||||||
|
"command": "./gradlew :list:test --tests LinkedListTest",
|
||||||
|
"metadata": {
|
||||||
|
"description": "Runs Gradle test LinkedListTest in CI",
|
||||||
|
"technologies": ["gradle"],
|
||||||
|
"help": { "command": "./gradlew help --task :list:test" }
|
||||||
|
},
|
||||||
|
"cache": true,
|
||||||
|
"parallelism": false,
|
||||||
|
"inputs": [
|
||||||
|
"{projectRoot}/src/test/java/org/example/list/LinkedListTest.java"
|
||||||
|
],
|
||||||
|
"dependsOn": [
|
||||||
|
"list:compileTestJava",
|
||||||
|
"list:testClasses",
|
||||||
|
"list:classes",
|
||||||
|
"list:compileJava"
|
||||||
|
],
|
||||||
|
"outputs": [
|
||||||
|
"{projectRoot}/build/test-results/test/binary",
|
||||||
|
"{projectRoot}/build/reports/tests/test",
|
||||||
|
"{projectRoot}/build/test-results/test"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"ci--LinkedList2Test": {
|
||||||
|
"command": "./gradlew :list:test --tests LinkedList2Test",
|
||||||
|
"metadata": {
|
||||||
|
"description": "Runs Gradle test LinkedList2Test in CI",
|
||||||
|
"technologies": ["gradle"],
|
||||||
|
"help": { "command": "./gradlew help --task :list:test" }
|
||||||
|
},
|
||||||
|
"cache": true,
|
||||||
|
"parallelism": false,
|
||||||
|
"inputs": [
|
||||||
|
"{projectRoot}/src/test/java/org/example/list/LinkedList2Test.java"
|
||||||
|
],
|
||||||
|
"dependsOn": [
|
||||||
|
"list:compileTestJava",
|
||||||
|
"list:testClasses",
|
||||||
|
"list:classes",
|
||||||
|
"list:compileJava"
|
||||||
|
],
|
||||||
|
"outputs": [
|
||||||
|
"{projectRoot}/build/test-results/test/binary",
|
||||||
|
"{projectRoot}/build/reports/tests/test",
|
||||||
|
"{projectRoot}/build/test-results/test"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"ci": {
|
||||||
|
"executor": "nx:noop",
|
||||||
|
"metadata": {
|
||||||
|
"description": "Runs Gradle Tests in CI",
|
||||||
|
"technologies": ["gradle"],
|
||||||
|
"help": { "command": "./gradlew help --task :list:test" }
|
||||||
|
},
|
||||||
|
"dependsOn": [
|
||||||
|
{
|
||||||
|
"target": "ci--LinkedListTest",
|
||||||
|
"projects": "self",
|
||||||
|
"params": "forward"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"target": "ci--LinkedList2Test",
|
||||||
|
"projects": "self",
|
||||||
|
"params": "forward"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"cache": true,
|
||||||
|
"parallelism": false
|
||||||
|
},
|
||||||
|
"components": {
|
||||||
|
"cache": true,
|
||||||
|
"parallelism": false,
|
||||||
|
"command": "./gradlew :list:components",
|
||||||
|
"metadata": {
|
||||||
|
"description": "Displays the components produced by project \u0027:list\u0027. [deprecated]",
|
||||||
|
"technologies": ["gradle"],
|
||||||
|
"help": { "command": "./gradlew help --task :list:components" }
|
||||||
|
},
|
||||||
|
"options": { "cwd": "." }
|
||||||
|
},
|
||||||
|
"nxProjectGraph": {
|
||||||
|
"cache": true,
|
||||||
|
"parallelism": false,
|
||||||
|
"dependsOn": ["list:nxProjectGraphLocal"],
|
||||||
|
"command": "./gradlew :list:nxProjectGraph",
|
||||||
|
"metadata": {
|
||||||
|
"description": "Print nodes report for Nx",
|
||||||
|
"technologies": ["gradle"],
|
||||||
|
"help": { "command": "./gradlew help --task :list:nxProjectGraph" }
|
||||||
|
},
|
||||||
|
"options": { "cwd": "." }
|
||||||
|
},
|
||||||
|
"createNodesLocal": {
|
||||||
|
"cache": true,
|
||||||
|
"parallelism": false,
|
||||||
|
"outputs": ["{projectRoot}/build/nx/list.json"],
|
||||||
|
"command": "./gradlew :list:nxProjectGraphLocal",
|
||||||
|
"metadata": {
|
||||||
|
"description": "Create nodes and dependencies for Nx",
|
||||||
|
"technologies": ["gradle"],
|
||||||
|
"help": {
|
||||||
|
"command": "./gradlew help --task :list:nxProjectGraphLocal"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"options": { "cwd": "." }
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"cache": true,
|
||||||
|
"parallelism": false,
|
||||||
|
"command": "./gradlew :list:dependencies",
|
||||||
|
"metadata": {
|
||||||
|
"description": "Displays all dependencies declared in project \u0027:list\u0027.",
|
||||||
|
"technologies": ["gradle"],
|
||||||
|
"help": { "command": "./gradlew help --task :list:dependencies" }
|
||||||
|
},
|
||||||
|
"options": { "cwd": "." }
|
||||||
|
},
|
||||||
|
"dependencyInsight": {
|
||||||
|
"cache": true,
|
||||||
|
"parallelism": false,
|
||||||
|
"command": "./gradlew :list:dependencyInsight",
|
||||||
|
"metadata": {
|
||||||
|
"description": "Displays the insight into a specific dependency in project \u0027:list\u0027.",
|
||||||
|
"technologies": ["gradle"],
|
||||||
|
"help": {
|
||||||
|
"command": "./gradlew help --task :list:dependencyInsight"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"options": { "cwd": "." }
|
||||||
|
},
|
||||||
|
"dependencyReport": {
|
||||||
|
"cache": true,
|
||||||
|
"parallelism": false,
|
||||||
|
"outputs": ["{projectRoot}/build/reports/project/dependencies.txt"],
|
||||||
|
"command": "./gradlew :list:dependencyReport",
|
||||||
|
"metadata": {
|
||||||
|
"description": "Generates a report about your library dependencies.",
|
||||||
|
"technologies": ["gradle"],
|
||||||
|
"help": {
|
||||||
|
"command": "./gradlew help --task :list:dependencyReport"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"options": { "cwd": "." }
|
||||||
|
},
|
||||||
|
"dependentComponents": {
|
||||||
|
"cache": true,
|
||||||
|
"parallelism": false,
|
||||||
|
"command": "./gradlew :list:dependentComponents",
|
||||||
|
"metadata": {
|
||||||
|
"description": "Displays the dependent components of components in project \u0027:list\u0027. [deprecated]",
|
||||||
|
"technologies": ["gradle"],
|
||||||
|
"help": {
|
||||||
|
"command": "./gradlew help --task :list:dependentComponents"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"options": { "cwd": "." }
|
||||||
|
},
|
||||||
|
"help": {
|
||||||
|
"cache": true,
|
||||||
|
"parallelism": false,
|
||||||
|
"command": "./gradlew :list:help",
|
||||||
|
"metadata": {
|
||||||
|
"description": "Displays a help message.",
|
||||||
|
"technologies": ["gradle"],
|
||||||
|
"help": { "command": "./gradlew help --task :list:help" }
|
||||||
|
},
|
||||||
|
"options": { "cwd": "." }
|
||||||
|
},
|
||||||
|
"htmlDependencyReport": {
|
||||||
|
"cache": true,
|
||||||
|
"parallelism": false,
|
||||||
|
"outputs": ["{projectRoot}/build/reports/project/dependencies"],
|
||||||
|
"command": "./gradlew :list:htmlDependencyReport",
|
||||||
|
"metadata": {
|
||||||
|
"description": "Generates an HTML report about your library dependencies.",
|
||||||
|
"technologies": ["gradle"],
|
||||||
|
"help": {
|
||||||
|
"command": "./gradlew help --task :list:htmlDependencyReport"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"options": { "cwd": "." }
|
||||||
|
},
|
||||||
|
"jar": {
|
||||||
|
"cache": true,
|
||||||
|
"parallelism": false,
|
||||||
|
"inputs": ["{projectRoot}/build/tmp/jar/MANIFEST.MF"],
|
||||||
|
"outputs": ["{projectRoot}/build/libs/list.jar"],
|
||||||
|
"dependsOn": ["list:classes", "list:compileJava"],
|
||||||
|
"command": "./gradlew :list:jar",
|
||||||
|
"metadata": {
|
||||||
|
"description": "Assembles a jar archive containing the classes of the \u0027main\u0027 feature.",
|
||||||
|
"technologies": ["gradle"],
|
||||||
|
"help": { "command": "./gradlew help --task :list:jar" }
|
||||||
|
},
|
||||||
|
"options": { "cwd": "." }
|
||||||
|
},
|
||||||
|
"javaToolchains": {
|
||||||
|
"cache": true,
|
||||||
|
"parallelism": false,
|
||||||
|
"command": "./gradlew :list:javaToolchains",
|
||||||
|
"metadata": {
|
||||||
|
"description": "Displays the detected java toolchains.",
|
||||||
|
"technologies": ["gradle"],
|
||||||
|
"help": { "command": "./gradlew help --task :list:javaToolchains" }
|
||||||
|
},
|
||||||
|
"options": { "cwd": "." }
|
||||||
|
},
|
||||||
|
"javadoc": {
|
||||||
|
"cache": true,
|
||||||
|
"parallelism": false,
|
||||||
|
"inputs": [
|
||||||
|
"{projectRoot}/src/main/java/org/example/list/LinkedList.java"
|
||||||
|
],
|
||||||
|
"outputs": ["{projectRoot}/build/docs/javadoc"],
|
||||||
|
"dependsOn": ["list:classes", "list:compileJava"],
|
||||||
|
"command": "./gradlew :list:javadoc",
|
||||||
|
"metadata": {
|
||||||
|
"description": "Generates Javadoc API documentation for the \u0027main\u0027 feature.",
|
||||||
|
"technologies": ["gradle"],
|
||||||
|
"help": { "command": "./gradlew help --task :list:javadoc" }
|
||||||
|
},
|
||||||
|
"options": { "cwd": "." }
|
||||||
|
},
|
||||||
|
"kotlinDslAccessorsReport": {
|
||||||
|
"cache": true,
|
||||||
|
"parallelism": false,
|
||||||
|
"command": "./gradlew :list:kotlinDslAccessorsReport",
|
||||||
|
"metadata": {
|
||||||
|
"description": "Prints the Kotlin code for accessing the currently available project extensions and conventions.",
|
||||||
|
"technologies": ["gradle"],
|
||||||
|
"help": {
|
||||||
|
"command": "./gradlew help --task :list:kotlinDslAccessorsReport"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"options": { "cwd": "." }
|
||||||
|
},
|
||||||
|
"model": {
|
||||||
|
"cache": true,
|
||||||
|
"parallelism": false,
|
||||||
|
"command": "./gradlew :list:model",
|
||||||
|
"metadata": {
|
||||||
|
"description": "Displays the configuration model of project \u0027:list\u0027. [deprecated]",
|
||||||
|
"technologies": ["gradle"],
|
||||||
|
"help": { "command": "./gradlew help --task :list:model" }
|
||||||
|
},
|
||||||
|
"options": { "cwd": "." }
|
||||||
|
},
|
||||||
|
"outgoingVariants": {
|
||||||
|
"cache": true,
|
||||||
|
"parallelism": false,
|
||||||
|
"command": "./gradlew :list:outgoingVariants",
|
||||||
|
"metadata": {
|
||||||
|
"description": "Displays the outgoing variants of project \u0027:list\u0027.",
|
||||||
|
"technologies": ["gradle"],
|
||||||
|
"help": {
|
||||||
|
"command": "./gradlew help --task :list:outgoingVariants"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"options": { "cwd": "." }
|
||||||
|
},
|
||||||
|
"processResources": {
|
||||||
|
"cache": true,
|
||||||
|
"parallelism": false,
|
||||||
|
"outputs": ["{projectRoot}/build/resources/main"],
|
||||||
|
"command": "./gradlew :list:processResources",
|
||||||
|
"metadata": {
|
||||||
|
"description": "Processes main resources.",
|
||||||
|
"technologies": ["gradle"],
|
||||||
|
"help": {
|
||||||
|
"command": "./gradlew help --task :list:processResources"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"options": { "cwd": "." }
|
||||||
|
},
|
||||||
|
"processTestResources": {
|
||||||
|
"cache": true,
|
||||||
|
"parallelism": false,
|
||||||
|
"outputs": ["{projectRoot}/build/resources/test"],
|
||||||
|
"command": "./gradlew :list:processTestResources",
|
||||||
|
"metadata": {
|
||||||
|
"description": "Processes test resources.",
|
||||||
|
"technologies": ["gradle"],
|
||||||
|
"help": {
|
||||||
|
"command": "./gradlew help --task :list:processTestResources"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"options": { "cwd": "." }
|
||||||
|
},
|
||||||
|
"projectReport": {
|
||||||
|
"cache": true,
|
||||||
|
"parallelism": false,
|
||||||
|
"dependsOn": [
|
||||||
|
"list:taskReport",
|
||||||
|
"list:dependencyReport",
|
||||||
|
"list:propertyReport",
|
||||||
|
"list:htmlDependencyReport"
|
||||||
|
],
|
||||||
|
"command": "./gradlew :list:projectReport",
|
||||||
|
"metadata": {
|
||||||
|
"description": "Generates a report about your project.",
|
||||||
|
"technologies": ["gradle"],
|
||||||
|
"help": { "command": "./gradlew help --task :list:projectReport" }
|
||||||
|
},
|
||||||
|
"options": { "cwd": "." }
|
||||||
|
},
|
||||||
|
"projects": {
|
||||||
|
"cache": true,
|
||||||
|
"parallelism": false,
|
||||||
|
"command": "./gradlew :list:projects",
|
||||||
|
"metadata": {
|
||||||
|
"description": "Displays the sub-projects of project \u0027:list\u0027.",
|
||||||
|
"technologies": ["gradle"],
|
||||||
|
"help": { "command": "./gradlew help --task :list:projects" }
|
||||||
|
},
|
||||||
|
"options": { "cwd": "." }
|
||||||
|
},
|
||||||
|
"properties": {
|
||||||
|
"cache": true,
|
||||||
|
"parallelism": false,
|
||||||
|
"command": "./gradlew :list:properties",
|
||||||
|
"metadata": {
|
||||||
|
"description": "Displays the properties of project \u0027:list\u0027.",
|
||||||
|
"technologies": ["gradle"],
|
||||||
|
"help": { "command": "./gradlew help --task :list:properties" }
|
||||||
|
},
|
||||||
|
"options": { "cwd": "." }
|
||||||
|
},
|
||||||
|
"propertyReport": {
|
||||||
|
"cache": true,
|
||||||
|
"parallelism": false,
|
||||||
|
"outputs": ["{projectRoot}/build/reports/project/properties.txt"],
|
||||||
|
"command": "./gradlew :list:propertyReport",
|
||||||
|
"metadata": {
|
||||||
|
"description": "Generates a report about your properties.",
|
||||||
|
"technologies": ["gradle"],
|
||||||
|
"help": { "command": "./gradlew help --task :list:propertyReport" }
|
||||||
|
},
|
||||||
|
"options": { "cwd": "." }
|
||||||
|
},
|
||||||
|
"resolvableConfigurations": {
|
||||||
|
"cache": true,
|
||||||
|
"parallelism": false,
|
||||||
|
"command": "./gradlew :list:resolvableConfigurations",
|
||||||
|
"metadata": {
|
||||||
|
"description": "Displays the configurations that can be resolved in project \u0027:list\u0027.",
|
||||||
|
"technologies": ["gradle"],
|
||||||
|
"help": {
|
||||||
|
"command": "./gradlew help --task :list:resolvableConfigurations"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"options": { "cwd": "." }
|
||||||
|
},
|
||||||
|
"taskReport": {
|
||||||
|
"cache": true,
|
||||||
|
"parallelism": false,
|
||||||
|
"outputs": ["{projectRoot}/build/reports/project/tasks.txt"],
|
||||||
|
"command": "./gradlew :list:taskReport",
|
||||||
|
"metadata": {
|
||||||
|
"description": "Generates a report about your tasks.",
|
||||||
|
"technologies": ["gradle"],
|
||||||
|
"help": { "command": "./gradlew help --task :list:taskReport" }
|
||||||
|
},
|
||||||
|
"options": { "cwd": "." }
|
||||||
|
},
|
||||||
|
"tasks": {
|
||||||
|
"cache": true,
|
||||||
|
"parallelism": false,
|
||||||
|
"command": "./gradlew :list:tasks",
|
||||||
|
"metadata": {
|
||||||
|
"description": "Displays the tasks runnable from project \u0027:list\u0027.",
|
||||||
|
"technologies": ["gradle"],
|
||||||
|
"help": { "command": "./gradlew help --task :list:tasks" }
|
||||||
|
},
|
||||||
|
"options": { "cwd": "." }
|
||||||
|
},
|
||||||
|
"test": {
|
||||||
|
"cache": true,
|
||||||
|
"parallelism": false,
|
||||||
|
"outputs": [
|
||||||
|
"{projectRoot}/build/test-results/test/binary",
|
||||||
|
"{projectRoot}/build/reports/tests/test",
|
||||||
|
"{projectRoot}/build/test-results/test"
|
||||||
|
],
|
||||||
|
"dependsOn": [
|
||||||
|
"list:compileTestJava",
|
||||||
|
"list:testClasses",
|
||||||
|
"list:classes",
|
||||||
|
"list:compileJava"
|
||||||
|
],
|
||||||
|
"command": "./gradlew :list:test",
|
||||||
|
"metadata": {
|
||||||
|
"description": "Runs the test suite.",
|
||||||
|
"technologies": ["gradle"],
|
||||||
|
"help": { "command": "./gradlew help --task :list:test" }
|
||||||
|
},
|
||||||
|
"options": { "cwd": "." }
|
||||||
|
},
|
||||||
|
"testClasses": {
|
||||||
|
"cache": true,
|
||||||
|
"parallelism": false,
|
||||||
|
"dependsOn": ["list:processTestResources", "list:compileTestJava"],
|
||||||
|
"command": "./gradlew :list:testClasses",
|
||||||
|
"metadata": {
|
||||||
|
"description": "Assembles test classes.",
|
||||||
|
"technologies": ["gradle"],
|
||||||
|
"help": { "command": "./gradlew help --task :list:testClasses" }
|
||||||
|
},
|
||||||
|
"options": { "cwd": "." }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"metadata": {
|
||||||
|
"targetGroups": {
|
||||||
|
"build": [
|
||||||
|
"assemble",
|
||||||
|
"build",
|
||||||
|
"buildDependents",
|
||||||
|
"buildNeeded",
|
||||||
|
"classes",
|
||||||
|
"clean",
|
||||||
|
"jar",
|
||||||
|
"testClasses"
|
||||||
|
],
|
||||||
|
"help": [
|
||||||
|
"buildEnvironment",
|
||||||
|
"dependencies",
|
||||||
|
"dependencyInsight",
|
||||||
|
"help",
|
||||||
|
"javaToolchains",
|
||||||
|
"kotlinDslAccessorsReport",
|
||||||
|
"outgoingVariants",
|
||||||
|
"projects",
|
||||||
|
"properties",
|
||||||
|
"resolvableConfigurations",
|
||||||
|
"tasks"
|
||||||
|
],
|
||||||
|
"verification": [
|
||||||
|
"check",
|
||||||
|
"ci--LinkedListTest",
|
||||||
|
"ci--LinkedList2Test",
|
||||||
|
"ci",
|
||||||
|
"test"
|
||||||
|
],
|
||||||
|
"Nx Custom": ["createNodes", "createNodesLocal"],
|
||||||
|
"documentation": ["javadoc"],
|
||||||
|
"reporting": ["projectReport"]
|
||||||
|
},
|
||||||
|
"technologies": ["gradle"]
|
||||||
|
},
|
||||||
|
"name": "list"
|
||||||
|
}
|
||||||
344
packages/gradle/src/plugin/utils/__mocks__/gradle_tutorial.json
Normal file
344
packages/gradle/src/plugin/utils/__mocks__/gradle_tutorial.json
Normal file
@ -0,0 +1,344 @@
|
|||||||
|
{
|
||||||
|
"nodes": {
|
||||||
|
"proj": {
|
||||||
|
"targets": {
|
||||||
|
"buildEnvironment": {
|
||||||
|
"cache": true,
|
||||||
|
"metadata": {
|
||||||
|
"description": "Displays all buildscript dependencies declared in root project \u0027gradle-tutorial\u0027.",
|
||||||
|
"technologies": ["gradle"]
|
||||||
|
},
|
||||||
|
"command": "./gradlew :buildEnvironment",
|
||||||
|
"options": { "cwd": "proj" }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"metadata": {
|
||||||
|
"targetGroups": {
|
||||||
|
"help": ["buildEnvironment"]
|
||||||
|
},
|
||||||
|
"technologies": ["gradle"]
|
||||||
|
},
|
||||||
|
"name": "gradle-tutorial"
|
||||||
|
},
|
||||||
|
"proj/application": {
|
||||||
|
"targets": {
|
||||||
|
"ci--DemoApplicationTest10": {
|
||||||
|
"inputs": [
|
||||||
|
"{projectRoot}/src/test/java/com/example/multimodule/application/DemoApplicationTest10.java"
|
||||||
|
],
|
||||||
|
"outputs": [
|
||||||
|
"{projectRoot}/build/classes/java/test",
|
||||||
|
"{projectRoot}/build/generated/sources/annotationProcessor/java/test",
|
||||||
|
"{projectRoot}/build/generated/sources/headers/java/test",
|
||||||
|
"{projectRoot}/build/tmp/compileTestJava/previous-compilation-data.bin"
|
||||||
|
],
|
||||||
|
"cache": true,
|
||||||
|
"dependsOn": [
|
||||||
|
"application:classes",
|
||||||
|
"application:compileJava",
|
||||||
|
"library:jar"
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"description": "Runs Gradle test proj/application/src/test/java/com/example/multimodule/application/DemoApplicationTest10.java in CI",
|
||||||
|
"technologies": ["gradle"]
|
||||||
|
},
|
||||||
|
"command": "./gradlew :application:test --tests DemoApplicationTest10",
|
||||||
|
"options": { "cwd": "proj" }
|
||||||
|
},
|
||||||
|
"ci--DemoApplicationTest7": {
|
||||||
|
"inputs": [
|
||||||
|
"{projectRoot}/src/test/java/com/example/multimodule/application/DemoApplicationTest7.java"
|
||||||
|
],
|
||||||
|
"outputs": [
|
||||||
|
"{projectRoot}/build/classes/java/test",
|
||||||
|
"{projectRoot}/build/generated/sources/annotationProcessor/java/test",
|
||||||
|
"{projectRoot}/build/generated/sources/headers/java/test",
|
||||||
|
"{projectRoot}/build/tmp/compileTestJava/previous-compilation-data.bin"
|
||||||
|
],
|
||||||
|
"cache": true,
|
||||||
|
"dependsOn": [
|
||||||
|
"application:classes",
|
||||||
|
"application:compileJava",
|
||||||
|
"library:jar"
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"description": "Runs Gradle test proj/application/src/test/java/com/example/multimodule/application/DemoApplicationTest7.java in CI",
|
||||||
|
"technologies": ["gradle"]
|
||||||
|
},
|
||||||
|
"command": "./gradlew :application:test --tests DemoApplicationTest7",
|
||||||
|
"options": { "cwd": "proj" }
|
||||||
|
},
|
||||||
|
"ci--DemoApplicationTest6": {
|
||||||
|
"inputs": [
|
||||||
|
"{projectRoot}/src/test/java/com/example/multimodule/application/DemoApplicationTest6.java"
|
||||||
|
],
|
||||||
|
"outputs": [
|
||||||
|
"{projectRoot}/build/classes/java/test",
|
||||||
|
"{projectRoot}/build/generated/sources/annotationProcessor/java/test",
|
||||||
|
"{projectRoot}/build/generated/sources/headers/java/test",
|
||||||
|
"{projectRoot}/build/tmp/compileTestJava/previous-compilation-data.bin"
|
||||||
|
],
|
||||||
|
"cache": true,
|
||||||
|
"dependsOn": [
|
||||||
|
"application:classes",
|
||||||
|
"application:compileJava",
|
||||||
|
"library:jar"
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"description": "Runs Gradle test proj/application/src/test/java/com/example/multimodule/application/DemoApplicationTest6.java in CI",
|
||||||
|
"technologies": ["gradle"]
|
||||||
|
},
|
||||||
|
"command": "./gradlew :application:test --tests DemoApplicationTest6",
|
||||||
|
"options": { "cwd": "proj" }
|
||||||
|
},
|
||||||
|
"ci--DemoApplicationTest3": {
|
||||||
|
"inputs": [
|
||||||
|
"{projectRoot}/src/test/java/com/example/multimodule/application/DemoApplicationTest3.java"
|
||||||
|
],
|
||||||
|
"outputs": [
|
||||||
|
"{projectRoot}/build/classes/java/test",
|
||||||
|
"{projectRoot}/build/generated/sources/annotationProcessor/java/test",
|
||||||
|
"{projectRoot}/build/generated/sources/headers/java/test",
|
||||||
|
"{projectRoot}/build/tmp/compileTestJava/previous-compilation-data.bin"
|
||||||
|
],
|
||||||
|
"cache": true,
|
||||||
|
"dependsOn": [
|
||||||
|
"application:classes",
|
||||||
|
"application:compileJava",
|
||||||
|
"library:jar"
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"description": "Runs Gradle test proj/application/src/test/java/com/example/multimodule/application/DemoApplicationTest3.java in CI",
|
||||||
|
"technologies": ["gradle"]
|
||||||
|
},
|
||||||
|
"command": "./gradlew :application:test --tests DemoApplicationTest3",
|
||||||
|
"options": { "cwd": "proj" }
|
||||||
|
},
|
||||||
|
"ci--DemoApplicationTest2": {
|
||||||
|
"inputs": [
|
||||||
|
"{projectRoot}/src/test/java/com/example/multimodule/application/DemoApplicationTest2.java"
|
||||||
|
],
|
||||||
|
"outputs": [
|
||||||
|
"{projectRoot}/build/classes/java/test",
|
||||||
|
"{projectRoot}/build/generated/sources/annotationProcessor/java/test",
|
||||||
|
"{projectRoot}/build/generated/sources/headers/java/test",
|
||||||
|
"{projectRoot}/build/tmp/compileTestJava/previous-compilation-data.bin"
|
||||||
|
],
|
||||||
|
"cache": true,
|
||||||
|
"dependsOn": [
|
||||||
|
"application:classes",
|
||||||
|
"application:compileJava",
|
||||||
|
"library:jar"
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"description": "Runs Gradle test proj/application/src/test/java/com/example/multimodule/application/DemoApplicationTest2.java in CI",
|
||||||
|
"technologies": ["gradle"]
|
||||||
|
},
|
||||||
|
"command": "./gradlew :application:test --tests DemoApplicationTest2",
|
||||||
|
"options": { "cwd": "proj" }
|
||||||
|
},
|
||||||
|
"ci--DemoApplicationTest9": {
|
||||||
|
"inputs": [
|
||||||
|
"{projectRoot}/src/test/java/com/example/multimodule/application/DemoApplicationTest9.java"
|
||||||
|
],
|
||||||
|
"outputs": [
|
||||||
|
"{projectRoot}/build/classes/java/test",
|
||||||
|
"{projectRoot}/build/generated/sources/annotationProcessor/java/test",
|
||||||
|
"{projectRoot}/build/generated/sources/headers/java/test",
|
||||||
|
"{projectRoot}/build/tmp/compileTestJava/previous-compilation-data.bin"
|
||||||
|
],
|
||||||
|
"cache": true,
|
||||||
|
"dependsOn": [
|
||||||
|
"application:classes",
|
||||||
|
"application:compileJava",
|
||||||
|
"library:jar"
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"description": "Runs Gradle test proj/application/src/test/java/com/example/multimodule/application/DemoApplicationTest9.java in CI",
|
||||||
|
"technologies": ["gradle"]
|
||||||
|
},
|
||||||
|
"command": "./gradlew :application:test --tests DemoApplicationTest9",
|
||||||
|
"options": { "cwd": "proj" }
|
||||||
|
},
|
||||||
|
"ci--DemoApplicationTest": {
|
||||||
|
"inputs": [
|
||||||
|
"{projectRoot}/src/test/java/com/example/multimodule/application/DemoApplicationTest.java"
|
||||||
|
],
|
||||||
|
"outputs": [
|
||||||
|
"{projectRoot}/build/classes/java/test",
|
||||||
|
"{projectRoot}/build/generated/sources/annotationProcessor/java/test",
|
||||||
|
"{projectRoot}/build/generated/sources/headers/java/test",
|
||||||
|
"{projectRoot}/build/tmp/compileTestJava/previous-compilation-data.bin"
|
||||||
|
],
|
||||||
|
"cache": true,
|
||||||
|
"dependsOn": [
|
||||||
|
"application:classes",
|
||||||
|
"application:compileJava",
|
||||||
|
"library:jar"
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"description": "Runs Gradle test proj/application/src/test/java/com/example/multimodule/application/DemoApplicationTest.java in CI",
|
||||||
|
"technologies": ["gradle"]
|
||||||
|
},
|
||||||
|
"command": "./gradlew :application:test --tests DemoApplicationTest",
|
||||||
|
"options": { "cwd": "proj" }
|
||||||
|
},
|
||||||
|
"ci--DemoApplicationTest5": {
|
||||||
|
"inputs": [
|
||||||
|
"{projectRoot}/src/test/java/com/example/multimodule/application/DemoApplicationTest5.java"
|
||||||
|
],
|
||||||
|
"outputs": [
|
||||||
|
"{projectRoot}/build/classes/java/test",
|
||||||
|
"{projectRoot}/build/generated/sources/annotationProcessor/java/test",
|
||||||
|
"{projectRoot}/build/generated/sources/headers/java/test",
|
||||||
|
"{projectRoot}/build/tmp/compileTestJava/previous-compilation-data.bin"
|
||||||
|
],
|
||||||
|
"cache": true,
|
||||||
|
"dependsOn": [
|
||||||
|
"application:classes",
|
||||||
|
"application:compileJava",
|
||||||
|
"library:jar"
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"description": "Runs Gradle test proj/application/src/test/java/com/example/multimodule/application/DemoApplicationTest5.java in CI",
|
||||||
|
"technologies": ["gradle"]
|
||||||
|
},
|
||||||
|
"command": "./gradlew :application:test --tests DemoApplicationTest5",
|
||||||
|
"options": { "cwd": "proj" }
|
||||||
|
},
|
||||||
|
"ci--DemoApplicationTest4": {
|
||||||
|
"inputs": [
|
||||||
|
"{projectRoot}/src/test/java/com/example/multimodule/application/DemoApplicationTest4.java"
|
||||||
|
],
|
||||||
|
"outputs": [
|
||||||
|
"{projectRoot}/build/classes/java/test",
|
||||||
|
"{projectRoot}/build/generated/sources/annotationProcessor/java/test",
|
||||||
|
"{projectRoot}/build/generated/sources/headers/java/test",
|
||||||
|
"{projectRoot}/build/tmp/compileTestJava/previous-compilation-data.bin"
|
||||||
|
],
|
||||||
|
"cache": true,
|
||||||
|
"dependsOn": [
|
||||||
|
"application:classes",
|
||||||
|
"application:compileJava",
|
||||||
|
"library:jar"
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"description": "Runs Gradle test proj/application/src/test/java/com/example/multimodule/application/DemoApplicationTest4.java in CI",
|
||||||
|
"technologies": ["gradle"]
|
||||||
|
},
|
||||||
|
"command": "./gradlew :application:test --tests DemoApplicationTest4",
|
||||||
|
"options": { "cwd": "proj" }
|
||||||
|
},
|
||||||
|
"ci--DemoApplicationTest8": {
|
||||||
|
"inputs": [
|
||||||
|
"{projectRoot}/src/test/java/com/example/multimodule/application/DemoApplicationTest8.java"
|
||||||
|
],
|
||||||
|
"outputs": [
|
||||||
|
"{projectRoot}/build/classes/java/test",
|
||||||
|
"{projectRoot}/build/generated/sources/annotationProcessor/java/test",
|
||||||
|
"{projectRoot}/build/generated/sources/headers/java/test",
|
||||||
|
"{projectRoot}/build/tmp/compileTestJava/previous-compilation-data.bin"
|
||||||
|
],
|
||||||
|
"cache": true,
|
||||||
|
"dependsOn": [
|
||||||
|
"application:classes",
|
||||||
|
"application:compileJava",
|
||||||
|
"library:jar"
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"description": "Runs Gradle test proj/application/src/test/java/com/example/multimodule/application/DemoApplicationTest8.java in CI",
|
||||||
|
"technologies": ["gradle"]
|
||||||
|
},
|
||||||
|
"command": "./gradlew :application:test --tests DemoApplicationTest8",
|
||||||
|
"options": { "cwd": "proj" }
|
||||||
|
},
|
||||||
|
"ci": {
|
||||||
|
"inputs": [
|
||||||
|
"{projectRoot}/src/test/java/com/example/multimodule/application/DemoApplicationTest10.java",
|
||||||
|
"{projectRoot}/src/test/java/com/example/multimodule/application/DemoApplicationTest7.java",
|
||||||
|
"{projectRoot}/src/test/java/com/example/multimodule/application/DemoApplicationTest6.java",
|
||||||
|
"{projectRoot}/src/test/java/com/example/multimodule/application/DemoApplicationTest3.java",
|
||||||
|
"{projectRoot}/src/test/java/com/example/multimodule/application/DemoApplicationTest2.java",
|
||||||
|
"{projectRoot}/src/test/java/com/example/multimodule/application/DemoApplicationTest9.java",
|
||||||
|
"{projectRoot}/src/test/java/com/example/multimodule/application/DemoApplicationTest.java",
|
||||||
|
"{projectRoot}/src/test/java/com/example/multimodule/application/DemoApplicationTest5.java",
|
||||||
|
"{projectRoot}/src/test/java/com/example/multimodule/application/DemoApplicationTest4.java",
|
||||||
|
"{projectRoot}/src/test/java/com/example/multimodule/application/DemoApplicationTest8.java"
|
||||||
|
],
|
||||||
|
"outputs": [
|
||||||
|
"{projectRoot}/build/classes/java/test",
|
||||||
|
"{projectRoot}/build/generated/sources/annotationProcessor/java/test",
|
||||||
|
"{projectRoot}/build/generated/sources/headers/java/test",
|
||||||
|
"{projectRoot}/build/tmp/compileTestJava/previous-compilation-data.bin"
|
||||||
|
],
|
||||||
|
"cache": true,
|
||||||
|
"dependsOn": [
|
||||||
|
{
|
||||||
|
"target": "ci--DemoApplicationTest10",
|
||||||
|
"projects": "self",
|
||||||
|
"params": "forward"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"target": "ci--DemoApplicationTest7",
|
||||||
|
"projects": "self",
|
||||||
|
"params": "forward"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"target": "ci--DemoApplicationTest6",
|
||||||
|
"projects": "self",
|
||||||
|
"params": "forward"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"target": "ci--DemoApplicationTest3",
|
||||||
|
"projects": "self",
|
||||||
|
"params": "forward"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"target": "ci--DemoApplicationTest2",
|
||||||
|
"projects": "self",
|
||||||
|
"params": "forward"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"target": "ci--DemoApplicationTest9",
|
||||||
|
"projects": "self",
|
||||||
|
"params": "forward"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"target": "ci--DemoApplicationTest",
|
||||||
|
"projects": "self",
|
||||||
|
"params": "forward"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"target": "ci--DemoApplicationTest5",
|
||||||
|
"projects": "self",
|
||||||
|
"params": "forward"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"target": "ci--DemoApplicationTest4",
|
||||||
|
"projects": "self",
|
||||||
|
"params": "forward"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"target": "ci--DemoApplicationTest8",
|
||||||
|
"projects": "self",
|
||||||
|
"params": "forward"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"description": "Runs Gradle Tests in CI",
|
||||||
|
"technologies": ["gradle"]
|
||||||
|
},
|
||||||
|
"options": { "cwd": "proj" },
|
||||||
|
"executor": "nx:noop"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"metadata": {
|
||||||
|
"targetGroups": {
|
||||||
|
"verification": ["ci"]
|
||||||
|
},
|
||||||
|
"technologies": ["gradle"]
|
||||||
|
},
|
||||||
|
"name": "application"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,203 @@
|
|||||||
|
import { existsSync } from 'node:fs';
|
||||||
|
import { join } from 'node:path';
|
||||||
|
|
||||||
|
import {
|
||||||
|
AggregateCreateNodesError,
|
||||||
|
hashArray,
|
||||||
|
ProjectConfiguration,
|
||||||
|
ProjectGraphExternalNode,
|
||||||
|
readJsonFile,
|
||||||
|
StaticDependency,
|
||||||
|
writeJsonFile,
|
||||||
|
} from '@nx/devkit';
|
||||||
|
|
||||||
|
import { hashWithWorkspaceContext } from 'nx/src/utils/workspace-context';
|
||||||
|
import { gradleConfigAndTestGlob } from '../../utils/split-config-files';
|
||||||
|
import { workspaceDataDirectory } from 'nx/src/utils/cache-directory';
|
||||||
|
import { getNxProjectGraphLines } from './get-project-graph-lines';
|
||||||
|
import { GradlePluginOptions } from './gradle-plugin-options';
|
||||||
|
import { hashObject } from 'nx/src/devkit-internals';
|
||||||
|
|
||||||
|
// the output json file from the gradle plugin
|
||||||
|
export interface ProjectGraphReport {
|
||||||
|
nodes: {
|
||||||
|
[appRoot: string]: Partial<ProjectConfiguration>;
|
||||||
|
};
|
||||||
|
dependencies: Array<StaticDependency>;
|
||||||
|
externalNodes?: Record<string, ProjectGraphExternalNode>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ProjectGraphReportCache extends ProjectGraphReport {
|
||||||
|
hash: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
function readProjectGraphReportCache(
|
||||||
|
cachePath: string,
|
||||||
|
hash: string
|
||||||
|
): ProjectGraphReport | undefined {
|
||||||
|
const projectGraphReportCache: Partial<ProjectGraphReportCache> = existsSync(
|
||||||
|
cachePath
|
||||||
|
)
|
||||||
|
? readJsonFile(cachePath)
|
||||||
|
: undefined;
|
||||||
|
if (!projectGraphReportCache || projectGraphReportCache.hash !== hash) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
return projectGraphReportCache as ProjectGraphReport;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function writeProjectGraphReportToCache(
|
||||||
|
cachePath: string,
|
||||||
|
results: ProjectGraphReport
|
||||||
|
) {
|
||||||
|
let projectGraphReportJson: ProjectGraphReportCache = {
|
||||||
|
hash: gradleCurrentConfigHash,
|
||||||
|
...results,
|
||||||
|
};
|
||||||
|
|
||||||
|
writeJsonFile(cachePath, projectGraphReportJson);
|
||||||
|
}
|
||||||
|
|
||||||
|
let projectGraphReportCache: ProjectGraphReport;
|
||||||
|
let gradleCurrentConfigHash: string;
|
||||||
|
let projectGraphReportCachePath: string = join(
|
||||||
|
workspaceDataDirectory,
|
||||||
|
'gradle-nodes.hash'
|
||||||
|
);
|
||||||
|
|
||||||
|
export function getCurrentProjectGraphReport(): ProjectGraphReport {
|
||||||
|
if (!projectGraphReportCache) {
|
||||||
|
throw new AggregateCreateNodesError(
|
||||||
|
[
|
||||||
|
[
|
||||||
|
null,
|
||||||
|
new Error(
|
||||||
|
`Expected cached gradle report. Please open an issue at https://github.com/nrwl/nx/issues/new/choose`
|
||||||
|
),
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return projectGraphReportCache;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function populates the gradle report cache.
|
||||||
|
* For each gradlew file, it runs the `nxProjectGraph` task and processes the output.
|
||||||
|
* 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 populateProjectGraph(
|
||||||
|
workspaceRoot: string,
|
||||||
|
gradlewFiles: string[],
|
||||||
|
options: GradlePluginOptions
|
||||||
|
): Promise<void> {
|
||||||
|
const gradleConfigHash = hashArray([
|
||||||
|
await hashWithWorkspaceContext(workspaceRoot, [gradleConfigAndTestGlob]),
|
||||||
|
hashObject(options),
|
||||||
|
process.env.CI,
|
||||||
|
]);
|
||||||
|
projectGraphReportCache ??= readProjectGraphReportCache(
|
||||||
|
projectGraphReportCachePath,
|
||||||
|
gradleConfigHash
|
||||||
|
);
|
||||||
|
if (
|
||||||
|
projectGraphReportCache &&
|
||||||
|
(!gradleCurrentConfigHash || gradleConfigHash === gradleCurrentConfigHash)
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const gradleProjectGraphReportStart = performance.mark(
|
||||||
|
'gradleProjectGraphReport:start'
|
||||||
|
);
|
||||||
|
|
||||||
|
const projectGraphLines = await gradlewFiles.reduce(
|
||||||
|
async (
|
||||||
|
projectGraphLines: Promise<string[]>,
|
||||||
|
gradlewFile: string
|
||||||
|
): Promise<string[]> => {
|
||||||
|
const getNxProjectGraphLinesStart = performance.mark(
|
||||||
|
`${gradlewFile}GetNxProjectGraphLines:start`
|
||||||
|
);
|
||||||
|
const allLines = await projectGraphLines;
|
||||||
|
const currentLines = await getNxProjectGraphLines(
|
||||||
|
gradlewFile,
|
||||||
|
gradleConfigHash,
|
||||||
|
options
|
||||||
|
);
|
||||||
|
const getNxProjectGraphLinesEnd = performance.mark(
|
||||||
|
`${gradlewFile}GetNxProjectGraphLines:end`
|
||||||
|
);
|
||||||
|
performance.measure(
|
||||||
|
`${gradlewFile}GetNxProjectGraphLines`,
|
||||||
|
getNxProjectGraphLinesStart.name,
|
||||||
|
getNxProjectGraphLinesEnd.name
|
||||||
|
);
|
||||||
|
return [...allLines, ...currentLines];
|
||||||
|
},
|
||||||
|
Promise.resolve([])
|
||||||
|
);
|
||||||
|
|
||||||
|
const gradleProjectGraphReportEnd = performance.mark(
|
||||||
|
'gradleProjectGraphReport:end'
|
||||||
|
);
|
||||||
|
performance.measure(
|
||||||
|
'gradleProjectGraphReport',
|
||||||
|
gradleProjectGraphReportStart.name,
|
||||||
|
gradleProjectGraphReportEnd.name
|
||||||
|
);
|
||||||
|
gradleCurrentConfigHash = gradleConfigHash;
|
||||||
|
projectGraphReportCache = processNxProjectGraph(projectGraphLines);
|
||||||
|
writeProjectGraphReportToCache(
|
||||||
|
projectGraphReportCachePath,
|
||||||
|
projectGraphReportCache
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function processNxProjectGraph(
|
||||||
|
projectGraphLines: string[]
|
||||||
|
): ProjectGraphReport {
|
||||||
|
let index = 0;
|
||||||
|
let projectGraphReportForAllProjects: ProjectGraphReport = {
|
||||||
|
nodes: {},
|
||||||
|
dependencies: [],
|
||||||
|
externalNodes: {},
|
||||||
|
};
|
||||||
|
while (index < projectGraphLines.length) {
|
||||||
|
const line = projectGraphLines[index].trim();
|
||||||
|
if (line.startsWith('> Task ') && line.endsWith(':nxProjectGraph')) {
|
||||||
|
while (
|
||||||
|
index < projectGraphLines.length &&
|
||||||
|
!projectGraphLines[index].includes('.json')
|
||||||
|
) {
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
const file = projectGraphLines[index];
|
||||||
|
const projectGraphReportJson: ProjectGraphReport =
|
||||||
|
readJsonFile<ProjectGraphReport>(file);
|
||||||
|
projectGraphReportForAllProjects.nodes = {
|
||||||
|
...projectGraphReportForAllProjects.nodes,
|
||||||
|
...projectGraphReportJson.nodes,
|
||||||
|
};
|
||||||
|
if (projectGraphReportJson.dependencies) {
|
||||||
|
projectGraphReportForAllProjects.dependencies.push(
|
||||||
|
...projectGraphReportJson.dependencies
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (Object.keys(projectGraphReportJson.externalNodes ?? {}).length > 0) {
|
||||||
|
projectGraphReportForAllProjects.externalNodes = {
|
||||||
|
...projectGraphReportForAllProjects.externalNodes,
|
||||||
|
...projectGraphReportJson.externalNodes,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return projectGraphReportForAllProjects;
|
||||||
|
}
|
||||||
90
packages/gradle/src/plugin/utils/get-project-graph-lines.ts
Normal file
90
packages/gradle/src/plugin/utils/get-project-graph-lines.ts
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
import { AggregateCreateNodesError, output, workspaceRoot } from '@nx/devkit';
|
||||||
|
import { execGradleAsync, newLineSeparator } from '../../utils/exec-gradle';
|
||||||
|
import { GradlePluginOptions } from './gradle-plugin-options';
|
||||||
|
import { dirname } from 'node:path';
|
||||||
|
|
||||||
|
export async function getNxProjectGraphLines(
|
||||||
|
gradlewFile: string,
|
||||||
|
gradleConfigHash: string,
|
||||||
|
gradlePluginOptions: GradlePluginOptions
|
||||||
|
): Promise<string[]> {
|
||||||
|
if (process.env.VERCEL) {
|
||||||
|
// skip on Vercel
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
let nxProjectGraphBuffer: Buffer;
|
||||||
|
|
||||||
|
const gradlePluginOptionsArgs =
|
||||||
|
Object.entries(gradlePluginOptions ?? {})?.map(
|
||||||
|
([key, value]) => `-P${key}=${value}`
|
||||||
|
) ?? [];
|
||||||
|
|
||||||
|
try {
|
||||||
|
nxProjectGraphBuffer = await execGradleAsync(gradlewFile, [
|
||||||
|
'nxProjectGraph',
|
||||||
|
`-Phash=${gradleConfigHash}`,
|
||||||
|
'--no-configuration-cache', // disable configuration cache
|
||||||
|
'--parallel', // add parallel to improve performance
|
||||||
|
'--build-cache', // enable build cache
|
||||||
|
'--warning-mode',
|
||||||
|
'none',
|
||||||
|
...gradlePluginOptionsArgs,
|
||||||
|
`-Pcwd=${dirname(gradlewFile)}`,
|
||||||
|
`-PworkspaceRoot=${workspaceRoot}`,
|
||||||
|
process.env.NX_VERBOSE_LOGGING ? '--info' : '',
|
||||||
|
]);
|
||||||
|
} catch (e: Buffer | Error | any) {
|
||||||
|
if (e.toString()?.includes('ERROR: JAVA_HOME')) {
|
||||||
|
throw new AggregateCreateNodesError(
|
||||||
|
[
|
||||||
|
[
|
||||||
|
gradlewFile,
|
||||||
|
new Error(
|
||||||
|
`Could not find Java. Please install Java and try again: https://www.java.com/en/download/help/index_installing.html.\n\r${e.toString()}`
|
||||||
|
),
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[]
|
||||||
|
);
|
||||||
|
} else if (e.toString()?.includes(`Task 'nxProjectGraph' not found`)) {
|
||||||
|
throw new AggregateCreateNodesError(
|
||||||
|
[
|
||||||
|
[
|
||||||
|
gradlewFile,
|
||||||
|
new Error(
|
||||||
|
`Could not run 'nxProjectGraph' task. Please run 'nx generate @nx/gradle:init' to generate the necessary tasks.\n\r${e.toString()}`
|
||||||
|
),
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[]
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
throw new AggregateCreateNodesError(
|
||||||
|
[
|
||||||
|
[
|
||||||
|
gradlewFile,
|
||||||
|
new Error(
|
||||||
|
`Could not run 'nxProjectGraph' Gradle task. Please install Gradle and try again: https://gradle.org/install/.\r\n${e.toString()}`
|
||||||
|
),
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const projectGraphLines = nxProjectGraphBuffer
|
||||||
|
.toString()
|
||||||
|
.split(newLineSeparator)
|
||||||
|
.filter((line) => line.trim() !== '');
|
||||||
|
|
||||||
|
if (process.env.NX_VERBOSE_LOGGING === 'true') {
|
||||||
|
output.log({
|
||||||
|
title: `Successfully ran 'nxProjectGraph' task using ${gradlewFile} with hash ${gradleConfigHash}`,
|
||||||
|
bodyLines: projectGraphLines,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return projectGraphLines;
|
||||||
|
}
|
||||||
13
packages/gradle/src/plugin/utils/gradle-plugin-options.ts
Normal file
13
packages/gradle/src/plugin/utils/gradle-plugin-options.ts
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
export interface GradlePluginOptions {
|
||||||
|
testTargetName?: string;
|
||||||
|
ciTargetName?: string;
|
||||||
|
[taskTargetName: string]: string | undefined | boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function normalizeOptions(
|
||||||
|
options: GradlePluginOptions
|
||||||
|
): GradlePluginOptions {
|
||||||
|
options ??= {};
|
||||||
|
options.testTargetName ??= 'test';
|
||||||
|
return options;
|
||||||
|
}
|
||||||
@ -1,8 +1,8 @@
|
|||||||
import { TempFs } from 'nx/src/internal-testing-utils/temp-fs';
|
import { TempFs } from 'nx/src/internal-testing-utils/temp-fs';
|
||||||
import { findGraldewFile } from './exec-gradle';
|
import { findGradlewFile } from './exec-gradle';
|
||||||
|
|
||||||
describe('exec gradle', () => {
|
describe('exec gradle', () => {
|
||||||
describe('findGraldewFile', () => {
|
describe('findGradlewFile', () => {
|
||||||
let tempFs: TempFs;
|
let tempFs: TempFs;
|
||||||
let cwd: string;
|
let cwd: string;
|
||||||
|
|
||||||
@ -27,14 +27,14 @@ describe('exec gradle', () => {
|
|||||||
'nested/nested/proj/src/test/java/test/aTest.java': ``,
|
'nested/nested/proj/src/test/java/test/aTest.java': ``,
|
||||||
'nested/nested/proj/src/test/java/test/bTest.java': ``,
|
'nested/nested/proj/src/test/java/test/bTest.java': ``,
|
||||||
});
|
});
|
||||||
let gradlewFile = findGraldewFile('proj/build.gradle', tempFs.tempDir);
|
let gradlewFile = findGradlewFile('proj/build.gradle', tempFs.tempDir);
|
||||||
expect(gradlewFile).toEqual('gradlew');
|
expect(gradlewFile).toEqual('gradlew');
|
||||||
gradlewFile = findGraldewFile(
|
gradlewFile = findGradlewFile(
|
||||||
'nested/nested/proj/build.gradle',
|
'nested/nested/proj/build.gradle',
|
||||||
tempFs.tempDir
|
tempFs.tempDir
|
||||||
);
|
);
|
||||||
expect(gradlewFile).toEqual('gradlew');
|
expect(gradlewFile).toEqual('gradlew');
|
||||||
gradlewFile = findGraldewFile(
|
gradlewFile = findGradlewFile(
|
||||||
'nested/nested/proj/settings.gradle',
|
'nested/nested/proj/settings.gradle',
|
||||||
tempFs.tempDir
|
tempFs.tempDir
|
||||||
);
|
);
|
||||||
@ -54,16 +54,16 @@ describe('exec gradle', () => {
|
|||||||
'nested/nested/proj/src/test/java/test/bTest.java': ``,
|
'nested/nested/proj/src/test/java/test/bTest.java': ``,
|
||||||
});
|
});
|
||||||
|
|
||||||
let gradlewFile = findGraldewFile('proj/build.gradle', tempFs.tempDir);
|
let gradlewFile = findGradlewFile('proj/build.gradle', tempFs.tempDir);
|
||||||
expect(gradlewFile).toEqual('proj/gradlew');
|
expect(gradlewFile).toEqual('proj/gradlew');
|
||||||
gradlewFile = findGraldewFile('proj/settings.gradle', tempFs.tempDir);
|
gradlewFile = findGradlewFile('proj/settings.gradle', tempFs.tempDir);
|
||||||
expect(gradlewFile).toEqual('proj/gradlew');
|
expect(gradlewFile).toEqual('proj/gradlew');
|
||||||
gradlewFile = findGraldewFile(
|
gradlewFile = findGradlewFile(
|
||||||
'nested/nested/proj/build.gradle',
|
'nested/nested/proj/build.gradle',
|
||||||
tempFs.tempDir
|
tempFs.tempDir
|
||||||
);
|
);
|
||||||
expect(gradlewFile).toEqual('nested/nested/proj/gradlew');
|
expect(gradlewFile).toEqual('nested/nested/proj/gradlew');
|
||||||
gradlewFile = findGraldewFile(
|
gradlewFile = findGradlewFile(
|
||||||
'nested/nested/proj/settings.gradle',
|
'nested/nested/proj/settings.gradle',
|
||||||
tempFs.tempDir
|
tempFs.tempDir
|
||||||
);
|
);
|
||||||
@ -80,7 +80,7 @@ describe('exec gradle', () => {
|
|||||||
'nested/nested/proj/src/test/java/test/bTest.java': ``,
|
'nested/nested/proj/src/test/java/test/bTest.java': ``,
|
||||||
});
|
});
|
||||||
expect(() =>
|
expect(() =>
|
||||||
findGraldewFile('proj/build.gradle', tempFs.tempDir)
|
findGradlewFile('proj/build.gradle', tempFs.tempDir)
|
||||||
).toThrow();
|
).toThrow();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -4,6 +4,14 @@ import { existsSync } from 'node:fs';
|
|||||||
import { dirname, join } from 'node:path';
|
import { dirname, join } from 'node:path';
|
||||||
import { LARGE_BUFFER } from 'nx/src/executors/run-commands/run-commands.impl';
|
import { LARGE_BUFFER } from 'nx/src/executors/run-commands/run-commands.impl';
|
||||||
|
|
||||||
|
export const fileSeparator = process.platform.startsWith('win')
|
||||||
|
? 'file:///'
|
||||||
|
: 'file://';
|
||||||
|
|
||||||
|
export const newLineSeparator = process.platform.startsWith('win')
|
||||||
|
? '\r\n'
|
||||||
|
: '\n';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For gradle command, it needs to be run from the directory of the gradle binary
|
* For gradle command, it needs to be run from the directory of the gradle binary
|
||||||
* @returns gradle binary file name
|
* @returns gradle binary file name
|
||||||
@ -54,13 +62,13 @@ export function execGradleAsync(
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* This function recursively finds the nearest gradlew file in the workspace
|
* This function recursively finds the nearest gradlew file in the workspace
|
||||||
* @param originalFileToSearch the original file to search for
|
* @param originalFileToSearch the original file to search for, relative to workspace root, file path not directory path
|
||||||
* @param wr workspace root
|
* @param wr workspace root
|
||||||
* @param currentSearchPath the path to start searching for gradlew file
|
* @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
|
* @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
|
* It will return relative path to workspace root of gradlew.bat file on windows and gradlew file on other platforms
|
||||||
*/
|
*/
|
||||||
export function findGraldewFile(
|
export function findGradlewFile(
|
||||||
originalFileToSearch: string,
|
originalFileToSearch: string,
|
||||||
wr: string = workspaceRoot,
|
wr: string = workspaceRoot,
|
||||||
currentSearchPath?: string
|
currentSearchPath?: string
|
||||||
@ -92,5 +100,5 @@ export function findGraldewFile(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return findGraldewFile(originalFileToSearch, wr, parent);
|
return findGradlewFile(originalFileToSearch, wr, parent);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,6 +8,8 @@ export const GRADLE_TEST_FILES = [
|
|||||||
'**/src/test/kotlin/**/*Test.kt',
|
'**/src/test/kotlin/**/*Test.kt',
|
||||||
'**/src/test/java/**/*Tests.java',
|
'**/src/test/java/**/*Tests.java',
|
||||||
'**/src/test/kotlin/**/*Tests.kt',
|
'**/src/test/kotlin/**/*Tests.kt',
|
||||||
|
'**/src/test/groovy/**/*Test.groovy',
|
||||||
|
'**/src/test/groovy/**/*Tests.groovy',
|
||||||
];
|
];
|
||||||
|
|
||||||
export const gradleConfigGlob = combineGlobPatterns(
|
export const gradleConfigGlob = combineGlobPatterns(
|
||||||
|
|||||||
@ -1 +1,4 @@
|
|||||||
export const nxVersion = require('../../package.json').version;
|
export const nxVersion = require('../../package.json').version;
|
||||||
|
|
||||||
|
export const gradleProjectGraphPluginName = 'dev.nx.gradle.project-graph';
|
||||||
|
export const gradleProjectGraphVersion = '0.0.2';
|
||||||
|
|||||||
876
pnpm-lock.yaml
generated
876
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
18
settings.gradle.kts
Normal file
18
settings.gradle.kts
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
/*
|
||||||
|
* This file was generated by the Gradle 'init' task.
|
||||||
|
*
|
||||||
|
* The settings file is used to specify which projects to include in your build.
|
||||||
|
* For more detailed information on multi-project builds, please refer to https://docs.gradle.org/8.5/userguide/building_swift_projects.html in the Gradle documentation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
pluginManagement {
|
||||||
|
repositories {
|
||||||
|
mavenLocal()
|
||||||
|
mavenCentral()
|
||||||
|
gradlePluginPortal()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rootProject.name = "nx"
|
||||||
|
includeBuild("./packages/gradle/project-graph")
|
||||||
Loading…
x
Reference in New Issue
Block a user