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

소스 정보

저장소
apache/grails-core
최근 소스 활동
2026년 10월 7일 18:32
감지된 SKILL.md 언어
영어
스타
2,937
포크
977

설치 방법

기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.

소스 파일 검토

설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.

SKILL.md 표시 중

SKILL.md
소스 지침 · 읽기 전용 미리보기
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.
GitHub에서 보기
이 SKILL.md는 매우 커서 SkillsMP가 여기에는 첫 섹션만 미리 보여줍니다. GitHub에서 보기