Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
15 commits
Select commit Hold shift + click to select a range
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
70 changes: 70 additions & 0 deletions .github/workflows/gradle.yml
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,11 @@ jobs:
- name: "🔍 Setup TestLens"
uses: testlens-app/setup-testlens@d96a555133c275a00949d2cc77b70fe9a4242ebf # v1.9.2
- name: "🔨 Build project"
# The Grails-Micronaut "island" (grails-micronaut, grails-micronaut-bom, the
# micronaut-tied test-examples) is auto-managed by settings.gradle based on the
# build JDK: it is pruned on a sub-25 JDK (Micronaut 5 GA targets JVM 25 bytecode)
# and included automatically on JDK 25+. So the Java 21 entries build everything
# except the island and the Java 25 entries build the full graph - no flag needed.
run: >
./gradlew build :grails-shell-cli:installDist groovydoc
--continue
Expand Down Expand Up @@ -162,6 +167,8 @@ jobs:
- name: "🔍 Setup TestLens"
uses: testlens-app/setup-testlens@d96a555133c275a00949d2cc77b70fe9a4242ebf # v1.9.2
- name: "🔨 Build project"
# This job only runs on Java 21, where settings.gradle auto-prunes the Micronaut
# island (Micronaut 5 GA targets JVM 25 bytecode). See comment on `build`.
run: >
./gradlew build :grails-shell-cli:installDist groovydoc
--continue
Expand Down Expand Up @@ -200,6 +207,10 @@ 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. On Java 21 that
# included build auto-prunes the Micronaut island (settings.gradle), so the
# Forge build never tries to compile the JVM-25 island; Java 25 includes it.
run: >
./gradlew build
--continue
Expand All @@ -210,6 +221,7 @@ jobs:
- name: "🔨 Build project with tests"
if: ${{ !contains(github.event.head_commit.message, '[skip tests]') }}
working-directory: 'grails-forge'
# See comment above on the auto-managed Micronaut island.
run: >
./gradlew build
--continue
Expand Down Expand Up @@ -263,6 +275,8 @@ jobs:
- name: "🔍 Setup TestLens"
uses: testlens-app/setup-testlens@d96a555133c275a00949d2cc77b70fe9a4242ebf # v1.9.2
- name: "🏃 Run Functional Tests"
# The Micronaut island is auto-pruned on a sub-25 JDK (settings.gradle), so the
# Java 21 entries skip it and the Java 25 entries include it (see comment on `build`).
run: >
./gradlew bootJar check
--continue
Expand Down Expand Up @@ -306,6 +320,8 @@ jobs:
- name: "🏃 Run Functional Tests"
env:
GITHUB_MAVEN_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
# The Micronaut island is auto-pruned on a sub-25 JDK (settings.gradle), so the
# Java 21 entries skip it and the Java 25 entries include it (see comment on `build`).
run: >
./gradlew bootJar check
--continue
Expand Down Expand Up @@ -345,6 +361,8 @@ jobs:
- name: "🏃 Run Functional Tests"
env:
GITHUB_MAVEN_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
# The Micronaut island is auto-pruned on a sub-25 JDK (settings.gradle), so the
# Java 21 entries skip it and the Java 25 entries include it (see comment on `build`).
run: >
./gradlew bootJar check
--continue
Expand Down Expand Up @@ -426,6 +444,10 @@ jobs:
- name: "🔍 Setup TestLens"
uses: testlens-app/setup-testlens@d96a555133c275a00949d2cc77b70fe9a4242ebf # v1.9.2
- name: "📤 Publish Grails-Core Snapshot Artifacts"
# This Java 21 publish excludes the Micronaut 5 / JVM 25 island automatically -
# settings.gradle prunes it on a sub-25 JDK. The island artifacts (grails-micronaut,
# grails-micronaut-bom) are published by the parallel publishMicronaut job below,
# which runs on JDK 25.
uses: nick-fields/retry@ad984534de44a9489a53aefd81eb77f87c70dc60 # v4.0.0
env:
GRAILS_PUBLISH_RELEASE: 'false'
Expand Down Expand Up @@ -459,6 +481,54 @@ 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, where settings.gradle
# auto-prunes the island, so it publishes 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@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: "☕️ Setup JDK"
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
with:
distribution: liberica
java-version: 25
- name: "🐘 Setup Gradle"
uses: gradle/actions/setup-gradle@50e97c2cd7a37755bbfafc9c5b7cafaece252f6e # v6.1.0
with:
cache-provider: basic # 'basic' uses the MIT-licensed, open-source cache provider; the default 'enhanced' provider (v6+) is proprietary (Gradle commercial Terms of Use)
develocity-access-key: ${{ secrets.DEVELOCITY_ACCESS_KEY }}
- name: "🔍 Setup TestLens"
uses: testlens-app/setup-testlens@d96a555133c275a00949d2cc77b70fe9a4242ebf # v1.9.2
- name: "📤 Publish Grails-Micronaut Snapshot Artifacts"
uses: nick-fields/retry@ad984534de44a9489a53aefd81eb77f87c70dc60 # v4.0.0
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
4 changes: 4 additions & 0 deletions .github/workflows/release-publish-docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,10 @@ jobs:
cache-provider: basic # 'basic' uses the MIT-licensed, open-source cache provider; the default 'enhanced' provider (v6+) is proprietary (Gradle commercial Terms of Use)
develocity-access-key: ${{ secrets.DEVELOCITY_ACCESS_KEY }}
- name: "📖 Generate Documentation"
# The Grails-Micronaut "island" requires JDK 25 (Micronaut 5 bytecode); this docs
# build runs on the JDK 21 reproducibility pin, where settings.gradle auto-prunes
# the island from the project graph so Gradle does not resolve its JVM 25 variants.
# The docs themselves have no code dependency on Micronaut.
run: ./gradlew grails-doc:build -PgithubBranch=${TARGET_BRANCH}
- name: "🚀 Publish to GitHub Pages"
uses: apache/grails-github-actions/deploy-github-pages@asf
Expand Down
76 changes: 76 additions & 0 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 @@ -93,11 +94,17 @@ jobs:
- name: "🔍 Validate dependency versions"
run: ./gradlew validateDependencyVersions
- name: "🧩 Run grails-core assemble"
# Pre-publish smoke check on JDK 21, where settings.gradle auto-prunes the
# Micronaut island. The island is built and smoke-checked by the JDK 25
# publishToSonatype step below; no separate JDK-25 assemble step is needed here.
run: ./gradlew assemble -PgithubBranch=${TARGET_BRANCH}
- name: "🧩 Run grails-forge assemble"
working-directory: grails-forge
run: ./gradlew assemble -PgithubBranch=${TARGET_BRANCH}
- name: "📦 Generate grails-core docs (to assert that is works, before proceeding)"
# grails-doc has no code dependency on the Micronaut island, and on this JDK 21
# runner settings.gradle auto-prunes the island from the project graph so Gradle
# does not try to resolve its JDK 25 deps during configuration.
run: ./gradlew grails-doc:build -PgithubBranch=${TARGET_BRANCH}
- name: "🔏 Sign grails-wrapper ZIP"
run: >
Expand Down Expand Up @@ -174,6 +181,10 @@ jobs:
aggregateChecksums
aggregatePublishedArtifacts
- name: "📤 Publish Grails Core to Staging Repository"
# On this JDK 21 runner settings.gradle auto-prunes the Grails-Micronaut
# "island" from the build. 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 @@ -189,6 +200,9 @@ jobs:
aggregateChecksums
aggregatePublishedArtifacts
- name: "📤 Publish Grails Forge to Staging Repository"
# The Forge composite build does includeBuild('..') so it pulls in the root
# grails-core build. On this JDK 21 runner settings.gradle auto-prunes the
# Micronaut island from that included build so it is not evaluated/resolved.
env:
NEXUS_PUBLISH_USERNAME: ${{ secrets.NEXUS_STAGE_DEPLOYER_USER }}
NEXUS_PUBLISH_PASSWORD: ${{ secrets.NEXUS_STAGE_DEPLOYER_PW }}
Expand All @@ -204,6 +218,39 @@ jobs:
publishToSonatype
aggregateChecksums
aggregatePublishedArtifacts
- 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
Comment thread
jamesfredley marked this conversation as resolved.
- 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 All @@ -222,12 +269,40 @@ jobs:
cat build/grails-core-checksums.txt > "$combined_file"
cat grails-gradle/build/grails-gradle-checksums.txt >> "$combined_file"
cat grails-forge/build/grails-forge-checksums.txt >> "$combined_file"
# The grails-core aggregation above ran on JDK 21, where settings.gradle auto-prunes
# the Micronaut "island" (grails-micronaut, grails-micronaut-bom), so it is excluded.
# Those artifacts were built/signed on JDK 25 and their per-project checksums
# were generated by publishedChecksums (finalizer of publishToSonatype). Append
# them here rather than re-running aggregateChecksums on JDK 25, which would
# re-fingerprint the JDK 21 artifacts against a JDK 25 compiler and break
# reproducibility. Format matches gradle/publish-root-config.gradle: "<jar> <sha512>".
for checksum_dir in grails-micronaut/build/checksums grails-bom/micronaut/build/checksums; do
[ -d "$checksum_dir" ] || continue
for checksum_file in "$checksum_dir"/*.sha512; do
[ -e "$checksum_file" ] || continue
jar_name="$(basename "$checksum_file" .sha512)"
checksum="$(awk '{print $1; exit}' "$checksum_file")"
echo "$jar_name $checksum" >> "$combined_file"
done
done
- name: "🩹 Combine published artifacts"
run: |
combined_file="build/PUBLISHED_ARTIFACTS.txt"
cat build/grails-core-artifacts.txt > "$combined_file"
cat grails-gradle/build/grails-gradle-artifacts.txt >> "$combined_file"
cat grails-forge/build/grails-forge-artifacts.txt >> "$combined_file"
# Append the Micronaut island artifacts (see "Combine checksums" above for why
# they are not in build/grails-core-artifacts.txt). The per-project lists were
# written by savePublishedArtifacts (finalizer of publishedChecksums) on JDK 25.
# Format matches gradle/publish-root-config.gradle: "<artifact> <coordinates>".
for artifacts_dir in grails-micronaut/build/artifacts grails-bom/micronaut/build/artifacts; do
[ -d "$artifacts_dir" ] || continue
for artifact_file in "$artifacts_dir"/*.txt; do
[ -e "$artifact_file" ] || continue
artifact_name="$(basename "$artifact_file" .txt)"
echo "$artifact_name $(cat "$artifact_file")" >> "$combined_file"
done
done
- name: "📅 Generate build date file"
run: echo "$SOURCE_DATE_EPOCH" >> build/BUILD_DATE.txt
- name: "📤 Upload build date, checksums and published artifact files"
Expand Down Expand Up @@ -612,6 +687,7 @@ jobs:
cache-provider: basic # 'basic' uses the MIT-licensed, open-source cache provider; the default 'enhanced' provider (v6+) is proprietary (Gradle commercial Terms of Use)
develocity-access-key: ${{ secrets.DEVELOCITY_ACCESS_KEY }}
- name: "📖 Generate Documentation"
# Runs on the JDK 21 pin, where settings.gradle auto-prunes the Micronaut island.
run: ./gradlew grails-doc:build -PgithubBranch=${TARGET_BRANCH}
- name: "🚀 Publish to GitHub Pages"
uses: apache/grails-github-actions/deploy-github-pages@asf
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