diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 8132d637e28..dfc83c1cb15 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -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' @@ -158,6 +162,8 @@ 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 @@ -165,6 +171,7 @@ jobs: --stacktrace -PonlyCoreTests -PskipCodeStyle + -PskipMicronautProjects buildForge: name: "Build Grails Forge (Java ${{ matrix.java }}, indy=${{ matrix.indy }})" strategy: @@ -195,6 +202,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, 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 @@ -202,9 +213,11 @@ jobs: -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 @@ -212,6 +225,7 @@ jobs: --stacktrace -PgrailsIndy=${{ matrix.indy }} -PskipCodeStyle + ${{ matrix.java == 21 && '-PskipMicronautProjects' || '' }} - name: "✅ Verify combined CLI" run: | cd grails-forge @@ -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 @@ -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 }})" @@ -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 @@ -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 }})" @@ -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 @@ -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 ] @@ -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' @@ -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: @@ -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 ] diff --git a/.github/workflows/release-publish-docs.yml b/.github/workflows/release-publish-docs.yml index 44ff29980bc..47111fedb96 100644 --- a/.github/workflows/release-publish-docs.yml +++ b/.github/workflows/release-publish-docs.yml @@ -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: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index d9d0f5bd92d..5a2bfc8682d 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -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 @@ -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 @@ -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 }} @@ -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 }} @@ -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 }} @@ -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: @@ -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 }} diff --git a/.sdkmanrc b/.sdkmanrc index 58b9f3d4e9b..7b10919442f 100644 --- a/.sdkmanrc +++ b/.sdkmanrc @@ -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 -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. diff --git a/RELEASE.md b/RELEASE.md index 9903369da42..94ffdeb0860 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -142,6 +142,15 @@ After all jar files are verified to be signed by a valid Grails key, we need to Further details on the building can be found in the [INSTALL](INSTALL) document. Otherwise, run the `verify-reproducible.sh` shell script to compare the published jar files to a locally built version of them. +#### Dual-JDK requirement for the Grails-Micronaut island + +Grails 8 release artifacts come from TWO different JDKs and therefore TWO different reproducibility pins: + +- **Primary JDK (`$JAVA_VERSION` in `release.yml`, also in `.sdkmanrc` and the primary `FROM` in `etc/bin/Dockerfile`)**: builds every published artifact EXCEPT the Grails-Micronaut "island" (`grails-micronaut`, `grails-micronaut-bom`). +- **Secondary JDK (`$JAVA_VERSION_MICRONAUT` in `release.yml`, installed alongside the primary in `etc/bin/Dockerfile` and exposed as `$JDK_25_HOME`)**: builds the two Micronaut island artifacts. The Micronaut 5 platform GA targets JVM 25 bytecode, so these two JARs cannot be reproduced on the primary JDK. + +The verify script understands both. Inside the verification container, `JDK_25_HOME` is already set so `verify-reproducible.sh` "just works". Outside the container, manual verifiers MUST install Liberica JDK matching `$JAVA_VERSION_MICRONAUT` from `release.yml` (for example via `sdk install java -librca`) and export `JDK_25_HOME=/path/to/jdk25` before running the script - otherwise the script fails fast with a clear error. + If there are any jar file differences, confirm they are relevant by following the following steps: 1. Extract the differing jar file using the `etc/bin/extract-build-artifact.sh ` 2. In IntelliJ, under `etc/bin/results` there will now be a `firstArtifact` & `secondArtifact` folder. Select them both, right click, and select `Compared Directories` @@ -401,6 +410,12 @@ Setup the key for validity: The Grails image is officially built on linux in a GitHub action using an Ubuntu container. To run a linux container locally, you can use the following command (substitute `` with the tag name): +The verification container ships with BOTH JDKs needed for full reproducible verification: the primary Liberica JDK +(`$JAVA_VERSION`, default on `PATH`/`JAVA_HOME`) and the secondary Liberica JDK 25 for the Grails-Micronaut "island" +(installed at `$JDK_25_HOME`). `verify-reproducible.sh` uses both automatically - no manual JDK switching required +inside the container. Both pins live in `etc/bin/Dockerfile` and must stay synced with +`$JAVA_VERSION` / `$JAVA_VERSION_MICRONAUT` in `.github/workflows/release.yml`. + **macOS/Linux** ```bash docker build -t grails:testing -f etc/bin/Dockerfile . && docker run -it --rm -v $(pwd):/home/groovy/project -p 8080:8080 grails:testing bash @@ -494,6 +509,14 @@ To test reproducibility locally, running etc/bin/test-reproducible-builds.sh wil to build the three gradle projects Grails uses. The artifacts are then saved off, and built again. Finally, the hashes are generated to ensure the artifacts are the same. +Note that Grails 8 release artifacts come from TWO pinned JDKs: the primary one (used for everything except the +Grails-Micronaut island) and a secondary Liberica JDK 25 (used only for `grails-micronaut` and `grails-micronaut-bom`, +because Micronaut 5 platform GA targets JVM 25 bytecode). Both pins live in `.github/workflows/release.yml` +(`JAVA_VERSION` and `JAVA_VERSION_MICRONAUT` respectively) and are installed side-by-side in `etc/bin/Dockerfile`. The +verify scripts switch `JAVA_HOME` to `$JDK_25_HOME` for the island and back to the default for everything else. Anyone +bumping either pin must also bump the matching pin in the Dockerfile so the verification container can reproduce the +new artifacts. + Some common gotchas with Java build reproducibility problems: 1. Most tools support a `SOURCE_DATE_EPOCH` environment variable that can be set to a fixed time to ensure timestamps diff --git a/dependencies.gradle b/dependencies.gradle index d2a51fb8e09..0b25eb7df20 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -219,7 +219,7 @@ ext { // enforcedPlatform(:grails-micronaut-bom). else if (project.name == 'grails-micronaut-bom') { customBomVersions = [ - 'groovy.version' : '5.0.5', + 'groovy.version' : '5.0.6', 'spock.version' : '2.4-groovy-5.0', 'protobuf.version': '4.30.2', ] diff --git a/etc/bin/Dockerfile b/etc/bin/Dockerfile index 675049eb75e..5215e39a1d5 100644 --- a/etc/bin/Dockerfile +++ b/etc/bin/Dockerfile @@ -16,12 +16,36 @@ # for testing in a container that is similar to the grails github action linux build environment # run this from the root of the project # `docker build -t grails:testing -f etc/bin/Dockerfile . && docker run -it --rm -v $(pwd):/home/groovy/project grails:testing bash` -# Keep java version synced with .sdkmanrc and .github/workflows/release.yml +# Keep java version synced with .sdkmanrc and .github/workflows/release.yml ($JAVA_VERSION) FROM bellsoft/liberica-openjdk-debian:21.0.7 USER root RUN apt-get update && apt-get install -y curl unzip coreutils libdigest-sha-perl gpg vim sudo psmisc locales groovy rsync nano +# Secondary Liberica JDK for the Grails-Micronaut "island" (grails-micronaut, +# grails-micronaut-bom). Micronaut 5 platform GA targets JVM 25 bytecode, so +# those two artifacts cannot be built or reproduced on the primary JDK 21 +# above. The verify scripts (etc/bin/verify-reproducible.sh, +# etc/bin/test-reproducible-builds.sh) switch JAVA_HOME to ${JDK_25_HOME} when +# building the island, and switch back to the default for everything else. +# Keep $JDK_25_VERSION synced with $JAVA_VERSION_MICRONAUT in +# .github/workflows/release.yml. +ENV JDK_25_VERSION=25.0.3+11 +ENV JDK_25_HOME=/opt/liberica-jdk25 +RUN set -eu; \ + DPKG_ARCH=$(dpkg --print-architecture); \ + case "${DPKG_ARCH}" in \ + amd64) JDK_ARCH=linux-amd64; JDK_SHA512=54e58ec3f34a20dcf6f0bd607e15c47d1f3c26ff1cfe1ecf107a862c3df7b58a9d39c0a8edf01038e83d838c28956b607e7382dda0059c04c2be5b9c0bdfa7c3 ;; \ + arm64) JDK_ARCH=linux-aarch64; JDK_SHA512=fb22b6f50186d76e19adbf990d83de4c32fee940b1f1150756529c7722254da36ff9872c4cdd342346e59d2211ae9f41d73ddf79b612dce4d7294d15c37c9349 ;; \ + *) echo "Unsupported architecture for JDK 25 install: ${DPKG_ARCH}" >&2; exit 1 ;; \ + esac; \ + curl -fsSL -o /tmp/liberica-jdk25.tar.gz "https://download.bell-sw.com/java/${JDK_25_VERSION}/bellsoft-jdk${JDK_25_VERSION}-${JDK_ARCH}.tar.gz"; \ + echo "${JDK_SHA512} /tmp/liberica-jdk25.tar.gz" | sha512sum -c -; \ + mkdir -p "${JDK_25_HOME}"; \ + tar -xzf /tmp/liberica-jdk25.tar.gz -C "${JDK_25_HOME}" --strip-components=1; \ + rm /tmp/liberica-jdk25.tar.gz; \ + "${JDK_25_HOME}/bin/java" -version + RUN sed -i -e 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen && \ dpkg-reconfigure --frontend=noninteractive locales && \ update-locale LANG=en_US.UTF-8 diff --git a/etc/bin/test-reproducible-builds.sh b/etc/bin/test-reproducible-builds.sh index 6ebc60cd0e9..99b1126425a 100755 --- a/etc/bin/test-reproducible-builds.sh +++ b/etc/bin/test-reproducible-builds.sh @@ -28,28 +28,40 @@ cd "${SCRIPT_DIR}/../.." rm -rf "${SCRIPT_DIR}/results" || true mkdir -p "${SCRIPT_DIR}/results" +if [[ -z "${JDK_25_HOME:-}" ]]; then + echo "❌ JDK_25_HOME is not set; the Grails-Micronaut island requires a separate Liberica JDK 25 install." + echo " Install Liberica JDK matching JAVA_VERSION_MICRONAUT in .github/workflows/release.yml," + echo " then export JDK_25_HOME=/path/to/jdk before running this script." + exit 1 +fi + +build_all() { + # JDK 21 (default) pass across the three composites, Micronaut island skipped. + killall -e java || true + cd grails-gradle + ./gradlew build --rerun-tasks -PskipTests --no-build-cache + cd .. + ./gradlew build --rerun-tasks -PskipTests --no-build-cache -PskipMicronautProjects + cd grails-forge + ./gradlew build --rerun-tasks -PskipTests --no-build-cache -PskipMicronautProjects + cd .. + + # JDK 25 pass: the Grails-Micronaut island only. + killall -e java || true + JAVA_HOME="${JDK_25_HOME}" PATH="${JDK_25_HOME}/bin:${PATH}" \ + ./gradlew :grails-micronaut:build :grails-micronaut-bom:build \ + --rerun-tasks -PskipTests --no-build-cache + killall -e java || true +} + git clean -xdf --exclude='etc/bin' --exclude='.idea' --exclude='.gradle' -killall -e java || true -cd grails-gradle -./gradlew build --rerun-tasks -PskipTests --no-build-cache -cd .. -./gradlew build --rerun-tasks -PskipTests --no-build-cache -cd grails-forge -./gradlew build --rerun-tasks -PskipTests --no-build-cache -cd .. +build_all "${SCRIPT_DIR}/generate-build-artifact-hashes.groovy" > "${SCRIPT_DIR}/results/first.txt" mkdir -p "${SCRIPT_DIR}/results/first" find . -path ./etc -prune -o -type f -path '*/build/libs/*.jar' -print0 | xargs -0 cp --parents -t "${SCRIPT_DIR}/results/first/" git clean -xdf --exclude='etc/bin' --exclude='.idea' --exclude='.gradle' -killall -e java || true -cd grails-gradle -./gradlew build --rerun-tasks -PskipTests --no-build-cache -cd .. -./gradlew build --rerun-tasks -PskipTests --no-build-cache -cd grails-forge -./gradlew build --rerun-tasks -PskipTests --no-build-cache -cd .. +build_all "${SCRIPT_DIR}/generate-build-artifact-hashes.groovy" > "${SCRIPT_DIR}/results/second.txt" mkdir -p "${SCRIPT_DIR}/results/second" find . -path ./etc -prune -o -type f -path '*/build/libs/*.jar' -print0 | xargs -0 cp --parents -t "${SCRIPT_DIR}/results/second/" diff --git a/etc/bin/verify-reproducible.sh b/etc/bin/verify-reproducible.sh index 824253b7143..0e9028f596d 100755 --- a/etc/bin/verify-reproducible.sh +++ b/etc/bin/verify-reproducible.sh @@ -58,13 +58,36 @@ else fi killall -e java || true + +# JDK 21 (default) pass: grails-gradle composite (no Micronaut island), root +# (Micronaut island skipped), grails-forge composite (transitively pulls in +# the root build via includeBuild('..'), island skipped there too). cd grails-gradle ./gradlew publishToMavenLocal --rerun-tasks -PskipTests --no-build-cache cd .. -./gradlew publishToMavenLocal --rerun-tasks -PskipTests --no-build-cache +./gradlew publishToMavenLocal --rerun-tasks -PskipTests --no-build-cache -PskipMicronautProjects cd grails-forge -./gradlew publishToMavenLocal --rerun-tasks -PskipTests --no-build-cache +./gradlew publishToMavenLocal --rerun-tasks -PskipTests --no-build-cache -PskipMicronautProjects cd .. + +# JDK 25 pass: the Grails-Micronaut "island" only (grails-micronaut, +# grails-micronaut-bom). Micronaut 5 platform GA targets JVM 25 bytecode so +# these two artifacts cannot be reproduced on JDK 21. The verification +# container provides ${JDK_25_HOME}; for local verification outside the +# container, install Liberica JDK matching $JAVA_VERSION_MICRONAUT in +# release.yml and export JDK_25_HOME before running this script. +if [[ -z "${JDK_25_HOME:-}" ]]; then + echo "❌ JDK_25_HOME is not set; the Grails-Micronaut island requires a separate Liberica JDK 25 install." + echo " In the verification container this is set automatically. Outside the container, install Liberica JDK" + echo " matching JAVA_VERSION_MICRONAUT in .github/workflows/release.yml and export JDK_25_HOME=/path/to/jdk." + exit 1 +fi +killall -e java || true +echo "Switching to JDK 25 at ${JDK_25_HOME} for the Micronaut island..." +JAVA_HOME="${JDK_25_HOME}" PATH="${JDK_25_HOME}/bin:${PATH}" \ + ./gradlew :grails-micronaut:publishToMavenLocal :grails-micronaut-bom:publishToMavenLocal \ + --rerun-tasks -PskipTests --no-build-cache +killall -e java || true echo "Generating Checksums for Built Jars" "${SCRIPT_DIR}/generate-build-artifact-hashes.groovy" "${DOWNLOAD_LOCATION}/grails" > "${DOWNLOAD_LOCATION}/grails/etc/bin/results/second.txt" if [ -e "${DOWNLOAD_LOCATION}/grails/etc/bin/results/second.txt" ] && [ ! -s "${DOWNLOAD_LOCATION}/grails/etc/bin/results/second.txt" ]; then diff --git a/gradle.properties b/gradle.properties index 547692b3272..2dc0a0232be 100644 --- a/gradle.properties +++ b/gradle.properties @@ -52,10 +52,7 @@ apacheRatVersion=0.8.1 gradleChecksumPluginVersion=1.4.0 gradleCycloneDxPluginVersion=3.0.0 -# micronaut libraries not in the bom due to the potential for spring mismatches -micronautPlatformVersion=5.0.0-M2 -micronautRxjava2Version=2.9.0 -micronautSerdeJacksonVersion=2.11.0 +micronautPlatformVersion=5.0.0 # Pass -PskipMicronautProjects (presence-based, like skipFunctionalTests / skipCodeStyle) # to drop the Grails-Micronaut "island" (grails-micronaut, grails-micronaut-bom, and diff --git a/grails-bom/micronaut/build.gradle b/grails-bom/micronaut/build.gradle index 3923b3f114a..f3eda80c75e 100644 --- a/grails-bom/micronaut/build.gradle +++ b/grails-bom/micronaut/build.gradle @@ -76,9 +76,11 @@ dependencies { // managed versions transitively and don't need to declare the platform themselves. // Exclude Groovy since we declare the required version explicitly below via customBomDependencies. // Exclude Spock since the base BOM manages that version. - // Exclude Jackson 3 (tools.jackson) since spring-boot-dependencies manages that version, - // and Micronaut can lag behind Spring Boot's patch bumps (e.g. SB 4.0.6 ships - // jackson-bom 3.1.2 while micronaut-platform 5.0.0-M2 still pins 3.1.0). + // Exclude Jackson 3 (tools.jackson) since spring-boot-dependencies manages that version + // and the two platforms routinely disagree on the patch (e.g. SB 4.0.6 ships + // jackson-bom 3.1.2 while micronaut-platform 5.0.0 pins 3.1.3). Let Spring Boot + // remain the single source of truth so the dependency-version validator does not + // see drift between probe and project resolution. api(platform("io.micronaut.platform:micronaut-platform:$micronautPlatformVersion")) { exclude group: 'org.apache.groovy' exclude group: 'org.spockframework' diff --git a/grails-data-graphql/plugin/build.gradle b/grails-data-graphql/plugin/build.gradle index c32901e795b..77988f52b69 100644 --- a/grails-data-graphql/plugin/build.gradle +++ b/grails-data-graphql/plugin/build.gradle @@ -72,16 +72,13 @@ dependencies { // api: HttpServletRequest/Response in GraphqlController } - // GraphQLSpec test trait imports types from io.micronaut.http.* and - // io.micronaut.rxjava2.http.client.* so the rxjava2 client (which transitively - // pulls micronaut-http-client and micronaut-http) is required to compile the - // trait. The trait is only useful from integration tests; the runtime - // dependency is therefore deferred to consumers (the example apps already - // declare it as `implementation`). Keeping it `compileOnly` here avoids - // shipping an unused micronaut HTTP client on every Grails app's runtime - // classpath - test dependencies must not leak onto the production classpath - // post Grails 7. - compileOnly "io.micronaut.rxjava2:micronaut-rxjava2-http-client:$micronautRxjava2Version" + // GraphQLSpec test trait talks to the running app over HTTP via + // org.springframework.web.client.RestClient (Spring Boot 4 / Spring 7). The + // trait is only useful from integration tests, and every Grails app already + // has spring-web on its runtime classpath via grails-web-boot, so the + // dependency stays `compileOnly` to avoid shipping anything new on the + // production classpath. + compileOnly 'org.springframework:spring-web' testImplementation project(':grails-testing-support-web') testImplementation 'net.bytebuddy:byte-buddy' diff --git a/grails-data-graphql/plugin/src/main/groovy/org/grails/gorm/graphql/plugin/testing/GraphQLSpec.groovy b/grails-data-graphql/plugin/src/main/groovy/org/grails/gorm/graphql/plugin/testing/GraphQLSpec.groovy index 3b6464bf722..32334f5beb4 100644 --- a/grails-data-graphql/plugin/src/main/groovy/org/grails/gorm/graphql/plugin/testing/GraphQLSpec.groovy +++ b/grails-data-graphql/plugin/src/main/groovy/org/grails/gorm/graphql/plugin/testing/GraphQLSpec.groovy @@ -19,13 +19,14 @@ package org.grails.gorm.graphql.plugin.testing -import groovy.json.StreamingJsonBuilder +import groovy.json.JsonOutput +import groovy.json.JsonSlurper import groovy.transform.TupleConstructor -import io.micronaut.http.HttpRequest -import io.micronaut.http.HttpResponse -import io.micronaut.http.uri.UriBuilder -import io.micronaut.rxjava2.http.client.RxHttpClient import org.springframework.beans.factory.annotation.Value +import org.springframework.http.MediaType +import org.springframework.http.ResponseEntity +import org.springframework.http.converter.StringHttpMessageConverter +import org.springframework.web.client.RestClient trait GraphQLSpec { @@ -37,7 +38,15 @@ trait GraphQLSpec { GraphQLRequestHelper getGraphQL() { if (_graphql == null) { - _graphql = new GraphQLRequestHelper(rest: RxHttpClient.create(new URL(getServerUrl()))) + StringHttpMessageConverter stringConverter = new StringHttpMessageConverter() + stringConverter.supportedMediaTypes = [MediaType.ALL] + _graphql = new GraphQLRequestHelper(rest: RestClient.builder() + .baseUrl(getServerUrl()) + .messageConverters({ converters -> + converters.clear() + converters.add(stringConverter) + }) + .build()) } _graphql } @@ -56,59 +65,90 @@ trait GraphQLSpec { @TupleConstructor static class GraphQLRequestHelper { - RxHttpClient rest + private static final MediaType APPLICATION_GRAPHQL = MediaType.parseMediaType('application/graphql') + private static final JsonSlurper SLURPER = new JsonSlurper() - HttpResponse graphql(String requestBody) { - rest.exchange(HttpRequest.POST('/graphql', requestBody).contentType('application/graphql'), Map) - .firstOrError().blockingGet() + RestClient rest + + ResponseEntity graphql(String requestBody) { + wrapJson(exchangeGraphql(requestBody)) + } + + // Overload that returns the raw body for callers asserting on the + // unparsed JSON payload (only String is supported - tests asserting on + // a structured body should use the no-class overload above which parses + // into a Map). + @SuppressWarnings('unchecked') + def ResponseEntity graphql(String requestBody, Class bodyType) { + if (bodyType != String) { + throw new IllegalArgumentException( + "graphql(String, Class) only supports String.class; got ${bodyType.name}") + } + (ResponseEntity) exchangeGraphql(requestBody) } - def HttpResponse graphql(String requestBody, Class bodyType) { - rest.exchange(HttpRequest.POST('/graphql', requestBody).contentType('application/graphql'), bodyType) - .firstOrError().blockingGet() + private ResponseEntity exchangeGraphql(String requestBody) { + rest.post() + .uri('/graphql') + .contentType(APPLICATION_GRAPHQL) + .body(requestBody) + .retrieve() + .toEntity(String) } - private HttpResponse buildJsonRequest(Map data) { - rest.exchange(HttpRequest.POST('/graphql', data), Map).firstOrError().blockingGet() + private ResponseEntity buildJsonRequest(Map data) { + wrapJson(rest.post() + .uri('/graphql') + .contentType(MediaType.APPLICATION_JSON) + .body(JsonOutput.toJson(data)) + .retrieve() + .toEntity(String)) } - private HttpResponse buildGetRequest(Map data) { + + private ResponseEntity buildGetRequest(Map data) { if (data.containsKey('variables')) { - StringWriter sw = new StringWriter() - new StreamingJsonBuilder(sw).call(data.variables) - data.put('variables', sw.toString()) + data.put('variables', JsonOutput.toJson(data.variables)) } + wrapJson(rest.get() + .uri('/', { uriBuilder -> + data.each { key, value -> + uriBuilder.queryParam(key, value) + } + uriBuilder.build() + }) + .retrieve() + .toEntity(String)) + } - UriBuilder uriBuilder = UriBuilder.of('/') - data.forEach({ key, value -> - uriBuilder.queryParam(key, value) - }) - - rest.exchange(HttpRequest.GET(uriBuilder.build()), Map).firstOrError().blockingGet() + private static ResponseEntity wrapJson(ResponseEntity raw) { + String body = raw.body + Map parsed = (body == null || body.isEmpty()) ? null : (Map) SLURPER.parseText(body) + new ResponseEntity(parsed, raw.headers, raw.statusCode) } - HttpResponse json(String query) { + ResponseEntity json(String query) { buildJsonRequest([query: query]) } - HttpResponse json(String query, String operationName) { + ResponseEntity json(String query, String operationName) { buildJsonRequest([query: query, operationName: operationName]) } - HttpResponse json(String query, Map variables) { + ResponseEntity json(String query, Map variables) { buildJsonRequest([query: query, variables: variables]) } - HttpResponse json(String query, Map variables, String operationName) { + ResponseEntity json(String query, Map variables, String operationName) { buildJsonRequest([query: query, operationName: operationName, variables: variables]) } - HttpResponse get(String query) { + ResponseEntity get(String query) { buildGetRequest([query: query]) } - HttpResponse get(String query, String operationName) { + ResponseEntity get(String query, String operationName) { buildGetRequest([query: query, operationName: operationName]) } - HttpResponse get(String query, Map variables) { + ResponseEntity get(String query, Map variables) { buildGetRequest([query: query, variables: variables]) } - HttpResponse get(String query, Map variables, String operationName) { + ResponseEntity get(String query, Map variables, String operationName) { buildGetRequest([query: query, operationName: operationName, variables: variables]) } } diff --git a/grails-test-examples/graphql/grails-docs-app/build.gradle b/grails-test-examples/graphql/grails-docs-app/build.gradle index b9cfdb411ef..dc65eb109a8 100644 --- a/grails-test-examples/graphql/grails-docs-app/build.gradle +++ b/grails-test-examples/graphql/grails-docs-app/build.gradle @@ -54,9 +54,6 @@ dependencies { implementation 'org.apache.grails:grails-data-mongodb-gson-templates' implementation "org.hibernate:hibernate-core-jakarta:$hibernate5Version" - implementation "io.micronaut.rxjava2:micronaut-rxjava2-http-client:$micronautRxjava2Version" - // JSON mapper for the micronaut HTTP client used by the GraphQLSpec trait. - implementation "io.micronaut.serde:micronaut-serde-jackson:$micronautSerdeJacksonVersion" console 'org.apache.grails:grails-console' profile 'org.apache.grails.profiles:rest-api' diff --git a/grails-test-examples/graphql/grails-multi-datastore-app/build.gradle b/grails-test-examples/graphql/grails-multi-datastore-app/build.gradle index 74d697bc1df..a62db2edf36 100644 --- a/grails-test-examples/graphql/grails-multi-datastore-app/build.gradle +++ b/grails-test-examples/graphql/grails-multi-datastore-app/build.gradle @@ -55,9 +55,6 @@ dependencies { implementation "org.hibernate:hibernate-core-jakarta:$hibernate5Version" implementation 'com.graphql-java:graphql-java' - implementation "io.micronaut.rxjava2:micronaut-rxjava2-http-client:$micronautRxjava2Version" - // JSON mapper for the micronaut HTTP client used by the GraphQLSpec trait. - implementation "io.micronaut.serde:micronaut-serde-jackson:$micronautSerdeJacksonVersion" implementation 'com.h2database:h2' implementation 'org.apache.tomcat:tomcat-jdbc' diff --git a/grails-test-examples/graphql/grails-multi-datastore-app/src/integration-test/groovy/myapp/BarIntegrationSpec.groovy b/grails-test-examples/graphql/grails-multi-datastore-app/src/integration-test/groovy/myapp/BarIntegrationSpec.groovy index 1c1bd3baa97..13f9633e8eb 100644 --- a/grails-test-examples/graphql/grails-multi-datastore-app/src/integration-test/groovy/myapp/BarIntegrationSpec.groovy +++ b/grails-test-examples/graphql/grails-multi-datastore-app/src/integration-test/groovy/myapp/BarIntegrationSpec.groovy @@ -42,7 +42,7 @@ class BarIntegrationSpec extends Specification implements GraphQLSpec { } } """) - Map obj = resp.body().data.barCreate + Map obj = resp.body.data.barCreate then: 'bar is created in the Mongo datastore with a valid ObjectId' new ObjectId((String) obj.id) diff --git a/grails-test-examples/graphql/grails-multi-datastore-app/src/integration-test/groovy/myapp/FooIntegrationSpec.groovy b/grails-test-examples/graphql/grails-multi-datastore-app/src/integration-test/groovy/myapp/FooIntegrationSpec.groovy index 10a2644be20..5fa27c3e31c 100644 --- a/grails-test-examples/graphql/grails-multi-datastore-app/src/integration-test/groovy/myapp/FooIntegrationSpec.groovy +++ b/grails-test-examples/graphql/grails-multi-datastore-app/src/integration-test/groovy/myapp/FooIntegrationSpec.groovy @@ -41,7 +41,7 @@ class FooIntegrationSpec extends Specification implements GraphQLSpec { } } """) - Map obj = resp.body().data.fooCreate + Map obj = resp.body.data.fooCreate then: 'foo is created in the Hibernate datastore' obj.id == 1 diff --git a/grails-test-examples/graphql/grails-tenant-app/build.gradle b/grails-test-examples/graphql/grails-tenant-app/build.gradle index b9cfdb411ef..dc65eb109a8 100644 --- a/grails-test-examples/graphql/grails-tenant-app/build.gradle +++ b/grails-test-examples/graphql/grails-tenant-app/build.gradle @@ -54,9 +54,6 @@ dependencies { implementation 'org.apache.grails:grails-data-mongodb-gson-templates' implementation "org.hibernate:hibernate-core-jakarta:$hibernate5Version" - implementation "io.micronaut.rxjava2:micronaut-rxjava2-http-client:$micronautRxjava2Version" - // JSON mapper for the micronaut HTTP client used by the GraphQLSpec trait. - implementation "io.micronaut.serde:micronaut-serde-jackson:$micronautSerdeJacksonVersion" console 'org.apache.grails:grails-console' profile 'org.apache.grails.profiles:rest-api' diff --git a/grails-test-examples/graphql/grails-tenant-app/src/integration-test/groovy/grails/tenant/app/UserIntegrationSpec.groovy b/grails-test-examples/graphql/grails-tenant-app/src/integration-test/groovy/grails/tenant/app/UserIntegrationSpec.groovy index a8a581e5b7f..4d6e840c010 100644 --- a/grails-test-examples/graphql/grails-tenant-app/src/integration-test/groovy/grails/tenant/app/UserIntegrationSpec.groovy +++ b/grails-test-examples/graphql/grails-tenant-app/src/integration-test/groovy/grails/tenant/app/UserIntegrationSpec.groovy @@ -45,7 +45,7 @@ class UserIntegrationSpec extends Specification implements GraphQLSpec { } } """) - Map obj = resp.body().data.userCreate + Map obj = resp.body.data.userCreate then: "The company is supplied via multi-tenancy" obj.id == 1 @@ -77,7 +77,7 @@ class UserIntegrationSpec extends Specification implements GraphQLSpec { } } """) - Map obj = resp.body().data + Map obj = resp.body.data then: "The company is supplied via multi-tenancy" obj.john.name == 'John' @@ -98,7 +98,7 @@ class UserIntegrationSpec extends Specification implements GraphQLSpec { } } """) - List obj = resp.body().data.userList + List obj = resp.body.data.userList then: "The list is filtered by the company" obj.size() == 1 @@ -117,7 +117,7 @@ class UserIntegrationSpec extends Specification implements GraphQLSpec { } } """) - List obj = resp.body().data.userList + List obj = resp.body.data.userList then: "The list is filtered by the company" obj.size() == 2 diff --git a/grails-test-examples/graphql/grails-test-app/build.gradle b/grails-test-examples/graphql/grails-test-app/build.gradle index 9213618f444..5acad3ec71e 100644 --- a/grails-test-examples/graphql/grails-test-app/build.gradle +++ b/grails-test-examples/graphql/grails-test-app/build.gradle @@ -55,9 +55,6 @@ dependencies { implementation "org.hibernate:hibernate-core-jakarta:$hibernate5Version" implementation 'com.graphql-java:graphql-java' - implementation "io.micronaut.rxjava2:micronaut-rxjava2-http-client:$micronautRxjava2Version" - // JSON mapper for the micronaut HTTP client used by the GraphQLSpec trait. - implementation "io.micronaut.serde:micronaut-serde-jackson:$micronautSerdeJacksonVersion" console 'org.apache.grails:grails-console' profile 'org.apache.grails.profiles:rest-api' diff --git a/grails-test-examples/graphql/grails-test-app/src/integration-test/groovy/grails/test/app/ArguedFieldIntegrationSpec.groovy b/grails-test-examples/graphql/grails-test-app/src/integration-test/groovy/grails/test/app/ArguedFieldIntegrationSpec.groovy index 3448cd35cf2..192302cae09 100644 --- a/grails-test-examples/graphql/grails-test-app/src/integration-test/groovy/grails/test/app/ArguedFieldIntegrationSpec.groovy +++ b/grails-test-examples/graphql/grails-test-app/src/integration-test/groovy/grails/test/app/ArguedFieldIntegrationSpec.groovy @@ -47,7 +47,7 @@ class ArguedFieldIntegrationSpec extends Specification implements GraphQLSpec { } } """) - def obj = resp.body().data.arguedField + def obj = resp.body.data.arguedField then: obj.withArgument == "PONG" @@ -62,7 +62,7 @@ class ArguedFieldIntegrationSpec extends Specification implements GraphQLSpec { } } """) - def obj = resp.body().data.arguedField + def obj = resp.body.data.arguedField then: obj.withArgumentList == "P-O-N-G" @@ -77,7 +77,7 @@ class ArguedFieldIntegrationSpec extends Specification implements GraphQLSpec { } } """) - def obj = resp.body().data.arguedField + def obj = resp.body.data.arguedField then: obj.withCustomArgument == "PONG" diff --git a/grails-test-examples/graphql/grails-test-app/src/integration-test/groovy/grails/test/app/ArtistIntegrationSpec.groovy b/grails-test-examples/graphql/grails-test-app/src/integration-test/groovy/grails/test/app/ArtistIntegrationSpec.groovy index 310ab3d9b45..106e6a1ed0d 100644 --- a/grails-test-examples/graphql/grails-test-app/src/integration-test/groovy/grails/test/app/ArtistIntegrationSpec.groovy +++ b/grails-test-examples/graphql/grails-test-app/src/integration-test/groovy/grails/test/app/ArtistIntegrationSpec.groovy @@ -51,7 +51,7 @@ class ArtistIntegrationSpec extends Specification implements GraphQLSpec { } } """) - def json = resp.body() + def json = resp.body println json.toString() def artists = json.data.artistList def artist = artists[0] diff --git a/grails-test-examples/graphql/grails-test-app/src/integration-test/groovy/grails/test/app/AuthorIntegrationSpec.groovy b/grails-test-examples/graphql/grails-test-app/src/integration-test/groovy/grails/test/app/AuthorIntegrationSpec.groovy index 402003798b7..d17c9bb85a5 100644 --- a/grails-test-examples/graphql/grails-test-app/src/integration-test/groovy/grails/test/app/AuthorIntegrationSpec.groovy +++ b/grails-test-examples/graphql/grails-test-app/src/integration-test/groovy/grails/test/app/AuthorIntegrationSpec.groovy @@ -50,7 +50,7 @@ class AuthorIntegrationSpec extends Specification implements GraphQLSpec { } """) - def obj = resp.body().data.authorCreate + def obj = resp.body.data.authorCreate then: obj.id == 1 @@ -82,7 +82,7 @@ class AuthorIntegrationSpec extends Specification implements GraphQLSpec { """) - def obj = resp.body().data.authorCreate + def obj = resp.body.data.authorCreate then: obj.id == 2 @@ -108,7 +108,7 @@ class AuthorIntegrationSpec extends Specification implements GraphQLSpec { """) - def obj = resp.body().data.authorCreate.errors + def obj = resp.body.data.authorCreate.errors then: obj.size() == 1 @@ -130,7 +130,7 @@ class AuthorIntegrationSpec extends Specification implements GraphQLSpec { } } """) - def json = resp.body() + def json = resp.body println json.toString() def authors = json.data.authorList def author1 = authors[0] @@ -166,7 +166,7 @@ class AuthorIntegrationSpec extends Specification implements GraphQLSpec { } """) - def author = resp.body().data.author + def author = resp.body.data.author then: author.id == 2 @@ -197,7 +197,7 @@ class AuthorIntegrationSpec extends Specification implements GraphQLSpec { } """) - def obj = resp.body().data.authorUpdate + def obj = resp.body.data.authorUpdate then: obj.id == 1 @@ -218,7 +218,7 @@ class AuthorIntegrationSpec extends Specification implements GraphQLSpec { """) then: - resp.body().data.authorDelete.success == true + resp.body.data.authorDelete.success == true } void cleanupSpec() { diff --git a/grails-test-examples/graphql/grails-test-app/src/integration-test/groovy/grails/test/app/BookIntegrationSpec.groovy b/grails-test-examples/graphql/grails-test-app/src/integration-test/groovy/grails/test/app/BookIntegrationSpec.groovy index 7e4ad9ed8a9..fd714d2fb63 100644 --- a/grails-test-examples/graphql/grails-test-app/src/integration-test/groovy/grails/test/app/BookIntegrationSpec.groovy +++ b/grails-test-examples/graphql/grails-test-app/src/integration-test/groovy/grails/test/app/BookIntegrationSpec.groovy @@ -36,7 +36,7 @@ class BookIntegrationSpec extends Specification implements GraphQLSpec { } """) - def result = resp.body() + def result = resp.body then: result.errors.size() == 1 diff --git a/grails-test-examples/graphql/grails-test-app/src/integration-test/groovy/grails/test/app/CommentIntegrationSpec.groovy b/grails-test-examples/graphql/grails-test-app/src/integration-test/groovy/grails/test/app/CommentIntegrationSpec.groovy index 4a0b0ade814..5eab8757b81 100644 --- a/grails-test-examples/graphql/grails-test-app/src/integration-test/groovy/grails/test/app/CommentIntegrationSpec.groovy +++ b/grails-test-examples/graphql/grails-test-app/src/integration-test/groovy/grails/test/app/CommentIntegrationSpec.groovy @@ -46,7 +46,7 @@ class CommentIntegrationSpec extends Specification implements GraphQLSpec { } } """) - Map obj = resp.body().data.commentCreate + Map obj = resp.body.data.commentCreate then: obj.id == 1 @@ -75,7 +75,7 @@ class CommentIntegrationSpec extends Specification implements GraphQLSpec { } } """) - Map obj = resp.body().data.commentCreate + Map obj = resp.body.data.commentCreate then: obj.id == 2 @@ -97,7 +97,7 @@ class CommentIntegrationSpec extends Specification implements GraphQLSpec { } } """) - Map obj = resp.body().data.comment + Map obj = resp.body.data.comment then: obj.id == 1 @@ -129,7 +129,7 @@ class CommentIntegrationSpec extends Specification implements GraphQLSpec { } } """) - Map obj = resp.body().data.comment + Map obj = resp.body.data.comment then: //The parent comment object is not queried obj.parentComment.id == 1 @@ -150,7 +150,7 @@ class CommentIntegrationSpec extends Specification implements GraphQLSpec { } } """) - obj = resp.body().data.comment + obj = resp.body.data.comment then: //The parent comment object is queried obj.parentComment.id == 1 @@ -179,7 +179,7 @@ class CommentIntegrationSpec extends Specification implements GraphQLSpec { } } """) - Map obj = resp.body().data.commentCreate + Map obj = resp.body.data.commentCreate then: obj.id == 3 @@ -200,7 +200,7 @@ class CommentIntegrationSpec extends Specification implements GraphQLSpec { } } """) - obj = resp.body().data.comment + obj = resp.body.data.comment then: obj.id == 1 @@ -225,7 +225,7 @@ class CommentIntegrationSpec extends Specification implements GraphQLSpec { } } """) - Map obj = resp.body().data.commentUpdate + Map obj = resp.body.data.commentUpdate then: obj.id == 3 @@ -248,7 +248,7 @@ class CommentIntegrationSpec extends Specification implements GraphQLSpec { } } """) - List obj = resp.body().data.commentList + List obj = resp.body.data.commentList then: obj[0].id == 1 @@ -278,7 +278,7 @@ class CommentIntegrationSpec extends Specification implements GraphQLSpec { } } """) - Map obj = resp.body().data.commentDelete + Map obj = resp.body.data.commentDelete then: obj.success diff --git a/grails-test-examples/graphql/grails-test-app/src/integration-test/groovy/grails/test/app/GrailsTeamMemberIntegrationSpec.groovy b/grails-test-examples/graphql/grails-test-app/src/integration-test/groovy/grails/test/app/GrailsTeamMemberIntegrationSpec.groovy index 36ae5486d02..8824ecc55f8 100644 --- a/grails-test-examples/graphql/grails-test-app/src/integration-test/groovy/grails/test/app/GrailsTeamMemberIntegrationSpec.groovy +++ b/grails-test-examples/graphql/grails-test-app/src/integration-test/groovy/grails/test/app/GrailsTeamMemberIntegrationSpec.groovy @@ -39,7 +39,7 @@ class GrailsTeamMemberIntegrationSpec extends Specification implements GraphQLSp } } """) - Map data = resp.body().data.grailsTeamMemberList + Map data = resp.body.data.grailsTeamMemberList JSONArray results = data.results expect: @@ -63,7 +63,7 @@ class GrailsTeamMemberIntegrationSpec extends Specification implements GraphQLSp } } """) - Map data = resp.body().data.grailsTeamMemberList + Map data = resp.body.data.grailsTeamMemberList JSONArray results = data.results expect: diff --git a/grails-test-examples/graphql/grails-test-app/src/integration-test/groovy/grails/test/app/InheritanceIntegrationSpec.groovy b/grails-test-examples/graphql/grails-test-app/src/integration-test/groovy/grails/test/app/InheritanceIntegrationSpec.groovy index f59615c9cb4..f3afca76407 100644 --- a/grails-test-examples/graphql/grails-test-app/src/integration-test/groovy/grails/test/app/InheritanceIntegrationSpec.groovy +++ b/grails-test-examples/graphql/grails-test-app/src/integration-test/groovy/grails/test/app/InheritanceIntegrationSpec.groovy @@ -50,7 +50,7 @@ class InheritanceIntegrationSpec extends Specification implements GraphQLSpec { } } """, String.class) - String data = resp.getBody().get() + String data = resp.getBody() then: data == '{"data":{"mammalList":[{"id":1,"name":"Spot","barks":true},{"id":2,"name":"Chloe","cutenessLevel":100},{"id":3,"name":"Kotlin Ken","language":true}]}}' diff --git a/grails-test-examples/graphql/grails-test-app/src/integration-test/groovy/grails/test/app/NumberLengthIntegrationSpec.groovy b/grails-test-examples/graphql/grails-test-app/src/integration-test/groovy/grails/test/app/NumberLengthIntegrationSpec.groovy index 50dedcb8a93..97e534cd92d 100644 --- a/grails-test-examples/graphql/grails-test-app/src/integration-test/groovy/grails/test/app/NumberLengthIntegrationSpec.groovy +++ b/grails-test-examples/graphql/grails-test-app/src/integration-test/groovy/grails/test/app/NumberLengthIntegrationSpec.groovy @@ -42,7 +42,7 @@ class NumberLengthIntegrationSpec extends Specification implements GraphQLSpec { } } """) - Map data = resp.body() + Map data = resp.body then: data.data.numberLengthCreate.id @@ -62,7 +62,7 @@ class NumberLengthIntegrationSpec extends Specification implements GraphQLSpec { } } """) - Map data = resp.body() + Map data = resp.body then: data.data == null @@ -83,7 +83,7 @@ class NumberLengthIntegrationSpec extends Specification implements GraphQLSpec { } } """) - Map data = resp.body() + Map data = resp.body then: data.data == null @@ -104,7 +104,7 @@ class NumberLengthIntegrationSpec extends Specification implements GraphQLSpec { } } """) - Map data = resp.body() + Map data = resp.body then: data.data == null @@ -125,7 +125,7 @@ class NumberLengthIntegrationSpec extends Specification implements GraphQLSpec { } } """) - Map data = resp.body() + Map data = resp.body then: data.data == null diff --git a/grails-test-examples/graphql/grails-test-app/src/integration-test/groovy/grails/test/app/PaymentIntegrationSpec.groovy b/grails-test-examples/graphql/grails-test-app/src/integration-test/groovy/grails/test/app/PaymentIntegrationSpec.groovy index 057211dbf9a..397f8301083 100644 --- a/grails-test-examples/graphql/grails-test-app/src/integration-test/groovy/grails/test/app/PaymentIntegrationSpec.groovy +++ b/grails-test-examples/graphql/grails-test-app/src/integration-test/groovy/grails/test/app/PaymentIntegrationSpec.groovy @@ -40,7 +40,7 @@ class PaymentIntegrationSpec extends Specification implements GraphQLSpec { } """) - Map result = resp.body() + Map result = resp.body then: result.errors.size() == 1 @@ -65,7 +65,7 @@ class PaymentIntegrationSpec extends Specification implements GraphQLSpec { } } """) - Map obj = resp.body().data.creditCardPaymentCreate + Map obj = resp.body.data.creditCardPaymentCreate then: obj.id @@ -85,7 +85,7 @@ class PaymentIntegrationSpec extends Specification implements GraphQLSpec { } } """) - Map obj = resp.body().data.creditCardPayment + Map obj = resp.body.data.creditCardPayment then: obj.id @@ -104,7 +104,7 @@ class PaymentIntegrationSpec extends Specification implements GraphQLSpec { } } """) - Map json = resp.body() + Map json = resp.body obj = json.data.payment then: @@ -122,7 +122,7 @@ class PaymentIntegrationSpec extends Specification implements GraphQLSpec { } } """) - obj = resp.body() + obj = resp.body then: 'An error is returned' obj.data == null @@ -153,7 +153,7 @@ class PaymentIntegrationSpec extends Specification implements GraphQLSpec { } } """) - List obj = resp.body().data.creditCardPaymentList + List obj = resp.body.data.creditCardPaymentList then: obj.size() == 2 @@ -169,7 +169,7 @@ class PaymentIntegrationSpec extends Specification implements GraphQLSpec { } } """) - obj = resp.body().data.paymentList + obj = resp.body.data.paymentList then: obj.size() == 2 @@ -191,7 +191,7 @@ class PaymentIntegrationSpec extends Specification implements GraphQLSpec { } } """) - Map obj = resp.body().data.creditCardPaymentUpdate + Map obj = resp.body.data.creditCardPaymentUpdate then: obj.id == 1 @@ -210,7 +210,7 @@ class PaymentIntegrationSpec extends Specification implements GraphQLSpec { } } """) - obj = resp.body() + obj = resp.body then: 'An error is thrown' obj.data == null @@ -229,7 +229,7 @@ class PaymentIntegrationSpec extends Specification implements GraphQLSpec { } } """) - obj = resp.body().data.paymentUpdate + obj = resp.body.data.paymentUpdate then: obj.amount == new BigDecimal('2') @@ -244,7 +244,7 @@ class PaymentIntegrationSpec extends Specification implements GraphQLSpec { } } """) - Map obj = resp.body().data.creditCardPaymentDelete + Map obj = resp.body.data.creditCardPaymentDelete then: obj.success @@ -257,7 +257,7 @@ class PaymentIntegrationSpec extends Specification implements GraphQLSpec { } } """) - obj = resp.body().data.paymentDelete + obj = resp.body.data.paymentDelete then: obj.success diff --git a/grails-test-examples/graphql/grails-test-app/src/integration-test/groovy/grails/test/app/PostIntegrationSpec.groovy b/grails-test-examples/graphql/grails-test-app/src/integration-test/groovy/grails/test/app/PostIntegrationSpec.groovy index 409bcdeef17..d746ffe2778 100644 --- a/grails-test-examples/graphql/grails-test-app/src/integration-test/groovy/grails/test/app/PostIntegrationSpec.groovy +++ b/grails-test-examples/graphql/grails-test-app/src/integration-test/groovy/grails/test/app/PostIntegrationSpec.groovy @@ -54,7 +54,7 @@ class PostIntegrationSpec extends Specification implements GraphQLSpec { } } """) - def obj = resp.body().data.postCreate + def obj = resp.body.data.postCreate then: obj.id @@ -96,7 +96,7 @@ class PostIntegrationSpec extends Specification implements GraphQLSpec { } } """) - def obj = resp.body().data.postCreate + def obj = resp.body.data.postCreate postId = obj.id tagId = obj?.tags?.find { it.name == 'Grails' }?.id tag2Id = obj?.tags?.find { it.name == 'Groovy' }?.id @@ -137,7 +137,7 @@ class PostIntegrationSpec extends Specification implements GraphQLSpec { } } """) - def obj = resp.body().data.postCreate + def obj = resp.body.data.postCreate post2Id = obj.id then: @@ -172,7 +172,7 @@ class PostIntegrationSpec extends Specification implements GraphQLSpec { } } """) - def obj = resp.body().data.postUpdate + def obj = resp.body.data.postUpdate then: obj.id @@ -196,7 +196,7 @@ class PostIntegrationSpec extends Specification implements GraphQLSpec { } } """) - def obj = resp.body().data.postList + def obj = resp.body.data.postList then: obj.size() == 2 @@ -215,7 +215,7 @@ class PostIntegrationSpec extends Specification implements GraphQLSpec { } } """) - def obj = resp.body().data.postList + def obj = resp.body.data.postList then: obj.size() == 1 @@ -229,7 +229,7 @@ class PostIntegrationSpec extends Specification implements GraphQLSpec { } } """) - obj = resp.body().data.postList + obj = resp.body.data.postList then: obj.size() == 1 @@ -245,7 +245,7 @@ class PostIntegrationSpec extends Specification implements GraphQLSpec { } } """) - def obj = resp.body().data.post + def obj = resp.body.data.post then: obj.title == 'Grails 3.5 Release' @@ -260,7 +260,7 @@ class PostIntegrationSpec extends Specification implements GraphQLSpec { } } """) - def obj = resp.body().data.postDelete + def obj = resp.body.data.postDelete then: obj.success @@ -284,7 +284,7 @@ class PostIntegrationSpec extends Specification implements GraphQLSpec { } } """) - resp.body().data.tagList.each { + resp.body.data.tagList.each { graphQL.graphql(""" mutation { tagDelete(id: ${it.id}) { diff --git a/grails-test-examples/graphql/grails-test-app/src/integration-test/groovy/grails/test/app/RestrictedIntegrationSpec.groovy b/grails-test-examples/graphql/grails-test-app/src/integration-test/groovy/grails/test/app/RestrictedIntegrationSpec.groovy index bb543d482f4..0d24ae57d0c 100644 --- a/grails-test-examples/graphql/grails-test-app/src/integration-test/groovy/grails/test/app/RestrictedIntegrationSpec.groovy +++ b/grails-test-examples/graphql/grails-test-app/src/integration-test/groovy/grails/test/app/RestrictedIntegrationSpec.groovy @@ -41,7 +41,7 @@ class RestrictedIntegrationSpec extends Specification implements GraphQLSpec { } """) - def obj = resp.body().data.restrictedCreate + def obj = resp.body.data.restrictedCreate then: obj.id == 1 @@ -58,7 +58,7 @@ class RestrictedIntegrationSpec extends Specification implements GraphQLSpec { } """) - def obj = resp.body().data.restrictedDelete + def obj = resp.body.data.restrictedDelete then: "the registered interceptor prevented the action" obj == null @@ -77,7 +77,7 @@ class RestrictedIntegrationSpec extends Specification implements GraphQLSpec { } """) - def obj = resp.body().data.restrictedUpdate + def obj = resp.body.data.restrictedUpdate then: "the registered interceptor prevented the action" obj == null @@ -94,7 +94,7 @@ class RestrictedIntegrationSpec extends Specification implements GraphQLSpec { } """) - def obj = resp.body().data.restricted + def obj = resp.body.data.restricted then: "the registered interceptor prevented the action" obj.id == 1 @@ -109,7 +109,7 @@ class RestrictedIntegrationSpec extends Specification implements GraphQLSpec { } """) - def obj = resp.body().data.restrictedCount + def obj = resp.body.data.restrictedCount then: "the registered interceptor prevented the action" obj == 1 @@ -126,7 +126,7 @@ class RestrictedIntegrationSpec extends Specification implements GraphQLSpec { } """) - def obj = resp.body().data.restrictedList + def obj = resp.body.data.restrictedList then: "the registered interceptor prevented the action" obj.size() == 1 diff --git a/grails-test-examples/graphql/grails-test-app/src/integration-test/groovy/grails/test/app/SimpleCompositeIntegrationSpec.groovy b/grails-test-examples/graphql/grails-test-app/src/integration-test/groovy/grails/test/app/SimpleCompositeIntegrationSpec.groovy index ef4edeb821d..d93ae386af2 100644 --- a/grails-test-examples/graphql/grails-test-app/src/integration-test/groovy/grails/test/app/SimpleCompositeIntegrationSpec.groovy +++ b/grails-test-examples/graphql/grails-test-app/src/integration-test/groovy/grails/test/app/SimpleCompositeIntegrationSpec.groovy @@ -45,7 +45,7 @@ class SimpleCompositeIntegrationSpec extends Specification implements GraphQLSpe } } """) - Map obj = resp.body().data.simpleCompositeCreate + Map obj = resp.body.data.simpleCompositeCreate then: obj.title == 'x' @@ -66,7 +66,7 @@ class SimpleCompositeIntegrationSpec extends Specification implements GraphQLSpe } } """) - Map obj = resp.body().data.simpleCompositeUpdate + Map obj = resp.body.data.simpleCompositeUpdate then: obj.title == 'x' @@ -85,7 +85,7 @@ class SimpleCompositeIntegrationSpec extends Specification implements GraphQLSpe } } """) - Map obj = resp.body().data.simpleComposite + Map obj = resp.body.data.simpleComposite then: obj.title == 'x' @@ -104,7 +104,7 @@ class SimpleCompositeIntegrationSpec extends Specification implements GraphQLSpe } } """) - List obj = resp.body().data.simpleCompositeList + List obj = resp.body.data.simpleCompositeList then: obj.size() == 1 @@ -122,7 +122,7 @@ class SimpleCompositeIntegrationSpec extends Specification implements GraphQLSpe } } """) - Map obj = resp.body().data.simpleCompositeDelete + Map obj = resp.body.data.simpleCompositeDelete then: obj.success diff --git a/grails-test-examples/graphql/grails-test-app/src/integration-test/groovy/grails/test/app/SoftDeleteIntegrationSpec.groovy b/grails-test-examples/graphql/grails-test-app/src/integration-test/groovy/grails/test/app/SoftDeleteIntegrationSpec.groovy index b1d1b9a8a7d..180512a0004 100644 --- a/grails-test-examples/graphql/grails-test-app/src/integration-test/groovy/grails/test/app/SoftDeleteIntegrationSpec.groovy +++ b/grails-test-examples/graphql/grails-test-app/src/integration-test/groovy/grails/test/app/SoftDeleteIntegrationSpec.groovy @@ -43,7 +43,7 @@ class SoftDeleteIntegrationSpec extends Specification implements GraphQLSpec { } } """) - id = resp.body().data.softDeleteCreate.id + id = resp.body.data.softDeleteCreate.id assert id != null } @@ -56,7 +56,7 @@ class SoftDeleteIntegrationSpec extends Specification implements GraphQLSpec { } } """) - def json = resp.body().data.softDelete + def json = resp.body.data.softDelete then: json.name == 'foo' @@ -71,7 +71,7 @@ class SoftDeleteIntegrationSpec extends Specification implements GraphQLSpec { } } """) - List json = resp.body().data.softDeleteList + List json = resp.body.data.softDeleteList then: json.size() == 1 @@ -87,7 +87,7 @@ class SoftDeleteIntegrationSpec extends Specification implements GraphQLSpec { } } """) - def json = resp.body().data.softDeleteDelete + def json = resp.body.data.softDeleteDelete SoftDelete softDelete SoftDelete.withNewSession { softDelete = SoftDelete.get(id) @@ -108,7 +108,7 @@ class SoftDeleteIntegrationSpec extends Specification implements GraphQLSpec { } } """) - def json = resp.body().data.softDelete + def json = resp.body.data.softDelete then: json == null @@ -123,7 +123,7 @@ class SoftDeleteIntegrationSpec extends Specification implements GraphQLSpec { } } """) - List json = resp.body().data.softDeleteList + List json = resp.body.data.softDeleteList then: json.empty diff --git a/grails-test-examples/graphql/grails-test-app/src/integration-test/groovy/grails/test/app/TagIntegrationSpec.groovy b/grails-test-examples/graphql/grails-test-app/src/integration-test/groovy/grails/test/app/TagIntegrationSpec.groovy index 7b8cfe1c98f..0c6c5f92b0d 100644 --- a/grails-test-examples/graphql/grails-test-app/src/integration-test/groovy/grails/test/app/TagIntegrationSpec.groovy +++ b/grails-test-examples/graphql/grails-test-app/src/integration-test/groovy/grails/test/app/TagIntegrationSpec.groovy @@ -53,7 +53,7 @@ class TagIntegrationSpec extends Specification implements GraphQLSpec { } } """) - List obj = resp.body().data.postCreate.tags + List obj = resp.body.data.postCreate.tags def grails = obj.find { it.name == 'Grails' }.id grailsId = grails def groovy = obj.find { it.name == 'Groovy' }.id @@ -76,7 +76,7 @@ class TagIntegrationSpec extends Specification implements GraphQLSpec { } } """) - assert resp.body().data.postCreate.tags.size() == 3 + assert resp.body.data.postCreate.tags.size() == 3 } void "test getting the count"() { @@ -86,7 +86,7 @@ class TagIntegrationSpec extends Specification implements GraphQLSpec { tagCount } """) - def obj = resp.body().data.tagCount + def obj = resp.body.data.tagCount then: obj == 4 @@ -105,7 +105,7 @@ class TagIntegrationSpec extends Specification implements GraphQLSpec { } } """) - List obj = resp.body().data.tagList + List obj = resp.body.data.tagList then: obj.size() == 4 @@ -141,7 +141,7 @@ class TagIntegrationSpec extends Specification implements GraphQLSpec { } } """) - Map obj = resp.body().data.tag + Map obj = resp.body.data.tag then: //queries.size() == 2 ignored due to GORM issue https://github.com/apache/grails-data-mapping/issues/989 @@ -166,7 +166,7 @@ class TagIntegrationSpec extends Specification implements GraphQLSpec { } } """) - Map obj = resp.body().data.tagUpdate + Map obj = resp.body.data.tagUpdate then: obj.id == grailsId @@ -187,7 +187,7 @@ class TagIntegrationSpec extends Specification implements GraphQLSpec { } } """) - resp.body().data.postList.each { + resp.body.data.postList.each { graphQL.graphql(""" mutation { postDelete(id: ${it.id}) { @@ -203,7 +203,7 @@ class TagIntegrationSpec extends Specification implements GraphQLSpec { } } """) - resp.body().data.tagList.each { + resp.body.data.tagList.each { graphQL.graphql(""" mutation { tagDelete(id: ${it.id}) { diff --git a/grails-test-examples/graphql/grails-test-app/src/integration-test/groovy/grails/test/app/TypeTestIntegrationSpec.groovy b/grails-test-examples/graphql/grails-test-app/src/integration-test/groovy/grails/test/app/TypeTestIntegrationSpec.groovy index d1552929c62..6267e7d29c9 100644 --- a/grails-test-examples/graphql/grails-test-app/src/integration-test/groovy/grails/test/app/TypeTestIntegrationSpec.groovy +++ b/grails-test-examples/graphql/grails-test-app/src/integration-test/groovy/grails/test/app/TypeTestIntegrationSpec.groovy @@ -81,7 +81,7 @@ class TypeTestIntegrationSpec extends Specification implements GraphQLSpec { } """) - Map json = resp.body().data.typeTestCreate + Map json = resp.body.data.typeTestCreate then: json.id @@ -139,7 +139,7 @@ class TypeTestIntegrationSpec extends Specification implements GraphQLSpec { charPrimitive: "x", booleanPrimitive: true]]) - Map json = resp.body().data.typeTestCreate + Map json = resp.body.data.typeTestCreate then: json.id diff --git a/grails-test-examples/graphql/grails-test-app/src/integration-test/groovy/grails/test/app/UserIntegrationSpec.groovy b/grails-test-examples/graphql/grails-test-app/src/integration-test/groovy/grails/test/app/UserIntegrationSpec.groovy index c0dd26b71b5..87f29c71a4e 100644 --- a/grails-test-examples/graphql/grails-test-app/src/integration-test/groovy/grails/test/app/UserIntegrationSpec.groovy +++ b/grails-test-examples/graphql/grails-test-app/src/integration-test/groovy/grails/test/app/UserIntegrationSpec.groovy @@ -50,7 +50,7 @@ class UserIntegrationSpec extends Specification implements GraphQLSpec { } } """) - Map obj = resp.body() + Map obj = resp.body then: obj.data == null @@ -78,7 +78,7 @@ class UserIntegrationSpec extends Specification implements GraphQLSpec { } } """) - obj = resp.body() + obj = resp.body then: obj.data == null @@ -104,7 +104,7 @@ class UserIntegrationSpec extends Specification implements GraphQLSpec { } } """) - Map obj = resp.body() + Map obj = resp.body then: obj.data == null @@ -132,7 +132,7 @@ class UserIntegrationSpec extends Specification implements GraphQLSpec { } } """) - obj = resp.body() + obj = resp.body then: obj.data == null @@ -177,7 +177,7 @@ class UserIntegrationSpec extends Specification implements GraphQLSpec { } } """) - Map obj = resp.body().data.userCreate + Map obj = resp.body.data.userCreate managerId = obj.id as Long then: @@ -231,7 +231,7 @@ class UserIntegrationSpec extends Specification implements GraphQLSpec { } } """) - Map obj = resp.body().data.userCreate + Map obj = resp.body.data.userCreate subordinateId = obj.id as Long then: @@ -282,7 +282,7 @@ class UserIntegrationSpec extends Specification implements GraphQLSpec { } } """) - Map obj = resp.body().data.userUpdate + Map obj = resp.body.data.userUpdate then: obj.id == subordinateId @@ -320,7 +320,7 @@ class UserIntegrationSpec extends Specification implements GraphQLSpec { } } """) - List obj = resp.body().data.userList + List obj = resp.body.data.userList then: JSONObject subordinate = obj.find { it.id == subordinateId } @@ -372,7 +372,7 @@ class UserIntegrationSpec extends Specification implements GraphQLSpec { } } """) - Map json = resp.body() + Map json = resp.body JSONObject obj = json.data.user then: @@ -397,7 +397,7 @@ class UserIntegrationSpec extends Specification implements GraphQLSpec { } } """) - Map obj = resp.body().data.userDelete + Map obj = resp.body.data.userDelete then: !obj.success @@ -412,7 +412,7 @@ class UserIntegrationSpec extends Specification implements GraphQLSpec { } } """) - Map obj = resp.body().data.userDelete + Map obj = resp.body.data.userDelete then: obj.success @@ -427,7 +427,7 @@ class UserIntegrationSpec extends Specification implements GraphQLSpec { } } """) - Map obj = resp.body().data.userDelete + Map obj = resp.body.data.userDelete then: obj.success diff --git a/grails-test-examples/graphql/grails-test-app/src/integration-test/groovy/grails/test/app/UserRoleIntegrationSpec.groovy b/grails-test-examples/graphql/grails-test-app/src/integration-test/groovy/grails/test/app/UserRoleIntegrationSpec.groovy index de7b00b2c43..14f4e341822 100644 --- a/grails-test-examples/graphql/grails-test-app/src/integration-test/groovy/grails/test/app/UserRoleIntegrationSpec.groovy +++ b/grails-test-examples/graphql/grails-test-app/src/integration-test/groovy/grails/test/app/UserRoleIntegrationSpec.groovy @@ -58,7 +58,7 @@ class UserRoleIntegrationSpec extends Specification implements GraphQLSpec { } } """) - Map obj = resp.body().data.userCreate + Map obj = resp.body.data.userCreate userId = obj.id resp = graphQL.graphql(""" @@ -70,7 +70,7 @@ class UserRoleIntegrationSpec extends Specification implements GraphQLSpec { } } """) - obj = resp.body().data.roleCreate + obj = resp.body.data.roleCreate roleId = obj.id } @@ -97,7 +97,7 @@ class UserRoleIntegrationSpec extends Specification implements GraphQLSpec { } } """) - Map obj = resp.body().data.userRoleCreate + Map obj = resp.body.data.userRoleCreate then: obj.user.profile.email == 'admin@email.com' @@ -130,7 +130,7 @@ class UserRoleIntegrationSpec extends Specification implements GraphQLSpec { } } """.toString()) - Map obj = resp.body().data.userRole + Map obj = resp.body.data.userRole then: obj.user.id == userId @@ -154,7 +154,7 @@ class UserRoleIntegrationSpec extends Specification implements GraphQLSpec { } } """.toString()) - obj = resp.body().data.userRole + obj = resp.body.data.userRole then: 'The user and role will be fetched with the same query' obj.user.profile.email == 'admin@email.com' @@ -182,7 +182,7 @@ class UserRoleIntegrationSpec extends Specification implements GraphQLSpec { } } """.toString()) - Map result = resp.body() + Map result = resp.body then: result.errors.size() == 1 @@ -205,7 +205,7 @@ class UserRoleIntegrationSpec extends Specification implements GraphQLSpec { } } """.toString()) - List obj = resp.body().data.userRoleList + List obj = resp.body.data.userRoleList then: obj.size() == 1 @@ -224,7 +224,7 @@ class UserRoleIntegrationSpec extends Specification implements GraphQLSpec { } } """.toString()) - List obj = resp.body().data.usersByRole + List obj = resp.body.data.usersByRole then: obj.size() == 1 @@ -242,7 +242,7 @@ class UserRoleIntegrationSpec extends Specification implements GraphQLSpec { } } """) - Long newRoleId = resp.body().data.roleCreate.id + Long newRoleId = resp.body.data.roleCreate.id graphQL.graphql(""" mutation { userRoleCreate(userRole: { @@ -273,7 +273,7 @@ class UserRoleIntegrationSpec extends Specification implements GraphQLSpec { } } """.toString()) - List list = resp.body().data.userRoleList + List list = resp.body.data.userRoleList then: list.size() == 2 @@ -286,7 +286,7 @@ class UserRoleIntegrationSpec extends Specification implements GraphQLSpec { } } """.toString()) - Map obj = resp.body().data.revokeAllRoles + Map obj = resp.body.data.revokeAllRoles then: obj.success @@ -304,7 +304,7 @@ class UserRoleIntegrationSpec extends Specification implements GraphQLSpec { } } """.toString()) - list = resp.body().data.userRoleList + list = resp.body.data.userRoleList then: 'Check if the delete worked' list.empty @@ -340,7 +340,7 @@ class UserRoleIntegrationSpec extends Specification implements GraphQLSpec { } } """.toString()) - Map obj = resp.body().data.userRoleDelete + Map obj = resp.body.data.userRoleDelete then: obj.success