Skip to main content

gradle-developer

Expert guide for Gradle 9 builds in apache/grails-core on the 8.0.x line - multi-project topology, convention plugins, BOM platforms, dependency rules, task configuration hygiene, and repo-specific patterns that override generic Gradle docs

Datos de origen

Repositorio
apache/grails-core
Última actividad en el origen
7 de octubre de 2026 a las 18:32
Idioma detectado de SKILL.md
inglés
Estrellas
2937
Forks
977

Opciones de instalación

De forma predeterminada está seleccionado el prompt que primero revisa el origen. Puedes cambiar a un comando directo o descargar una copia local.

Revisa los archivos de origen

Lee SKILL.md y los archivos complementarios que muestra SkillsMP antes de decidir si quieres instalarlo.

Mostrando SKILL.md

SKILL.md
Instrucciones de origen · Vista previa de solo lectura
name
gradle-developer
description
Expert guide for Gradle 9 builds in apache/grails-core on the 8.0.x line - multi-project topology, convention plugins, BOM platforms, dependency rules, task configuration hygiene, and repo-specific patterns that override generic Gradle docs
license
Apache-2.0
<!-- SPDX-License-Identifier: Apache-2.0 Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements; and to You under the Apache License, Version 2.0. --> ## What I Do - Write and change Gradle build scripts the way **this repository** already does them on `8.0.x` (Gradle **9.8.x**). - Keep agents off generic Gradle "best practice" when it conflicts with established monorepo patterns. - Cover composite builds (`build-logic`, `grails-gradle`, `grails-forge`, `end-to-end`), convention plugins, BOM/`platform()` dependency management, test wiring, publishing hooks, and Gradle 9 task-configuration traps learned from recent PRs. - Make Gradle changes boring, copy-paste consistent, and correct on the first try. ## When to Use Me **MANDATORY** before any of the following: - Editing `build.gradle`, `settings.gradle`, `gradle.properties`, `dependencies.gradle`, or anything under `gradle/`, `build-logic/`, `grails-gradle/` - Adding or renaming a module / subproject - Bumping a dependency version or the Gradle wrapper - Changing test, publish, SBOM, code-style, or JaCoCo Gradle wiring - Touching Grails Gradle plugins used by apps (`org.apache.grails.gradle.*`) - Diagnosing configuration-cache, resolution, `afterEvaluate`, or task-graph failures Also load when a change *looks* like application code but requires build script updates (new module, new published artifact, CLI companion jar, functional test app). Related skills (do not substitute this one): | Need | Skill | |------|-------| | CodeNarc / Checkstyle / PMD / SpotBugs reports | `violation-fixer` | | Failing tests / aggregate reports | `test-fixer` | | Merging an external plugin repo into the monorepo | `mono-repo-integration` | | App-facing Grails 8 upgrade guidance | `grails-8-upgrade` | --- ## Prime Directive: This Repo Wins 1. **Match neighboring modules.** Before inventing structure, open 2-3 similar `build.gradle` files and copy their plugin block, dependency style, and `apply { from ... }` scripts. 2. **Prefer existing convention plugins** over inline configuration. If `CompilePlugin` already sets encoding, release, jars, and reproducibility, do not re-declare those in the module script. 3. **Gradle docs are secondary.** Official Gradle 9 docs are useful for APIs and deprecations, but this monorepo intentionally diverges (no Spring DM plugin, heavy `projectDir` remapping, presence-based `-P` flags, custom BOM validator). When docs and this repo disagree, **follow this repo** unless you are deliberately fixing a known issue with a tracked reason. 4. **Do not use** `io.spring.dependency-management` / Spring Dependency Management plugin in core modules or applications. The intentional regression fixture at `grails-test-examples/spring-dependency-management` is the only exception. Grails 8 otherwise uses native `platform()` / `enforcedPlatform()` plus `org.apache.grails.gradle.bom-property-overrides` (see PR #15467). 5. **Scope Gradle invocations** to the touched subproject (`:module:test`, not root `test`) unless the change is cross-cutting. ### Change workflow 1. Inspect 2-3 sibling modules and the relevant convention plugin or shared script. 2. Confirm the Gradle project path in `settings.gradle`, including any `projectDir` mapping. 3. Edit the smallest appropriate build file or convention plugin. 4. Run scoped compile, test, and `validateDependencyVersions` tasks for the changed project. 5. For `grails-gradle` changes, run the relevant plugin TestKit tests from `grails-gradle/` with its wrapper. --- ## Topology (Know Where You Are) This git repo is **several independent Gradle builds**, not one flat multiproject: | Build | Path | Role | How to run | |-------|------|------|------------| | **Root framework** | repo root | 60+ published modules, BOMs, test-examples, profiles, docs | `./gradlew …` from root | | **build-logic** | `build-logic/` | Shared **convention plugins** via `includeBuild` | `cd build-logic && ./gradlew …` (or root pluginManagement includeBuild) | | **grails-gradle** | `grails-gradle/` | **Published** Grails Gradle plugins for apps | `cd grails-gradle && ./gradlew …` | | **grails-forge** | `grails-forge/` | App generator (own wrapper, own deps) | `cd grails-forge && ./gradlew …` | | **end-to-end** | `end-to-end/` | Tests against **published** artifacts in `build/local-maven` | Full 3-step flow below (see `end-to-end/README.md`) | | **gradle-bootstrap** | `gradle-bootstrap/` | Regenerates shared wrappers from `.sdkmanrc` | `gradle -p gradle-bootstrap` (see wrapper section) | **end-to-end is not a composite consumer of the root build.** It resolves real published coordinates from **`<repo>/build/local-maven`** (the TestCaseMavenRepo), **not** `~/.m2` and **not** via `publishAllToMavenLocal`. Do not add `includeBuild('..')` substitution - that defeats validating consumer metadata, CLI companions, and POM/BOM shape. Full local run (three steps, in order): ```bash # 1) Publish grails-gradle + root into build/local-maven (both required) (cd grails-gradle && ./gradlew publishAllPublicationsToTestCaseMavenRepoRepository) ./gradlew publishAllPublicationsToTestCaseMavenRepoRepository # 2) Build the standalone Grails 7 fixture jar (JDK 17 / Gradle 8.x via its .sdkmanrc) cd end-to-end/legacy-g7-command-plugin sdk env ./gradlew jar cd ../.. # 3) Run the suite on the root JDK 21 environment sdk env # from repository root (.sdkmanrc) cd end-to-end ./gradlew check ``` Leave `legacy-g7-command-plugin`'s wrapper on its pinned Grails 7 Gradle version when bumping the main line. Root `settings.gradle` wires: ```groovy pluginManagement { includeBuild('./grails-gradle') { name = 'grails-gradle' } includeBuild('./build-logic') { name = 'build-logic-root' } // ... } ``` `build-logic` exists because composite builds do **not** share `buildSrc` plugins. Internal conventions live there so root, grails-gradle, and forge can consume them. ### Project path != directory name Root settings heavily remaps `projectDir` (100+ entries). Examples: | Gradle path | Directory | |-------------|-----------| | `:grails-bom` | `grails-bom/default` | | `:grails-base-bom` | `grails-bom/base` | | `:grails-hibernate7-bom` | `grails-bom/hibernate7` | | `:grails-controllers` | `grails-controllers` (often 1:1) | | `:grails-data-hibernate7-core` | `grails-data-hibernate7/core` | | `:grails-test-examples-app1` | `grails-test-examples/app1` | Always use the **Gradle project path** in task names (`./gradlew :grails-data-hibernate7-core:test`). Confirm with `settings.gradle` `include` + `projectDir` when unsure. Do not invent paths from folder names alone. ### Micronaut "island" `grails-micronaut*`, micronaut BOMs, and related test-examples are gated in `settings.gradle`: - Auto-**excluded** on JDK &lt; 25 (Micronaut 5 targets JVM 25 bytecode) - Auto-**included** on JDK 25+ - `-PskipMicronautProjects` forces exclude (used by groovy-joint CI) - `-PincludeMicronautProjects` forces include on older JDKs (still may not compile) Presence-based flags (property **present**, value optional) match `skipFunctionalTests` / `skipCodeStyle` style elsewhere. --- ## Gradle Version Sync (Hard Rule) Current line: **Gradle 9.8.0** (`distributionUrl` + `gradleToolingApiVersion=9.8.0`). Upstream may already ship a newer 9.8.x patch - this repo rides close to latest **only after** a deliberate multi-location bump PR. Do not "helpfully" jump one wrapper ahead of the rest. **Two Groovy stacks:** Gradle itself embeds **Groovy 4** for build logic. Application/runtime code on 8.0.x is **Groovy 5**. That is why `dependencies.gradle` keeps separate maps: - `gradleBomDependencyVersions` / `gradle-groovy.version` / `gradle-spock.version` → build tooling (Groovy 4 / Spock groovy-4) - `bomDependencyVersions` / `groovy.version` / `spock.version` → apps and framework modules (Groovy 5 / Spock groovy-5.0) Never unify those casually. ### Preferred bump workflow 1. Set the new Gradle version in **`.sdkmanrc`** (`gradle=…`). 2. Run the bootstrap project (uses a system `gradle` to regenerate shared wrappers from `.sdkmanrc`): ```bash gradle -p gradle-bootstrap ``` Bootstrap generates the wrapper under `gradle-bootstrap/`, **copies** it to **grails-forge**, **grails-gradle**, and **end-to-end**, then **moves** the generated wrapper into the **repository root**. It also runs `legacyG7Wrapper` so **`end-to-end/legacy-g7-command-plugin` stays on its pinned Grails 7 Gradle version** (currently 8.x - do **not** force it to 9). Root is therefore bootstrap-covered; do not re-list it as a manual step. 3. Manually refresh the locations bootstrap does **not** cover. For each tree, keep the **full** wrapper set in sync (`gradle-wrapper.properties`, `gradle-wrapper.jar`, `gradlew`, `gradlew.bat`) - not properties alone: - `build-logic/` - run its wrapper task or copy the complete set from root after bootstrap - `grails-profiles/base/skeleton/` and `grails-profiles/profile/skeleton/` - `grails-shell-cli/src/test/resources/gradle-sample/` (and `bin/test` copy if present) - Forge **generated-app** wrapper assets (all of these - properties alone is not enough): - `grails-forge/grails-forge-core/.../gradleWrapperProperties.rocker.raw` (properties template) - `grails-forge/grails-forge-core/src/main/resources/gradle/gradlew` - `grails-forge/grails-forge-core/src/main/resources/gradle/gradlew.bat` - `grails-forge/grails-forge-core/src/main/resources/gradle/wrapper/gradle-wrapper.jar` - `gradle.properties` → `gradleToolingApiVersion` (must match the new Gradle version) 4. Verify every **main-line** tree matches on properties **and** scripts/jars. The only intentional holdout is `end-to-end/legacy-g7-command-plugin` (Gradle 8.x). Also keep `gradlew.bat` LF line endings on this line (PR #15709). Comment at top of root `gradle-wrapper.properties` remains a human checklist. --- ## Root `gradle.properties` Flags (Do Not "Fix" Blindly) | Property | Value / note | |----------|----------------| | `org.gradle.caching` | `true` | | `org.gradle.parallel` | `true` | | `org.gradle.daemon` | `true` | | `org.gradle.configuration-cache` | **`true`** in every build (root, `build-logic`, `grails-gradle`, `grails-forge`) - build logic must stay compatible, see [Configuration Cache](#configuration-cache) | | `org.gradle.configureondemand` | **commented off** - Gradle issue #9489 | | `org.gradle.jvmargs` | `-Xmx3G` (daemon only; groovydoc and the guide run in their own JVMs) | | `javaVersion` | `21` (CompilePlugin reads this for `--release`) | | `projectVersion` | framework version | | `slf4jPreventExclusion` | `true` - Grails Gradle plugin POM behavior | CI vs local behavior is branched on `System.getenv('CI')` and `SOURCE_DATE_EPOCH` (reproducible builds disable remote cache). `groovydocMaxHeapSize` and `guideMaxHeapSize` are **not** keys in `gradle.properties` - do not add them. Each documentation JVM carries its own default (1g per groovydoc task, raised to 3g/2g by the two aggregates; 1500m for the guide), and these exist only as `-P` overrides that beat the build script when a documentation run will not fit. --- ## Standard Published Library Module Canonical pattern (see `grails-core/build.gradle`, `grails-controllers/build.gradle`, `grails-services/build.gradle`): ```groovy /* * Licensed to the Apache Software Foundation (ASF) under one * ... Apache header ... */ plugins { id 'groovy' id 'java-library' id 'project-report' // optional but common id 'org.apache.grails.buildsrc.properties' id 'org.apache.grails.buildsrc.dependency-validator' id 'org.apache.grails.buildsrc.compile' id 'org.apache.grails.buildsrc.publish' id 'org.apache.grails.buildsrc.sbom' id 'org.apache.grails.buildsrc.vulnerability-scan' // when appropriate id 'org.apache.grails.gradle.grails-code-style' id 'org.apache.grails.gradle.grails-jacoco' } version = projectVersion group = 'org.apache.grails' // or org.apache.grails.web / .data / etc. - match siblings dependencies { implementation platform(project(':grails-bom')) // or :grails-hibernate7-bom, etc. api project(':grails-core') api 'org.apache.groovy:groovy' // versions come from the platform - do NOT hardcode versions here compileOnly 'jakarta.servlet:jakarta.servlet-api' testImplementation 'org.spockframework:spock-core' testImplementation 'org.apache.groovy:groovy-test-junit5' testImplementation 'org.junit.jupiter:junit-jupiter-api' testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine' // junit-platform-launcher is added by gradle/test-config.gradle } apply { from rootProject.layout.projectDirectory.file('gradle/docs-config.gradle') from rootProject.layout.projectDirectory.file('gradle/test-config.gradle') } ``` ### Rules for module scripts - **Apache license header** on every new `.gradle` / `.gradle.kts` file.
Ver en GitHub
Este SKILL.md es muy grande, por eso SkillsMP muestra aqui solo la primera seccion. Ver en GitHub