Skip to content

Commit

Permalink
feat(gradle): add gradle init generator
Browse files Browse the repository at this point in the history
  • Loading branch information
xiongemi committed Mar 18, 2024
1 parent 55f31cf commit 9c108d8
Show file tree
Hide file tree
Showing 14 changed files with 359 additions and 89 deletions.
123 changes: 66 additions & 57 deletions e2e/gradle/src/gradle.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,80 +8,89 @@ import {
runCommand,
uniq,
updateFile,
updateJson,
} from '@nx/e2e/utils';
import { execSync } from 'child_process';

describe('Gradle', () => {
let gradleProjectName = uniq('my-gradle-project');
describe.each([{ type: 'kotlin' }, { type: 'groovy' }])(
'$type',
({ type }: { type: 'kotlin' | 'groovy' }) => {
let gradleProjectName = uniq('my-gradle-project');
beforeAll(() => {
newProject();
createGradleProject(gradleProjectName, type);
});
afterAll(() => cleanupProject());

beforeAll(() => {
newProject();
createGradleProject(gradleProjectName);
});
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);

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 });
// app depends on list and utilities
expect(buildOutput).toContain('nx run list:build');
expect(buildOutput).toContain('nx run utilities:build');

const buildOutput = runCLI('build app', { verbose: true });
// app depends on list and utilities
expect(buildOutput).toContain('nx run list:build');
expect(buildOutput).toContain('nx run utilities:build');
checkFilesExist(
`app/build/libs/app.jar`,
`list/build/libs/list.jar`,
`utilities/build/libs/utilities.jar`
);
});

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 'gradleProject.groovy-application-conventions'
}
it('should track dependencies for new app', () => {
createFile(
'app2/build.gradle.kts',
`
plugins {
id("gradleProject.kotlin-application-conventions")
}
dependencies {
implementation(project(":app"))
dependencies {
implementation project(':app')
}`
);
} else {
createFile(
`app2/build.gradle.kts`,
`plugins {
id("gradleProject.kotlin-library-conventions")
}
dependencies {
implementation(project(":app"))
}`
);
}
updateFile(
`settings.gradle${type === 'kotlin' ? '.kts' : ''}`,
(content) => {
content += `\r\ninclude("app2")`;
return content;
}
);
const buildOutput = runCLI('build app2', { verbose: true });
// app2 depends on app
expect(buildOutput).toContain('nx run app:build');
});
}
`
);
updateFile(`settings.gradle.kts`, (content) => {
content += `\r\ninclude("app2")`;
return content;
});
const buildOutput = runCLI('build app2', { verbose: true });
// app2 depends on app
expect(buildOutput).toContain('nx run app:build');
});
);
});

function createGradleProject(projectName: string) {
function createGradleProject(
projectName: string,
type: 'kotlin' | 'groovy' = 'kotlin'
) {
e2eConsoleLogger(`Using java version: ${execSync('java --version')}`);
e2eConsoleLogger(`Using gradle version: ${execSync('gradle --version')}`);
e2eConsoleLogger(execSync(`gradle help --task :init`).toString());
e2eConsoleLogger(
runCommand(
`gradle init --type kotlin-application --dsl kotlin --project-name ${projectName} --package gradleProject --no-incubating --split-project`
`gradle init --type ${type}-application --dsl ${type} --project-name ${projectName} --package gradleProject --no-incubating --split-project`
)
);
updateJson('nx.json', (nxJson) => {
nxJson.plugins = ['@nx/gradle'];
return nxJson;
});
createFile(
'build.gradle.kts',
`allprojects {
apply {
plugin("project-report")
}
}`
);
runCLI(`add @nx/gradle`);
}
11 changes: 11 additions & 0 deletions packages/gradle/generators.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"name": "Nx Gradle",
"version": "0.1",
"generators": {
"init": {
"factory": "./src/generators/init/init#initGeneratorInternal",
"schema": "./src/generators/init/schema.json",
"description": "Initializes a Gradle project in the current workspace"
}
}
}
1 change: 1 addition & 0 deletions packages/gradle/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export * from './plugin';
export { initGenerator } from './src/generators/init/init';
8 changes: 8 additions & 0 deletions packages/gradle/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,14 @@
"url": "https://github.com/nrwl/nx/issues"
},
"homepage": "https://nx.dev",
"generators": "./generators.json",
"exports": {
".": "./index.js",
"./package.json": "./package.json",
"./migrations.json": "./migrations.json",
"./generators.json": "./generators.json",
"./plugin": "./plugin.js"
},
"nx-migrate": {
"migrations": "./migrations.json"
},
Expand Down
73 changes: 73 additions & 0 deletions packages/gradle/src/generators/init/init.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import { readNxJson, Tree, updateNxJson } from '@nx/devkit';
import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing';

import { initGenerator } from './init';

describe('@nx/gradle:init', () => {
let tree: Tree;

beforeEach(() => {
tree = createTreeWithEmptyWorkspace();
tree.write('settings.gradle', '');
});

it('should add the plugin', async () => {
await initGenerator(tree, {
skipFormat: true,
skipPackageJson: false,
});
const nxJson = readNxJson(tree);
expect(nxJson.plugins).toMatchInlineSnapshot(`
[
{
"options": {
"buildTargetName": "build",
"classesTargetName": "classes",
"testTargetName": "test",
},
"plugin": "@nx/gradle/plugin",
},
]
`);
});

it('should not overwrite existing plugins', async () => {
updateNxJson(tree, {
plugins: ['foo'],
});
await initGenerator(tree, {
skipFormat: true,
skipPackageJson: false,
});
const nxJson = readNxJson(tree);
expect(nxJson.plugins).toMatchInlineSnapshot(`
[
"foo",
{
"options": {
"buildTargetName": "build",
"classesTargetName": "classes",
"testTargetName": "test",
},
"plugin": "@nx/gradle/plugin",
},
]
`);
});

it('should not add plugin if already in array', async () => {
updateNxJson(tree, {
plugins: ['@nx/gradle/plugin'],
});
await initGenerator(tree, {
skipFormat: true,
skipPackageJson: false,
});
const nxJson = readNxJson(tree);
expect(nxJson.plugins).toMatchInlineSnapshot(`
[
"@nx/gradle/plugin",
]
`);
});
});
102 changes: 102 additions & 0 deletions packages/gradle/src/generators/init/init.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
import {
addDependenciesToPackageJson,
formatFiles,
GeneratorCallback,
logger,
readNxJson,
runTasksInSerial,
Tree,
updateNxJson,
} from '@nx/devkit';
import { updatePackageScripts } from '@nx/devkit/src/utils/update-package-scripts';
import { createNodes } from '../../plugin/nodes';
import { nxVersion } from '../../utils/versions';
import { InitGeneratorSchema } from './schema';
import { hasGradlePlugin } from '../../utils/has-gradle-plugin';

export async function initGenerator(tree: Tree, options: InitGeneratorSchema) {
const tasks: GeneratorCallback[] = [];

if (!options.skipPackageJson && tree.exists('package.json')) {
tasks.push(
addDependenciesToPackageJson(
tree,
{},
{
'@nx/gradle': nxVersion,
},
undefined,
options.keepExistingVersions
)
);
}

addPlugin(tree);
addProjectReportToBuildGradle(tree);

if (options.updatePackageScripts && tree.exists('package.json')) {
await updatePackageScripts(tree, createNodes);
}

if (!options.skipFormat) {
await formatFiles(tree);
}

return runTasksInSerial(...tasks);
}

function addPlugin(tree: Tree) {
const nxJson = readNxJson(tree);

if (!hasGradlePlugin(tree)) {
nxJson.plugins ??= [];
nxJson.plugins.push({
plugin: '@nx/gradle/plugin',
options: {
testTargetName: 'test',
classesTargetName: 'classes',
buildTargetName: 'build',
},
});
updateNxJson(tree, nxJson);
}
}

/**
* This function adds the project-report plugin to the build.gradle or build.gradle.kts file
*/
function addProjectReportToBuildGradle(tree: Tree) {
let buildGradleFile: string;
if (tree.exists('settings.gradle.kts')) {
buildGradleFile = 'build.gradle.kts';
} else if (tree.exists('settings.gradle')) {
buildGradleFile = 'build.gradle';
} else {
throw new Error(
'Could not find settings.gradle or settings.gradle.kts file in your gradle workspace.'
);
}
let buildGradleContent = '';
if (tree.exists(buildGradleFile)) {
buildGradleContent = tree.read(buildGradleFile).toString();
}
if (buildGradleContent.includes('allprojects')) {
if (!buildGradleContent.includes('"project-report')) {
logger.warn(`Please add the project-report plugin to your ${buildGradleFile}:
allprojects {
apply {
plugin("project-report")
}
}`);
}
} else {
buildGradleContent += `\n\rallprojects {
apply {
plugin("project-report")
}
}`;
tree.write(buildGradleFile, buildGradleContent);
}
}

export default initGenerator;
6 changes: 6 additions & 0 deletions packages/gradle/src/generators/init/schema.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export interface InitGeneratorSchema {
skipFormat?: boolean;
skipPackageJson?: boolean;
keepExistingVersions?: boolean;
updatePackageScripts?: boolean;
}
34 changes: 34 additions & 0 deletions packages/gradle/src/generators/init/schema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
{
"$schema": "https://json-schema.org/schema",
"$id": "NxGradleInitSchema",
"title": "Gradle Init Generator",
"description": "Initializes a Gradle project in the current workspace.",
"type": "object",
"properties": {
"skipFormat": {
"description": "Skip formatting files.",
"type": "boolean",
"default": false,
"x-priority": "internal"
},
"skipPackageJson": {
"type": "boolean",
"default": false,
"description": "Do not add dependencies to `package.json`.",
"x-priority": "internal"
},
"keepExistingVersions": {
"type": "boolean",
"x-priority": "internal",
"description": "Keep existing dependencies versions",
"default": false
},
"updatePackageScripts": {
"type": "boolean",
"x-priority": "internal",
"description": "Update `package.json` scripts with inferred targets",
"default": false
}
},
"required": []
}
Loading

0 comments on commit 9c108d8

Please sign in to comment.