Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 75 additions & 1 deletion .github/workflows/gradle.yml
Original file line number Diff line number Diff line change
Expand Up @@ -125,12 +125,16 @@ jobs:
- name: "🔍 Setup TestLens"
uses: testlens-app/setup-testlens@v1
- name: "🔨 Build project"
# Micronaut 5 platform GA targets JVM 25 bytecode, so on the Java 21 jobs we
# skip the Grails-Micronaut "island" (grails-micronaut, grails-micronaut-bom,
# the micronaut-tied test-examples). Java 25 jobs build the full graph.
run: >
./gradlew build :grails-shell-cli:installDist groovydoc
--continue
--stacktrace
-PonlyCoreTests
-PskipCodeStyle
${{ matrix.java == 21 && '-PskipMicronautProjects' || '' }}
buildRerunTasks:
if: ${{ !contains(github.event.head_commit.message, '[skip tests]') }}
name: 'Build Grails-Core Rerunning all Tasks'
Expand Down Expand Up @@ -158,13 +162,16 @@ jobs:
- name: "🔍 Setup TestLens"
uses: testlens-app/setup-testlens@v1
- name: "🔨 Build project"
# This job only runs on Java 21; skip the Micronaut island because the
# Micronaut 5 platform GA targets JVM 25 bytecode (see comment on `build`).
run: >
./gradlew build :grails-shell-cli:installDist groovydoc
--continue
--rerun-tasks
--stacktrace
-PonlyCoreTests
-PskipCodeStyle
-PskipMicronautProjects
buildForge:
name: "Build Grails Forge (Java ${{ matrix.java }}, indy=${{ matrix.indy }})"
strategy:
Expand Down Expand Up @@ -195,23 +202,30 @@ jobs:
- name: "🔨 Build project without tests"
if: ${{ contains(github.event.head_commit.message, '[skip tests]') }}
working-directory: 'grails-forge'
# The Forge composite build includes the root grails-core via
# `includeBuild('..')` in grails-forge/settings.gradle, so on Java 21
# we must propagate -PskipMicronautProjects to keep the included
# grails-core build from trying to compile the JVM-25 Micronaut island.
run: >
./gradlew build
--continue
--stacktrace
-PgrailsIndy=${{ matrix.indy }}
-PskipCodeStyle
-PskipTests
${{ matrix.java == 21 && '-PskipMicronautProjects' || '' }}
- name: "🔨 Build project with tests"
if: ${{ !contains(github.event.head_commit.message, '[skip tests]') }}
working-directory: 'grails-forge'
# See comment above on '-PskipMicronautProjects'.
run: >
./gradlew build
--continue
--rerun-tasks
--stacktrace
-PgrailsIndy=${{ matrix.indy }}
-PskipCodeStyle
${{ matrix.java == 21 && '-PskipMicronautProjects' || '' }}
- name: "✅ Verify combined CLI"
run: |
cd grails-forge
Expand Down Expand Up @@ -257,6 +271,8 @@ jobs:
- name: "🔍 Setup TestLens"
uses: testlens-app/setup-testlens@v1
- name: "🏃 Run Functional Tests"
# Micronaut 5 platform GA targets JVM 25 bytecode, so skip the Micronaut
# island on Java 21 jobs (see comment on `build`).
run: >
./gradlew bootJar check
--continue
Expand All @@ -268,6 +284,7 @@ jobs:
-PskipCodeStyle
-PskipHibernate5Tests
-PskipMongodbTests
${{ matrix.java == 21 && '-PskipMicronautProjects' || '' }}
mongodbFunctional:
if: ${{ !contains(github.event.head_commit.message, '[skip tests]') }}
name: "Mongodb Functional Tests (Java ${{ matrix.java }}, MongoDB ${{ matrix.mongodb-version }}, indy=${{ matrix.indy }})"
Expand Down Expand Up @@ -299,6 +316,8 @@ jobs:
- name: "🏃 Run Functional Tests"
env:
GITHUB_MAVEN_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
# Micronaut 5 platform GA targets JVM 25 bytecode, so skip the Micronaut
# island on Java 21 jobs (see comment on `build`).
run: >
./gradlew bootJar check
--continue
Expand All @@ -308,6 +327,7 @@ jobs:
-PonlyMongodbTests
-PmongodbContainerVersion=${{ matrix.mongodb-version }}
-PskipCodeStyle
${{ matrix.java == 21 && '-PskipMicronautProjects' || '' }}
hibernate5Functional:
if: ${{ !contains(github.event.head_commit.message, '[skip tests]') }}
name: "Hibernate5 Functional Tests (Java ${{ matrix.java }}, indy=${{ matrix.indy }})"
Expand Down Expand Up @@ -337,6 +357,8 @@ jobs:
- name: "🏃 Run Functional Tests"
env:
GITHUB_MAVEN_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
# Micronaut 5 platform GA targets JVM 25 bytecode, so skip the Micronaut
# island on Java 21 jobs (see comment on `build`).
run: >
./gradlew bootJar check
--continue
Expand All @@ -345,6 +367,7 @@ jobs:
-PgrailsIndy=${{ matrix.indy }}
-PonlyHibernate5Tests
-PskipCodeStyle
${{ matrix.java == 21 && '-PskipMicronautProjects' || '' }}
publishGradle:
if: github.repository_owner == 'apache' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch')
needs: [ buildGradle ]
Expand Down Expand Up @@ -416,6 +439,10 @@ jobs:
- name: "🔍 Setup TestLens"
uses: testlens-app/setup-testlens@v1
- name: "📤 Publish Grails-Core Snapshot Artifacts"
# -PskipMicronautProjects keeps this Java 21 publish from trying to compile
# the Micronaut 5 / JVM 25 island. The Micronaut artifacts (grails-micronaut,
# grails-micronaut-bom) are published by the parallel publishMicronaut job
# below, which runs on JDK 25.
uses: nick-fields/retry@ce71cc2ab81d554ebbe88c79ab5975992d79ba08 #v3.0.2
env:
GRAILS_PUBLISH_RELEASE: 'false'
Expand All @@ -426,7 +453,7 @@ jobs:
timeout_seconds: 1200 # normal range 14min if build is not cached (no tests running)
max_attempts: 3 # Attempts to address: Could not write to resource 'https://repository.apache.org/content/repositories/snapshots/...' Read timed out
retry_wait_seconds: 180
command: ./gradlew publish aggregateChecksums aggregatePublishedArtifacts --no-build-cache --rerun-tasks
command: ./gradlew publish aggregateChecksums aggregatePublishedArtifacts --no-build-cache --rerun-tasks -PskipMicronautProjects
- name: "📤 Upload grails-core checksums"
uses: actions/upload-artifact@v7.0.1
with:
Expand All @@ -449,6 +476,53 @@ jobs:
with:
name: apache-grails-wrapper-SNAPSHOT-bin
path: build/tmp/wrapper
publishMicronaut:
# Micronaut 5.0.0 publishes JARs targeting JVM 25 bytecode, so the Micronaut
# "island" (grails-micronaut, grails-micronaut-bom) must publish from a JDK 25
# runner. The sibling `publish` job runs on JDK 21 with
# -PskipMicronautProjects to publish everything else; this job publishes the
# two Micronaut artifacts. The two test-example projects in the island are
# not published.
needs: [ publishGradle, build, functional, hibernate5Functional, mongodbFunctional ]
if: >-
${{ always() &&
github.repository_owner == 'apache' &&
(github.event_name == 'push' || github.event_name == 'workflow_dispatch') &&
needs.publishGradle.result == 'success' &&
(needs.build.result == 'success' || needs.build.result == 'skipped') &&
(needs.functional.result == 'success' || needs.functional.result == 'skipped') &&
(needs.hibernate5Functional.result == 'success' || needs.hibernate5Functional.result == 'skipped') &&
(needs.mongodbFunctional.result == 'success' || needs.mongodbFunctional.result == 'skipped')
}}
runs-on: ubuntu-24.04
steps:
- name: "Output Agent IP" # in the event RAO blocks this agent, this can be used to debug it
run: curl -s https://api.ipify.org
- name: "📥 Checkout repository"
uses: actions/checkout@v6
- name: "☕️ Setup JDK"
uses: actions/setup-java@v4
with:
distribution: liberica
java-version: 25
- name: "🐘 Setup Gradle"
uses: gradle/actions/setup-gradle@4d9f0ba0025fe599b4ebab900eb7f3a1d93ef4c2 # v5.0.0
with:
develocity-access-key: ${{ secrets.DEVELOCITY_ACCESS_KEY }}
- name: "🔍 Setup TestLens"
uses: testlens-app/setup-testlens@v1
- name: "📤 Publish Grails-Micronaut Snapshot Artifacts"
uses: nick-fields/retry@ce71cc2ab81d554ebbe88c79ab5975992d79ba08 #v3.0.2
env:
GRAILS_PUBLISH_RELEASE: 'false'
MAVEN_PUBLISH_URL: ${{ secrets.GRAILS_NEXUS_PUBLISH_SNAPSHOT_URL }}
MAVEN_PUBLISH_USERNAME: ${{ secrets.NEXUS_USER }}
MAVEN_PUBLISH_PASSWORD: ${{ secrets.NEXUS_PW }}
with:
timeout_seconds: 1200
max_attempts: 3
retry_wait_seconds: 180
command: ./gradlew :grails-micronaut:publish :grails-micronaut-bom:publish --no-build-cache --rerun-tasks
publishForge:
if: github.repository_owner == 'apache' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch')
needs: [ buildForge, publishGradle, publish ]
Expand Down
6 changes: 5 additions & 1 deletion .github/workflows/release-publish-docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,11 @@ jobs:
with:
develocity-access-key: ${{ secrets.DEVELOCITY_ACCESS_KEY }}
- name: "📖 Generate Documentation"
run: ./gradlew grails-doc:build -PgithubBranch=${TARGET_BRANCH}
# The Grails-Micronaut "island" requires JDK 25 (Micronaut 5 bytecode);
# this docs build runs on the JDK 21 reproducibility pin, so prune the
# island from the project graph to avoid Gradle resolving its JVM 25
# variants. The docs themselves have no code dependency on Micronaut.
run: ./gradlew grails-doc:build -PgithubBranch=${TARGET_BRANCH} -PskipMicronautProjects
- name: "🚀 Publish to GitHub Pages"
uses: apache/grails-github-actions/deploy-github-pages@asf
env:
Expand Down
62 changes: 56 additions & 6 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ env:
GRAILS_PUBLISH_RELEASE: 'true'
JAVA_DISTRIBUTION: liberica
JAVA_VERSION: 21.0.7 # this must be a specific version for reproducible builds, keep it synced with .sdkmanrc and verification container
JAVA_VERSION_MICRONAUT: 25.0.3 # the Grails-Micronaut "island" (grails-micronaut, grails-micronaut-bom) is built against Micronaut 5 which targets JVM 25 bytecode. Keep this synced with the secondary JDK installed in etc/bin/Dockerfile and the JDK_25_HOME branch in etc/bin/verify-reproducible.sh.
PROJECT_DESC: >
Grails is a powerful Groovy-based web application framework for the JVM,
built on top of Spring Boot, and supported by a rich ecosystem of plugins
Expand Down Expand Up @@ -92,12 +93,19 @@ jobs:
- name: "🔍 Validate dependency versions"
run: ./gradlew validateDependencyVersions
- name: "🧩 Run grails-core assemble"
run: ./gradlew assemble -PgithubBranch=${TARGET_BRANCH}
# Pre-publish smoke check on JDK 21. The Micronaut island is built and
# smoke-checked implicitly by the JDK 25 publishToSonatype step below;
# no separate JDK-25 assemble step is needed here.
run: ./gradlew assemble -PgithubBranch=${TARGET_BRANCH} -PskipMicronautProjects
- name: "🧩 Run grails-forge assemble"
working-directory: grails-forge
run: ./gradlew assemble -PgithubBranch=${TARGET_BRANCH}
run: ./gradlew assemble -PgithubBranch=${TARGET_BRANCH} -PskipMicronautProjects
- name: "📦 Generate grails-core docs (to assert that is works, before proceeding)"
run: ./gradlew grails-doc:build -PgithubBranch=${TARGET_BRANCH}
# grails-doc has no code dependency on the Micronaut island, but the
# configuration phase still evaluates all sibling projects in the
# multi-project build. -PskipMicronautProjects prunes the island from
# the project graph so Gradle does not try to resolve its JDK 25 deps.
run: ./gradlew grails-doc:build -PgithubBranch=${TARGET_BRANCH} -PskipMicronautProjects
- name: "🔏 Sign grails-wrapper ZIP"
run: >
gpg
Expand Down Expand Up @@ -173,6 +181,10 @@ jobs:
aggregateChecksums
aggregatePublishedArtifacts
- name: "📤 Publish Grails Core to Staging Repository"
# -PskipMicronautProjects excludes the Grails-Micronaut "island" from
# this JDK 21 publish. The two island artifacts (grails-micronaut,
# grails-micronaut-bom) are signed and staged by the
# `Publish Grails-Micronaut` step below, which switches to JDK 25.
env:
NEXUS_PUBLISH_USERNAME: ${{ secrets.NEXUS_STAGE_DEPLOYER_USER }}
NEXUS_PUBLISH_PASSWORD: ${{ secrets.NEXUS_STAGE_DEPLOYER_PW }}
Expand All @@ -187,7 +199,11 @@ jobs:
publishToSonatype
aggregateChecksums
aggregatePublishedArtifacts
-PskipMicronautProjects
- name: "📤 Publish Grails Forge to Staging Repository"
# The Forge composite build does includeBuild('..') so it pulls in the
# root grails-core build. Without -PskipMicronautProjects the Micronaut
# island would be evaluated on JDK 21 and fail to resolve.
env:
NEXUS_PUBLISH_USERNAME: ${{ secrets.NEXUS_STAGE_DEPLOYER_USER }}
NEXUS_PUBLISH_PASSWORD: ${{ secrets.NEXUS_STAGE_DEPLOYER_PW }}
Expand All @@ -203,6 +219,40 @@ jobs:
publishToSonatype
aggregateChecksums
aggregatePublishedArtifacts
-PskipMicronautProjects
- name: "☕️ Switch to JDK 25 for Micronaut publish"
# Micronaut 5 platform GA targets JVM 25 bytecode, so the island
# artifacts (grails-micronaut, grails-micronaut-bom) must be built and
# staged from a JDK 25 runner. This is a NEW reproducibility pin -
# keep $JAVA_VERSION_MICRONAUT synced with the secondary JDK in
# etc/bin/Dockerfile so verifiers can reproduce the resulting JARs.
uses: actions/setup-java@v4
with:
distribution: liberica
java-version: ${{ env.JAVA_VERSION_MICRONAUT }}
- name: "📤 Publish Grails-Micronaut to Staging Repository"
env:
NEXUS_PUBLISH_USERNAME: ${{ secrets.NEXUS_STAGE_DEPLOYER_USER }}
NEXUS_PUBLISH_PASSWORD: ${{ secrets.NEXUS_STAGE_DEPLOYER_PW }}
NEXUS_PUBLISH_URL: ${{ vars.STAGING_URL }}
NEXUS_PUBLISH_STAGING_PROFILE_ID: ${{ secrets.STAGING_PROFILE_ID }}
NEXUS_PUBLISH_DESCRIPTION: '${{ env.REPO_NAME }}:${{ env.VERSION }}'
SIGNING_KEY: ${{ secrets.GPG_KEY_ID }}
run: >
./gradlew
-x initializeSonatypeStagingRepository
findSonatypeStagingRepository
:grails-micronaut:publishToSonatype
:grails-micronaut-bom:publishToSonatype
- name: "☕️ Restore JDK 21 for staging-repo close"
# Symmetry with the rest of the release flow - the close step and the
# downstream checksum/artifact-list combination steps all expect the
# default JDK 21 toolchain. Also keeps any future steps that touch the
# repository's own (non-Micronaut) Gradle config on the documented JDK.
uses: actions/setup-java@v4
with:
distribution: liberica
java-version: ${{ env.JAVA_VERSION }}
- name: "✅ Close Staging Repository"
env:
NEXUS_PUBLISH_USERNAME: ${{ secrets.NEXUS_STAGE_DEPLOYER_USER }}
Expand Down Expand Up @@ -610,7 +660,7 @@ jobs:
with:
develocity-access-key: ${{ secrets.DEVELOCITY_ACCESS_KEY }}
- name: "📖 Generate Documentation"
run: ./gradlew grails-doc:build -PgithubBranch=${TARGET_BRANCH}
run: ./gradlew grails-doc:build -PgithubBranch=${TARGET_BRANCH} -PskipMicronautProjects
- name: "🚀 Publish to GitHub Pages"
uses: apache/grails-github-actions/deploy-github-pages@asf
env:
Expand Down Expand Up @@ -650,14 +700,14 @@ jobs:
- name: "🚀 Grails SDK Minor Release"
if: contains(env.VERSION, 'M') || contains(env.VERSION, 'RC')
working-directory: grails-forge
run: ./gradlew sdkMinorRelease
run: ./gradlew sdkMinorRelease -PskipMicronautProjects
env:
GVM_SDKVENDOR_KEY: ${{ secrets.GVM_SDKVENDOR_KEY }}
GVM_SDKVENDOR_TOKEN: ${{ secrets.GVM_SDKVENDOR_TOKEN }}
- name: "🚀 Grails SDK Major Release"
if: startsWith(env.VERSION, '7.') && !contains(env.VERSION, 'M') && !contains(env.VERSION, 'RC')
working-directory: grails-forge
run: ./gradlew sdkMajorRelease
run: ./gradlew sdkMajorRelease -PskipMicronautProjects
env:
GVM_SDKVENDOR_KEY: ${{ secrets.GVM_SDKVENDOR_KEY }}
GVM_SDKVENDOR_TOKEN: ${{ secrets.GVM_SDKVENDOR_TOKEN }}
Expand Down
8 changes: 7 additions & 1 deletion .sdkmanrc
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
# Keep java version synced with .github/workflows/release.yml and etc/bin/Dockerfile
# Keep java version synced with .github/workflows/release.yml ($JAVA_VERSION) and etc/bin/Dockerfile (primary JDK).
# This is the default JDK for all of grails-core EXCEPT the Grails-Micronaut "island"
# (grails-micronaut, grails-micronaut-bom), which is built against Micronaut 5 / JVM 25
# bytecode. The release workflow installs a secondary Liberica JDK pinned via
# $JAVA_VERSION_MICRONAUT in release.yml; for local verification, install that JDK 25
# alongside this one (sdk install java <version>-librca) and follow the dual-JDK
# instructions in RELEASE.md "Manual Verification: Reproducible Jar Files".
java=21.0.7-librca
# Keep gradle version synced with gradle.properties (gradleToolingApiVersion).
# Update the gradle-bootstrap project to propagate the version to all gradle-wrapper.properties files.
Expand Down
Loading
Loading