diff --git a/.github/workflows/aws-lambda-snapshot.yml b/.github/workflows/aws-lambda-snapshot.yml index e901b857370..8fe4b9ade25 100644 --- a/.github/workflows/aws-lambda-snapshot.yml +++ b/.github/workflows/aws-lambda-snapshot.yml @@ -2,7 +2,7 @@ name: Snapshot to AWS Lambda on: push: branches: - - 4.3.x + - 4.5.x jobs: deploy: name: Deploy Job @@ -31,7 +31,7 @@ jobs: GRADLE_ENTERPRISE_CACHE_USERNAME: ${{ secrets.GRADLE_ENTERPRISE_CACHE_USERNAME }} GRADLE_ENTERPRISE_CACHE_PASSWORD: ${{ secrets.GRADLE_ENTERPRISE_CACHE_PASSWORD }} - name: AWS Lambda Deploy - uses: appleboy/lambda-action@v0.1.9 + uses: appleboy/lambda-action@v0.2.0 with: aws_access_key_id: ${{ secrets.AWS_ACCESS_KEY_ID }} aws_secret_access_key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} diff --git a/.github/workflows/gcf-snapshot.yml b/.github/workflows/gcf-snapshot.yml index 63db7f83824..c8da3696bf9 100644 --- a/.github/workflows/gcf-snapshot.yml +++ b/.github/workflows/gcf-snapshot.yml @@ -2,7 +2,7 @@ name: Snapshot to GCF on: push: branches: - - 4.3.x + - 4.5.x jobs: deploy: name: Deploy job diff --git a/.github/workflows/gcr-snapshot.yml b/.github/workflows/gcr-snapshot.yml index 29a674b9f05..505490db884 100644 --- a/.github/workflows/gcr-snapshot.yml +++ b/.github/workflows/gcr-snapshot.yml @@ -2,7 +2,7 @@ name: Snapshot to GCR on: push: branches: - - 4.3.x + - 4.5.x jobs: deploy: name: Deploy job diff --git a/.github/workflows/mavenCentral.yml b/.github/workflows/mavenCentral.yml index 1572501c463..a776c913e70 100644 --- a/.github/workflows/mavenCentral.yml +++ b/.github/workflows/mavenCentral.yml @@ -13,7 +13,7 @@ jobs: - uses: actions/checkout@v4 with: ref: v${{ github.event.inputs.release_version }} - - uses: gradle/wrapper-validation-action@v1 + - uses: gradle/wrapper-validation-action@v3 - name: Set up JDK uses: actions/setup-java@v4 with: diff --git a/.github/workflows/mn-linux-snapshot.yml b/.github/workflows/mn-linux-snapshot.yml index 90d214a78de..5dbb8c3733e 100644 --- a/.github/workflows/mn-linux-snapshot.yml +++ b/.github/workflows/mn-linux-snapshot.yml @@ -16,10 +16,10 @@ jobs: with: fetch-depth: 0 - name: "โ˜•๏ธ Setup GraalVM CE" - uses: graalvm/setup-graalvm@v1.1.5 + uses: graalvm/setup-graalvm@v1.1.9 with: - version: '22.3.2' java-version: '17' + distribution: 'graalvm-community' native-image-musl: 'true' components: 'native-image' github-token: ${{ secrets.GITHUB_TOKEN }} @@ -42,8 +42,8 @@ jobs: cp ./LICENSE mn-linux-amd64-snapshot/ zip -r mn-linux-amd64-snapshot.zip ./mn-linux-amd64-snapshot - name: "๐Ÿ†™ Upload Snapshot" - if: success() && github.event_name == 'push' && github.ref == 'refs/heads/4.0.x' - uses: actions/upload-artifact@v3 + if: success() && github.event_name == 'push' && github.ref == 'refs/heads/4.5.x' + uses: actions/upload-artifact@v4 with: name: mn-linux-amd64-snapshot path: mn-linux-amd64-snapshot.zip diff --git a/.github/workflows/mn-macos-snapshot.yml b/.github/workflows/mn-macos-snapshot.yml index 8230d50d7b6..0a703ffb440 100644 --- a/.github/workflows/mn-macos-snapshot.yml +++ b/.github/workflows/mn-macos-snapshot.yml @@ -7,19 +7,19 @@ on: branches: - '[1-9]+.[0-9]+.x' jobs: - build: - name: Builds OS X Native CLI - runs-on: macos-latest + intel: + name: Builds OS X Intel Native CLI + runs-on: macos-13 steps: - name: "โฌ‡ Checkout the repository" uses: actions/checkout@v4 with: fetch-depth: 0 - name: "โ˜•๏ธ Setup GraalVM CE" - uses: graalvm/setup-graalvm@v1.1.5 + uses: graalvm/setup-graalvm@v1.1.9 with: - version: '22.3.2' java-version: '17' + distribution: 'graalvm-community' components: 'native-image' github-token: ${{ secrets.GITHUB_TOKEN }} - name: "๐Ÿ“ธ Build the Native Image" @@ -41,8 +41,47 @@ jobs: cp ./LICENSE mn-darwin-amd64-snapshot/ zip -r mn-darwin-amd64-snapshot.zip ./mn-darwin-amd64-snapshot -x '*.DS_Store*' -x '__MAC_OSX' - name: "๐Ÿ†™ Upload Snapshot" - if: success() && github.event_name == 'push' && github.ref == 'refs/heads/4.0.x' - uses: actions/upload-artifact@v3 + if: success() && github.event_name == 'push' && github.ref == 'refs/heads/4.5.x' + uses: actions/upload-artifact@v4 with: name: mn-darwin-amd64-snapshot path: mn-darwin-amd64-snapshot.zip + arm: + name: Builds OS X Arm Native CLI + runs-on: macos-latest + steps: + - name: "โฌ‡ Checkout the repository" + uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: "โ˜•๏ธ Setup GraalVM CE" + uses: graalvm/setup-graalvm@v1.1.9 + with: + java-version: '17' + distribution: 'graalvm-community' + components: 'native-image' + github-token: ${{ secrets.GITHUB_TOKEN }} + - name: "๐Ÿ“ธ Build the Native Image" + run: ./gradlew micronaut-cli:nativeCompile --no-daemon + env: + GRADLE_ENTERPRISE_ACCESS_KEY: ${{ secrets.GRADLE_ENTERPRISE_ACCESS_KEY }} + GRADLE_ENTERPRISE_CACHE_USERNAME: ${{ secrets.GRADLE_ENTERPRISE_CACHE_USERNAME }} + GRADLE_ENTERPRISE_CACHE_PASSWORD: ${{ secrets.GRADLE_ENTERPRISE_CACHE_PASSWORD }} + - name: "โœ… Verify Build" + run: ./starter-cli/build/native/nativeCompile/mn --version + - name: "โœ… Verify Create App" + run: ./starter-cli/build/native/nativeCompile/mn create-app test + - name: "๐Ÿ‘ทโ€โ™€๏ธPackage Build" + env: + VERSION: ${{ github.event.release.tag_name }} + run: | + mkdir -p mn-darwin-aarch64-snapshot/bin + mv ./starter-cli/build/native/nativeCompile/mn mn-darwin-aarch64-snapshot/bin + cp ./LICENSE mn-darwin-aarch64-snapshot/ + zip -r mn-darwin-aarch64-snapshot.zip ./mn-darwin-aarch64-snapshot -x '*.DS_Store*' -x '__MAC_OSX' + - name: "๐Ÿ†™ Upload Snapshot" + if: success() && github.event_name == 'push' && github.ref == 'refs/heads/4.4.x' + uses: actions/upload-artifact@v4 + with: + name: mn-darwin-aarch64-snapshot + path: mn-darwin-aarch64-snapshot.zip diff --git a/.github/workflows/mn-windows-snapshot.yml b/.github/workflows/mn-windows-snapshot.yml index 81d1a724191..4501e759269 100644 --- a/.github/workflows/mn-windows-snapshot.yml +++ b/.github/workflows/mn-windows-snapshot.yml @@ -16,10 +16,10 @@ jobs: with: fetch-depth: 0 - name: "โ˜•๏ธ Setup GraalVM CE" - uses: graalvm/setup-graalvm@v1.1.5 + uses: graalvm/setup-graalvm@v1.1.9 with: - version: '22.3.2' java-version: '17' + distribution: 'graalvm-community' components: 'native-image' github-token: ${{ secrets.GITHUB_TOKEN }} - name: "๐Ÿ“ธ Build the Native Image" @@ -46,8 +46,8 @@ jobs: Copy-Item "./LICENSE" -Destination "./mn-win-amd64-snapshot" Compress-Archive -Path "./mn-win-amd64-snapshot" -Update -DestinationPath ./mn-win-amd64-snapshot.zip - name: "๐Ÿ†™ Upload Snapshot" - if: success() && github.event_name == 'push' && github.ref == 'refs/heads/4.0.x' - uses: actions/upload-artifact@v3 + if: success() && github.event_name == 'push' && github.ref == 'refs/heads/4.5.x' + uses: actions/upload-artifact@v4 with: name: mn-win-amd64-snapshot path: ./mn-win-amd64-snapshot.zip diff --git a/.github/workflows/release-manually.yml b/.github/workflows/release-manually.yml index 271fa700931..42b5cbfd462 100644 --- a/.github/workflows/release-manually.yml +++ b/.github/workflows/release-manually.yml @@ -9,7 +9,7 @@ jobs: uses: actions/checkout@v4 with: token: ${{ secrets.GH_TOKEN }} - - uses: gradle/wrapper-validation-action@v1 + - uses: gradle/wrapper-validation-action@v3 - name: Set up JDK uses: actions/setup-java@v4 with: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 90c15a3b53f..5e2e92555fb 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -4,14 +4,14 @@ on: types: [published] jobs: build: - name: Release artifacts to Maven Central & SDKMAN, and publish documentation + name: Release artifacts to Maven Central & SDKMAN!, and publish documentation runs-on: ubuntu-latest steps: - name: Checkout repository uses: actions/checkout@v4 with: token: ${{ secrets.GH_TOKEN }} - - uses: gradle/wrapper-validation-action@v1 + - uses: gradle/wrapper-validation-action@v3 - name: Set up JDK uses: actions/setup-java@v4 with: @@ -83,7 +83,7 @@ jobs: run: | echo "Setting new Micronaut snapshot version" sed -i "s/^micronautVersion.*$/micronautVersion\=${{ steps.post_release.outputs.next_version }}-SNAPSHOT/" gradle.properties - - uses: stefanzweifel/git-auto-commit-action@v5.0.0 + - uses: stefanzweifel/git-auto-commit-action@v5.0.1 continue-on-error: true with: commit_message: Back Micronaut version to snapshot @@ -107,10 +107,10 @@ jobs: sed -i "s/^projectVersion.*$/projectVersion\=${release_version}/" gradle.properties echo "release_version=${release_version}" >> $GITHUB_OUTPUT - name: "โ˜•๏ธ Setup GraalVM CE" - uses: graalvm/setup-graalvm@v1.1.5 + uses: graalvm/setup-graalvm@v1.1.9 with: - version: '22.3.2' java-version: '17' + distribution: 'graalvm-community' native-image-musl: 'true' components: 'native-image' github-token: ${{ secrets.GITHUB_TOKEN }} @@ -143,8 +143,8 @@ jobs: asset_name: mn-linux-amd64-${{ github.event.release.tag_name }}.zip asset_content_type: application/zip macos: - name: Release OS X Native CLI - runs-on: macos-latest + name: Release OS X Intel Native CLI + runs-on: macos-13 needs: [build] steps: - name: Checkout repository @@ -158,10 +158,10 @@ jobs: sed -i -e "s/^projectVersion.*$/projectVersion\=${release_version}/" gradle.properties echo "release_version=${release_version}" >> $GITHUB_OUTPUT - name: "โ˜•๏ธ Setup GraalVM CE" - uses: graalvm/setup-graalvm@v1.1.5 + uses: graalvm/setup-graalvm@v1.1.9 with: - version: '22.3.2' java-version: '17' + distribution: 'graalvm-community' components: 'native-image' github-token: ${{ secrets.GITHUB_TOKEN }} - name: "๐Ÿ“ธ Build the Native Image" @@ -192,6 +192,56 @@ jobs: asset_path: ./mn-darwin-amd64-${{ github.event.release.tag_name }}.zip asset_name: mn-darwin-amd64-${{ github.event.release.tag_name }}.zip asset_content_type: application/zip + macos-arm: + name: Release OS X Arm Native CLI + runs-on: macos-latest + needs: [build] + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + token: ${{ secrets.GH_TOKEN }} + - name: Set the current release version + id: release_version + run: | + release_version=${GITHUB_REF:11} + sed -i -e "s/^projectVersion.*$/projectVersion\=${release_version}/" gradle.properties + echo "release_version=${release_version}" >> $GITHUB_OUTPUT + - name: "โ˜•๏ธ Setup GraalVM CE" + uses: graalvm/setup-graalvm@v1.1.9 + with: + java-version: '17' + distribution: 'graalvm-community' + components: 'native-image' + github-token: ${{ secrets.GITHUB_TOKEN }} + - name: "๐Ÿ“ธ Build the Native Image" + run: ./gradlew micronaut-cli:nativeCompile --no-daemon + env: + GRADLE_ENTERPRISE_ACCESS_KEY: ${{ secrets.GRADLE_ENTERPRISE_ACCESS_KEY }} + GRADLE_ENTERPRISE_CACHE_USERNAME: ${{ secrets.GRADLE_ENTERPRISE_CACHE_USERNAME }} + GRADLE_ENTERPRISE_CACHE_PASSWORD: ${{ secrets.GRADLE_ENTERPRISE_CACHE_PASSWORD }} + - name: "โœ… Verify Build" + run: ./starter-cli/build/native/nativeCompile/mn --version + - name: "โœ… Verify Create App" + run: ./starter-cli/build/native/nativeCompile/mn create-app test + - name: Package Build + env: + VERSION: ${{ github.event.release.tag_name }} + run: | + mkdir -p "mn-darwin-aarch64-${VERSION}/bin" + mv ./starter-cli/build/native/nativeCompile/mn "mn-darwin-aarch64-${VERSION}/bin" + cp ./LICENSE "mn-darwin-aarch64-${VERSION}/" + zip -r "mn-darwin-aarch64-${VERSION}.zip" "mn-darwin-aarch64-${VERSION}/" -x '*.DS_Store*' -x '__MAC_OSX' + - name: Upload Release Asset + id: upload-release-asset + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ github.event.release.upload_url }} + asset_path: ./mn-darwin-aarch64-${{ github.event.release.tag_name }}.zip + asset_name: mn-darwin-aarch64-${{ github.event.release.tag_name }}.zip + asset_content_type: application/zip windows: name: Release Windows Native CLI runs-on: windows-latest @@ -202,10 +252,10 @@ jobs: with: token: ${{ secrets.GH_TOKEN }} - name: "โ˜•๏ธ Setup GraalVM CE" - uses: graalvm/setup-graalvm@v1.1.5 + uses: graalvm/setup-graalvm@v1.1.9 with: - version: '22.3.2' java-version: '17' + distribution: 'graalvm-community' components: 'native-image' github-token: ${{ secrets.GITHUB_TOKEN }} - name: "๐Ÿ“ธ Build the Native Image" @@ -244,7 +294,7 @@ jobs: sdkman: name: Release to SDKMAN! runs-on: ubuntu-latest - needs: [linux, macos, windows] + needs: [linux, macos, macos-arm, windows] steps: - name: Checkout repository uses: actions/checkout@v4 @@ -261,7 +311,7 @@ jobs: release_version=${GITHUB_REF:11} sed -i "s/^projectVersion.*$/projectVersion\=${release_version}/" gradle.properties echo "release_version=${release_version}" >> $GITHUB_OUTPUT - - name: SDKMAN release + - name: SDKMAN! release env: GVM_SDKVENDOR_KEY: ${{ secrets.GVM_SDKVENDOR_KEY }} GVM_SDKVENDOR_TOKEN: ${{ secrets.GVM_SDKVENDOR_TOKEN }} @@ -318,7 +368,7 @@ jobs: gcloud beta run deploy "micronaut-starter-$version" --quiet --image gcr.io/${{ secrets.GCLOUD_PROJECT }}/micronaut-starter:${{ steps.release_version.outputs.release_version }} --project ${{ secrets.GCLOUD_PROJECT }} --region us-central1 --update-env-vars=HOSTNAME="launch.micronaut.io",GITHUB_OAUTH_APP_CLIENT_ID=${{ secrets.GH_OAUTH_CLIENT_ID }},GITHUB_OAUTH_APP_CLIENT_SECRET=${{ secrets.GH_OAUTH_CLIENT_SECRET }} --platform managed --allow-unauthenticated --service-account=${{ secrets.GCLOUD_EMAIL }} homebrew: name: Update Homebrew cask - needs: [macos] + needs: [macos, macos-arm] runs-on: ubuntu-latest steps: - name: Checkout https://github.com/micronaut-projects/homebrew-tap @@ -326,22 +376,29 @@ jobs: with: token: ${{ secrets.GH_TOKEN }} repository: micronaut-projects/homebrew-tap - - name: Download ZIP - run: wget -q https://github.com/micronaut-projects/micronaut-starter/releases/download/${{ github.event.release.tag_name }}/mn-darwin-amd64-${{ github.event.release.tag_name }}.zip -O mn.zip + - name: Download Intel ZIP + run: wget -q https://github.com/micronaut-projects/micronaut-starter/releases/download/${{ github.event.release.tag_name }}/mn-darwin-amd64-${{ github.event.release.tag_name }}.zip -O intel.zip + - name: Download Arm ZIP + run: wget -q https://github.com/micronaut-projects/micronaut-starter/releases/download/${{ github.event.release.tag_name }}/mn-darwin-aarch64-${{ github.event.release.tag_name }}.zip -O arm.zip - name: Calculate SHA256 id: sha run: | - s=$(sha256sum mn.zip | awk '{ print $1 }') - echo "SHA256 is: $s" - echo "sha=${s}" >> $GITHUB_OUTPUT + s=$(sha256sum intel.zip | awk '{ print $1 }') + echo "INTEL SHA256 is: $s" + echo "intelsha=${s}" >> $GITHUB_OUTPUT + s=$(sha256sum arm.zip | awk '{ print $1 }') + echo "ARM SHA256 is: $s" + echo "armsha=${s}" >> $GITHUB_OUTPUT - name: Update Cask file env: - SHA: ${{ steps.sha.outputs.sha }} + INTELSHA: ${{ steps.sha.outputs.intelsha }} + ARMSHA: ${{ steps.sha.outputs.armsha }} run: | sed -i -e "s/ version.*/ version '${GITHUB_REF:11}'/" Casks/micronaut.rb - sed -i -e "s/sha256.*/sha256 '${SHA}'/" Casks/micronaut.rb + sed -i -e "s/ sha256 arm: '.*/ sha256 arm: '${ARMSHA}',/" Casks/micronaut.rb + sed -i -e "s/ intel: '.*/ intel: '${INTELSHA}'/" Casks/micronaut.rb cat Casks/micronaut.rb - - uses: stefanzweifel/git-auto-commit-action@v5.0.0 + - uses: stefanzweifel/git-auto-commit-action@v5.0.1 with: commit_message: Update Micronaut cask to ${{ github.event.release.tag_name }} commit_user_name: micronaut-build @@ -394,7 +451,7 @@ jobs: run: | choco apikey --key $Env:API_KEY --source https://push.chocolatey.org/ choco push micronaut.${{ steps.choco.outputs.nuget_version }}.nupkg --source https://push.chocolatey.org/ --force - - uses: stefanzweifel/git-auto-commit-action@v5.0.0 + - uses: stefanzweifel/git-auto-commit-action@v5.0.1 with: commit_message: Bump Micronaut Chocolatey package to ${{ github.event.release.tag_name }} commit_user_name: micronaut-build @@ -410,7 +467,7 @@ jobs: with: token: ${{ secrets.GH_TOKEN }} ref: ${{ github.event.release.target_commitish }} - - uses: gradle/wrapper-validation-action@v1 + - uses: gradle/wrapper-validation-action@v3 - name: Set up JDK uses: actions/setup-java@v4 with: @@ -422,7 +479,7 @@ jobs: - name: Back to Micronaut Platform snapshot continue-on-error: true run: ./gradlew micronautPlatformNextSnapshot - - uses: stefanzweifel/git-auto-commit-action@v5.0.0 + - uses: stefanzweifel/git-auto-commit-action@v5.0.1 continue-on-error: true with: commit_message: Back Core and Platform version to snapshot diff --git a/buildSrc/build.gradle b/buildSrc/build.gradle index faf473a2810..37ca1011d6d 100644 --- a/buildSrc/build.gradle +++ b/buildSrc/build.gradle @@ -10,11 +10,11 @@ repositories { dependencies { implementation "com.fizzed:rocker-compiler:1.4.0" - implementation "com.fasterxml.jackson.core:jackson-databind:2.16.0" + implementation "com.fasterxml.jackson.core:jackson-databind:2.17.0" implementation "io.sdkman:gradle-sdkvendor-plugin:3.0.0" implementation "org.asciidoctor:asciidoctor-gradle-jvm:2.4.0" implementation "com.github.johnrengelman:shadow:8.1.1" - implementation "com.microsoft.azure:azure-functions-gradle-plugin:1.12.1" + implementation "com.microsoft.azure:azure-functions-gradle-plugin:1.15.0" } gradlePlugin { diff --git a/buildSrc/src/main/groovy/io.micronaut.internal.build.starter-openapi-module.gradle b/buildSrc/src/main/groovy/io.micronaut.internal.build.starter-openapi-module.gradle index 27bcdb77ff5..6aeb2983e62 100644 --- a/buildSrc/src/main/groovy/io.micronaut.internal.build.starter-openapi-module.gradle +++ b/buildSrc/src/main/groovy/io.micronaut.internal.build.starter-openapi-module.gradle @@ -10,8 +10,9 @@ def openApiOutputFile = layout.buildDirectory.file('generated/openapi/openapi.pr def openApiProperties = tasks.register("openApiProperties", WriteProperties) { outputFile(openApiOutputFile.get().asFile) properties( - 'swagger-ui.enabled':true, - 'redoc.enabled':true, + 'swagger-ui.enabled': true, + 'redoc.enabled': true, + 'openapi-explorer.enabled': true, 'rapidoc.enabled': true, 'rapidoc.bg-color': '#14191f', 'rapidoc.text-color': '#aec2e0', diff --git a/buildSrc/src/main/groovy/io.micronaut.internal.starter.coordinates.gradle b/buildSrc/src/main/groovy/io.micronaut.internal.starter.coordinates.gradle index cadc0d82463..fc1895eaf36 100644 --- a/buildSrc/src/main/groovy/io.micronaut.internal.starter.coordinates.gradle +++ b/buildSrc/src/main/groovy/io.micronaut.internal.starter.coordinates.gradle @@ -6,6 +6,7 @@ def generateCoordinateUtils = tasks.register("generateCoordinateUtils", io.micro packageName = "io.micronaut.starter.build.dependencies" outputDirectory = layout.buildDirectory.dir("generated-sources/coordinates") versionCatalog = project.extensions.getByType(VersionCatalogsExtension).named("templateLibs") + lineSeparator = System.lineSeparator() } sourceSets.main.java.srcDir(generateCoordinateUtils) diff --git a/buildSrc/src/main/java/io/micronaut/starter/coordinates/CoordinatesSourceGenerator.java b/buildSrc/src/main/java/io/micronaut/starter/coordinates/CoordinatesSourceGenerator.java index 9f6be543aa4..0c1b9fd2ace 100644 --- a/buildSrc/src/main/java/io/micronaut/starter/coordinates/CoordinatesSourceGenerator.java +++ b/buildSrc/src/main/java/io/micronaut/starter/coordinates/CoordinatesSourceGenerator.java @@ -46,6 +46,7 @@ @CacheableTask public abstract class CoordinatesSourceGenerator extends DefaultTask { + @Internal public abstract Property getVersionCatalog(); @@ -72,6 +73,17 @@ public Provider> getCoordinates() { @Input public abstract Property getPackageName(); + /** + * The line separator to use. + *

+ * We use this as a cache key, as otherwise we can cache the Windows CLI build, which results in checkstyle errors. + * + * @return The line separator + * @see A build with the issue + */ + @Input + public abstract Property getLineSeparator(); + @OutputDirectory public abstract DirectoryProperty getOutputDirectory(); diff --git a/chocolatey/micronaut.nuspec b/chocolatey/micronaut.nuspec index c722923d317..d7d1dc3e3b4 100644 --- a/chocolatey/micronaut.nuspec +++ b/chocolatey/micronaut.nuspec @@ -3,7 +3,7 @@ micronaut - 4.2.1 + 4.4.2 https://github.com/micronaut-projects/micronaut-starter/tree/master/chocolatey รlvaro Sรกnchez-Mariscal micronaut (Install) diff --git a/chocolatey/tools/chocolateyinstall.ps1 b/chocolatey/tools/chocolateyinstall.ps1 index a21068e8476..0f6c6c2c6b5 100644 --- a/chocolatey/tools/chocolateyinstall.ps1 +++ b/chocolatey/tools/chocolateyinstall.ps1 @@ -1,10 +1,10 @@ -$version = '4.2.1' +$version = '4.4.2' $packageArgs = @{ packageName = $env:ChocolateyPackageName unzipLocation = "$(Split-Path -parent $MyInvocation.MyCommand.Definition)" url = "https://github.com/micronaut-projects/micronaut-starter/releases/download/v$version/mn-win-amd64-v$version.zip" - checksum = '72180FCE41107D7F81B6B4A749EEFE7304D48B6F969C5B55FE4ECAF53CF31C0C' + checksum = '01ED97D7467E353A38270C79037CF09006B263073DAE3D2E9FDBE92F9D510D80' checksumType = 'sha256' } diff --git a/config/checkstyle/suppressions.xml b/config/checkstyle/suppressions.xml index b5689e7a845..f480e49d54a 100644 --- a/config/checkstyle/suppressions.xml +++ b/config/checkstyle/suppressions.xml @@ -8,4 +8,5 @@ + diff --git a/gradle.properties b/gradle.properties index 92652627855..3b0dfcc21e4 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,5 +1,5 @@ # -#Mon Dec 04 21:27:26 UTC 2023 +#Tue Apr 23 06:06:27 UTC 2024 org.gradle.caching=true projectUrl=https\://micronaut.io micronautBuildVersion=1.1.5 @@ -8,14 +8,14 @@ micronautDocsVersion=2.0.0 org.gradle.parallel=true spockVersion=2.3-groovy-4.0 projectGroup=io.micronaut.starter -title=Micronaut Launch +title=Micronaut Starter githubSlug=micronaut-projects/micronaut-starter rockerVersion=1.4.0 grailsVersion=3.3.8 -groovyVersion=4.0.16 -micronautVersion=4.3.0-SNAPSHOT +groovyVersion=4.0.20 +micronautVersion=4.5.0-SNAPSHOT kafkaVersion=NA -micronautCoreVersion=4.3.0-SNAPSHOT +micronautCoreVersion=4.5.0-SNAPSHOT projectDesc=Generates Micronaut applications githubBranch=master -projectVersion=4.3.0-SNAPSHOT +projectVersion=4.5.0-SNAPSHOT diff --git a/gradle/templates.versions.toml b/gradle/templates.versions.toml index 9a1a67a690b..85a6be07c1e 100644 --- a/gradle/templates.versions.toml +++ b/gradle/templates.versions.toml @@ -11,64 +11,66 @@ [versions] agorapulse-gru = "1.4.0" agorapulse-micronaut-console = "2.0.2-micronaut-3.0" -agorapulse-micronaut-permissions = "1.1.1-micronaut-3.0" +agorapulse-micronaut-permissions = "1.2.0-micronaut-3.0" agorapulse-micronaut-slack = "1.0.4-micronaut-3.0" agorapulse-micronaut-worker = "1.3.0-micronaut-3.0" -aws-cdk-lib = "2.110.1" -apigatewayv2 = "2.93.0-alpha.0" -apigatewayv2-integrations = "2.93.0-alpha.0" -appengine-gradle-plugin = "2.5.0" +aws-cdk-lib = "2.129.0" +apigatewayv2 = "2.110.1-alpha.0" +apigatewayv2-integrations = "2.110.1-alpha.0" +appengine-gradle-plugin = "2.8.0" asciidoctor-gradle-jvm = "3.3.2" -asciidoctor-maven-plugin = "2.2.2" +asciidoctor-maven-plugin = "2.2.6" asciidoctorj = "2.5.10" asciidoctorj-diagram = "2.2.13" -awaitility = "4.2.0" -azure-functions-gradle-plugin = "1.13.0" -azure-functions-maven-plugin = "1.26.0" +awaitility = "4.2.1" +azure-functions-gradle-plugin = "1.15.0" +azure-functions-maven-plugin = "1.31.0" bom-opentelemetry = "1.14.0-alpha" -bpm-assert = "7.19.0" -bpm-micronaut = "2.14.0" -buildless = "1.0.0-beta6" -camunda-micronaut-client = "2.12.0" -gradle-enterprise = "3.13.4" -gradle-enterprise-maven-custom-data = "1.12.4" -gradle-enterprise-maven-extension = "1.17.4" +bpm-assert = "7.20.0" +bpm-micronaut = "2.16.0" +buildless = "1.0.0-rc2" +camunda-micronaut-client = "2.13.0" +gradle-enterprise = "3.16.2" +gradle-enterprise-maven-custom-data = "1.13" +gradle-enterprise-maven-extension = "1.20.1" gradle-jrebel-plugin = "1.1.10" gradle-shadow-plugin = "8.1.1" jib-gradle-plugin = "2.8.0" -jobrunr = "6.3.3" +jobrunr = "6.3.5" jooq-gradle-plugin = "3.19.0" jruby = "9.4.5.0" json-bind = "2.0.0" -jte-gradle-plugin= "3.0.3" -jte-maven-plugin= "3.0.3" -kotest = "4.2.5" -kotlin = "1.9.21" -ksp = "1.9.21-1.0.15" -log4j = "2.19.0" -log4j-slf4j = "2.17.2" -micronaut-aot = "2.0.1" -micronaut-build-plugins = "6.5.7" -micronaut-gradle-plugin = "4.2.0" +json-smart = "2.5.1" +jte-gradle-plugin= "3.1.9" +jte-maven-plugin= "3.1.9" +kotest = "5.8.1" +kotlin = "1.9.23" +ksp = "1.9.23-1.0.19" +log4j = "2.23.1" +log4j-slf4j = "2.23.1" +micronaut-aot = "2.2.0" +micronaut-build-plugins = "6.6.4" +micronaut-gradle-plugin = "4.3.8" mockserver-client-java = "5.15.0" mockk = "1.9.3" protobuf-gradle-plugin = "0.9.2" -rewrite-gradle-plugin = "5.12.0" -rewrite-maven-plugin = "4.47.0" -rewrite-micronaut = "1.15.1" +rewrite-gradle-plugin = "6.8.4" +rewrite-maven-plugin = "5.23.1" +rewrite-micronaut = "2.2.4" rocker-gradle-plugin = "3.0.4" -rocker-maven-plugin = "1.3.0" +rocker-maven-plugin = "1.4.0" scram-client = "2.1" slf4j = "1.7.36" -jul-to-slf4j="2.0.9" +jul-to-slf4j="2.0.12" slf4j-simple-logger = "2.0.0" -zeebe-micronaut-client = "1.14.0" -ktor = "2.2.4" +zeebe-micronaut-client = "1.17.0" +ktor = "2.3.9" jakarta-validation-api = "3.0.2" -spring-boot-gradle-plugin = "3.1.5" +spring-boot-gradle-plugin = "3.2.4" spring-dependency-management-plugin = "1.1.4" -micronaut-starter-aws-cdk = "4.1.6" -spring-boot-starter-parent="3.1.5" +micronaut-starter-aws-cdk = "4.3.7" +spring-boot-starter-parent="3.2.4" + [libraries] spring-boot-starter-parent = { module = "org.springframework.boot:spring-boot-starter-parent", version.ref = "spring-boot-starter-parent" } spring-dependency-management-plugin = { module = "io.spring.gradle:dependency-management-plugin", version.ref = "spring-dependency-management-plugin" } @@ -108,6 +110,7 @@ jobrunr-micronaut = { module = "org.jobrunr:jobrunr-micronaut-feature", version. jooq-gradle-plugin = { module = "org.jooq.jooq-codegen-gradle:org.jooq.jooq-codegen-gradle.gradle.plugin", version.ref = "jooq-gradle-plugin" } jruby = { module = "org.jruby:jruby", version.ref = "jruby" } json-bind = { module = "jakarta.json.bind:jakarta.json.bind-api", version.ref = "json-bind" } +json-smart = { module = "net.minidev:json-smart", version.ref = "json-smart" } jte-gradle-plugin = { module = "gg.jte:jte-gradle-plugin", version.ref = "jte-gradle-plugin" } jte-maven-plugin = { module = "gg.jte:jte-maven-plugin", version.ref = "jte-maven-plugin" } kotest-assertions-core-jvm = { module = "io.kotest:kotest-assertions-core-jvm", version.ref = "kotest" } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 7f93135c49b..e6441136f3d 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index ac72c34e8ac..b82aa23a4f0 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/gradlew b/gradlew index 0adc8e1a532..1aa94a42690 100755 --- a/gradlew +++ b/gradlew @@ -145,7 +145,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then case $MAX_FD in #( max*) # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC2039,SC3045 MAX_FD=$( ulimit -H -n ) || warn "Could not query maximum file descriptor limit" esac @@ -153,7 +153,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then '' | soft) :;; #( *) # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC2039,SC3045 ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac @@ -202,11 +202,11 @@ fi # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' -# Collect all arguments for the java command; -# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of -# shell script including quotes and variable substitutions, so put them in -# double quotes to make sure that they get re-expanded; and -# * put everything else in single quotes, so that it's not re-expanded. +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ diff --git a/gradlew.bat b/gradlew.bat index 6689b85beec..7101f8e4676 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -43,11 +43,11 @@ set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 if %ERRORLEVEL% equ 0 goto execute -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail @@ -57,11 +57,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe if exist "%JAVA_EXE%" goto execute -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail diff --git a/settings.gradle b/settings.gradle index a0c64f2fd16..3e161f2f2ab 100644 --- a/settings.gradle +++ b/settings.gradle @@ -4,7 +4,7 @@ pluginManagement { mavenCentral() } plugins { - id 'com.microsoft.azure.azurefunctions' version '1.12.1' + id 'com.microsoft.azure.azurefunctions' version '1.15.0' } } @@ -16,7 +16,7 @@ buildscript { } plugins { - id 'io.micronaut.build.shared.settings' version '6.6.1' + id 'io.micronaut.build.shared.settings' version '6.7.0' } rootProject.name = 'micronaut-starter' diff --git a/src/main/docs/guide/cdk/micronautFunction.adoc b/src/main/docs/guide/cdk/micronautFunction.adoc index cb17178b29f..1d7f349e952 100644 --- a/src/main/docs/guide/cdk/micronautFunction.adoc +++ b/src/main/docs/guide/cdk/micronautFunction.adoc @@ -1,13 +1,13 @@ api:aws.cdk.function.MicronautFunction[] eases the selection of the correct environment and sets the handler automatically. -[source, java] +[source,java] ---- include::starter-aws-cdk/src/test/java/io/micronaut/docs/aws/cdk/function/AppStack.java[tag="micronautFunctionDefault",indent=0] ---- If you use `ApplicationType.FUNCTION` you have to provide your handler. -[source, java] +[source,java] ---- include::starter-aws-cdk/src/test/java/io/micronaut/docs/aws/cdk/function/AppStack.java[tag="micronautFunction",indent=0] ----- \ No newline at end of file +---- diff --git a/src/main/docs/guide/cdk/micronautFunctionFile.adoc b/src/main/docs/guide/cdk/micronautFunctionFile.adoc index b6eb12a6cbe..db10ec16b25 100644 --- a/src/main/docs/guide/cdk/micronautFunctionFile.adoc +++ b/src/main/docs/guide/cdk/micronautFunctionFile.adoc @@ -1,6 +1,6 @@ api:aws.cdk.function.MicronautFunctionFile[] has a fluid API to ease generating the file name of the asset. -[source, java] +[source,java] ---- include::starter-aws-cdk/src/test/java/io/micronaut/docs/aws/cdk/function/MicronautFunctionFileExample.java[tag=micronautFunctionFile,indent=0] ----- \ No newline at end of file +---- diff --git a/src/main/docs/guide/commands.adoc b/src/main/docs/guide/commands.adoc index 84dfe4d645b..91cbe194084 100644 --- a/src/main/docs/guide/commands.adoc +++ b/src/main/docs/guide/commands.adoc @@ -18,4 +18,4 @@ include::{includedir}/mn-create-grpc-app.adoc[] == create-messaging-app -include::{includedir}/mn-create-messaging-app.adoc[] \ No newline at end of file +include::{includedir}/mn-create-messaging-app.adoc[] diff --git a/src/main/docs/guide/communityFeature.adoc b/src/main/docs/guide/communityFeature.adoc index 8d74eb6b627..e3d18849c32 100644 --- a/src/main/docs/guide/communityFeature.adoc +++ b/src/main/docs/guide/communityFeature.adoc @@ -2,5 +2,5 @@ Micronaut Launch includes Community Features such as those from https://agorapulse.github.io/agorapulse-oss/#_micronaut_libraries[Agorapulse], https://github.com/camunda-community-hub/micronaut-camunda-external-client[Camunda], and https://www.jobrunr.io/en/documentation/configuration/micronaut/[JobRunr]. -A feature that adds a Micronaut library which the Micronaut Foundation does not maintain is considered a Community Feature. In the event that Micronaut Foundation assumes responsibility for a Community Feature, it could potentially become an official Micronaut Launch feature instead. - +A feature that adds a Micronaut library which the Micronaut Foundation does not maintain is considered a Community Feature. +In the event that Micronaut Foundation assumes responsibility for a Community Feature, it could potentially become an official Micronaut Launch feature instead. diff --git a/src/main/docs/guide/installation/installChocolatey.adoc b/src/main/docs/guide/installation/installChocolatey.adoc index 9ed3ec1ea89..10650d6c044 100644 --- a/src/main/docs/guide/installation/installChocolatey.adoc +++ b/src/main/docs/guide/installation/installChocolatey.adoc @@ -1,6 +1,6 @@ If using Windows, you can use https://chocolatey.org[Chocolatey] to install the Micronaut CLI: -[source, bash] +[source,bash] ---- $ choco install micronaut ---- @@ -15,4 +15,4 @@ $ mn | Starting interactive mode... | Enter a command name to run. Use TAB for completion: mn> ----- \ No newline at end of file +---- diff --git a/src/main/docs/guide/installation/installFromSource.adoc b/src/main/docs/guide/installation/installFromSource.adoc index 84cf89237ce..70f49f3d386 100644 --- a/src/main/docs/guide/installation/installFromSource.adoc +++ b/src/main/docs/guide/installation/installFromSource.adoc @@ -5,7 +5,6 @@ Clone the repository as follows: $ git clone https://github.com/micronaut-projects/micronaut-starter.git ---- - `cd` into the `micronaut-starter` directory and run the following command: [source,bash] @@ -15,7 +14,8 @@ $ ./gradlew micronaut-cli:assembleDist This will create a zip distribution of the CLI (named with the current version) in the `starter-cli/build/distributions/` folder. -You'll need to unzip this somewhere convenient. For example, to unzip it to a dot directory in your user home, you could do: +You'll need to unzip this somewhere convenient. +For example, to unzip it to a dot directory in your user home, you could do: [source,bash] ---- @@ -32,8 +32,7 @@ export MICRONAUT_HOME=~/path/to/unzipped/cli export PATH="$PATH:$MICRONAUT_HOME/bin" ---- -TIP: If you're using SDKMAN and don't want to mess with your $MICRONAUT_HOME, you can also point SDKMAN to your -local installation for dev purposes by using `sdk install micronaut dev path/to/unzipped/cli` +TIP: If you're using SDKMAN! and don't want to mess with your $MICRONAUT_HOME, you can also point SDKMAN! to your local installation for dev purposes by using `sdk install micronaut dev path/to/unzipped/cli` Reload your terminal or `source` your shell profile with `source`: @@ -42,7 +41,7 @@ Reload your terminal or `source` your shell profile with `source`: $ source ~/.bash_profile ---- -You are now be able to run the Micronaut CLI. +You are now able to run the Micronaut CLI. [source,bash] ---- diff --git a/src/main/docs/guide/installation/installHomebrew.adoc b/src/main/docs/guide/installation/installHomebrew.adoc index 3851ff06570..5338c4c1aa9 100644 --- a/src/main/docs/guide/installation/installHomebrew.adoc +++ b/src/main/docs/guide/installation/installHomebrew.adoc @@ -9,9 +9,10 @@ You can find more information about Homebrew usage on their https://brew.sh/[hom You should now be able to run the Micronaut CLI. -TIP: On macOS you may get a warning message saying that `โ€œmnโ€ cannot be opened because the developer cannot be verified.`. -To resolve it, click the Apple menu, and select *System Settings*. Then browse to *Privacy & Security*, and scroll down -to the *Security* section. There should be a warning that `"mn" was blocked`, with an *Allow Anyway* button. +TIP: On macOS, you may get a warning message saying that `โ€œmnโ€ cannot be opened because the developer cannot be verified.`. +To resolve it, click the Apple menu, and select *System Settings*. +Then browse to *Privacy & Security*, and scroll down to the *Security* section. +There should be a warning that `"mn" was blocked`, with an *Allow Anyway* button. Clicking this button will fix the issue. See the https://docs.brew.sh/FAQ#why-cant-i-open-a-mac-app-from-an-unidentified-developer[Homebrew documentation] for more details about this. diff --git a/src/main/docs/guide/installation/installMacports.adoc b/src/main/docs/guide/installation/installMacports.adoc index 864e0c2ac20..06140a11973 100644 --- a/src/main/docs/guide/installation/installMacports.adoc +++ b/src/main/docs/guide/installation/installMacports.adoc @@ -1,4 +1,4 @@ -Before installing it is recommended to sync the latest Portfiles. +Before installing, it is recommended to sync the latest Portfiles. [source,bash] ---- diff --git a/src/main/docs/guide/installation/installSdkman.adoc b/src/main/docs/guide/installation/installSdkman.adoc index ac638556b27..7d1db0b61f4 100644 --- a/src/main/docs/guide/installation/installSdkman.adoc +++ b/src/main/docs/guide/installation/installSdkman.adoc @@ -1,7 +1,7 @@ -The best way to install Micronaut on Unix systems is with http://sdkman.io/[SDKMAN] which greatly simplifies installing -and managing multiple Micronaut versions. +The best way to install Micronaut on Unix systems is with http://sdkman.io/[SDKMAN!] which greatly simplifies installing and managing multiple Micronaut versions. -Before updating make sure you have latest version of SDKMAN installed. If not, run +Before updating make sure you have the latest version of SDKMAN! installed. +If not, run [source,bash] ---- @@ -22,7 +22,7 @@ You can also specify the version to the `sdk install` command. $ sdk install micronaut {project-version} ---- -You can find more information about SDKMAN usage on the http://sdkman.io/usage[SDKMAN Docs] +You can find more information about SDKMAN! usage on the http://sdkman.io/usage[SDKMAN! Docs] You should now be able to run the Micronaut CLI. @@ -32,4 +32,4 @@ $ mn | Starting interactive mode... | Enter a command name to run. Use TAB for completion: mn> ----- \ No newline at end of file +---- diff --git a/src/main/docs/guide/introduction.adoc b/src/main/docs/guide/introduction.adoc index 4a660215d6d..22deaac7b24 100644 --- a/src/main/docs/guide/introduction.adoc +++ b/src/main/docs/guide/introduction.adoc @@ -1 +1 @@ -This project implements a project generator for Micronaut as is both a Command Line (CLI) application and an API that can be run as a HTTP server, deployed to a Servlet container or executed on a Serverless platform (Google Cloud Run, Google Cloud Function, AWS Lambda or Azure Function). \ No newline at end of file +This project implements a project generator for Micronaut as is both a Command Line (CLI) application and an API that can be run as an HTTP server, deployed to a Servlet container or executed on a Serverless platform (Google Cloud Run, Google Cloud Function, AWS Lambda or Azure Function). diff --git a/src/main/docs/guide/releaseHistory.adoc b/src/main/docs/guide/releaseHistory.adoc index 8f9590312f5..928da7dd993 100644 --- a/src/main/docs/guide/releaseHistory.adoc +++ b/src/main/docs/guide/releaseHistory.adoc @@ -1,3 +1,3 @@ ==== 2.0.0.M3 -* Initial Milestone Release \ No newline at end of file +* Initial Milestone Release diff --git a/src/main/docs/guide/starterImpls.adoc b/src/main/docs/guide/starterImpls.adoc index cd724f75ddc..e202dbc2ba7 100644 --- a/src/main/docs/guide/starterImpls.adoc +++ b/src/main/docs/guide/starterImpls.adoc @@ -1,4 +1,3 @@ The core functionality of the project generator is contained within the `micronaut-starter-core` subproject: dependency:io.micronaut.starter:micronaut-starter-core[version="{version}"] - diff --git a/src/main/docs/guide/starterImpls/starterApi.adoc b/src/main/docs/guide/starterImpls/starterApi.adoc index 78066acb7e1..39cc6053924 100644 --- a/src/main/docs/guide/starterImpls/starterApi.adoc +++ b/src/main/docs/guide/starterImpls/starterApi.adoc @@ -1,15 +1,15 @@ -This project uses https://micronaut-projects.github.io/micronaut-openapi/latest/guide/index.html[Micronaut's OpenAPI] support to generate an https://www.openapis.org[OpenAPI specification]; a broadly adopted industry standard to describe APIs. +This project uses https://micronaut-projects.github.io/micronaut-openapi/latest/guide/index.html[Micronaut OpenAPI] support to generate an https://www.openapis.org[OpenAPI specification]; a broadly adopted industry standard to describe APIs. Run: -[source, bash] +[source,bash] ---- $ ./gradlew starter-api:classes ---- You can open the OPEN API specification in YAML format: -[source, bash] +[source,bash,subs="attributes"] +---- +$ open starter-api/build/classes/java/main/META-INF/swagger/micronaut-launch-{version}.yml ---- -$ open starter-api/build/classes/java/main/META-INF/swagger/micronaut-starter-1.0.yml ----- \ No newline at end of file diff --git a/src/main/docs/guide/starterImpls/starterAzure.adoc b/src/main/docs/guide/starterImpls/starterAzure.adoc index 702dd75dc82..c32b17081c6 100644 --- a/src/main/docs/guide/starterImpls/starterAzure.adoc +++ b/src/main/docs/guide/starterImpls/starterAzure.adoc @@ -4,9 +4,10 @@ The subproject `starter-azure-function` provides a function that can be deployed First uncomment the Azure plugin from `starter-azure-function/build.grade`: -```cmd +[source,cmd] +---- ./gradlew clean starter-azure-function:azureFunctionsRun -``` +---- And visit http://localhost:7071/api/application-types @@ -22,6 +23,7 @@ https://micronaut-starter.azurewebsites.net/api/application-types First uncomment the Azure plugin from `starter-azure-function/build.grade` then run: -```cmd +[source,cmd] +---- ./gradlew clean starter-azure-function:azureFunctionsDeploy -``` +---- diff --git a/src/main/docs/guide/starterImpls/starterCLI.adoc b/src/main/docs/guide/starterImpls/starterCLI.adoc index 942daaeca14..fed67c9fbbb 100644 --- a/src/main/docs/guide/starterImpls/starterCLI.adoc +++ b/src/main/docs/guide/starterImpls/starterCLI.adoc @@ -18,7 +18,8 @@ java -jar starter-cli/build/libs/micronaut-cli-{version}-all.jar === Building a Native Image -Install GraalVM and Native Image. Follow the steps in the previous section to build the CLI and then run: +Install GraalVM and Native Image. +Follow the steps in the previous section to build the CLI and then run: [source,bash,subs="attributes"] ---- @@ -31,4 +32,3 @@ This will produce the `mn` executable which you can start with: ---- ./mn ---- - diff --git a/src/main/docs/guide/starterImpls/starterCloudRun.adoc b/src/main/docs/guide/starterImpls/starterCloudRun.adoc index 65ac21e09eb..3fa582d967c 100644 --- a/src/main/docs/guide/starterImpls/starterCloudRun.adoc +++ b/src/main/docs/guide/starterImpls/starterCloudRun.adoc @@ -4,16 +4,17 @@ The subproject `starter-web-netty` provides an implementation that can be contin Install GraalVM and the native image tool and then run: -```cmd +[source,cmd] +---- $ docker build . -t micronaut-starter -f DockerfileCloudRun $ docker run -p 8080:8080 micronaut-starter -``` +---- And then visit http://localhost:8080/swagger/views/swagger-ui/index.html === Continuous Deployment -Micronaut Starter is continuously deployed to https://cloud.google.com/run[Google Cloud Run] as a native GraalVM application using Github Actions. +Micronaut Starter is continuously deployed to https://cloud.google.com/run[Google Cloud Run] as a native GraalVM application using GitHub Actions. The https://github.com/micronaut-projects/micronaut-starter/actions?query=workflow%3A%22Snapshot+to+GCR%22[Snapshot to GCR Workflow] (defined by `.github/workflows/gcr-snapshot.yml`) deploys the application on each commit and the application can be accessed at the following URL: @@ -21,7 +22,7 @@ https://micronaut-starter-staging-ucxwqnh6ka-uc.a.run.app/swagger/views/swagger- === Deploying the Application -To build and deploy the project yourself install setup the Google Cloud CLI then from the project root build the docker image and push it to Google Container Registry: +To build and deploy the project yourself install set up the Google Cloud CLI then from the project root build the docker image and push it to Google Container Registry: [source] ---- @@ -37,7 +38,8 @@ You are now ready to deploy your application: $ gcloud beta run deploy --image gcr.io/[PROJECT ID]/micronaut-starter ---- -Where `[PROJECT ID]` is replaced for your project ID. You should see output like the following: +Where `[PROJECT ID]` is replaced for your project ID. +You should see output like the following: [source] ---- @@ -51,4 +53,4 @@ Done. Service [micronaut-starter] revision [micronaut-starter-00004] has been deployed and is serving traffic at https://micronaut-starter-xxxxxxx-uc.a.run.app ---- -The URL is the URL of your Cloud Run application. \ No newline at end of file +The URL is the URL of your Cloud Run application. diff --git a/src/main/docs/guide/starterImpls/starterLambda.adoc b/src/main/docs/guide/starterImpls/starterLambda.adoc index b5803987eca..58152a8360a 100644 --- a/src/main/docs/guide/starterImpls/starterLambda.adoc +++ b/src/main/docs/guide/starterImpls/starterLambda.adoc @@ -4,7 +4,7 @@ The subproject `starter-aws-lambda` provides a function that can be deployed to From the root of the project run: -[source, cmd] +[source,cmd] ---- $ docker build . -f DockerfileLambda -t micronaut-starter $ mkdir -p build @@ -22,9 +22,8 @@ And visit http://localhost:3000/ === Continuous Deployment -The Micronaut Starter API is continuously deployed by Github Actions to https://aws.amazon.com/lambda/[AWS Lambda] as a Serverless GraalVM native application using a custom AWS Lambda Runtime . +The Micronaut Starter API is continuously deployed by GitHub Actions to https://aws.amazon.com/lambda/[AWS Lambda] as a Serverless GraalVM native application using a custom AWS Lambda Runtime . The https://github.com/micronaut-projects/micronaut-starter/actions?query=workflow%3A%22Snapshot+to+AWS+Lambda%22[Snapshot to AWS Lambda Workflow] (defined by `.github/workflows/gcf-snapshot.yml`) deploys the application on each commit and the API can be accessed at the following URL: https://cn58jiuova.execute-api.us-east-1.amazonaws.com/staging/application-types - diff --git a/src/main/docs/guide/starterImpls/starterNetty.adoc b/src/main/docs/guide/starterImpls/starterNetty.adoc index 1e18616e496..d1846443c91 100644 --- a/src/main/docs/guide/starterImpls/starterNetty.adoc +++ b/src/main/docs/guide/starterImpls/starterNetty.adoc @@ -4,9 +4,10 @@ The subproject `starter-web-netty` provides an implementation that runs on Netty From the project root: -```cmd +[source,cmd] +---- ./gradlew clean starter-web-netty:run -``` +---- And visit http://localhost:8080/application-types @@ -22,9 +23,10 @@ http://localhost:8080/swagger/views/rapidoc/index.html You can build the WAR file with: -```cmd +[source,cmd] +---- ./gradlew clean starter-web-netty:shadowJar -``` +---- A runnable JAR file will be located in `starter-web-servlet/build/libs`: diff --git a/src/main/docs/guide/starterImpls/starterServlet.adoc b/src/main/docs/guide/starterImpls/starterServlet.adoc index 32386dcf9be..72ecdf87a3b 100644 --- a/src/main/docs/guide/starterImpls/starterServlet.adoc +++ b/src/main/docs/guide/starterImpls/starterServlet.adoc @@ -1,12 +1,13 @@ -The subproject `starter-web-servlet` provides an implementation that can be deployed to any recent Servlet 4+ container (Tomcat 9, Jetty 9 etc.). +The subproject `starter-web-servlet` provides an implementation that can be deployed to any recent Servlet 4+ container (Tomcat 9, Jetty 9 etc). === Running the Application locally From the project root: -```cmd +[source,cmd] +---- ./gradlew clean starter-web-servlet:run -``` +---- And visit http://localhost:8080/application-types @@ -22,8 +23,9 @@ http://localhost:8080/swagger/views/rapidoc You can build the WAR file with: -```cmd +[source,cmd] +---- ./gradlew clean starter-web-servlet:assemble -``` +---- -The WAR file will be located in `starter-web-servlet/build/libs` and can be deployed to any modern Servlet container (example Jetty 9 or Tomcat 9). \ No newline at end of file +The WAR file will be located in `starter-web-servlet/build/libs` and can be deployed to any modern Servlet container (example Jetty 9 or Tomcat 9). diff --git a/src/main/docs/guide/starterImpls/starterUI.adoc b/src/main/docs/guide/starterImpls/starterUI.adoc index f0fa6e1f85e..9eb0d614d2a 100644 --- a/src/main/docs/guide/starterImpls/starterUI.adoc +++ b/src/main/docs/guide/starterImpls/starterUI.adoc @@ -1 +1 @@ -The https://micronaut.io/launch[UI for Micronaut Launch] is written in React and the sources can be found https://github.com/micronaut-projects/static-website/tree/master/main/src/main/js/launch[here] as a separate project. \ No newline at end of file +The https://micronaut.io/launch[UI for Micronaut Launch] is written in React and the sources can be found https://github.com/micronaut-projects/micronaut-starter-ui/tree/master/app/launch[here] as a separate project. diff --git a/src/main/docs/guide/toc.yml b/src/main/docs/guide/toc.yml index 9e4d6fa6e27..38fc66ca9ee 100644 --- a/src/main/docs/guide/toc.yml +++ b/src/main/docs/guide/toc.yml @@ -3,9 +3,9 @@ cdk: title: AWS CDK micronautFunctionFile: MicronautFunctionFile micronautFunction: MicronautFunction -installation: +installation: title: Installation - installSdkman: Install with SDKman + installSdkman: Install with SDKMAN! installHomebrew: Install with Homebrew installMacports: Install with MacPorts installChocolatey: Install with Chocolatey diff --git a/starter-api/build.gradle b/starter-api/build.gradle index 964731507f5..92925dc14f9 100644 --- a/starter-api/build.gradle +++ b/starter-api/build.gradle @@ -5,19 +5,24 @@ plugins { dependencies { annotationProcessor("io.micronaut.openapi:micronaut-openapi") annotationProcessor("io.micronaut.docs:micronaut-docs-asciidoc-config-props:$micronautDocsVersion") - api project(":starter-core"), { - exclude group:'org.slf4j', module:'slf4j-nop' + annotationProcessor("io.micronaut.validation:micronaut-validation-processor") + annotationProcessor("io.micronaut.serde:micronaut-serde-processor") + + api(project(":starter-core")) { + exclude group: 'org.slf4j', module: 'slf4j-nop' } - implementation("io.swagger.core.v3:swagger-annotations") + + compileOnly("io.micronaut.openapi:micronaut-openapi-annotations") api("io.micronaut:micronaut-inject") api("io.micronaut:micronaut-http") api("io.micronaut:micronaut-http-client") - implementation("io.micronaut.reactor:micronaut-reactor") api("io.micronaut.validation:micronaut-validation") - annotationProcessor("io.micronaut.validation:micronaut-validation-processor") + api("io.micronaut.serde:micronaut-serde-jackson") + + implementation("io.micronaut.openapi:micronaut-openapi-annotations") + implementation("io.micronaut.reactor:micronaut-reactor") testCompileOnly("io.micronaut:micronaut-inject-groovy") - testImplementation("io.micronaut:micronaut-jackson-databind") testImplementation("io.micronaut:micronaut-http-server-netty") testImplementation("io.micronaut:micronaut-http-client") testImplementation("io.micronaut.test:micronaut-test-spock") diff --git a/starter-api/src/main/java/io/micronaut/starter/api/ApplicationController.java b/starter-api/src/main/java/io/micronaut/starter/api/ApplicationController.java index 25398aa9839..cca7e247f70 100644 --- a/starter-api/src/main/java/io/micronaut/starter/api/ApplicationController.java +++ b/starter-api/src/main/java/io/micronaut/starter/api/ApplicationController.java @@ -46,7 +46,7 @@ import java.util.stream.Collectors; /** - * Main interface on the the starter API. + * Main interface on the starter API. * * @author graemerocher * @since 1.0.0 diff --git a/starter-api/src/main/java/io/micronaut/starter/api/FeatureDTO.java b/starter-api/src/main/java/io/micronaut/starter/api/FeatureDTO.java index 9f51d67c232..ced649e008e 100644 --- a/starter-api/src/main/java/io/micronaut/starter/api/FeatureDTO.java +++ b/starter-api/src/main/java/io/micronaut/starter/api/FeatureDTO.java @@ -65,13 +65,18 @@ public FeatureDTO(Feature feature, MessageSource messageSource, MessageSource.Me * @param category The category */ @Creator - public FeatureDTO(String name, String title, String description, String category) { + public FeatureDTO(String name, + String title, + String description, + String category, + boolean preview, + boolean community) { this.name = name; this.title = title; this.description = description; this.category = category; - this.preview = false; - this.community = false; + this.preview = preview; + this.community = community; } /** diff --git a/starter-api/src/main/java/io/micronaut/starter/api/JdkVersionDTO.java b/starter-api/src/main/java/io/micronaut/starter/api/JdkVersionDTO.java index f7572f9fe23..431b811dae9 100644 --- a/starter-api/src/main/java/io/micronaut/starter/api/JdkVersionDTO.java +++ b/starter-api/src/main/java/io/micronaut/starter/api/JdkVersionDTO.java @@ -18,10 +18,10 @@ import io.micronaut.context.MessageSource; import io.micronaut.core.annotation.Creator; import io.micronaut.core.annotation.Internal; -import io.micronaut.core.annotation.Introspected; import io.micronaut.core.annotation.NonNull; import io.micronaut.core.naming.Described; import io.micronaut.core.naming.Named; +import io.micronaut.serde.annotation.Serdeable; import io.micronaut.starter.options.JdkVersion; import io.swagger.v3.oas.annotations.media.Schema; @@ -32,7 +32,7 @@ * @since 1.0.0 */ @Schema(name = "JdkVersionInfo") -@Introspected +@Serdeable public class JdkVersionDTO extends Linkable implements Named, Described, Selectable { static final String MESSAGE_PREFIX = StarterConfiguration.PREFIX + ".jdkVersion."; private final JdkVersion value; diff --git a/starter-api/src/main/java/io/micronaut/starter/api/JdkVersionTypeConverter.java b/starter-api/src/main/java/io/micronaut/starter/api/JdkVersionTypeConverter.java new file mode 100644 index 00000000000..13ba516971d --- /dev/null +++ b/starter-api/src/main/java/io/micronaut/starter/api/JdkVersionTypeConverter.java @@ -0,0 +1,34 @@ +/* + * Copyright 2017-2024 original authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.micronaut.starter.api; + +import io.micronaut.core.convert.ConversionContext; +import io.micronaut.core.convert.TypeConverter; +import io.micronaut.starter.options.JdkVersion; +import jakarta.inject.Singleton; + +import java.util.Optional; + +/** + * Type converter required to convert strings such as "JDK_21" to JdkVersion objects for api REST calls. + */ +@Singleton +public class JdkVersionTypeConverter implements TypeConverter { + @Override + public Optional convert(String object, Class targetType, ConversionContext context) { + return Optional.of(JdkVersion.valueOf(object)); + } +} diff --git a/starter-api/src/main/java/io/micronaut/starter/api/SelectOptionsDTO.java b/starter-api/src/main/java/io/micronaut/starter/api/SelectOptionsDTO.java index 127f3100a46..e876095c501 100644 --- a/starter-api/src/main/java/io/micronaut/starter/api/SelectOptionsDTO.java +++ b/starter-api/src/main/java/io/micronaut/starter/api/SelectOptionsDTO.java @@ -17,7 +17,7 @@ import io.micronaut.context.MessageSource; import io.micronaut.core.annotation.Creator; -import io.micronaut.core.annotation.Introspected; +import io.micronaut.serde.annotation.Serdeable; import io.micronaut.starter.api.options.ApplicationTypeSelectOptions; import io.micronaut.starter.api.options.BuildToolSelectOptions; import io.micronaut.starter.api.options.JdkVersionSelectOptions; @@ -40,7 +40,7 @@ * @since 2.2.0 */ @Schema(name = "SelectOptions") -@Introspected +@Serdeable public class SelectOptionsDTO { private ApplicationTypeSelectOptions type; diff --git a/starter-api/src/main/java/io/micronaut/starter/api/StarterConfiguration.java b/starter-api/src/main/java/io/micronaut/starter/api/StarterConfiguration.java index 8ea08658f96..12e89b8bfb4 100644 --- a/starter-api/src/main/java/io/micronaut/starter/api/StarterConfiguration.java +++ b/starter-api/src/main/java/io/micronaut/starter/api/StarterConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2022 original authors + * Copyright 2017-2024 original authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,7 +25,7 @@ import java.util.Optional; /** - * Allows configuration of the the links exposed in URLs. + * Allows configuration of the links exposed in URLs. * * @author graemerocher * @since 1.0.0 @@ -88,58 +88,4 @@ public Optional getPath() { public void setPath(String path) { this.path = path; } - - @ConfigurationProperties(GitHubConfiguration.PREFIX) - public static class GitHubConfiguration { - public static final String PREFIX = "github"; - - private String clientId; - private String clientSecret; - private String tokenPermissions; - - /** - * @return GitHub OAuth App client id - */ - public String getClientId() { - return clientId; - } - - /** - * Sets GitHub OAuth App client id - * @param clientId client id - */ - public void setClientId(String clientId) { - this.clientId = clientId; - } - - /** - * @return GitHub OAuth App secret id - */ - public String getClientSecret() { - return clientSecret; - } - - /** - * Sets GitHub OAuth App secret - * @param clientSecret secret - */ - public void setClientSecret(String clientSecret) { - this.clientSecret = clientSecret; - } - - /** - * @return token permission to request from user - */ - public String getTokenPermissions() { - return tokenPermissions; - } - - /** - * Sets GitHub token permissions - * @param tokenPermissions token permissions - */ - public void setTokenPermissions(String tokenPermissions) { - this.tokenPermissions = tokenPermissions; - } - } } diff --git a/starter-api/src/main/java/io/micronaut/starter/api/create/github/GitHubCreateController.java b/starter-api/src/main/java/io/micronaut/starter/api/create/github/GitHubCreateController.java deleted file mode 100644 index 1db5b322832..00000000000 --- a/starter-api/src/main/java/io/micronaut/starter/api/create/github/GitHubCreateController.java +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Copyright 2017-2022 original authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.micronaut.starter.api.create.github; - -import io.micronaut.context.annotation.Requires; -import io.micronaut.core.annotation.NonNull; -import io.micronaut.core.annotation.Nullable; -import io.micronaut.core.util.StringUtils; -import io.micronaut.http.HttpHeaders; -import io.micronaut.http.HttpResponse; -import io.micronaut.http.MediaType; -import io.micronaut.http.annotation.Controller; -import io.micronaut.http.annotation.Get; -import io.micronaut.http.annotation.Header; -import io.micronaut.http.annotation.QueryValue; -import io.micronaut.scheduling.TaskExecutors; -import io.micronaut.scheduling.annotation.ExecuteOn; -import io.micronaut.starter.api.RequestInfo; -import io.micronaut.starter.api.TestFramework; -import io.micronaut.starter.application.ApplicationType; -import io.micronaut.starter.client.github.v3.GitHubRepository; -import io.micronaut.starter.options.BuildTool; -import io.micronaut.starter.options.JdkVersion; -import io.micronaut.starter.options.Language; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.responses.ApiResponses; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import jakarta.validation.constraints.Pattern; -import java.net.URI; -import java.util.List; - -/** - * GitHub create controller. - * - * @author Pavol Gressa - * @since 2.2 - */ -@Controller -@ExecuteOn(TaskExecutors.BLOCKING) -@Requires(beans = {GitHubCreateService.class, GitHubRedirectService.class}) -public class GitHubCreateController implements GitHubCreateOperation { - - private static final Logger LOG = LoggerFactory.getLogger(GitHubCreateController.class); - private final GitHubCreateService gitHubCreateService; - private final GitHubRedirectService redirectService; - - public GitHubCreateController(GitHubCreateService gitHubCreateService, - GitHubRedirectService redirectService) { - this.gitHubCreateService = gitHubCreateService; - this.redirectService = redirectService; - } - - /** - * Creates an application in GitHub repository, generating a json file as the response. - * - * @param type The application type The application type - * @param name The name of the application The name of the application - * @param features The features The chosen features - * @param build The build type (optional, defaults to Gradle) - * @param test The test framework (optional, defaults to JUnit) - * @param lang The language (optional, defaults to Java) - * @return A json containing the generated application details. - */ - @Override - @Get(uri = "/github/{type}/{name}{?features,lang,build,test,javaVersion,code,state}", produces = MediaType.APPLICATION_JSON) - @ApiResponses(value = { - @ApiResponse( - responseCode = "200", - description = """ - Created GitHub repository containing the generated application. In case \ - the configuration contains launcher URI the redirect to launcher is sent.\ - """, - content = @Content( - mediaType = MediaType.APPLICATION_JSON - ) - ), - @ApiResponse( - responseCode = "307", - description = """ - Redirects to GitHub OAuth API to obtain user authorisation code before creating \ - the GitHub repository.\ - """ - ), - @ApiResponse( - responseCode = "307", - description = "Redirects back to launcher in case of successfully created GitHub repository." - )}) - public HttpResponse createApp( - @NonNull ApplicationType type, - @Pattern(regexp = "[\\w\\d-_\\.]+") String name, - @Nullable List features, - @Nullable BuildTool build, - @Nullable TestFramework test, - @Nullable Language lang, - @Nullable JdkVersion javaVersion, - @Nullable String code, - @Nullable String state, - @Nullable @Header(HttpHeaders.USER_AGENT) String userAgent, - @Parameter(hidden = true) @NonNull RequestInfo requestInfo) { - URI launcherURI = redirectService.getLauncherURI(); - try { - if (StringUtils.isEmpty(code) || StringUtils.isEmpty(state)) { - return HttpResponse.temporaryRedirect(redirectService.constructOAuthRedirectUrl(requestInfo)); - } else { - GitHubRepository repository = gitHubCreateService.creatApp( - type, name, features, build, test, lang, javaVersion, code, state, userAgent); - - if (launcherURI == null) { - return HttpResponse.ok(new GitHubCreateDTO(repository.getUrl(), repository.getCloneUrl(), repository.getHtmlUrl())); - } else { - return HttpResponse.temporaryRedirect(redirectService.constructLauncherRedirectUrl(repository)); - } - } - } catch (Exception e) { - if (LOG.isDebugEnabled()) { - LOG.debug("", e); - } - - if (launcherURI == null) { - throw e; - } else { - return HttpResponse.temporaryRedirect(redirectService.constructLauncherErrorRedirectUrl(e.getMessage())); - } - } - } - - /** - * Endpoint handles GitHub OAuth authorisation errors. - * - * @param error error code - * @param errorDescription description - * @return Http redirects - * @see Troubleshooting OAuth App access token request errors - */ - @Get(uri = "/github{?error,error_description}", produces = MediaType.APPLICATION_JSON) - @ApiResponses(value = { - @ApiResponse( - responseCode = "307", - description = "Forwarded GitHub OAuth error message." - ), - @ApiResponse( - responseCode = "200", - description = "Returns GitHub OAuth application callback error." - )}) - public HttpResponse handleCallback( - @Nullable String error, - @Nullable @QueryValue("error_description") String errorDescription) { - URI redirect; - if (!StringUtils.isEmpty(error)) { - redirect = redirectService.constructLauncherErrorRedirectUrl(errorDescription); - } else { - redirect = redirectService.getLauncherURI(); - } - - if (redirect == null) { - return HttpResponse.ok(errorDescription); - } else { - return HttpResponse.temporaryRedirect(redirect); - } - } -} diff --git a/starter-api/src/main/java/io/micronaut/starter/api/create/github/GitHubCreateDTO.java b/starter-api/src/main/java/io/micronaut/starter/api/create/github/GitHubCreateDTO.java deleted file mode 100644 index d8c161f6d05..00000000000 --- a/starter-api/src/main/java/io/micronaut/starter/api/create/github/GitHubCreateDTO.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2017-2022 original authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.micronaut.starter.api.create.github; - -import io.micronaut.core.annotation.Introspected; -import io.swagger.v3.oas.annotations.media.Schema; - -/** - * Create application in GitHub repository. - * - * @author Pavol Gressa - * @since 2.2 - */ -@Introspected -@Schema(name = "GitHubCreate", description = "Details of created GitHub repository with Micronaut application.") -public class GitHubCreateDTO { - private final String url; - private final String cloneUrl; - private final String htmlUrl; - - public GitHubCreateDTO(String url, String cloneUrl, String htmlUrl) { - this.url = url; - this.cloneUrl = cloneUrl; - this.htmlUrl = htmlUrl; - } - - @Schema(description = "Repository url") - public String getUrl() { - return url; - } - - @Schema(description = "Repository clone url") - public String getCloneUrl() { - return cloneUrl; - } - - @Schema(description = "Repository html url") - public String getHtmlUrl() { - return htmlUrl; - } -} diff --git a/starter-api/src/main/java/io/micronaut/starter/api/create/github/GitHubCreateOperation.java b/starter-api/src/main/java/io/micronaut/starter/api/create/github/GitHubCreateOperation.java deleted file mode 100644 index 881321ae547..00000000000 --- a/starter-api/src/main/java/io/micronaut/starter/api/create/github/GitHubCreateOperation.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright 2017-2022 original authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.micronaut.starter.api.create.github; - -import io.micronaut.core.annotation.NonNull; -import io.micronaut.core.annotation.Nullable; -import io.micronaut.http.HttpHeaders; -import io.micronaut.http.HttpResponse; -import io.micronaut.http.annotation.Header; -import io.micronaut.starter.api.RequestInfo; -import io.micronaut.starter.api.TestFramework; -import io.micronaut.starter.application.ApplicationType; -import io.micronaut.starter.options.BuildTool; -import io.micronaut.starter.options.JdkVersion; -import io.micronaut.starter.options.Language; - -import jakarta.validation.constraints.Pattern; -import java.util.List; - -/** - * Defines the signature for creating an application in Github repository. - * - * @author Pavol Gressa - * @since 2.2 - */ -public interface GitHubCreateOperation { - - /** - * Creates and push application to GitHub repository. - * @param type The application type - * @param name The name of the application and GitHub repository - * @param features The features - * @param buildTool The build tool - * @param testFramework The test framework - * @param lang The lang - * @param javaVersion The java version - * @param code The github code - * @return An information about newly created GitHub repository - */ - HttpResponse createApp( - @NonNull ApplicationType type, - @Pattern(regexp = "[\\w\\d-_\\.]+") String name, - @Nullable List features, - @Nullable BuildTool buildTool, - @Nullable TestFramework testFramework, - @Nullable Language lang, - @Nullable JdkVersion javaVersion, - @NonNull String code, - @NonNull String state, - @Nullable @Header(HttpHeaders.USER_AGENT) String userAgent, - @NonNull RequestInfo requestInfo - ); -} diff --git a/starter-api/src/main/java/io/micronaut/starter/api/create/github/GitHubCreateService.java b/starter-api/src/main/java/io/micronaut/starter/api/create/github/GitHubCreateService.java deleted file mode 100644 index c50319d4509..00000000000 --- a/starter-api/src/main/java/io/micronaut/starter/api/create/github/GitHubCreateService.java +++ /dev/null @@ -1,208 +0,0 @@ -/* - * Copyright 2017-2022 original authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.micronaut.starter.api.create.github; - -import io.micronaut.context.annotation.Requires; -import io.micronaut.context.event.ApplicationEventPublisher; -import io.micronaut.core.annotation.NonNull; -import io.micronaut.core.annotation.Nullable; -import io.micronaut.http.client.exceptions.HttpClientResponseException; -import io.micronaut.starter.api.StarterConfiguration; -import io.micronaut.starter.api.TestFramework; -import io.micronaut.starter.api.create.AbstractCreateController; -import io.micronaut.starter.application.ApplicationType; -import io.micronaut.starter.application.generator.GeneratorContext; -import io.micronaut.starter.application.generator.ProjectGenerator; -import io.micronaut.starter.client.github.oauth.AccessToken; -import io.micronaut.starter.client.github.oauth.GitHubOAuthClient; -import io.micronaut.starter.client.github.v3.GitHubApiClient; -import io.micronaut.starter.client.github.v3.GitHubRepository; -import io.micronaut.starter.client.github.v3.GitHubUser; -import io.micronaut.starter.io.ConsoleOutput; -import io.micronaut.starter.io.FileSystemOutputHandler; -import io.micronaut.starter.io.OutputHandler; -import io.micronaut.starter.options.BuildTool; -import io.micronaut.starter.options.JdkVersion; -import io.micronaut.starter.options.Language; -import io.micronaut.starter.util.GitHubUtil; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import jakarta.inject.Singleton; -import jakarta.validation.constraints.NotNull; -import java.io.File; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.Comparator; -import java.util.List; - -/** - * GitHub create service. - * - * @author Pavol Gressa - * @since 2.2 - */ -@Singleton -@Requires(beans = GitHubOAuthClient.class) -public class GitHubCreateService extends AbstractCreateController { - - private static final Logger LOG = LoggerFactory.getLogger(GitHubCreateService.class); - private static final String TOKEN_PREFIX = "token "; - private static final String REPO_PREFIX = "generated"; - private static final String TMP_DIR = "/tmp"; - - private final GitHubOAuthClient gitHubOAuthClient; - private final GitHubApiClient gitHubApiClient; - private final StarterConfiguration.GitHubConfiguration gitHubConfiguration; - - public GitHubCreateService( - @NotNull ProjectGenerator projectGenerator, - @NotNull ApplicationEventPublisher eventPublisher, - @NotNull GitHubOAuthClient gitHubOAuthClient, - @NotNull GitHubApiClient gitHubApiClient, - @NotNull StarterConfiguration.GitHubConfiguration gitHubConfiguration) { - super(projectGenerator, eventPublisher); - this.gitHubOAuthClient = gitHubOAuthClient; - this.gitHubApiClient = gitHubApiClient; - this.gitHubConfiguration = gitHubConfiguration; - } - - protected GitHubRepository creatApp( - @NonNull ApplicationType type, - @NonNull String name, - @Nullable List features, - @Nullable BuildTool buildTool, - @Nullable TestFramework testFramework, - @Nullable Language lang, - @Nullable JdkVersion javaVersion, - @NonNull String code, - @NonNull String state, - @Nullable String userAgent) { - AccessToken accessToken = getGitHubAccessToken(code, state); - String authToken = TOKEN_PREFIX + accessToken.getAccessToken(); - - GitHubUser gitHubUser = getGitHubUser(authToken); - - GeneratorContext generatorContext = createProjectGeneratorContext( - type, name, features, buildTool, testFramework, lang, javaVersion, userAgent); - - String repoName = generatorContext.getProject().getName(); - String repoDescription = "Micronaut %s Application".formatted(generatorContext.getProject().getNaturalName()); - GitHubRepository githubRepository = createGitHubRepository(authToken, repoName, repoDescription, gitHubUser); - - pushToGithubRepository(generatorContext, gitHubUser, githubRepository, accessToken); - - return githubRepository; - } - - private void pushToGithubRepository(GeneratorContext generatorContext, GitHubUser gitHubUser, - GitHubRepository githubRepository, AccessToken accessToken) { - Path repoPath = null; - try { - repoPath = Files.createTempDirectory(Paths.get(TMP_DIR), REPO_PREFIX); - generateAppLocally(generatorContext, repoPath); - GitHubUtil.initAndPushToGitHubRepository( - githubRepository, gitHubUser, repoPath, accessToken.getAccessToken()); - - if (LOG.isDebugEnabled()) { - LOG.debug("Successfully pushed application to {}", githubRepository); - } - } catch (Exception e) { - throw new RuntimeException("Failed to push to created repository: " + githubRepository.getUrl()); - } finally { - try { - if (repoPath != null) { - deleteDirectory(repoPath); - } - } catch (IOException e) { - LOG.error("Error cleaning up temporary project directory: {}", e.getMessage(), e); - } - } - } - - private GitHubRepository createGitHubRepository(String authToken, String repoName, String repoDescription, - GitHubUser gitHubUser) { - try { - if (gitHubApiClient.getRepository(authToken, gitHubUser.getLogin(), repoName) != null) { - throw new IllegalArgumentException("Repository " + repoName + " already exists."); - } - - GitHubRepository githubRepository = gitHubApiClient.createRepository(authToken, - new GitHubRepository(repoName, repoDescription)); - - if (LOG.isDebugEnabled()) { - LOG.debug("Created repository {}", githubRepository); - } - return githubRepository; - } catch (HttpClientResponseException e) { - throw new RuntimeException("Failed to create repository " + repoName); - } - } - - private AccessToken getGitHubAccessToken(String code, String state) { - try { - return gitHubOAuthClient.accessToken(gitHubConfiguration.getClientId(), - gitHubConfiguration.getClientSecret(), code, state); - } catch (HttpClientResponseException e) { - throw new RuntimeException("Failed to get user access token."); - } - } - - private GitHubUser getGitHubUser(String authToken) { - try { - GitHubUser gitHubUser = gitHubApiClient.getUser(authToken); - if (LOG.isDebugEnabled()) { - LOG.debug("Fetched user {}", gitHubUser); - } - return gitHubUser; - } catch (HttpClientResponseException e) { - throw new RuntimeException("Failed to get user."); - } - } - - /** - * Generates the micronaut application into specified {@code repoPath} directory - * - * @param generatorContext context - * @param repoPath path - * @throws IOException - */ - protected void generateAppLocally(@NotNull GeneratorContext generatorContext, @NotNull Path repoPath) throws IOException { - try { - if (!Files.isDirectory(repoPath)) { - throw new IllegalArgumentException("The path %s must be a directory!".formatted(repoPath.toString())); - } - - OutputHandler outputHandler = new FileSystemOutputHandler(repoPath.toFile(), ConsoleOutput.NOOP); - projectGenerator.generate(generatorContext.getApplicationType(), - generatorContext.getProject(), - outputHandler, - generatorContext); - } catch (Exception e) { - LOG.error("Error generating application: {}", e.getMessage(), e); - throw new IOException(e.getMessage(), e); - } - } - - private static void deleteDirectory(Path dir) throws IOException { - Files.walk(dir) - .sorted(Comparator.reverseOrder()) - .map(Path::toFile) - .forEach(File::delete); - } -} diff --git a/starter-api/src/main/java/io/micronaut/starter/api/create/github/GitHubRedirectService.java b/starter-api/src/main/java/io/micronaut/starter/api/create/github/GitHubRedirectService.java deleted file mode 100644 index 11504c4574a..00000000000 --- a/starter-api/src/main/java/io/micronaut/starter/api/create/github/GitHubRedirectService.java +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Copyright 2017-2022 original authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.micronaut.starter.api.create.github; - -import io.micronaut.context.annotation.Property; -import io.micronaut.context.annotation.Requires; -import io.micronaut.http.uri.UriBuilder; -import io.micronaut.starter.api.RequestInfo; -import io.micronaut.starter.api.StarterConfiguration; -import io.micronaut.starter.client.github.oauth.GitHubOAuthClient; -import io.micronaut.starter.client.github.v3.GitHubRepository; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import jakarta.inject.Singleton; -import jakarta.validation.constraints.NotNull; -import java.net.URI; -import java.util.UUID; - -/** - * Redirect service. - * - * @author Pavol Gressa - * @since 2.2 - */ -@Singleton -@Requires(property = GitHubRedirectService.OAUTH_URL) -public class GitHubRedirectService { - - public static final String OAUTH_URL = "micronaut.http.services." + GitHubOAuthClient.SERVICE_ID + ".url"; - private static final Logger LOG = LoggerFactory.getLogger(GitHubRedirectService.class); - private static final String AUTHORIZE_PATH = "/login/oauth/authorize"; - - private final String githubOAuthUrl; - private final StarterConfiguration starterConfiguration; - private final StarterConfiguration.GitHubConfiguration gitHubConfiguration; - - public GitHubRedirectService( - @NotNull @Property(name = OAUTH_URL) String githubOAuthUrl, - @NotNull StarterConfiguration starterConfiguration, - @NotNull StarterConfiguration.GitHubConfiguration gitHubConfiguration) { - this.githubOAuthUrl = githubOAuthUrl + AUTHORIZE_PATH; - this.starterConfiguration = starterConfiguration; - this.gitHubConfiguration = gitHubConfiguration; - } - - /** - * Creates redirect URI to github oauth auhtorise in order to receive the user access code. - * - * @param requestInfo origin request info - * @return URI to github oauth authorise - */ - protected URI constructOAuthRedirectUrl(RequestInfo requestInfo) { - try { - UriBuilder uriBuilder = UriBuilder.of(requestInfo.getServerURL()).path(requestInfo.getPath()); - requestInfo.getParameters().forEachValue(uriBuilder::queryParam); - URI redirectUri = uriBuilder.build(); - - return UriBuilder.of(githubOAuthUrl) - .queryParam("scope", gitHubConfiguration.getTokenPermissions()) - .queryParam("client_id", gitHubConfiguration.getClientId()) - .queryParam("redirect_uri", redirectUri.toString()) - .queryParam("state", UUID.randomUUID().toString()) - .build(); - } catch (Exception e) { - String msg = "Failed to construct redirect URI using request " + requestInfo + " to GiHub OAuth: " + e.getMessage(); - LOG.error(msg, e); - throw new RuntimeException(msg); - } - } - - /** - * Creates redirect URI back to launcher app with details about created github repository in query parameters. - * - * @param gitHubRepository github repository - * @return URI or null if the launcher url is missing in starter - */ - protected URI constructLauncherRedirectUrl(GitHubRepository gitHubRepository) { - URI redirectUri = getLauncherURI(); - if (redirectUri == null) { - if (LOG.isWarnEnabled()) { - LOG.warn("Can't construct redirect back to launcher as configuration is missing redirect uri."); - } - return null; - } - - try { - return UriBuilder.of(redirectUri) - .queryParam("url", gitHubRepository.getUrl()) - .queryParam("cloneUrl", gitHubRepository.getCloneUrl()) - .queryParam("htmlUrl", gitHubRepository.getHtmlUrl()) - .build(); - } catch (Exception e) { - String msg = "Failed to construct redirect to URI back to launcher: " + e.getMessage(); - LOG.error(msg, e); - throw new RuntimeException(msg); - } - } - - /** - * Creates redirect URI back to launcher app with error message. - * - * @param error message - * @return URI or null if the launcher url is missing in starter - */ - protected URI constructLauncherErrorRedirectUrl(String error) { - URI redirectUri = getLauncherURI(); - if (redirectUri == null) { - if (LOG.isWarnEnabled()) { - LOG.warn("Can't construct redirect back to launcher as configuration is missing redirect uri."); - } - return null; - } - - try { - return UriBuilder.of(redirectUri) - .queryParam("error", error) - .build(); - } catch (Exception e) { - String msg = "Failed to construct error redirect to URI back to launcher: " + e.getMessage(); - LOG.error(msg, e); - throw new RuntimeException(msg); - } - } - - /** - * Returns launcher uri. - * @return uri - */ - protected URI getLauncherURI() { - return starterConfiguration.getRedirectUri().orElse(null); - } -} diff --git a/starter-api/src/main/java/io/micronaut/starter/api/preview/PreviewController.java b/starter-api/src/main/java/io/micronaut/starter/api/preview/PreviewController.java index a504a1cadb7..463c08cb404 100644 --- a/starter-api/src/main/java/io/micronaut/starter/api/preview/PreviewController.java +++ b/starter-api/src/main/java/io/micronaut/starter/api/preview/PreviewController.java @@ -75,6 +75,7 @@ public PreviewController(ProjectGenerator projectGenerator, ApplicationEventPubl * @param build The build type (optional, defaults to Gradle) * @param test The test framework (optional, defaults to JUnit) * @param lang The language (optional, defaults to Java) + * @param javaVersion The jdk version (optional, defaults to {@link MicronautJdkVersionConfiguration#DEFAULT_OPTION}) * @return A preview of the application contents. */ @Get(uri = "/{type}/{name}{?features,lang,build,test,javaVersion}", produces = MediaType.APPLICATION_JSON) diff --git a/starter-api/src/main/java/io/micronaut/starter/api/preview/PreviewOperations.java b/starter-api/src/main/java/io/micronaut/starter/api/preview/PreviewOperations.java index 1df241eb104..ba0e7af62db 100644 --- a/starter-api/src/main/java/io/micronaut/starter/api/preview/PreviewOperations.java +++ b/starter-api/src/main/java/io/micronaut/starter/api/preview/PreviewOperations.java @@ -36,6 +36,7 @@ public interface PreviewOperations { * @param buildTool The build tool * @param testFramework The test framework * @param lang The lang + * @param javaVersion The JdkVersion * @param requestInfo The request info * @return An HTTP response that emits a writable */ diff --git a/starter-api/src/test/groovy/io/micronaut/starter/api/JdkVersionDTOSpec.groovy b/starter-api/src/test/groovy/io/micronaut/starter/api/JdkVersionDTOSpec.groovy new file mode 100644 index 00000000000..42f2fdf7b9c --- /dev/null +++ b/starter-api/src/test/groovy/io/micronaut/starter/api/JdkVersionDTOSpec.groovy @@ -0,0 +1,27 @@ +package io.micronaut.starter.api + +import io.micronaut.json.JsonMapper +import io.micronaut.starter.options.JdkVersion +import io.micronaut.starter.options.MicronautJdkVersionConfiguration +import io.micronaut.test.extensions.spock.annotation.MicronautTest +import jakarta.inject.Inject +import spock.lang.Specification + +@MicronautTest +class JdkVersionDTOSpec extends Specification { + @Inject + JsonMapper jsonMapper + + void "Serialize JdkVersionDTO with jdk = #jdkVersion"(JdkVersion jdkVersion) { + when: + String json = jsonMapper.writeValueAsString(new JdkVersionDTO(jdkVersion)) + int jdk = jdkVersion.majorVersion() + then: + json.contains("\"value\":\"JDK_${jdk}\"") + json.contains("\"label\":\"${jdk}\"}") + json.contains("\"name\":\"JDK_${jdk}\"") + + where: + jdkVersion << MicronautJdkVersionConfiguration.SUPPORTED_JDKS + } +} diff --git a/starter-api/src/test/groovy/io/micronaut/starter/api/JdkVersionSpec.groovy b/starter-api/src/test/groovy/io/micronaut/starter/api/JdkVersionSpec.groovy new file mode 100644 index 00000000000..e677454f8f5 --- /dev/null +++ b/starter-api/src/test/groovy/io/micronaut/starter/api/JdkVersionSpec.groovy @@ -0,0 +1,41 @@ +package io.micronaut.starter.api + +import io.micronaut.json.JsonMapper +import io.micronaut.serde.annotation.Serdeable +import io.micronaut.starter.options.JdkVersion +import io.micronaut.starter.options.MicronautJdkVersionConfiguration +import io.micronaut.test.extensions.spock.annotation.MicronautTest +import jakarta.inject.Inject +import spock.lang.Specification + +@MicronautTest +class JdkVersionSpec extends Specification { + @Inject + JsonMapper jsonMapper + + void "Serialize and deserialize JdkVersion with jdk = #jdkVersion"(JdkVersion jdkVersion) { + given: + int jdk = jdkVersion.majorVersion() + + when: + String json = jsonMapper.writeValueAsString(new Foo(jdk: jdkVersion)) + + then: + json.contains("{\"jdk\":\"JDK_${jdk}\"}") + + when: + Foo foo = jsonMapper.readValue("{\"jdk\":\"JDK_${jdk}\"}", Foo.class) + + then: + jdkVersion == foo.jdk + + where: + jdkVersion << MicronautJdkVersionConfiguration.SUPPORTED_JDKS + + } + + @Serdeable + static class Foo { + JdkVersion jdk + } +} diff --git a/starter-api/src/test/groovy/io/micronaut/starter/api/PreviewControllerSpec.groovy b/starter-api/src/test/groovy/io/micronaut/starter/api/PreviewControllerSpec.groovy index 8d752c8f1a9..1d5d42c7ec1 100644 --- a/starter-api/src/test/groovy/io/micronaut/starter/api/PreviewControllerSpec.groovy +++ b/starter-api/src/test/groovy/io/micronaut/starter/api/PreviewControllerSpec.groovy @@ -1,5 +1,6 @@ package io.micronaut.starter.api +import io.micronaut.context.annotation.Property import io.micronaut.core.annotation.Nullable import io.micronaut.http.HttpStatus import io.micronaut.http.MediaType @@ -9,10 +10,13 @@ import io.micronaut.http.client.exceptions.HttpClientResponseException import io.micronaut.starter.api.preview.PreviewDTO import io.micronaut.starter.application.ApplicationType import io.micronaut.starter.options.BuildTool +import io.micronaut.starter.options.JdkVersion import io.micronaut.starter.options.Language +import io.micronaut.starter.options.MicronautJdkVersionConfiguration import io.micronaut.starter.options.TestFramework import io.micronaut.test.extensions.spock.annotation.MicronautTest import jakarta.inject.Inject +import spock.lang.Issue import spock.lang.Specification @MicronautTest @@ -22,7 +26,7 @@ class PreviewControllerSpec extends Specification { void "test default create app command"() { when: - def map = client.previewApp(ApplicationType.DEFAULT, "test", Collections.emptyList(), null, null, null) + def map = client.previewApp(ApplicationType.DEFAULT, "test", Collections.emptyList(), null, null, null, null) then: map.contents.containsKey("build.gradle.kts") @@ -31,7 +35,7 @@ class PreviewControllerSpec extends Specification { void "test preview - bad feature"() { when: - def map = client.previewApp(ApplicationType.DEFAULT, "test", ['juikkkk'], null, null, null) + def map = client.previewApp(ApplicationType.DEFAULT, "test", ['juikkkk'], null, null, null, null) then: def e = thrown(HttpClientResponseException) @@ -39,16 +43,34 @@ class PreviewControllerSpec extends Specification { e.getResponse().getBody(Map).get()._embedded.errors[0].message == 'The requested feature does not exist: juikkkk' } + @Issue("https://github.com/micronaut-projects/micronaut-starter/issues/2321") + void "test preview - jdk version=#jdkVersion"(JdkVersion jdkVersion) { + when: + def map = client.previewApp(ApplicationType.DEFAULT, "com.example.demo", Collections.emptyList(), + BuildTool.GRADLE_KOTLIN, TestFramework.JUNIT, Language.JAVA, jdkVersion) + String buildFile = map.contents.get("build.gradle.kts") + int jdk = jdkVersion.majorVersion + + then: + buildFile + buildFile.contains("sourceCompatibility = JavaVersion.toVersion(\"${jdk}\")") + buildFile.contains("targetCompatibility = JavaVersion.toVersion(\"${jdk}\")") + + where: + jdkVersion << MicronautJdkVersionConfiguration.SUPPORTED_JDKS + } + @Client('/preview') static interface PreviewClient { - @Get(uri = "/default/{name}{?features,build,test,lang}", consumes = MediaType.APPLICATION_JSON) + @Get(uri = "/default/{name}{?features,build,test,lang,javaVersion}", consumes = MediaType.APPLICATION_JSON) PreviewDTO previewApp( ApplicationType type, String name, @Nullable List features, @Nullable BuildTool build, @Nullable TestFramework test, - @Nullable Language lang + @Nullable Language lang, + @Nullable JdkVersion javaVersion ); } } diff --git a/starter-api/src/test/groovy/io/micronaut/starter/api/ZipCreateControllerSpec.groovy b/starter-api/src/test/groovy/io/micronaut/starter/api/ZipCreateControllerSpec.groovy index 8739fc3fea6..c1db69a4da8 100644 --- a/starter-api/src/test/groovy/io/micronaut/starter/api/ZipCreateControllerSpec.groovy +++ b/starter-api/src/test/groovy/io/micronaut/starter/api/ZipCreateControllerSpec.groovy @@ -10,12 +10,15 @@ import io.micronaut.http.client.annotation.Client import io.micronaut.http.client.exceptions.HttpClientResponseException import io.micronaut.starter.api.event.ApplicationGeneratingEvent import io.micronaut.starter.options.BuildTool +import io.micronaut.starter.options.JdkVersion import io.micronaut.starter.options.Language +import io.micronaut.starter.options.MicronautJdkVersionConfiguration import io.micronaut.starter.options.TestFramework import io.micronaut.starter.util.ZipUtil import io.micronaut.test.extensions.spock.annotation.MicronautTest import jakarta.inject.Inject import jakarta.inject.Singleton +import spock.lang.Issue import spock.lang.Specification @MicronautTest @@ -29,7 +32,7 @@ class ZipCreateControllerSpec extends Specification { void "test default create app command"() { when: - def bytes = client.createApp("test", Collections.emptyList(), null, null, null) + def bytes = client.createApp("test", Collections.emptyList(), null, null, null, null) then: ZipUtil.isZip(bytes) @@ -38,7 +41,7 @@ class ZipCreateControllerSpec extends Specification { void "test default create app - bad project name"() { when: - client.createApp("tes%*&*t", Collections.emptyList(), null, null, null) + client.createApp("tes%*&*t", Collections.emptyList(), null, null, null, null) then: HttpClientResponseException e = thrown() @@ -48,7 +51,7 @@ class ZipCreateControllerSpec extends Specification { void "test default create app - missing feature"() { when: - client.createApp("test",['junkkkk'], null, null, null) + client.createApp("test",['junkkkk'], null, null, null, null) then: def e = thrown(HttpClientResponseException) @@ -58,7 +61,7 @@ class ZipCreateControllerSpec extends Specification { void "test default create app file name"() { when: - def response = client.createResponse("test", Collections.emptyList(), null, null, null) + def response = client.createResponse("test", Collections.emptyList(), null, null, null, null) def bytes = response.body() then: @@ -68,7 +71,7 @@ class ZipCreateControllerSpec extends Specification { void "test get zip"() { when: - def response = client.getZip("test", Collections.emptyList(), null, null, null) + def response = client.getZip("test", Collections.emptyList(), null, null, null, null) def bytes = response.body() then: @@ -78,7 +81,7 @@ class ZipCreateControllerSpec extends Specification { void "test default create app with feature"() { when: - def bytes = client.createApp("test", ['graalvm'], null, null, null) + def bytes = client.createApp("test", ['graalvm'], null, null, null, null) then: ZipUtil.containsFile(bytes, "build.gradle.kts") @@ -87,7 +90,7 @@ class ZipCreateControllerSpec extends Specification { void "test create app with kotlin"() { when: - def bytes = client.createApp("test", ['graalvm'], null, null, Language.KOTLIN) + def bytes = client.createApp("test", ['graalvm'], null, null, Language.KOTLIN, null) then: ZipUtil.containsFile(bytes, "Application.kt") @@ -95,7 +98,7 @@ class ZipCreateControllerSpec extends Specification { void "test create app with groovy"() { when: - def bytes = client.createApp("test", ['flyway'], null, null, Language.GROOVY) + def bytes = client.createApp("test", ['flyway'], null, null, Language.GROOVY, null) then: ZipUtil.containsFile(bytes, "Application.groovy") @@ -103,7 +106,7 @@ class ZipCreateControllerSpec extends Specification { void "test create app with maven"() { when: - def bytes = client.createApp("test", ['flyway'], BuildTool.MAVEN, null, Language.GROOVY) + def bytes = client.createApp("test", ['flyway'], BuildTool.MAVEN, null, Language.GROOVY, null) then: ZipUtil.containsFile(bytes, "pom.xml") @@ -111,12 +114,25 @@ class ZipCreateControllerSpec extends Specification { void "test create app with spock"() { when: - def bytes = client.createApp("test", ['flyway'], BuildTool.GRADLE, TestFramework.SPOCK, Language.GROOVY) + def bytes = client.createApp("test", ['flyway'], BuildTool.GRADLE, TestFramework.SPOCK, Language.GROOVY, null) then: ZipUtil.containsFileWithContents(bytes, "build.gradle", "spock") } + @Issue("https://github.com/micronaut-projects/micronaut-starter/issues/2321") + void "test create app with jdk=#jdkVersion"(JdkVersion jdkVersion) { + when: + def bytes = client.createApp("test", ['flyway'], BuildTool.GRADLE, TestFramework.SPOCK, Language.GROOVY, jdkVersion) + + then: + ZipUtil.containsFileWithContents(bytes, "build.gradle", "sourceCompatibility = JavaVersion.toVersion(\"${jdkVersion.majorVersion}\")") + ZipUtil.containsFileWithContents(bytes, "build.gradle", "targetCompatibility = JavaVersion.toVersion(\"${jdkVersion.majorVersion}\")") + + where: + jdkVersion << MicronautJdkVersionConfiguration.SUPPORTED_JDKS + } + @Singleton static class MyEventListener implements ApplicationEventListener { boolean fired = false @@ -128,31 +144,34 @@ class ZipCreateControllerSpec extends Specification { @Client('/') static interface CreateClient { - @Get(uri = "/create/default/{name}{?features,build,test,lang}", consumes = "application/zip") + @Get(uri = "/create/default/{name}{?features,build,test,lang,javaVersion}", consumes = "application/zip") byte[] createApp( String name, @Nullable List features, @Nullable BuildTool build, @Nullable TestFramework test, - @Nullable Language lang + @Nullable Language lang, + @Nullable JdkVersion javaVersion ); - @Get(uri = "/create/default/{name}{?features,build,test,lang}", consumes = "application/zip") + @Get(uri = "/create/default/{name}{?features,build,test,lang,javaVersion}", consumes = "application/zip") HttpResponse createResponse( String name, @Nullable List features, @Nullable BuildTool build, @Nullable TestFramework test, - @Nullable Language lang + @Nullable Language lang, + @Nullable JdkVersion javaVersion ); - @Get(uri = "/{name}.zip{?features,build,test,lang}", consumes = "application/zip") + @Get(uri = "/{name}.zip{?features,build,test,lang,javaVersion}", consumes = "application/zip") HttpResponse getZip( String name, @Nullable List features, @Nullable BuildTool build, @Nullable TestFramework test, - @Nullable Language lang + @Nullable Language lang, + @Nullable JdkVersion javaVersion ); } } diff --git a/starter-api/src/test/groovy/io/micronaut/starter/api/create/github/GitHubCreateControllerSpec.groovy b/starter-api/src/test/groovy/io/micronaut/starter/api/create/github/GitHubCreateControllerSpec.groovy deleted file mode 100644 index a8727aa4edf..00000000000 --- a/starter-api/src/test/groovy/io/micronaut/starter/api/create/github/GitHubCreateControllerSpec.groovy +++ /dev/null @@ -1,178 +0,0 @@ -package io.micronaut.starter.api.create.github - -import io.micronaut.context.ApplicationContext -import io.micronaut.context.annotation.Requires -import io.micronaut.core.util.StringUtils -import io.micronaut.http.HttpHeaders -import io.micronaut.http.HttpRequest -import io.micronaut.http.HttpResponse -import io.micronaut.http.MediaType -import io.micronaut.http.annotation.* -import io.micronaut.http.client.HttpClient -import io.micronaut.runtime.server.EmbeddedServer -import io.micronaut.starter.client.github.oauth.AccessToken -import io.micronaut.starter.client.github.oauth.GitHubOAuthOperations -import io.micronaut.starter.client.github.v3.* -import io.micronaut.starter.util.GitHubUtil -import org.eclipse.jgit.api.Git -import org.eclipse.jgit.revwalk.RevCommit -import org.eclipse.jgit.transport.URIish -import spock.lang.PendingFeature -import spock.lang.Specification - -import java.nio.file.Files -import java.nio.file.Path -import java.nio.file.Paths - -class GitHubCreateControllerSpec extends Specification { - - void "returns redirect with error when repository exists"() { - given: - EmbeddedServer githubServer = ApplicationContext.run(EmbeddedServer, Collections.singletonMap("spec.name", "GitHubCreateControllerSpec")) - Map configuration = new HashMap<>(serverConfiguration(githubServer)) - configuration.put("micronaut.http.client.follow-redirects", StringUtils.FALSE) - EmbeddedServer server = ApplicationContext.run(EmbeddedServer, configuration) - HttpClient httpClient = server.applicationContext.createBean(HttpClient, server.URL) - - when: - HttpResponse response = httpClient.toBlocking().exchange(HttpRequest.GET("/github/default/foo.bar.existing?code=123&state=123")) - - then: - response.getStatus().code == 307 - response.header(HttpHeaders.LOCATION).contains("error") - response.header(HttpHeaders.LOCATION).startsWith("https://micronaut.io/launch") - - cleanup: - server.close() - githubServer.close() - } - - @PendingFeature - void "returns redirect to launcher if redirectUri is configured"() { - given: - EmbeddedServer githubServer = ApplicationContext.run(EmbeddedServer, Collections.singletonMap("spec.name", "GitHubCreateControllerSpec")) - Map configuration = new HashMap<>(serverConfiguration(githubServer)) - configuration.put("micronaut.http.client.follow-redirects", StringUtils.FALSE) - EmbeddedServer server = ApplicationContext.run(EmbeddedServer, configuration) - HttpClient httpClient = server.applicationContext.createBean(HttpClient, server.URL) - - when: - HttpResponse response = httpClient.toBlocking().exchange(HttpRequest.GET("/github/default/foo?code=123&state=123")) - - then: - response.getStatus().code == 307 - response.header(HttpHeaders.LOCATION).contains("cloneUrl") - response.header(HttpHeaders.LOCATION).contains("htmlUrl") - response.header(HttpHeaders.LOCATION).contains("url") - response.header(HttpHeaders.LOCATION).startsWith("https://micronaut.io/launch") - - cleanup: - server.close() - githubServer.close() - } - - @PendingFeature - void "returns github repository details when launcher missing"() { - given: - EmbeddedServer githubServer = ApplicationContext.run(EmbeddedServer, Collections.singletonMap("spec.name", "GitHubCreateControllerSpec")) - Map configuration = new HashMap<>(serverConfiguration(githubServer)) - configuration.put("micronaut.starter.redirectUri", "") - EmbeddedServer server = ApplicationContext.run(EmbeddedServer, configuration) - HttpClient httpClient = server.applicationContext.createBean(HttpClient, server.URL) - - when: - GitHubCreateDTO dto = httpClient.toBlocking().retrieve(HttpRequest.GET("/github/default/foo?code=123&state=123"), GitHubCreateDTO.class) - - then: - Path clonePath = Paths.get(new URL(dto.cloneUrl).toURI()) - Git bareRepo = Git.open(clonePath.toFile()) - List commits = bareRepo.log().call().toList() - commits.size() == 1 - commits.get(0).fullMessage == GitHubUtil.INIT_COMMIT_MESSAGE - commits.get(0).authorIdent.name == "name" - commits.get(0).authorIdent.emailAddress == "email" - - cleanup: - server.close() - githubServer.close() - clonePath.toFile().deleteDir() - } - - @Requires(property = 'spec.name', value = 'GitHubCreateControllerSpec') - @Controller(value = "/") - static class GitHubApiMockedController implements GitHubApiOperations { - - @Override - @Post(value = "/user/repos", processes = [GitHubApiClient.GITHUB_V3_TYPE, MediaType.APPLICATION_JSON]) - GitHubRepository createRepository( - @Header(HttpHeaders.AUTHORIZATION) String oauthToken, - @Body GitHubRepository gitHubRepository) { - Path temp = Files.createTempDirectory('test-github-create') - Git repo = Git.init().setDirectory(temp.toFile()).setBare(true).call() - URIish uri = new URIish(repo.getRepository().getDirectory().toURI().toURL()) - return new GitHubRepository(gitHubRepository.name, gitHubRepository.description, 'url', 'html_url', uri.toString()) - } - - @Override - @Get(value = "/repos/{owner}/{repo}", processes = [GitHubApiClient.GITHUB_V3_TYPE]) - GitHubRepository getRepository( - @Header(HttpHeaders.AUTHORIZATION) String oauthToken, - @PathVariable String owner, - @PathVariable String repo) { - return repo == "existing" ? new GitHubRepository("existing", null) : null - } - - @Override - void deleteRepository(@Header(HttpHeaders.AUTHORIZATION) String oauthToken, @PathVariable String owner, @PathVariable String repo) { - // no-op - } - - @Override - @Get(value = "/user", processes = [GitHubApiClient.GITHUB_V3_TYPE, MediaType.APPLICATION_JSON]) - GitHubUser getUser(@Header(HttpHeaders.AUTHORIZATION) String oauthToken) { - return new GitHubUser("login", "email", "name") - } - - @Override - void createSecret(@Header(HttpHeaders.AUTHORIZATION) String oauthToken, @PathVariable String owner, @PathVariable String repo, @PathVariable String secretName, @Body GitHubSecret secret) { - // no-op - } - - @Override - GitHubSecretsPublicKey getSecretPublicKey(@Header(HttpHeaders.AUTHORIZATION) String oauthToken, @PathVariable String owner, @PathVariable String repo) { - return null - } - - @Override - GitHubWorkflowRuns listWorkflows(@Header(HttpHeaders.AUTHORIZATION) String oauthToken, @PathVariable String owner, @PathVariable String repo) { - return null - } - - @Override - GitHubWorkflowRun getWorkflowRun(@Header(HttpHeaders.AUTHORIZATION) String oauthToken, @PathVariable String owner, @PathVariable String repo, @PathVariable Long runId) { - return null - } - } - - @Requires(property = 'spec.name', value = 'GitHubCreateControllerSpec') - @Controller("/login/oauth") - static class GitHubOauthMockedController implements GitHubOAuthOperations { - - @Override - @Post(value = "/access_token") - AccessToken accessToken( - @QueryValue("client_id") String clientId, - @QueryValue("client_secret") String clientSecret, - @QueryValue String code, - @QueryValue String state) { - return new AccessToken("foo", "repo,user", "123") - } - } - - private static Map serverConfiguration(EmbeddedServer server) { - return Map.of("micronaut.http.services.github-oauth.url", "http://localhost:" + server.port, - "micronaut.http.services.github-api-v3.url", "http://localhost:" + server.port, - "micronaut.starter.github.client-id", "clientId", - "micronaut.starter.github.client-secret", "clientSecret") - } -} diff --git a/starter-api/src/test/groovy/io/micronaut/starter/api/create/github/GitHubCreateServiceTest.groovy b/starter-api/src/test/groovy/io/micronaut/starter/api/create/github/GitHubCreateServiceTest.groovy deleted file mode 100644 index 5623741952b..00000000000 --- a/starter-api/src/test/groovy/io/micronaut/starter/api/create/github/GitHubCreateServiceTest.groovy +++ /dev/null @@ -1,49 +0,0 @@ -package io.micronaut.starter.api.create.github - -import io.micronaut.context.annotation.Property -import io.micronaut.starter.application.ApplicationType -import io.micronaut.starter.application.Project -import io.micronaut.starter.application.generator.GeneratorContext -import io.micronaut.starter.application.generator.ProjectGenerator -import io.micronaut.starter.io.ConsoleOutput -import io.micronaut.starter.options.Options -import io.micronaut.starter.util.NameUtils -import io.micronaut.test.extensions.spock.annotation.MicronautTest -import spock.lang.Specification - -import jakarta.inject.Inject -import java.nio.file.Files -import java.nio.file.Path -import java.nio.file.Paths - -@Property(name = "micronaut.http.services.github-oauth.url", value = "https://github.com") -@Property(name = "micronaut.http.services.github-api-v3.url", value = "https://api.github.com") -@MicronautTest -class GitHubCreateServiceTest extends Specification{ - - @Inject GitHubCreateService gitHubCreateService - @Inject ProjectGenerator projectGenerator - - void 'test generate app to local path'(){ - given: - Project project = NameUtils.parse('io.micronaut.foo') - GeneratorContext context = projectGenerator.createGeneratorContext( - ApplicationType.DEFAULT, - project, - new Options(), - null, - [], - ConsoleOutput.NOOP - ) - Path path = Files.createTempDirectory("test-generate") - - when: - gitHubCreateService.generateAppLocally(context, path) - - then: - Files.exists(Paths.get(path.toString(), "build.gradle.kts")) - - cleanup: - path.toFile().deleteDir() - } -} diff --git a/starter-api/src/test/groovy/io/micronaut/starter/api/create/github/GitHubRedirectServiceTest.groovy b/starter-api/src/test/groovy/io/micronaut/starter/api/create/github/GitHubRedirectServiceTest.groovy deleted file mode 100644 index a5aa50cb05d..00000000000 --- a/starter-api/src/test/groovy/io/micronaut/starter/api/create/github/GitHubRedirectServiceTest.groovy +++ /dev/null @@ -1,58 +0,0 @@ -package io.micronaut.starter.api.create.github - -import io.micronaut.context.annotation.Property -import io.micronaut.http.HttpParameters -import io.micronaut.starter.api.RequestInfo -import io.micronaut.starter.client.github.v3.GitHubRepository -import io.micronaut.test.extensions.spock.annotation.MicronautTest -import spock.lang.Specification - -import jakarta.inject.Inject - -@Property(name = "micronaut.http.services.github-oauth.url", value = "https://api.github.com") -@Property(name = "micronaut.starter.github.clientId", value = "clientId") -@Property(name = "micronaut.starter.github.tokenPermissions", value = "user,repo,workflow") -@MicronautTest -@spock.lang.IgnoreIf({ jvm.java17 }) // fails on java 16 due to spock bug -class GitHubRedirectServiceTest extends Specification{ - - @Inject GitHubRedirectService gitHubRedirectService - - void 'generates redirect to oauth github'(){ - given: - def parameters = Spy(HttpParameters) - parameters.names() >> ["lang", "build"] - parameters.getAll("lang") >> Collections.singletonList("java") - parameters.getAll("build") >> Collections.singletonList("maven") - RequestInfo requestInfo = new RequestInfo("https://localhost:8080", - "/github/default/foo", parameters, Locale.ENGLISH, "") - - when: - URI redirectUri = gitHubRedirectService.constructOAuthRedirectUrl(requestInfo) - - then: - redirectUri.query.contains('scope=user,repo,workflow') - redirectUri.query.contains('client_id=clientId') - redirectUri.query.contains('state=') - redirectUri.query.contains('github/default/foo') - redirectUri.query.contains('lang=java') - redirectUri.query.contains('build=maven') - } - - void 'generates redirect to launcher'(){ - given: - GitHubRepository repo = new GitHubRepository("name", "desc", - "https://api.github/micronaut-projects/micronaut", - "https://github.com/micronaut-projects/micronaut-starter", - "https://github.com/micronaut-projects/micronaut-starter.git") - - when: - URI redirectUri = gitHubRedirectService.constructLauncherRedirectUrl(repo) - - then: - redirectUri.host == 'micronaut.io' - redirectUri.query.contains("cloneUrl") - redirectUri.query.contains("url") - redirectUri.query.contains("htmlUrl") - } -} diff --git a/starter-api/src/test/groovy/io/micronaut/starter/api/features/GoogleCloudFunctionSpec.groovy b/starter-api/src/test/groovy/io/micronaut/starter/api/features/GoogleCloudFunctionSpec.groovy index 4235a7995b6..10ae797ed5e 100644 --- a/starter-api/src/test/groovy/io/micronaut/starter/api/features/GoogleCloudFunctionSpec.groovy +++ b/starter-api/src/test/groovy/io/micronaut/starter/api/features/GoogleCloudFunctionSpec.groovy @@ -28,7 +28,7 @@ class GoogleCloudFunctionSpec extends Specification { null, null, null, - MicronautJdkVersionConfiguration.DEFAULT_OPTION, + JdkVersion.JDK_17, new RequestInfo("http://localhost", "", null, Locale.ENGLISH, "") ) diff --git a/starter-api/src/test/groovy/io/micronaut/starter/api/options/SelectOptionsControllerTest.groovy b/starter-api/src/test/groovy/io/micronaut/starter/api/options/SelectOptionsControllerTest.groovy index ab243914312..6a25cc36e58 100644 --- a/starter-api/src/test/groovy/io/micronaut/starter/api/options/SelectOptionsControllerTest.groovy +++ b/starter-api/src/test/groovy/io/micronaut/starter/api/options/SelectOptionsControllerTest.groovy @@ -30,7 +30,7 @@ class SelectOptionsControllerTest extends Specification { ['JDK_17', 'JDK_21'] == selectOptionsDTO.jdkVersion.options.name and: - selectOptionsDTO.jdkVersion.defaultOption.name == 'JDK_17' + selectOptionsDTO.jdkVersion.defaultOption.name == 'JDK_21' } void "default build tool is Gradle Kotlin"() { diff --git a/starter-aws-cdk/build.gradle.kts b/starter-aws-cdk/build.gradle.kts index 9078eaacfeb..3684433f663 100644 --- a/starter-aws-cdk/build.gradle.kts +++ b/starter-aws-cdk/build.gradle.kts @@ -4,8 +4,9 @@ plugins { val micronautVersion: String by project dependencies { - api("software.amazon.awscdk:aws-cdk-lib:2.110.1") + api("software.amazon.awscdk:aws-cdk-lib:2.129.0") api(project(":starter-core")) + testImplementation(platform("io.micronaut.platform:micronaut-platform:$micronautVersion")) testImplementation("io.micronaut.aws:micronaut-function-aws-api-proxy") } diff --git a/starter-aws-cdk/src/main/java/io/micronaut/aws/cdk/function/MicronautFunction.java b/starter-aws-cdk/src/main/java/io/micronaut/aws/cdk/function/MicronautFunction.java index 6f3a7944908..51e1251b4e5 100644 --- a/starter-aws-cdk/src/main/java/io/micronaut/aws/cdk/function/MicronautFunction.java +++ b/starter-aws-cdk/src/main/java/io/micronaut/aws/cdk/function/MicronautFunction.java @@ -57,7 +57,7 @@ public static Function.Builder create(final ApplicationType applicationType, } private static Runtime runtime(boolean graalVMNative) { - return graalVMNative ? Runtime.PROVIDED_AL2 : Runtime.JAVA_17; + return graalVMNative ? Runtime.PROVIDED_AL2023 : Runtime.JAVA_21; } } diff --git a/starter-aws-cdk/src/test/groovy/io/micronaut/aws/cdk/function/MicronautFunctionSpec.groovy b/starter-aws-cdk/src/test/groovy/io/micronaut/aws/cdk/function/MicronautFunctionSpec.groovy index 58ae789e622..716ecb1cb0f 100644 --- a/starter-aws-cdk/src/test/groovy/io/micronaut/aws/cdk/function/MicronautFunctionSpec.groovy +++ b/starter-aws-cdk/src/test/groovy/io/micronaut/aws/cdk/function/MicronautFunctionSpec.groovy @@ -43,9 +43,9 @@ class MicronautFunctionSpec extends Specification { where: applicationType | graalVMNative | runtime | handler - ApplicationType.DEFAULT | true | Runtime.PROVIDED_AL2 | null - ApplicationType.DEFAULT | false | Runtime.JAVA_17 | null - ApplicationType.FUNCTION | true | Runtime.PROVIDED_AL2 | "example.micronaut.MyHandler" - ApplicationType.FUNCTION | false | Runtime.JAVA_17 | "example.micronaut.MyHandler" + ApplicationType.DEFAULT | true | Runtime.PROVIDED_AL2023 | null + ApplicationType.DEFAULT | false | Runtime.JAVA_21 | null + ApplicationType.FUNCTION | true | Runtime.PROVIDED_AL2023 | "example.micronaut.MyHandler" + ApplicationType.FUNCTION | false | Runtime.JAVA_21 | "example.micronaut.MyHandler" } } diff --git a/starter-aws-lambda/build.gradle b/starter-aws-lambda/build.gradle index eb6ccb09449..40d95225e38 100644 --- a/starter-aws-lambda/build.gradle +++ b/starter-aws-lambda/build.gradle @@ -10,9 +10,12 @@ micronaut { dependencies { annotationProcessor("io.micronaut.serde:micronaut-serde-processor") + implementation("io.micronaut.serde:micronaut-serde-jackson") implementation(project(":starter-api")) + runtimeOnly("ch.qos.logback:logback-classic") + testCompileOnly("io.micronaut:micronaut-inject-groovy") } @@ -29,10 +32,10 @@ graalvmNative { } tasks.named("dockerfileNative") { - baseImage = "amazonlinux:2" + baseImage = "amazonlinux:2023" args( "-XX:MaximumHeapSizePercent=80", "-Dio.netty.allocator.numDirectArenas=0", "-Dio.netty.noPreferDirect=true" ) -} \ No newline at end of file +} diff --git a/starter-azure-function/build.gradle b/starter-azure-function/build.gradle index 0a7e10ef939..818e3228882 100644 --- a/starter-azure-function/build.gradle +++ b/starter-azure-function/build.gradle @@ -4,15 +4,17 @@ plugins { } dependencies { - implementation project(":starter-api") + implementation(project(":starter-api")) implementation("io.micronaut:micronaut-jackson-databind") - implementation "io.micronaut.azure:micronaut-azure-function-http" - implementation 'com.microsoft.azure.functions:azure-functions-java-library:3.0.0' - implementation "io.micronaut:micronaut-inject" + implementation("io.micronaut.azure:micronaut-azure-function-http") + implementation('com.microsoft.azure.functions:azure-functions-java-library:3.1.0') + implementation("io.micronaut:micronaut-inject") + runtimeOnly("ch.qos.logback:logback-classic") - testCompileOnly "io.micronaut:micronaut-inject-groovy" - testImplementation "io.micronaut.test:micronaut-test-spock" + testCompileOnly("io.micronaut:micronaut-inject-groovy") + + testImplementation("io.micronaut.test:micronaut-test-spock") } diff --git a/starter-cli/build.gradle b/starter-cli/build.gradle index 7caab1860c6..a84d5c0d100 100644 --- a/starter-cli/build.gradle +++ b/starter-cli/build.gradle @@ -4,7 +4,7 @@ plugins { } ext { - picocliVersion = '4.6.3' + picocliVersion = '4.7.5' } configurations { @@ -20,31 +20,28 @@ configurations.all { dependencies { annotationProcessor("io.micronaut:micronaut-graal") - api project(":starter-core") - api "info.picocli:picocli:${picocliVersion}" - api "info.picocli:picocli-shell-jline3:${picocliVersion}" - api "com.fizzed:rocker-runtime:$rockerVersion" - implementation "org.slf4j:slf4j-nop:2.0.9" + compileOnly("org.graalvm.nativeimage:svm") - compileOnly "org.graalvm.nativeimage:svm" + api(project(":starter-core")) + api("info.picocli:picocli:$picocliVersion") + api("info.picocli:picocli-shell-jline3:$picocliVersion") + api("com.fizzed:rocker-runtime:$rockerVersion") - implementation "org.fusesource.jansi:jansi:1.18" - implementation "org.yaml:snakeyaml" - - implementation group: 'javax.inject', name: 'javax.inject', version: '1' - - implementation 'org.shredzone.acme4j:acme4j-client:2.16' - implementation 'org.shredzone.acme4j:acme4j-utils:2.12' - - generateConfig "info.picocli:picocli-codegen:${picocliVersion}" + implementation("org.slf4j:slf4j-nop:2.0.13") + implementation("org.fusesource.jansi:jansi:1.18") + implementation("org.yaml:snakeyaml") + implementation("javax.inject:javax.inject:1") + implementation("org.shredzone.acme4j:acme4j-client") + implementation("org.shredzone.acme4j:acme4j-utils:2.16") + implementation("org.jline:jline:3.19.0") testImplementation("io.micronaut.picocli:micronaut-picocli") + testImplementation("org.testcontainers:spock") + testImplementation("org.reflections:reflections:0.10.2") + testImplementation("org.apache.groovy:groovy-xml") - testImplementation "org.testcontainers:spock" - testImplementation 'org.reflections:reflections:0.10.2' - testImplementation 'org.apache.groovy:groovy-xml' - implementation("org.jline:jline:3.19.0") + generateConfig("info.picocli:picocli-codegen:$picocliVersion") } graalvmNative { @@ -77,6 +74,10 @@ startScripts { applicationName = 'mn' } +run { + standardInput = System.in +} + sdkman { api = "https://vendors.sdkman.io" consumerKey = System.getenv("GVM_SDKVENDOR_KEY") ?: project.hasProperty("gvmSdkvendorKey") ? project.gvmSdkvendorKey : '' @@ -85,8 +86,7 @@ sdkman { version = project.version hashtag = "#micronautfw" platforms = [ - // TODO: Once graal native-image works for arm OSX, we should switch to building and publishing a non-rosetta release (https://github.com/oracle/graal/issues/2666) - "MAC_ARM64":"https://github.com/micronaut-projects/micronaut-starter/releases/download/v${project.version}/mn-darwin-amd64-v${project.version}.zip", + "MAC_ARM64":"https://github.com/micronaut-projects/micronaut-starter/releases/download/v${project.version}/mn-darwin-aarch64-v${project.version}.zip", "MAC_OSX":"https://github.com/micronaut-projects/micronaut-starter/releases/download/v${project.version}/mn-darwin-amd64-v${project.version}.zip", "WINDOWS_64":"https://github.com/micronaut-projects/micronaut-starter/releases/download/v${project.version}/mn-win-amd64-v${project.version}.zip", "LINUX_64":"https://github.com/micronaut-projects/micronaut-starter/releases/download/v${project.version}/mn-linux-amd64-v${project.version}.zip" diff --git a/starter-cli/src/main/java/io/micronaut/starter/cli/command/BuilderCommand.java b/starter-cli/src/main/java/io/micronaut/starter/cli/command/BuilderCommand.java index 2f7dca00813..69f5982a6f4 100644 --- a/starter-cli/src/main/java/io/micronaut/starter/cli/command/BuilderCommand.java +++ b/starter-cli/src/main/java/io/micronaut/starter/cli/command/BuilderCommand.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2023 original authors + * Copyright 2017-2024 original authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -44,12 +44,12 @@ import java.util.ArrayList; import java.util.Arrays; +import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.concurrent.Callable; import java.util.function.Function; import java.util.function.Supplier; -import java.util.stream.Collectors; import static picocli.CommandLine.Help.Ansi.AUTO; @@ -83,7 +83,8 @@ public Integer call() throws Exception { .parser(new DefaultParser()) .build(); GenerateOptions options = createGenerateOptions(reader); - Set selectedFeatures = options.getFeatures(); + // options.getFeatures() may be an unmodifiable set, so unpack it into a modifiable set + Set selectedFeatures = new HashSet<>(options.getFeatures()); selectedFeatures.addAll(getFeatures(options.getApplicationType(), terminal, features)); Project project = getProject(reader); try (OutputHandler outputHandler = new FileSystemOutputHandler(project, false, this)) { @@ -106,7 +107,7 @@ public Integer call() throws Exception { protected List getFeatures(ApplicationType applicationType, Terminal terminal, List features) { AvailableFeatures availableFeatures = new BaseAvailableFeatures(features, applicationType); - List featureNames = availableFeatures.getFeatures().map(Feature::getName).collect(Collectors.toList()); + List featureNames = availableFeatures.getFeatures().map(Feature::getName).toList(); LineReader featuresReader = LineReaderBuilder.builder() .terminal(terminal) .completer(new StringsCompleter(featureNames)) @@ -123,7 +124,7 @@ protected List getFeatures(ApplicationType applicationType, Terminal ter List selectedFeatures = Arrays.asList(featuresLine.split(" ")); List invalidFeatures = new ArrayList<>(); for (String name: selectedFeatures) { - if (!availableFeatures.findFeature(name).isPresent()) { + if (availableFeatures.findFeature(name).isEmpty()) { invalidFeatures.add(name); } } @@ -147,7 +148,7 @@ protected BuildTool getBuildTool(LineReader reader, Language language) { } protected JdkVersion getJdkVersion(LineReader reader) { - List candidates = new JdkVersionCandidates(); + List candidates = getJdkVersionCandidates(); JdkVersion defaultOption = MicronautJdkVersionConfiguration.DEFAULT_OPTION; if (candidates.size() == 1) { return defaultOption; @@ -161,6 +162,10 @@ protected JdkVersion getJdkVersion(LineReader reader) { ))); } + protected List getJdkVersionCandidates() { + return new JdkVersionCandidates(); + } + protected YesOrNo getYesOrNo(LineReader reader) { return getEnumOption(YesOrNo.class, yesOrNo -> StringUtils.capitalize(yesOrNo.name().toLowerCase()), YesOrNo.YES, reader); } diff --git a/starter-cli/src/main/java/io/micronaut/starter/cli/command/CreateChatBotBuilderCommand.java b/starter-cli/src/main/java/io/micronaut/starter/cli/command/CreateChatBotBuilderCommand.java index d02b3b7eae1..6c787d9c591 100644 --- a/starter-cli/src/main/java/io/micronaut/starter/cli/command/CreateChatBotBuilderCommand.java +++ b/starter-cli/src/main/java/io/micronaut/starter/cli/command/CreateChatBotBuilderCommand.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2023 original authors + * Copyright 2017-2024 original authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,6 +23,10 @@ import io.micronaut.starter.feature.architecture.CpuArchitecture; import io.micronaut.starter.feature.architecture.X86; import io.micronaut.starter.feature.aws.LambdaFunctionUrl; +import io.micronaut.starter.feature.chatbots.basecamp.BasecampAwsChatBot; +import io.micronaut.starter.feature.chatbots.basecamp.BasecampAzureChatBot; +import io.micronaut.starter.feature.chatbots.basecamp.BasecampGcpChatBot; +import io.micronaut.starter.feature.chatbots.basecamp.BasecampHttpChatBot; import io.micronaut.starter.feature.chatbots.telegram.TelegramAwsChatBot; import io.micronaut.starter.feature.chatbots.telegram.TelegramAzureChatBot; import io.micronaut.starter.feature.chatbots.telegram.TelegramGcpChatBot; @@ -35,6 +39,7 @@ import java.util.List; import java.util.Optional; import java.util.Set; +import java.util.function.Function; @Command(name = CreateChatBotBuilderCommand.NAME, description = "A guided walk-through to create a chat bot application") @Prototype @@ -53,8 +58,8 @@ public CreateChatBotBuilderCommand( public GenerateOptions createGenerateOptions(LineReader reader) { ChatBotType chatBotType = getChatBotType(reader); Set applicationFeatures = new HashSet<>(); - ChatBotDeployment deployment = getDeployment(chatBotType, reader); - applicationFeatures.add(deployment.feature); + ChatBotDeployment deployment = getDeployment(reader); + applicationFeatures.add(deployment.getFeature(chatBotType)); ApplicationType applicationType = deployment.applicationType; if (deployment == ChatBotDeployment.LAMBDA) { @@ -90,18 +95,15 @@ protected Optional getCdk(LineReader reader) { : Optional.empty(); } - private ChatBotDeployment getDeployment(ChatBotType chatBotType, LineReader reader) { + private ChatBotDeployment getDeployment(LineReader reader) { out("Choose your preferred deployment. (enter for default)"); - if (chatBotType == ChatBotType.TELEGRAM) { - return getEnumOption(ChatBotDeployment.class, f -> "%s - %s".formatted(f.title, f.description), ChatBotDeployment.LAMBDA, reader); - } else { - throw new IllegalArgumentException("Unsupported chat bot type: " + chatBotType); - } + return getEnumOption(ChatBotDeployment.class, f -> "%s - %s".formatted(f.title, f.description), ChatBotDeployment.LAMBDA, reader); } enum ChatBotType { - TELEGRAM("Telegram", "A chat bot for the telegram messaging platform"); + BASECAMP("Basecamp", "A chat bot for Basecamp chats"), + TELEGRAM("Telegram", "A chat bot for the Telegram messaging platform"); private final String title; private final String description; @@ -114,21 +116,42 @@ enum ChatBotType { enum ChatBotDeployment { - LAMBDA("AWS Lambda", "Deploy to AWS Lambda", TelegramAwsChatBot.NAME, ApplicationType.FUNCTION), - AZURE("Azure Function", "Deploy to Azure as a Function", TelegramAzureChatBot.NAME, ApplicationType.FUNCTION), - GCP("Google Cloud Function", "Deploy to Google Cloud as a Function", TelegramGcpChatBot.NAME, ApplicationType.FUNCTION), - HTTP("HTTP", "Deploy as an HTTP Server", TelegramHttpChatBot.NAME, ApplicationType.DEFAULT); + LAMBDA("AWS Lambda", "Deploy to AWS Lambda", ApplicationType.FUNCTION, type -> switch (type) { + case BASECAMP -> BasecampAwsChatBot.NAME; + case TELEGRAM -> TelegramAwsChatBot.NAME; + }), + AZURE("Azure Function", "Deploy to Azure as a Function", ApplicationType.FUNCTION, type -> switch (type) { + case BASECAMP -> BasecampAzureChatBot.NAME; + case TELEGRAM -> TelegramAzureChatBot.NAME; + }), + GCP("Google Cloud Function", "Deploy to Google Cloud as a Function", ApplicationType.FUNCTION, type -> switch (type) { + case BASECAMP -> BasecampGcpChatBot.NAME; + case TELEGRAM -> TelegramGcpChatBot.NAME; + }), + HTTP("HTTP", "Deploy as an HTTP Server", ApplicationType.DEFAULT, type -> switch (type) { + case BASECAMP -> BasecampHttpChatBot.NAME; + case TELEGRAM -> TelegramHttpChatBot.NAME; + }); private final String title; private final String description; - private final String feature; private final ApplicationType applicationType; - - ChatBotDeployment(String title, String description, String feature, ApplicationType applicationType) { + private final Function featureName; + + ChatBotDeployment( + String title, + String description, + ApplicationType applicationType, + Function featureName + ) { this.title = title; this.description = description; - this.feature = feature; this.applicationType = applicationType; + this.featureName = featureName; + } + + String getFeature(ChatBotType chatBotType) { + return featureName.apply(chatBotType); } } } diff --git a/starter-cli/src/main/java/io/micronaut/starter/cli/command/CreateLambdaBuilderCommand.java b/starter-cli/src/main/java/io/micronaut/starter/cli/command/CreateLambdaBuilderCommand.java index 20aecee217f..44e31a64ca5 100644 --- a/starter-cli/src/main/java/io/micronaut/starter/cli/command/CreateLambdaBuilderCommand.java +++ b/starter-cli/src/main/java/io/micronaut/starter/cli/command/CreateLambdaBuilderCommand.java @@ -47,9 +47,9 @@ import java.util.List; import java.util.Optional; import java.util.Set; -import java.util.stream.Collectors; import java.util.stream.Stream; + @CommandLine.Command(name = CreateLambdaBuilderCommand.NAME, description = "A guided walk-through to create an lambda function") @Prototype public class CreateLambdaBuilderCommand extends BuilderCommand { @@ -95,35 +95,17 @@ public GenerateOptions createGenerateOptions(LineReader reader) { Language language = getLanguage(deployment, reader); TestFramework testFramework = getTestFramework(reader, language); BuildTool buildTool = getBuildTool(reader, language); - JdkVersion jdkVersion = getJdkVersion(deployment, reader); + JdkVersion jdkVersion = getJdkVersion(reader); Options options = new Options(language, testFramework, buildTool, jdkVersion); return new GenerateOptions(applicationType, options, applicationFeatures); } - protected JdkVersion getJdkVersion(LambdaDeployment deployment, LineReader reader) { - JdkVersion[] versions = jdkVersionsForDeployment(deployment); - out("Choose the target JDK. (enter for default)"); - return getEnumOption( - versions, - jdkVersion -> Integer.toString(jdkVersion.majorVersion()), - versions.length > 0 ? versions[0] : JdkVersion.JDK_17, - reader - ); - } - - JdkVersion[] jdkVersionsForDeployment(LambdaDeployment deployment) { - switch (deployment) { - case NATIVE_EXECUTABLE: - return new JdkVersion[]{ - JdkVersion.JDK_17 - }; - case FAT_JAR: - default: - List supportedJdks = AwsLambdaFeatureValidator.supportedJdks(); - JdkVersion[] arr = new JdkVersion[supportedJdks.size()]; - supportedJdks.toArray(arr); - return arr; - } + @Override + protected List getJdkVersionCandidates() { + return AwsLambdaFeatureValidator.supportedJdks().stream() + .map(JdkVersion::majorVersion) + .map(String::valueOf) + .toList(); } protected ApplicationType applicationTypeForCodingStyle(CodingStyle codingStyle) { @@ -137,7 +119,7 @@ protected ApplicationType applicationTypeForCodingStyle(CodingStyle codingStyle) } } - protected Language[] languagesForDeployment(LambdaDeployment deployment) { + static Language[] languagesForDeployment(LambdaDeployment deployment) { return deployment == LambdaDeployment.NATIVE_EXECUTABLE ? Stream.of(Language.values()) .filter(GraalVMFeatureValidator::supports) @@ -221,15 +203,15 @@ protected Optional getCdk(LineReader reader) { : Optional.empty(); } - protected List apiTriggerFeatures(ApplicationType applicationType, Collection features) { + static List apiTriggerFeatures(ApplicationType applicationType, Collection features) { return features.stream() .filter(AwsApiFeature.class::isInstance) .filter(f -> f.supports(applicationType)) .sorted(Comparator.comparing(Feature::getTitle).reversed()) - .collect(Collectors.toList()); + .toList(); } - protected List triggerFeatures(Collection features) { + static List triggerFeatures(Collection features) { return features.stream() .filter(LambdaTrigger.class::isInstance) .sorted((o1, o2) -> { @@ -244,6 +226,6 @@ protected List triggerFeatures(Collection features) { } return o1.getTitle().compareTo(o2.getTitle()); }) - .collect(Collectors.toList()); + .toList(); } } diff --git a/starter-cli/src/test/groovy/io/micronaut/starter/cli/command/CreateChatBotBuilderCommandSpec.groovy b/starter-cli/src/test/groovy/io/micronaut/starter/cli/command/CreateChatBotBuilderCommandSpec.groovy index 2fe1904155d..abfc419849c 100644 --- a/starter-cli/src/test/groovy/io/micronaut/starter/cli/command/CreateChatBotBuilderCommandSpec.groovy +++ b/starter-cli/src/test/groovy/io/micronaut/starter/cli/command/CreateChatBotBuilderCommandSpec.groovy @@ -6,6 +6,10 @@ import io.micronaut.starter.feature.architecture.Arm import io.micronaut.starter.feature.architecture.CpuArchitecture import io.micronaut.starter.feature.architecture.X86 import io.micronaut.starter.feature.aws.LambdaFunctionUrl +import io.micronaut.starter.feature.chatbots.basecamp.BasecampAwsChatBot +import io.micronaut.starter.feature.chatbots.basecamp.BasecampAzureChatBot +import io.micronaut.starter.feature.chatbots.basecamp.BasecampGcpChatBot +import io.micronaut.starter.feature.chatbots.basecamp.BasecampHttpChatBot import io.micronaut.starter.feature.chatbots.telegram.TelegramAwsChatBot import io.micronaut.starter.feature.chatbots.telegram.TelegramAzureChatBot import io.micronaut.starter.feature.chatbots.telegram.TelegramGcpChatBot @@ -30,7 +34,8 @@ class CreateChatBotBuilderCommandSpec extends Specification { } /* Choose your ChatBot type. (enter for Telegram) -*1) Telegram - A chat bot for the telegram messaging platform + 1) Basecamp - A chat bot for Basecamp chats +*2) Telegram - A chat bot for the Telegram messaging platform > Choose your preferred deployment. (enter for default) @@ -140,13 +145,13 @@ Choose the target JDK. (enter for default) List getFeatures() { switch (applicationType) { case CreateChatBotBuilderCommand.ChatBotDeployment.LAMBDA: - return [TelegramAwsChatBot.NAME, cpuArchitecture.getName()] + (cdk ? [LambdaFunctionUrl.NAME] : []) + return [chatBotType == CreateChatBotBuilderCommand.ChatBotType.BASECAMP ? BasecampAwsChatBot.NAME : TelegramAwsChatBot.NAME, cpuArchitecture.getName()] + (cdk ? [LambdaFunctionUrl.NAME] : []) case CreateChatBotBuilderCommand.ChatBotDeployment.AZURE: - return [TelegramAzureChatBot.NAME] + return [chatBotType == CreateChatBotBuilderCommand.ChatBotType.BASECAMP ? BasecampAzureChatBot.NAME : TelegramAzureChatBot.NAME] case CreateChatBotBuilderCommand.ChatBotDeployment.GCP: - return [TelegramGcpChatBot.NAME] + return [chatBotType == CreateChatBotBuilderCommand.ChatBotType.BASECAMP ? BasecampGcpChatBot.NAME : TelegramGcpChatBot.NAME] case CreateChatBotBuilderCommand.ChatBotDeployment.HTTP: - return [TelegramHttpChatBot.NAME] + return [chatBotType == CreateChatBotBuilderCommand.ChatBotType.BASECAMP ? BasecampHttpChatBot.NAME : TelegramHttpChatBot.NAME] } } diff --git a/starter-cli/src/test/groovy/io/micronaut/starter/cli/command/CreateLambdaBuilderCommandSpec.groovy b/starter-cli/src/test/groovy/io/micronaut/starter/cli/command/CreateLambdaBuilderCommandSpec.groovy index d64736b4679..50b52d80b6f 100644 --- a/starter-cli/src/test/groovy/io/micronaut/starter/cli/command/CreateLambdaBuilderCommandSpec.groovy +++ b/starter-cli/src/test/groovy/io/micronaut/starter/cli/command/CreateLambdaBuilderCommandSpec.groovy @@ -3,36 +3,55 @@ package io.micronaut.starter.cli.command import io.micronaut.context.ApplicationContext import io.micronaut.starter.application.ApplicationType import io.micronaut.starter.feature.Feature -import io.micronaut.starter.feature.aws.LambdaTrigger -import spock.lang.Specification +import io.micronaut.starter.feature.architecture.Arm +import io.micronaut.starter.feature.architecture.CpuArchitecture +import io.micronaut.starter.feature.architecture.X86 +import io.micronaut.starter.feature.aws.Cdk +import io.micronaut.starter.feature.function.awslambda.AwsLambda +import io.micronaut.starter.feature.graalvm.GraalVM +import io.micronaut.starter.options.BuildTool +import io.micronaut.starter.options.JdkVersion +import io.micronaut.starter.options.Language +import io.micronaut.starter.options.TestFramework import org.jline.reader.LineReader - -import java.util.stream.Collectors +import spock.lang.AutoCleanup +import spock.lang.Shared +import spock.lang.Specification class CreateLambdaBuilderCommandSpec extends Specification { + @Shared + @AutoCleanup + ApplicationContext applicationContext + + @Shared + CreateLambdaBuilderCommand command + + def setupSpec() { + applicationContext = ApplicationContext.run(); + command = applicationContext.getBean(CreateLambdaBuilderCommand) + } + void "test lambda triggers"() { given: ApplicationContext applicationContext = ApplicationContext.run(); CreateLambdaBuilderCommand command = applicationContext.getBean(CreateLambdaBuilderCommand) - Collection features = applicationContext.getBeansOfType(LambdaTrigger) + List features = applicationContext.getBeansOfType(Feature) when: - List result = command.triggerFeatures(features) - .stream() - .map(f -> f.getName()) - .collect(Collectors.toList()); + List result = command.triggerFeatures(features).name + then: - [ + result == [ 'amazon-api-gateway', 'amazon-api-gateway-http', 'aws-lambda-function-url', 'aws-lambda-scheduled-event', 'aws-lambda-s3-event-notification', - ] == result + ] and: - ['amazon-api-gateway', 'amazon-api-gateway-http'] == command.apiTriggerFeatures(command.applicationTypeForCodingStyle(CodingStyle.CONTROLLERS), features)*.name + command.apiTriggerFeatures(command.applicationTypeForCodingStyle(CodingStyle.CONTROLLERS), features).name == ['amazon-api-gateway', 'amazon-api-gateway-http'] cleanup: applicationContext.close() @@ -79,92 +98,136 @@ class CreateLambdaBuilderCommandSpec extends Specification { *1) 11 2) 8 */ - void "test prompt"(List answers, ApplicationType expectedApplicationType, Set expectedFeatures) { - given: - ApplicationContext applicationContext = ApplicationContext.run(); + void "#cliOptions.cliCommands -- #cliOptions"(LambdaCliOptions cliOptions) { + when: CreateLambdaBuilderCommand command = applicationContext.getBean(CreateLambdaBuilderCommand) - when: def reader = Stub(LineReader) { - readLine(BuilderCommand.PROMPT.get()) >>> answers - + readLine(BuilderCommand.PROMPT.get()) >>> cliOptions.cliCommands } GenerateOptions options = command.createGenerateOptions(reader) then: - expectedApplicationType == options.applicationType - expectedFeatures =~ options.features - - cleanup: - applicationContext.close() + cliOptions.expectedApplicationType == options.applicationType + cliOptions.features ==~ options.features + cliOptions.language == options.options.language + cliOptions.buildTool == options.options.buildTool + cliOptions.testFramework == options.options.testFramework + cliOptions.javaVersion == options.options.javaVersion.asString() where: - answers | expectedApplicationType | expectedFeatures - [ - "1", // with Controller - "1", // Amazon Api Gateway - "1", // FAT JAR - "1", // ARM - "1", // CDK Yes - "1", // Java - "1", // Junit - "1", // Gradle Groovy DSL - "1", // Java 11 - ] | ApplicationType.DEFAULT | ['amazon-api-gateway', 'arm', 'aws-cdk','aws-lambda'] - [ - "2", // with Controller - "1", // Amazon Api Gateway - "1", // FAT JAR - "1", // ARM - "1", // CDK Yes - "1", // Java - "1", // Junit - "1", // Gradle Groovy DSL - "1", // Java 11 - ] | ApplicationType.FUNCTION | ['amazon-api-gateway', 'arm', 'aws-cdk','aws-lambda'] - [ - "2", // with Controller - "4", // Scheduled event - "1", // FAT JAR - "1", // ARM - "1", // CDK Yes - "1", // Java - "1", // Junit - "1", // Gradle Groovy DSL - "1", // Java 11 - ] | ApplicationType.FUNCTION | ['aws-lambda-scheduled-event', 'arm', 'aws-cdk','aws-lambda'] - [ - "1", // with Controller - "1", // Amazon Api Gateway - "2", // FAT JAR - "1", // ARM - "1", // CDK Yes - "1", // Java - "1", // Junit - "1", // Gradle Groovy DSL - "1", // Java 11 - ] | ApplicationType.DEFAULT | ['amazon-api-gateway', 'arm', 'aws-cdk','aws-lambda','graalvm'] - [ - "1", // with Controller - "1", // Amazon Api Gateway - "1", // FAT JAR - "2", // x86 - "1", // CDK Yes - "1", // Java - "1", // Junit - "1", // Gradle Groovy DSL - "1", // Java 11 - ] | ApplicationType.DEFAULT | ['amazon-api-gateway', 'x86', 'aws-cdk','aws-lambda'] + cliOptions << [CodingStyle.values(), LambdaDeployment.values()].combinations().collectMany { CodingStyle codingStyle, LambdaDeployment deployment -> + combinations( + command, + applicationContext, + codingStyle == CodingStyle.CONTROLLERS ? + CreateLambdaBuilderCommand.apiTriggerFeatures(ApplicationType.DEFAULT, applicationContext.getBeansOfType(Feature)) : + CreateLambdaBuilderCommand.triggerFeatures(applicationContext.getBeansOfType(Feature)), + codingStyle, + deployment + ) + } + } + + static combinations(CreateLambdaBuilderCommand command, ApplicationContext ctx, List triggerFeatures, CodingStyle codingStyle, LambdaDeployment deployment) { [ - "1", // with Controller - "1", // Amazon Api Gateway - "1", // FAT JAR - "1", // ARM - "2", // CDK Yes - "1", // Java - "1", // Junit - "1", // Gradle Groovy DSL - "1", // Java 11 - ] | ApplicationType.DEFAULT | ['amazon-api-gateway','arm','aws-lambda'] + triggerFeatures, + [triggerFeatures], + [deployment], + [ctx.getBean(Arm), ctx.getBean(X86)], + [true, false], // cdk + CreateLambdaBuilderCommand.languagesForDeployment(deployment), + [CreateLambdaBuilderCommand.languagesForDeployment(deployment)], + [TestFramework.JUNIT, TestFramework.SPOCK, TestFramework.KOTEST], + [BuildTool.GRADLE, BuildTool.GRADLE_KOTLIN, BuildTool.MAVEN], + command.jdkVersionCandidates, + [command.jdkVersionCandidates] + ].combinations().collect { new LambdaCliOptions(codingStyle, *it) } + } + + private static class LambdaCliOptions { + + final CodingStyle codingStyle + final Feature apiFeature + final LambdaDeployment lambdaDeployment + final CpuArchitecture cpuArchitecture + final boolean cdk + final Language language + final TestFramework testFramework + final BuildTool buildTool + final String javaVersion + + final List allApiFeatures + final List allLanguages + final List allJdkVersions + + LambdaCliOptions( + CodingStyle codingStyle, + Feature apiFeatures, + List allApiFeatures, + LambdaDeployment lambdaDeployment, + CpuArchitecture cpuArchitecture, + boolean cdk, + Language language, + Language[] allLanguages, + TestFramework testFramework, + BuildTool buildTool, + String javaVersion, + List allJdkVersions + ) { + this.codingStyle = codingStyle + this.apiFeature = apiFeatures + this.allApiFeatures = allApiFeatures + this.lambdaDeployment = lambdaDeployment + this.cpuArchitecture = cpuArchitecture + this.cdk = cdk + this.language = language + this.allLanguages = allLanguages.toList() + this.testFramework = testFramework + this.buildTool = buildTool + this.javaVersion = javaVersion + this.allJdkVersions = allJdkVersions + } + + List getFeatures() { + List features = [ + AwsLambda.FEATURE_NAME_AWS_LAMBDA, + apiFeature.getName(), + ] + if (lambdaDeployment == LambdaDeployment.NATIVE_EXECUTABLE) { + features += [GraalVM.FEATURE_NAME_GRAALVM] + } + features += [cpuArchitecture.getName()] + if (cdk) { + features += [Cdk.NAME] + } + return features + } + + ApplicationType getExpectedApplicationType() { + if (codingStyle != CodingStyle.HANDLER) { + return ApplicationType.DEFAULT + } + return ApplicationType.FUNCTION + } + + List getCliCommands() { + [ + "${codingStyle.ordinal() + 1}".toString(), + "${allApiFeatures.indexOf(apiFeature) + 1}".toString(), + "${lambdaDeployment.ordinal() + 1}".toString(), + cpuArchitecture instanceof Arm ? "1" : "2", + cdk ? "1" : "2", + "${allLanguages.indexOf(language) + 1}".toString(), + "${testFramework.ordinal() + 1}".toString(), + "${buildTool.ordinal() + 1}".toString(), + "${allJdkVersions.indexOf(javaVersion) + 1}".toString() + ] + } + + @Override + String toString() { + "${codingStyle} ${apiFeature?.name} ${lambdaDeployment} ${cpuArchitecture.name} cdk:${cdk} $language $testFramework $buildTool $javaVersion" + } } } diff --git a/starter-core/build.gradle b/starter-core/build.gradle index 38610648b48..ac9c5c27199 100644 --- a/starter-core/build.gradle +++ b/starter-core/build.gradle @@ -16,17 +16,23 @@ sourceSets { } dependencies { - api platform("io.micronaut.platform:micronaut-platform:$micronautVersion") - api "com.fizzed:rocker-runtime:$rockerVersion" - api "io.micronaut:micronaut-inject" + + annotationProcessor("io.micronaut.serde:micronaut-serde-processor") + + api(platform("io.micronaut.platform:micronaut-platform:$micronautVersion")) + api("com.fizzed:rocker-runtime:$rockerVersion") + api("io.micronaut:micronaut-inject") api("com.fasterxml.jackson.core:jackson-annotations") - api "io.micronaut:micronaut-http-client" - api "io.github.java-diff-utils:java-diff-utils:4.10" - api "org.eclipse.jgit:org.eclipse.jgit:6.5.0.202303070854-r" + api("io.micronaut:micronaut-http-client") + api("io.github.java-diff-utils:java-diff-utils:4.12") + api("org.eclipse.jgit:org.eclipse.jgit:6.8.0.202311291450-r") api("org.yaml:snakeyaml") - implementation("com.typesafe:config:1.4.2") + api("io.micronaut.serde:micronaut-serde-jackson") + + implementation("com.typesafe:config:1.4.3") implementation("io.micronaut.testresources:micronaut-test-resources-build-tools") - implementation 'org.apache.commons:commons-compress:1.25.0' + implementation("org.apache.commons:commons-compress:1.25.0") + testImplementation("org.apache.groovy:groovy-xml") } @@ -47,4 +53,3 @@ rocker { javaVersion = '17' postProcessing = ['io.micronaut.starter.rocker.WhitespaceProcessor'] } - diff --git a/starter-core/src/main/java/io/micronaut/starter/build/dependencies/MicronautDependencyUtils.java b/starter-core/src/main/java/io/micronaut/starter/build/dependencies/MicronautDependencyUtils.java index 89fc7e77b81..ac60433bb93 100644 --- a/starter-core/src/main/java/io/micronaut/starter/build/dependencies/MicronautDependencyUtils.java +++ b/starter-core/src/main/java/io/micronaut/starter/build/dependencies/MicronautDependencyUtils.java @@ -28,7 +28,8 @@ public final class MicronautDependencyUtils { .build(); public static final String GROUP_ID_MICRONAUT = "io.micronaut"; - + public static final String GROUP_ID_MICRONAUT_TESTRESOURCES = "io.micronaut.testresources"; + public static final String GROUP_ID_MICRONAUT_JAXRS = "io.micronaut.jaxrs"; public static final String GROUP_ID_MICRONAUT_MICROSTREAM = "io.micronaut.microstream"; public static final String ARTIFACT_ID_MICRONAUT_INJECT_JAVA = "micronaut-inject-java"; public static final String GROUP_ID_MICRONAUT_AWS = "io.micronaut.aws"; @@ -41,11 +42,13 @@ public final class MicronautDependencyUtils { public static final String GROUP_ID_MICRONAUT_GCP = "io.micronaut.gcp"; public static final String GROUP_ID_MICRONAUT_KAFKA = "io.micronaut.kafka"; public static final String GROUP_ID_MICRONAUT_OCI = "io.micronaut.oraclecloud"; + public static final String GROUP_ID_MICRONAUT_OPENSEARCH = "io.micronaut.opensearch"; public static final String GROUP_ID_MICRONAUT_SERDE = "io.micronaut.serde"; public static final String GROUP_ID_MICRONAUT_REACTOR = "io.micronaut.reactor"; public static final String GROUP_ID_MICRONAUT_SECURITY = "io.micronaut.security"; public static final String GROUP_ID_MICRONAUT_SESSION = "io.micronaut.session"; public static final String GROUP_ID_MICRONAUT_SERVLET = "io.micronaut.servlet"; + public static final String GROUP_ID_MICRONAUT_SOURCEGEN = "io.micronaut.sourcegen"; public static final String GROUP_ID_MICRONAUT_TRACING = "io.micronaut.tracing"; public static final String GROUP_ID_MICRONAUT_TEST = "io.micronaut.test"; public static final String GROUP_ID_MICRONAUT_R2DBC = "io.micronaut.r2dbc"; @@ -83,6 +86,11 @@ public static Dependency.Builder coreDependency() { return micronautDependency(GROUP_ID_MICRONAUT); } + @NonNull + public static Dependency.Builder jaxrsDependency() { + return micronautDependency(GROUP_ID_MICRONAUT_JAXRS); + } + @NonNull public static Dependency.Builder awsDependency() { return micronautDependency(GROUP_ID_MICRONAUT_AWS); @@ -118,10 +126,16 @@ public static Dependency.Builder sessionDependency() { return micronautDependency(GROUP_ID_MICRONAUT_SESSION); } + @NonNull public static Dependency.Builder servletDependency() { return micronautDependency(GROUP_ID_MICRONAUT_SERVLET); } + @NonNull + public static Dependency.Builder sourcegenDependency() { + return micronautDependency(GROUP_ID_MICRONAUT_SOURCEGEN); + } + @NonNull public static Dependency.Builder testDependency() { return micronautDependency(GROUP_ID_MICRONAUT_TEST); @@ -213,6 +227,11 @@ public static Dependency.Builder ociDependency() { return micronautDependency(GROUP_ID_MICRONAUT_OCI); } + @NonNull + public static Dependency.Builder opensearchDependency() { + return micronautDependency(GROUP_ID_MICRONAUT_OPENSEARCH); + } + @NonNull public static Dependency.Builder platformDependency() { return micronautDependency(GROUP_ID_MICRONAUT_PLATFORM); @@ -228,6 +247,7 @@ public static Dependency.Builder jmsDependency() { return micronautDependency(GROUP_ID_IO_MICRONAUT_JMS); } + @NonNull public static Dependency.Builder neo4j() { return micronautDependency(GROUP_ID_IO_MICRONAUT_NEO4J); } @@ -256,7 +276,8 @@ public static Dependency.Builder picocliDependency() { public static Dependency.Builder discovery() { return micronautDependency(GROUP_ID_IO_MICRONAUT_DISCOVERY); } - + + @NonNull public static Dependency.Builder flywayDependency() { return micronautDependency(GROUP_ID_MICRONAUT_FLYWAY); } @@ -280,7 +301,30 @@ public static Dependency.Builder annotationProcessor(@NonNull BuildTool buildToo .groupId(groupId) .artifactId(artifactId) .annotationProcessor(); - case MAVEN -> moduleMavenAnnotationProcessor(groupId, artifactId, propertyName, requiresPriority); + case MAVEN -> moduleMavenAnnotationProcessor(groupId, artifactId, propertyName, false, requiresPriority); + }; + } + + @NonNull + public static Dependency.Builder testAnnotationProcessor(@NonNull BuildTool buildTool, + @NonNull String groupId, + @NonNull String artifactId, + @NonNull String propertyName) { + return testAnnotationProcessor(buildTool, groupId, artifactId, propertyName, false); + } + + @NonNull + public static Dependency.Builder testAnnotationProcessor(@NonNull BuildTool buildTool, + @NonNull String groupId, + @NonNull String artifactId, + @NonNull String propertyName, + boolean requiresPriority) { + return switch (buildTool) { + case GRADLE, GRADLE_KOTLIN -> Dependency.builder() + .groupId(groupId) + .artifactId(artifactId) + .testAnnotationProcessor(); + case MAVEN -> moduleMavenAnnotationProcessor(groupId, artifactId, propertyName, true, requiresPriority); }; } @@ -288,13 +332,15 @@ public static Dependency.Builder annotationProcessor(@NonNull BuildTool buildToo public static Dependency.Builder moduleMavenAnnotationProcessor(@NonNull String groupId, @NonNull String artifactId, @NonNull String propertyName, + boolean isTestScope, boolean requiresPriority) { - return Dependency.builder() + Dependency.Builder dependency = Dependency.builder() .groupId(groupId) .artifactId(artifactId) - .annotationProcessor(requiresPriority) - .versionProperty(propertyName) - .exclude(MICRONAUT_INJECT); + .exclude(MICRONAUT_INJECT) + .versionProperty(propertyName); + + return isTestScope ? dependency.testAnnotationProcessor(requiresPriority) : dependency.annotationProcessor(requiresPriority); } @NonNull @@ -307,14 +353,17 @@ public static Dependency.Builder oracleCloudDependency() { return micronautDependency(GROUP_ID_IO_MICRONAUT_ORACLE_CLOUD); } + @NonNull public static Dependency.Builder microstreamDependency() { return micronautDependency(GROUP_ID_MICRONAUT_MICROSTREAM); } + @NonNull public static Dependency.Builder springDependency() { return micronautDependency(GROUP_ID_MICRONAUT_SPRING); } + @NonNull public static Dependency.Builder viewsDependency() { return micronautDependency(GROUP_ID_MICRONAUT_VIEWS); } diff --git a/starter-core/src/main/java/io/micronaut/starter/build/maven/MavenBuild.java b/starter-core/src/main/java/io/micronaut/starter/build/maven/MavenBuild.java index b81b48b917d..a14ff06474d 100644 --- a/starter-core/src/main/java/io/micronaut/starter/build/maven/MavenBuild.java +++ b/starter-core/src/main/java/io/micronaut/starter/build/maven/MavenBuild.java @@ -20,6 +20,7 @@ import io.micronaut.starter.build.dependencies.Coordinate; import io.micronaut.starter.build.dependencies.DependencyCoordinate; +import io.micronaut.starter.build.dependencies.MavenCoordinate; import io.micronaut.starter.feature.build.maven.Profile; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -56,6 +57,7 @@ public class MavenBuild { private final List repositories; private final List aotDependencies; + private final List testResourcesDependencies; @NonNull private final String artifactId; @@ -71,6 +73,7 @@ public MavenBuild(String artifactId) { MavenCombineAttribute.APPEND, MavenCombineAttribute.APPEND, Collections.emptyList(), + Collections.emptyList(), Collections.emptyList()); } @@ -88,6 +91,7 @@ public MavenBuild(@NonNull String artifactId, MavenCombineAttribute.APPEND, MavenCombineAttribute.APPEND, Collections.emptyList(), + Collections.emptyList(), Collections.emptyList()); } @@ -101,7 +105,8 @@ public MavenBuild(@NonNull String artifactId, @NonNull MavenCombineAttribute annotationProcessorCombineAttribute, @NonNull MavenCombineAttribute testAnnotationProcessorCombineAttribute, @NonNull Collection profiles, - @NonNull List aotDependencies) { + @NonNull List aotDependencies, + @NonNull List testResourcesDependencies) { this.artifactId = artifactId; this.annotationProcessors = annotationProcessors; this.testAnnotationProcessors = testAnnotationProcessors; @@ -113,6 +118,7 @@ public MavenBuild(@NonNull String artifactId, this.testAnnotationProcessorCombineAttribute = testAnnotationProcessorCombineAttribute; this.profiles = profiles; this.aotDependencies = aotDependencies; + this.testResourcesDependencies = testResourcesDependencies; } @NonNull @@ -185,4 +191,9 @@ public MavenCombineAttribute getTestAnnotationProcessorCombineAttribute() { public List getAotDependencies() { return aotDependencies; } + + public List getTestResourcesDependencies() { + return testResourcesDependencies; + } + } diff --git a/starter-core/src/main/java/io/micronaut/starter/build/maven/MavenBuildCreator.java b/starter-core/src/main/java/io/micronaut/starter/build/maven/MavenBuildCreator.java index 66719daa4aa..f72884d7713 100644 --- a/starter-core/src/main/java/io/micronaut/starter/build/maven/MavenBuildCreator.java +++ b/starter-core/src/main/java/io/micronaut/starter/build/maven/MavenBuildCreator.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2022 original authors + * Copyright 2017-2024 original authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,18 +23,19 @@ import io.micronaut.starter.build.dependencies.Coordinate; import io.micronaut.starter.build.dependencies.Dependency; import io.micronaut.starter.build.dependencies.DependencyCoordinate; +import io.micronaut.starter.build.dependencies.MavenCoordinate; import io.micronaut.starter.build.dependencies.MicronautDependencyUtils; import io.micronaut.starter.build.dependencies.Phase; import io.micronaut.starter.build.dependencies.Priority; import io.micronaut.starter.build.dependencies.Scope; import io.micronaut.starter.build.dependencies.Source; +import io.micronaut.starter.feature.testresources.TestResourcesAdditionalModulesProvider; import io.micronaut.starter.options.Language; import io.micronaut.starter.options.Options; import jakarta.inject.Singleton; import java.util.ArrayList; import java.util.List; -import java.util.stream.Collectors; @Singleton public class MavenBuildCreator { @@ -53,7 +54,9 @@ public MavenBuild create(GeneratorContext generatorContext, List rep for (Dependency dependency : generatorContext.getDependencies()) { if (dependency.getScope().getPhases().contains(Phase.ANNOTATION_PROCESSING)) { - if (dependency.getScope().getSource() == Source.MAIN) { + if (dependency.getScope().getSource() == Source.MAIN && generatorContext.getLanguage() != Language.GROOVY) { + // Don't add these for Groovy projects: it results in multiple dependencies. + // DependencyContext has already resolved Groovy annotation processors as dependencies annotationProcessorsCoordinates.add(new DependencyCoordinate(dependency, true)); if (dependency.isAnnotationProcessorPriority()) { combineAttribute = MavenCombineAttribute.OVERRIDE; @@ -94,7 +97,7 @@ public MavenBuild create(GeneratorContext generatorContext, List rep .filter(MavenPlugin.class::isInstance) .map(MavenPlugin.class::cast) .sorted(OrderUtil.COMPARATOR) - .collect(Collectors.toList()); + .toList(); return new MavenBuild(generatorContext.getProject().getName(), annotationProcessorsCoordinates, @@ -106,6 +109,18 @@ public MavenBuild create(GeneratorContext generatorContext, List rep combineAttribute, testCombineAttribute, generatorContext.getProfiles(), - generatorContext.getDependencies().stream().filter(dep -> dep.getScope() == Scope.AOT_PLUGIN).map(DependencyCoordinate::new).toList()); + generatorContext.getDependencies().stream().filter(dep -> dep.getScope() == Scope.AOT_PLUGIN).map(DependencyCoordinate::new).toList(), + testResourcesDependencies(generatorContext)); + } + + @NonNull + private static List testResourcesDependencies(@NonNull GeneratorContext generatorContext) { + return generatorContext.getFeatures().getFeatures() + .stream() + .filter(TestResourcesAdditionalModulesProvider.class::isInstance) + .map(f -> ((TestResourcesAdditionalModulesProvider) f).getTestResourcesDependencies(generatorContext)) + .flatMap(List::stream) + .distinct() + .toList(); } } diff --git a/starter-core/src/main/java/io/micronaut/starter/client/github/oauth/AccessToken.java b/starter-core/src/main/java/io/micronaut/starter/client/github/oauth/AccessToken.java deleted file mode 100644 index c359720d235..00000000000 --- a/starter-core/src/main/java/io/micronaut/starter/client/github/oauth/AccessToken.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2017-2022 original authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.micronaut.starter.client.github.oauth; - -import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.annotation.JsonProperty; -import io.micronaut.core.annotation.Introspected; - -/** - * @author Pavol Gressa - * @since 2.2 - */ -@Introspected -public class AccessToken { - - private final String tokenType; - private final String scope; - private final String accessToken; - - @JsonCreator - public AccessToken( - @JsonProperty("token_type") String tokenType, - @JsonProperty("scope") String scope, - @JsonProperty("access_token") String accessToken) { - this.tokenType = tokenType; - this.scope = scope; - this.accessToken = accessToken; - } - - public String getTokenType() { - return tokenType; - } - - public String getScope() { - return scope; - } - - public String getAccessToken() { - return accessToken; - } -} diff --git a/starter-core/src/main/java/io/micronaut/starter/client/github/oauth/GitHubOAuthClient.java b/starter-core/src/main/java/io/micronaut/starter/client/github/oauth/GitHubOAuthClient.java deleted file mode 100644 index 61a2dc40078..00000000000 --- a/starter-core/src/main/java/io/micronaut/starter/client/github/oauth/GitHubOAuthClient.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2017-2022 original authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.micronaut.starter.client.github.oauth; - -import io.micronaut.context.annotation.Requires; -import io.micronaut.http.MediaType; -import io.micronaut.http.annotation.Header; -import io.micronaut.http.client.annotation.Client; - -/** - * GitHub OAuth client. - * - * @author Pavol Gressa - * @since 2.2 - */ -@Client(id = GitHubOAuthClient.SERVICE_ID, path = "/login/oauth") -@Requires(property = "micronaut.http.services." + GitHubOAuthClient.SERVICE_ID) -@Header(name = "User-Agent", value = "https://micronaut.io/launch/") -@Header(name = "Accept", value = MediaType.APPLICATION_JSON) -public interface GitHubOAuthClient extends GitHubOAuthOperations { - String SERVICE_ID = "github-oauth"; - String SERVICE_URL = "https://github.com"; -} diff --git a/starter-core/src/main/java/io/micronaut/starter/client/github/oauth/GitHubOAuthOperations.java b/starter-core/src/main/java/io/micronaut/starter/client/github/oauth/GitHubOAuthOperations.java deleted file mode 100644 index a1416190bd1..00000000000 --- a/starter-core/src/main/java/io/micronaut/starter/client/github/oauth/GitHubOAuthOperations.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2017-2022 original authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.micronaut.starter.client.github.oauth; - -import io.micronaut.http.annotation.Post; -import io.micronaut.http.annotation.QueryValue; - -/** - * GitHub Oauth operations. - * - * @author Pavol Gressa - * @since 2.2 - */ -public interface GitHubOAuthOperations { - - @Post(value = "/access_token") - AccessToken accessToken(@QueryValue("client_id") String clientId, @QueryValue("client_secret") String clientSecret, @QueryValue String code, @QueryValue String state); - -} diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/GroovySpecificFeature.java b/starter-core/src/main/java/io/micronaut/starter/feature/RequireKaptFeature.java similarity index 55% rename from starter-core/src/main/java/io/micronaut/starter/feature/GroovySpecificFeature.java rename to starter-core/src/main/java/io/micronaut/starter/feature/RequireKaptFeature.java index da7c7fdbd40..543d0232da8 100644 --- a/starter-core/src/main/java/io/micronaut/starter/feature/GroovySpecificFeature.java +++ b/starter-core/src/main/java/io/micronaut/starter/feature/RequireKaptFeature.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2022 original authors + * Copyright 2017-2024 original authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,18 +15,14 @@ */ package io.micronaut.starter.feature; -import io.micronaut.starter.options.Language; - /** - * A feature that only works with Groovy specific language. + * Some third party features apply annotation processors that are not compatible with Kotlin Symbol Processing (KSP) + * for Kotlin language projects. They require using the kapt compiler plugin (Kapt) instead. Note that Maven + * projects always use Kapt since Maven isn't compatible with KSP. * - * @author Sergio - * @since 3.7.0 + * @see io.micronaut.starter.feature.build.Kapt + * @see KotlinSymbolProcessing + * @see RequireKaptFeatureValidator */ -public interface GroovySpecificFeature extends LanguageSpecificFeature { - - @Override - default Language getRequiredLanguage() { - return Language.GROOVY; - } +public interface RequireKaptFeature extends Feature { } diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/RequireKaptFeatureValidator.java b/starter-core/src/main/java/io/micronaut/starter/feature/RequireKaptFeatureValidator.java new file mode 100644 index 00000000000..ff5a3496988 --- /dev/null +++ b/starter-core/src/main/java/io/micronaut/starter/feature/RequireKaptFeatureValidator.java @@ -0,0 +1,46 @@ +/* + * Copyright 2017-2024 original authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.micronaut.starter.feature; + +import io.micronaut.starter.application.ApplicationType; +import io.micronaut.starter.feature.validation.FeatureValidator; +import io.micronaut.starter.options.Language; +import io.micronaut.starter.options.Options; +import jakarta.inject.Singleton; + +import java.util.Set; + +@Singleton +public class RequireKaptFeatureValidator implements FeatureValidator { + + @Override + public void validatePreProcessing(Options options, ApplicationType applicationType, Set features) { + } + + @Override + public void validatePostProcessing(Options options, ApplicationType applicationType, Set features) { + if (options.getLanguage() == Language.KOTLIN) { + for (Feature feature : features) { + if (feature instanceof RequireKaptFeature) { + if (features.stream().anyMatch(KotlinSymbolProcessing.class::isInstance)) { + throw new IllegalArgumentException( + String.format("Feature %s is incompatible with Kotlin KSP and requires Kapt instead.", feature.getName())); + } + } + } + } + } +} diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/aws/Cdk.java b/starter-core/src/main/java/io/micronaut/starter/feature/aws/Cdk.java index 39e598703cc..1965c16f4ce 100644 --- a/starter-core/src/main/java/io/micronaut/starter/feature/aws/Cdk.java +++ b/starter-core/src/main/java/io/micronaut/starter/feature/aws/Cdk.java @@ -265,6 +265,7 @@ public String getValue() { MavenCombineAttribute.APPEND, MavenCombineAttribute.APPEND, Collections.emptyList(), + Collections.emptyList(), Collections.emptyList()); } diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/aws/template/cdkappstack.rocker.raw b/starter-core/src/main/java/io/micronaut/starter/feature/aws/template/cdkappstack.rocker.raw index fdd3dff2662..59309756274 100644 --- a/starter-core/src/main/java/io/micronaut/starter/feature/aws/template/cdkappstack.rocker.raw +++ b/starter-core/src/main/java/io/micronaut/starter/feature/aws/template/cdkappstack.rocker.raw @@ -18,9 +18,7 @@ import software.amazon.awscdk.CfnOutput; import software.amazon.awscdk.Duration; import software.amazon.awscdk.Stack; import software.amazon.awscdk.StackProps; -@if (!nativeImage) { import software.amazon.awscdk.services.lambda.Runtime; -} import software.amazon.awscdk.services.lambda.Architecture; @if (features.contains("dynamodb")) { import software.amazon.awscdk.services.dynamodb.Attribute; @@ -150,6 +148,11 @@ public class AppStack extends Stack { @if (jdkVersion == JdkVersion.JDK_17) { .runtime(Runtime.JAVA_17) } +@if (jdkVersion == JdkVersion.JDK_21) { + .runtime(Runtime.JAVA_21) +} +} else { + .runtime(Runtime.PROVIDED_AL2023) } .handler("@(handler)") .environment(environmentVariables) @@ -157,12 +160,11 @@ public class AppStack extends Stack { .timeout(Duration.seconds(10)) .memorySize(2048) .logRetention(RetentionDays.ONE_WEEK) + .tracing(Tracing.ACTIVE) @if (features.contains("snapstart")) { - .tracing(Tracing.DISABLED) .architecture(Architecture.X86_64) .snapStart(SnapStartConf.ON_PUBLISHED_VERSIONS) } else { - .tracing(Tracing.ACTIVE) @if (architecture instanceof Arm) { .architecture(Architecture.ARM_64) } else if (architecture instanceof X86) { diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/awslambdacustomruntime/AwsLambdaCustomRuntime.java b/starter-core/src/main/java/io/micronaut/starter/feature/awslambdacustomruntime/AwsLambdaCustomRuntime.java index 30ba827126e..9253e1931c2 100644 --- a/starter-core/src/main/java/io/micronaut/starter/feature/awslambdacustomruntime/AwsLambdaCustomRuntime.java +++ b/starter-core/src/main/java/io/micronaut/starter/feature/awslambdacustomruntime/AwsLambdaCustomRuntime.java @@ -18,6 +18,7 @@ import io.micronaut.context.exceptions.ConfigurationException; import io.micronaut.core.annotation.NonNull; import io.micronaut.core.annotation.Nullable; +import io.micronaut.http.client.HttpClient; import io.micronaut.starter.application.ApplicationType; import io.micronaut.starter.application.Project; import io.micronaut.starter.application.generator.GeneratorContext; @@ -35,8 +36,10 @@ import io.micronaut.starter.feature.function.FunctionFeature; import io.micronaut.starter.feature.function.awslambda.AwsLambda; import io.micronaut.starter.feature.graalvm.GraalVM; -import io.micronaut.starter.feature.other.HttpClient; +import io.micronaut.starter.feature.httpclient.HttpClientFeature; +import io.micronaut.starter.feature.httpclient.HttpClientJdk; import io.micronaut.starter.template.RockerWritable; +import jakarta.inject.Inject; import jakarta.inject.Provider; import jakarta.inject.Singleton; @@ -51,11 +54,24 @@ public class AwsLambdaCustomRuntime implements FunctionFeature, ApplicationFeatu public static final String FEATURE_NAME_AWS_LAMBDA_CUSTOM_RUNTIME = "aws-lambda-custom-runtime"; private final Provider awsLambda; - private final HttpClient httpClient; + private final HttpClientJdk httpClientJdk; - public AwsLambdaCustomRuntime(Provider awsLambda, HttpClient httpClient) { + @Inject + public AwsLambdaCustomRuntime(Provider awsLambda, + HttpClientJdk httpClientJdk) { this.awsLambda = awsLambda; - this.httpClient = httpClient; + this.httpClientJdk = httpClientJdk; + } + + /** + * + * @param awsLambda AWS Lambda + * @param httpClient Netty HTTP Client + * @deprecated Use {@link #AwsLambdaCustomRuntime(Provider, HttpClientJdk)} instead. + */ + @Deprecated + public AwsLambdaCustomRuntime(Provider awsLambda, HttpClient httpClient) { + this(awsLambda, new HttpClientJdk()); } @Override @@ -64,8 +80,8 @@ public void processSelectedFeatures(FeatureContext featureContext) { if (awsLambda.supports(featureContext.getApplicationType()) && !featureContext.isPresent(AwsLambda.class)) { featureContext.addFeature(awsLambda); } - if (!featureContext.isPresent(HttpClient.class)) { - featureContext.addFeature(httpClient); + if (!featureContext.isPresent(HttpClientFeature.class)) { + featureContext.addFeature(httpClientJdk); } } diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/awsparameterstore/AwsParameterStore.java b/starter-core/src/main/java/io/micronaut/starter/feature/awsparameterstore/AwsParameterStore.java index 4af2ebffa78..a6430c87d77 100644 --- a/starter-core/src/main/java/io/micronaut/starter/feature/awsparameterstore/AwsParameterStore.java +++ b/starter-core/src/main/java/io/micronaut/starter/feature/awsparameterstore/AwsParameterStore.java @@ -15,8 +15,10 @@ */ package io.micronaut.starter.feature.awsparameterstore; +import io.micronaut.core.annotation.NonNull; import io.micronaut.starter.application.generator.GeneratorContext; import io.micronaut.starter.build.dependencies.Dependency; +import io.micronaut.starter.build.dependencies.MicronautDependencyUtils; import io.micronaut.starter.feature.distributedconfig.DistributedConfigFeature; import jakarta.inject.Singleton; @@ -24,6 +26,19 @@ @Singleton public class AwsParameterStore implements DistributedConfigFeature { + private static final String ARTIFACT_ID_MICRONAUT_AWS_PARAMETER_STORE = "micronaut-aws-parameter-store"; + private static final Dependency.Builder DEPENDNCY_MICRONAUT_AWS_PARAMETER_STORE = MicronautDependencyUtils.awsDependency() + .artifactId(ARTIFACT_ID_MICRONAUT_AWS_PARAMETER_STORE) + .compile(); + private static final String PROPERTY_AWS_CLIENT_SYSTEM_MANAGER_PARAMETERSTORE_ENABLED = "aws.client.system-manager.parameterstore.enabled"; + private static final String PROPERTY_AWS_DISTRIBUTED_CONFIGURATION_SEARCH_ACTIVE_ENVIRONMENTS = "aws.distributed-configuration.search-active-environments"; + private static final String PROPERTY_AWS_DISTRIBUTED_CONFIGURATION_SEARCH_COMMON_APPLICATION = "aws.distributed-configuration.search-common-application"; + + public static final Map PROPERTIES_AWS_DISTRIBUTED_CONFIGURATION = Map.of( + PROPERTY_AWS_CLIENT_SYSTEM_MANAGER_PARAMETERSTORE_ENABLED, true, + PROPERTY_AWS_DISTRIBUTED_CONFIGURATION_SEARCH_ACTIVE_ENVIRONMENTS, false, + PROPERTY_AWS_DISTRIBUTED_CONFIGURATION_SEARCH_COMMON_APPLICATION, false); + @Override public String getTitle() { return "AWS Parameter Store Distributed Configuration"; @@ -41,13 +56,8 @@ public String getDescription() { @Override public void apply(GeneratorContext generatorContext) { - generatorContext.addDependency(Dependency.builder() - .groupId("io.micronaut.aws") - .artifactId("micronaut-aws-parameter-store") - .compile()); - - Map config = populateBootstrapForDistributedConfiguration(generatorContext); - config.put("aws.client.system-manager.parameterstore.enabled", true); + addDependencies(generatorContext); + addBootstrapProperties(generatorContext); } @Override @@ -59,4 +69,12 @@ public String getMicronautDocumentation() { public String getThirdPartyDocumentation() { return "https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-parameter-store.html"; } + + protected void addBootstrapProperties(@NonNull GeneratorContext generatorContext) { + populateBootstrapForDistributedConfiguration(generatorContext).putAll(PROPERTIES_AWS_DISTRIBUTED_CONFIGURATION); + } + + protected void addDependencies(@NonNull GeneratorContext generatorContext) { + generatorContext.addDependency(DEPENDNCY_MICRONAUT_AWS_PARAMETER_STORE); + } } diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/awssecretsmanager/AwsSecretsManager.java b/starter-core/src/main/java/io/micronaut/starter/feature/awssecretsmanager/AwsSecretsManager.java index ce6379502bb..69d7f18b7a0 100644 --- a/starter-core/src/main/java/io/micronaut/starter/feature/awssecretsmanager/AwsSecretsManager.java +++ b/starter-core/src/main/java/io/micronaut/starter/feature/awssecretsmanager/AwsSecretsManager.java @@ -15,11 +15,13 @@ */ package io.micronaut.starter.feature.awssecretsmanager; +import io.micronaut.core.annotation.NonNull; import io.micronaut.starter.application.generator.GeneratorContext; import io.micronaut.starter.build.dependencies.Dependency; +import io.micronaut.starter.build.dependencies.MicronautDependencyUtils; +import io.micronaut.starter.feature.awsparameterstore.AwsParameterStore; import io.micronaut.starter.feature.distributedconfig.DistributedConfigFeature; import jakarta.inject.Singleton; -import java.util.Map; /** * @see Micronaut AWS Secrets Manager @@ -28,6 +30,11 @@ */ @Singleton public class AwsSecretsManager implements DistributedConfigFeature { + private static final String ARTIFACT_ID_MICRONAUT_AWS_SECRETSMANAGER = "micronaut-aws-secretsmanager"; + private static final Dependency.Builder DEPENDENCY_MICRONAUT_AWS_SECRETSMANAGER = MicronautDependencyUtils.awsDependency() + .artifactId(ARTIFACT_ID_MICRONAUT_AWS_SECRETSMANAGER) + .compile(); + @Override public String getTitle() { return "AWS Secrets Manager"; @@ -45,12 +52,8 @@ public String getDescription() { @Override public void apply(GeneratorContext generatorContext) { - generatorContext.addDependency(Dependency.builder() - .groupId("io.micronaut.aws") - .artifactId("micronaut-aws-secretsmanager") - .compile()); - Map config = populateBootstrapForDistributedConfiguration(generatorContext); - config.put("aws.client.system-manager.parameterstore.enabled", true); + addDependencies(generatorContext); + addBootstrapProperties(generatorContext); } @Override @@ -62,4 +65,12 @@ public String getMicronautDocumentation() { public String getThirdPartyDocumentation() { return "https://aws.amazon.com/secrets-manager/"; } + + protected void addBootstrapProperties(@NonNull GeneratorContext generatorContext) { + populateBootstrapForDistributedConfiguration(generatorContext).putAll(AwsParameterStore.PROPERTIES_AWS_DISTRIBUTED_CONFIGURATION); + } + + protected static void addDependencies(@NonNull GeneratorContext generatorContext) { + generatorContext.addDependency(DEPENDENCY_MICRONAUT_AWS_SECRETSMANAGER); + } } diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/azure/AzureKeyVaultFeature.java b/starter-core/src/main/java/io/micronaut/starter/feature/azure/AzureKeyVaultFeature.java index c0ffbf410ce..05fca6c0e73 100644 --- a/starter-core/src/main/java/io/micronaut/starter/feature/azure/AzureKeyVaultFeature.java +++ b/starter-core/src/main/java/io/micronaut/starter/feature/azure/AzureKeyVaultFeature.java @@ -17,7 +17,11 @@ import io.micronaut.starter.application.generator.GeneratorContext; import io.micronaut.starter.build.dependencies.Dependency; +import io.micronaut.starter.build.dependencies.MicronautDependencyUtils; +import io.micronaut.starter.feature.FeatureContext; +import io.micronaut.starter.feature.discovery.DiscoveryClient; import io.micronaut.starter.feature.distributedconfig.DistributedConfigFeature; +import io.micronaut.starter.feature.httpclient.HttpClientFeature; import jakarta.inject.Singleton; /** @@ -28,6 +32,24 @@ */ @Singleton public class AzureKeyVaultFeature implements DistributedConfigFeature { + private static final String ARTIFACT_ID_MICRONAUT_AZURE_SECRET_MANAGER = "micronaut-azure-secret-manager"; + private static final Dependency KEY_VAULT_DEPENDENCY = MicronautDependencyUtils.azureDependency() + .artifactId(ARTIFACT_ID_MICRONAUT_AZURE_SECRET_MANAGER) + .compile() + .build(); + private final DiscoveryClient discoveryClient; + + public AzureKeyVaultFeature(DiscoveryClient discoveryClient) { + this.discoveryClient = discoveryClient; + } + + @Override + public void processSelectedFeatures(FeatureContext featureContext) { + if (!featureContext.isPresent(DiscoveryClient.class)) { + featureContext.addFeature(discoveryClient); + } + } + @Override public String getTitle() { return "Azure Key Vault"; @@ -55,10 +77,11 @@ public String getThirdPartyDocumentation() { @Override public void apply(GeneratorContext generatorContext) { - generatorContext.addDependency(Dependency.builder() - .groupId("io.micronaut.azure") - .artifactId("micronaut-azure-secret-manager") - .compile()); + addDependencies(generatorContext); populateBootstrapForDistributedConfiguration(generatorContext); } + + protected void addDependencies(GeneratorContext generatorContext) { + generatorContext.addDependency(KEY_VAULT_DEPENDENCY); + } } diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/build/MicronautAot.java b/starter-core/src/main/java/io/micronaut/starter/feature/build/MicronautAot.java index 789f4ee59c4..b015403fc7b 100644 --- a/starter-core/src/main/java/io/micronaut/starter/feature/build/MicronautAot.java +++ b/starter-core/src/main/java/io/micronaut/starter/feature/build/MicronautAot.java @@ -143,6 +143,7 @@ protected List optimizations(boolean graalvm, Generato final List optimizations = new ArrayList<>(); optimizations.add(new MicronautAotOptimization("cached.environment.enabled", true, "Caches environment property values: environment properties will be deemed immutable after application startup.")); optimizations.add(new MicronautAotOptimization("precompute.environment.properties.enabled", true, "Precomputes Micronaut configuration property keys from the current environment variables")); + optimizations.add(new MicronautAotOptimization("logback.xml.to.java.enabled", true, "Replaces logback.xml with a pure Java configuration")); if (graalvm) { optimizations.add(new MicronautAotOptimization("yaml.to.java.config.enabled", false, "Converts YAML configuration files to Java configuration")); optimizations.add(new MicronautAotOptimization("graalvm.config.enabled", true, "Generates GraalVM configuration files required to load the AOT optimizations")); diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/build/MicronautBuildPlugin.java b/starter-core/src/main/java/io/micronaut/starter/feature/build/MicronautBuildPlugin.java index 5ba1720a89c..1cf456492ef 100644 --- a/starter-core/src/main/java/io/micronaut/starter/feature/build/MicronautBuildPlugin.java +++ b/starter-core/src/main/java/io/micronaut/starter/feature/build/MicronautBuildPlugin.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2021 original authors + * Copyright 2017-2024 original authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -34,25 +34,25 @@ import io.micronaut.starter.feature.MicronautRuntimeFeature; import io.micronaut.starter.feature.build.gradle.Dockerfile; import io.micronaut.starter.feature.build.gradle.MicronautApplicationGradlePlugin; -import io.micronaut.starter.feature.database.Data; -import io.micronaut.starter.feature.database.DatabaseDriverFeature; -import io.micronaut.starter.feature.database.HibernateReactiveFeature; -import io.micronaut.starter.feature.database.r2dbc.R2dbc; import io.micronaut.starter.feature.function.LambdaRuntimeMainClass; import io.micronaut.starter.feature.function.awslambda.AwsLambda; import io.micronaut.starter.feature.graalvm.GraalVMFeatureValidator; import io.micronaut.starter.feature.messaging.SharedTestResourceFeature; import io.micronaut.starter.feature.security.SecurityJWT; import io.micronaut.starter.feature.security.SecurityOAuth2; -import io.micronaut.starter.feature.testresources.DbType; import io.micronaut.starter.feature.testresources.TestResources; +import io.micronaut.starter.feature.testresources.TestResourcesAdditionalModulesProvider; +import io.micronaut.starter.options.JdkVersion; import io.micronaut.starter.options.Options; import jakarta.inject.Singleton; + +import java.util.List; import java.util.Optional; import java.util.Set; +import java.util.stream.Collectors; -import static io.micronaut.starter.feature.graalvm.GraalVM.FEATURE_NAME_GRAALVM; import static io.micronaut.starter.build.dependencies.MicronautDependencyUtils.ARTIFACT_ID_MICRONAUT_DATA_PROCESSOR_ARTIFACT; +import static io.micronaut.starter.feature.graalvm.GraalVM.FEATURE_NAME_GRAALVM; @Singleton public class MicronautBuildPlugin implements BuildPluginFeature, DefaultFeature { @@ -83,7 +83,7 @@ public void apply(GeneratorContext generatorContext) { generatorContext.addBuildPlugin(gradlePlugin(generatorContext)); } } - + @NonNull protected GradlePlugin gradlePlugin(@NonNull GeneratorContext generatorContext) { GradlePlugin.Builder builder = null; @@ -168,19 +168,19 @@ protected MicronautApplicationGradlePlugin.Builder micronautGradleApplicationPlu builder = builder.testRuntime(testRuntimeOptional.get()); } if (generatorContext.getFeatures().hasFeature(TestResources.class)) { - Optional databaseDriverFeature = generatorContext.getFeatures().getFeature(DatabaseDriverFeature.class); - if ( - (!generatorContext.getFeatures().hasFeature(Data.class) || generatorContext.isFeaturePresent(HibernateReactiveFeature.class)) && - databaseDriverFeature.isPresent() - ) { - databaseDriverFeature.flatMap(DatabaseDriverFeature::getDbType) - .map(dbType -> getModuleName(generatorContext, dbType)) - .ifPresent(builder::addAdditionalTestResourceModules); + for (String addAdditionalTestResourceModule : generatorContext.getFeatures().getFeatures() + .stream() + .filter(TestResourcesAdditionalModulesProvider.class::isInstance) + .map(f -> ((TestResourcesAdditionalModulesProvider) f).getTestResourcesAdditionalModules(generatorContext)) + .flatMap(List::stream) + .collect(Collectors.toSet())) { + builder.addAdditionalTestResourceModules(addAdditionalTestResourceModule); } if (generatorContext.getFeatures().isFeaturePresent(SharedTestResourceFeature.class)) { builder = builder.withSharedTestResources(); } } + if (generatorContext.getFeatures().contains(MicronautAot.FEATURE_NAME_AOT)) { Coordinate coordinate = generatorContext.resolveCoordinate("micronaut-aot-core"); builder.aot(coordinate.getVersion()); @@ -194,26 +194,20 @@ protected MicronautApplicationGradlePlugin.Builder micronautGradleApplicationPlu return builder.id(id); } - private String getModuleName(GeneratorContext generatorContext, DbType dbType) { - if (generatorContext.isFeaturePresent(R2dbc.class)) { - return dbType.getR2dbcTestResourcesModuleName(); - } else if (generatorContext.isFeaturePresent(HibernateReactiveFeature.class)) { - return dbType.getHibernateReactiveTestResourcesModuleName(); - } else { - return dbType.getJdbcTestResourcesModuleName(); - } - } - protected MicronautApplicationGradlePlugin.Builder micronautGradleApplicationPluginBuilder(GeneratorContext generatorContext) { MicronautApplicationGradlePlugin.Builder builder = micronautGradleApplicationPluginBuilder(generatorContext, MicronautApplicationGradlePlugin.Builder.APPLICATION); if (generatorContext.getFeatures().contains(AwsLambda.FEATURE_NAME_AWS_LAMBDA) && ( (generatorContext.getApplicationType() == ApplicationType.FUNCTION && generatorContext.getFeatures().contains(FEATURE_NAME_GRAALVM)) || (generatorContext.getApplicationType() == ApplicationType.DEFAULT))) { - builder = builder.dockerNative(Dockerfile.builder().baseImage("amazonlinux:2") + builder.dockerNative(Dockerfile.builder() + .baseImage("amazonlinux:2023") + .javaVersion(generatorContext.getJdkVersion().asString()) .arg("-XX:MaximumHeapSizePercent=80") .arg("-Dio.netty.allocator.numDirectArenas=0") .arg("-Dio.netty.noPreferDirect=true") .build()); + } else if (generatorContext.getJdkVersion() != JdkVersion.JDK_17) { + builder.dockerNative(Dockerfile.builder().javaVersion(generatorContext.getJdkVersion().asString()).build()); } return builder; } diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/build/gradle/Dockerfile.java b/starter-core/src/main/java/io/micronaut/starter/feature/build/gradle/Dockerfile.java index e636d4c92ac..cfc8a14a38b 100644 --- a/starter-core/src/main/java/io/micronaut/starter/feature/build/gradle/Dockerfile.java +++ b/starter-core/src/main/java/io/micronaut/starter/feature/build/gradle/Dockerfile.java @@ -25,11 +25,15 @@ public class Dockerfile { @Nullable private String baseImage; + @Nullable + private String javaVersion; + @Nullable private List args; - public Dockerfile(@NonNull String baseImage, @NonNull List args) { + public Dockerfile(@Nullable String baseImage, @Nullable String javaVersion, @Nullable List args) { this.baseImage = baseImage; + this.javaVersion = javaVersion; this.args = args; } @@ -38,6 +42,11 @@ public String getBaseImage() { return baseImage; } + @Nullable + public String getJavaVersion() { + return javaVersion; + } + @Nullable public List getArgs() { return args; @@ -51,6 +60,7 @@ public static Builder builder() { public static class Builder { private String baseImage; + private String javaVersion; private List args; @NonNull @@ -59,6 +69,11 @@ public Builder baseImage(String baseImage) { return this; } + public Builder javaVersion(String javaVersion) { + this.javaVersion = javaVersion; + return this; + } + @NonNull public Builder arg(String arg) { if (args == null) { @@ -76,7 +91,7 @@ public Builder args(List args) { @NonNull public Dockerfile build() { - return new Dockerfile(baseImage, args); + return new Dockerfile(baseImage, javaVersion, args); } } } diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/build/gradle/Gradle.java b/starter-core/src/main/java/io/micronaut/starter/feature/build/gradle/Gradle.java index 25033181cd4..d6c08477840 100644 --- a/starter-core/src/main/java/io/micronaut/starter/feature/build/gradle/Gradle.java +++ b/starter-core/src/main/java/io/micronaut/starter/feature/build/gradle/Gradle.java @@ -57,7 +57,7 @@ public class Gradle implements BuildFeature { private static final Property PROPERTY_GRADLE_JVMARGS = new Property() { @Override public String getKey() { - return " org.gradle.jvmargs"; + return "org.gradle.jvmargs"; } @Override diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/build/gradle/templates/aotExtension.rocker.raw b/starter-core/src/main/java/io/micronaut/starter/feature/build/gradle/templates/aotExtension.rocker.raw index 8e6c8fa2c3d..7f5a16b224d 100644 --- a/starter-core/src/main/java/io/micronaut/starter/feature/build/gradle/templates/aotExtension.rocker.raw +++ b/starter-core/src/main/java/io/micronaut/starter/feature/build/gradle/templates/aotExtension.rocker.raw @@ -1,19 +1,9 @@ @import io.micronaut.starter.build.gradle.GradleDsl @import java.util.Map -@args(GradleDsl dsl, Map aotKeys) +@args(Map aotKeys) aot { // Please review carefully the optimizations enabled below // Check https://micronaut-projects.github.io/micronaut-aot/latest/guide/ for more details -@if (dsl == GradleDsl.KOTLIN) { - optimizeServiceLoading.set(false) - convertYamlToJava.set(false) - precomputeOperations.set(true) - cacheEnvironment.set(true) - optimizeClassLoading.set(true) - deduceEnvironment.set(true) - optimizeNetty.set(true) -} -@if (dsl == GradleDsl.GROOVY) { optimizeServiceLoading = false convertYamlToJava = false precomputeOperations = true @@ -21,7 +11,7 @@ optimizeClassLoading = true deduceEnvironment = true optimizeNetty = true -} + replaceLogbackXml = true @if(aotKeys != null) { @for (String keyName : aotKeys.keySet()) { configurationProperties.put("@(keyName)","@(aotKeys.get(keyName))") diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/build/gradle/templates/buildGradle.rocker.raw b/starter-core/src/main/java/io/micronaut/starter/feature/build/gradle/templates/buildGradle.rocker.raw index 782facf0620..13236f64520 100644 --- a/starter-core/src/main/java/io/micronaut/starter/feature/build/gradle/templates/buildGradle.rocker.raw +++ b/starter-core/src/main/java/io/micronaut/starter/feature/build/gradle/templates/buildGradle.rocker.raw @@ -48,11 +48,11 @@ repositories { @if (features.mainClass().isPresent()) { application { - mainClass.set("@features.mainClass().get()") + mainClass = "@features.mainClass().get()" } } else if (features.contains("oracle-function") && !features.contains("oracle-function-http")) { application { - mainClass.set("com.fnproject.fn.runtime.EntryPoint") + mainClass = "com.fnproject.fn.runtime.EntryPoint" } } @@ -104,46 +104,75 @@ tasks { } else { dockerfileNative { args("-XX:MaximumHeapSizePercent=80") - buildStrategy.set(io.micronaut.gradle.docker.DockerBuildStrategy.ORACLE_FUNCTION) - defaultCommand.set("@(project.getPackageName()).Function::handleRequest") + buildStrategy = io.micronaut.gradle.docker.DockerBuildStrategy.ORACLE_FUNCTION + defaultCommand = "@(project.getPackageName()).Function::handleRequest" } dockerfile { - buildStrategy.set(io.micronaut.gradle.docker.DockerBuildStrategy.ORACLE_FUNCTION) - defaultCommand.set("@(project.getPackageName()).Function::handleRequest") + buildStrategy = io.micronaut.gradle.docker.DockerBuildStrategy.ORACLE_FUNCTION + defaultCommand = "@(project.getPackageName()).Function::handleRequest" } } + + // Update these to match your region, tenancy and repo +@if(gradleBuild.getDsl() == GradleDsl.KOTLIN) { + val region = "region-key" + val tenancy = "tenancy" + val repo = "my-app" +} else { + String region = "region-key" + String tenancy = "tenancy" + String repo = "my-app" +} + + dockerBuild { @if(features.getFeatures().stream().anyMatch(f -> f instanceof AbstractDockerRegistryWorkflow)) { + @if(gradleBuild.getDsl() == GradleDsl.KOTLIN) { + images = listOf("${System.getenv("DOCKER_IMAGE") ?: project.name}:${project.version}") + } else { images = ["${System.env.DOCKER_IMAGE ?: project.name}:$project.version"] + } } else { @if(gradleBuild.getDsl() == GradleDsl.KOTLIN) { - images.set(listOf("[REGION].ocir.io/[TENANCY]/[REPO]/$project.name:$project.version")) + images = listOf("${region}.ocir.io/${tenancy}/${repo}/${project.name}:${project.version}") } else { - images = ["[REGION].ocir.io/[TENANCY]/[REPO]/$project.name:$project.version"] + images = ["${region}.ocir.io/${tenancy}/${repo}/${project.name}:${project.version}"] } } } dockerBuildNative { @if(features.getFeatures().stream().anyMatch(f -> f instanceof AbstractDockerRegistryWorkflow)) { + @if(gradleBuild.getDsl() == GradleDsl.KOTLIN) { + images = listOf("${System.getenv("DOCKER_IMAGE") ?: project.name}:${project.version}") + } else { images = ["${System.env.DOCKER_IMAGE ?: project.name}:$project.version"] + } } else { @if(gradleBuild.getDsl() == GradleDsl.KOTLIN) { - images.set(listOf("[REGION].ocir.io/[TENANCY]/[REPO]/$project.name-native:$project.version")) + images = listOf("${region}.ocir.io/${tenancy}/${repo}/${project.name}:${project.version}") } else { - images = ["[REGION].ocir.io/[TENANCY]/[REPO]/$project.name-native:$project.version"] + images = ["${region}.ocir.io/${tenancy}/${repo}/${project.name}:${project.version}"] } } } } else if(features.getFeatures().stream().anyMatch(f -> f instanceof AbstractDockerRegistryWorkflow)) { dockerBuild { + @if(gradleBuild.getDsl() == GradleDsl.KOTLIN) { + images = listOf("${System.getenv("DOCKER_IMAGE") ?: project.name}:${project.version}") + } else { images = ["${System.env.DOCKER_IMAGE ?: project.name}:$project.version"] + } } dockerBuildNative { + @if(gradleBuild.getDsl() == GradleDsl.KOTLIN) { + images = listOf("${System.getenv("DOCKER_IMAGE") ?: project.name}:${project.version}") + } else { images = ["${System.env.DOCKER_IMAGE ?: project.name}:$project.version"] + } } } @@ -159,11 +188,7 @@ tasks { } @if (applicationType == ApplicationType.DEFAULT || features.contains("oracle-function")) { - @if(gradleBuild.getDsl() == GradleDsl.KOTLIN) { -graalvmNative.toolchainDetection.set(false) - } else { graalvmNative.toolchainDetection = false - } } @if (features.contains("oracle-function")) { diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/build/gradle/templates/dockerfileExtension.rocker.raw b/starter-core/src/main/java/io/micronaut/starter/feature/build/gradle/templates/dockerfileExtension.rocker.raw new file mode 100644 index 00000000000..f9971fe39d9 --- /dev/null +++ b/starter-core/src/main/java/io/micronaut/starter/feature/build/gradle/templates/dockerfileExtension.rocker.raw @@ -0,0 +1,19 @@ +@import io.micronaut.starter.build.gradle.GradleDsl +@import io.micronaut.starter.feature.build.gradle.Dockerfile +@args(GradleDsl dsl, Dockerfile dockerfile) +@if (dsl == GradleDsl.GROOVY) { +@raw("tasks.named(\"dockerfile\") {\n") +} else { +@raw("tasks.named(\"dockerfile\") {\n") +} +@if(dockerfile.getBaseImage() != null) { + baseImage = "@(dockerfile.getBaseImage())" +} +@if (dockerfile.getArgs() != null) { + args( + @for (int i = 0; i < dockerfile.getArgs().size(); i++) { + "@(dockerfile.getArgs().get(i))"@if (i < (dockerfile.getArgs().size() -1)) {,} + } + ) +} +@raw("}\n") diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/build/gradle/templates/dockerfileNativeExtension.rocker.raw b/starter-core/src/main/java/io/micronaut/starter/feature/build/gradle/templates/dockerfileNativeExtension.rocker.raw new file mode 100644 index 00000000000..8592e026adc --- /dev/null +++ b/starter-core/src/main/java/io/micronaut/starter/feature/build/gradle/templates/dockerfileNativeExtension.rocker.raw @@ -0,0 +1,22 @@ +@import io.micronaut.starter.build.gradle.GradleDsl +@import io.micronaut.starter.feature.build.gradle.Dockerfile +@args(GradleDsl dsl, Dockerfile dockerfileNative) +@if (dsl == GradleDsl.GROOVY) { +@raw("\ntasks.named(\"dockerfileNative\") {\n") +} else { +@raw("\ntasks.named(\"dockerfileNative\") {\n") +} +@if(dockerfileNative.getBaseImage() != null) { + baseImage = "@(dockerfileNative.getBaseImage())" +} +@if(dockerfileNative.getJavaVersion() != null) { + jdkVersion = "@dockerfileNative.getJavaVersion()" +} +@if (dockerfileNative.getArgs() != null) { + args( + @for (int i = 0; i < dockerfileNative.getArgs().size(); i++) { + "@(dockerfileNative.getArgs().get(i))"@if (i < (dockerfileNative.getArgs().size() -1)) {,} + } + ) +} +@raw("}\n") diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/build/gradle/templates/genericBuildGradle.rocker.raw b/starter-core/src/main/java/io/micronaut/starter/feature/build/gradle/templates/genericBuildGradle.rocker.raw index 24afddb06d5..63acb6e7109 100644 --- a/starter-core/src/main/java/io/micronaut/starter/feature/build/gradle/templates/genericBuildGradle.rocker.raw +++ b/starter-core/src/main/java/io/micronaut/starter/feature/build/gradle/templates/genericBuildGradle.rocker.raw @@ -27,7 +27,7 @@ dependencies { } @if (mainClassName != null) { application { - mainClass.set("@(project.getPackageName()).@mainClassName") + mainClass = "@(project.getPackageName()).@mainClassName" } } diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/build/gradle/templates/micronautGradle.rocker.raw b/starter-core/src/main/java/io/micronaut/starter/feature/build/gradle/templates/micronautGradle.rocker.raw index 0b4c606d30e..3048340b2c0 100644 --- a/starter-core/src/main/java/io/micronaut/starter/feature/build/gradle/templates/micronautGradle.rocker.raw +++ b/starter-core/src/main/java/io/micronaut/starter/feature/build/gradle/templates/micronautGradle.rocker.raw @@ -37,12 +37,7 @@ micronaut { } @if(lambdaRuntimeMainClass != null) { nativeLambda { -@if (dsl == GradleDsl.KOTLIN) { - lambdaRuntimeClassName.set("@(lambdaRuntimeMainClass)") -} -@if (dsl == GradleDsl.GROOVY) { lambdaRuntimeClassName = "@(lambdaRuntimeMainClass)" -} } } @if(incremental) { @@ -59,64 +54,21 @@ micronaut { } } @if(sharedTestResources) { - @if (dsl == GradleDsl.KOTLIN) { - sharedServer.set(true) - } - @if (dsl == GradleDsl.GROOVY) { sharedServer = true - } } } } @if(aotVersion != null) { -@io.micronaut.starter.feature.build.gradle.templates.aotExtension.template(dsl, aotKeys) +@io.micronaut.starter.feature.build.gradle.templates.aotExtension.template(aotKeys) } } @if(dockerfile != null) { -dockerfile { -@if(dockerfile.getBaseImage() != null) { - baseImage("@(dockerfile.getBaseImage())") -} -@if (dockerfile.getArgs() != null) { - args( - @for (int i = 0; i < dockerfile.getArgs().size(); i++) { - "@(dockerfile.getArgs().get(i))"@if (i < (dockerfile.getArgs().size() -1)) {,} - } - ) -} -} +@dockerfileExtension.template(dsl, dockerfile) } @if(dockerfileNative != null) { -@if(build == BuildTool.GRADLE) { -@raw("\ntasks.named(\"dockerfileNative\") {\n") -} -@if(build == BuildTool.GRADLE_KOTLIN) { -@raw("\ntasks.named(\"dockerfileNative\") {\n") -} - -@if(dockerfileNative.getBaseImage() != null) { -@if(build == BuildTool.GRADLE) { - baseImage = "@(dockerfileNative.getBaseImage())" - jdkVersion = "@javaVersion" -} -@if(build == BuildTool.GRADLE_KOTLIN) { - baseImage.set("@(dockerfileNative.getBaseImage())") - jdkVersion.set("@javaVersion") -} -} - -@if (dockerfileNative.getArgs() != null) { - args( - @for (int i = 0; i < dockerfileNative.getArgs().size(); i++) { - "@(dockerfileNative.getArgs().get(i))"@if (i < (dockerfileNative.getArgs().size() -1)) {,} - } - ) -} - -@raw("}\n") - +@dockerfileNativeExtension.template(dsl, dockerfileNative) } @if(dockerBuilderNativeImages != null) { diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/build/gradle/templates/settingsGradle.rocker.raw b/starter-core/src/main/java/io/micronaut/starter/feature/build/gradle/templates/settingsGradle.rocker.raw index 30c014c319d..b9d51d8a5e7 100644 --- a/starter-core/src/main/java/io/micronaut/starter/feature/build/gradle/templates/settingsGradle.rocker.raw +++ b/starter-core/src/main/java/io/micronaut/starter/feature/build/gradle/templates/settingsGradle.rocker.raw @@ -16,11 +16,7 @@ import @(settingsImport) @if(!gradleBuild.getSettingsPlugins().isEmpty()) { plugins { @for (GradlePlugin gradlePlugin : gradleBuild.getSettingsPlugins()) { -@if (gradleBuild.getDsl() == GradleDsl.KOTLIN) { id("@gradlePlugin.getId()") @(gradlePlugin.getVersion() != null ? "version(\"" + gradlePlugin.getVersion() + "\")" : "") -} else { - id "@gradlePlugin.getId()" @(gradlePlugin.getVersion() != null ? "version \"" + gradlePlugin.getVersion() + "\"" : "") -} } } diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/build/maven/templates/pom.rocker.raw b/starter-core/src/main/java/io/micronaut/starter/feature/build/maven/templates/pom.rocker.raw index 1cf36a2dc09..c207393f55c 100644 --- a/starter-core/src/main/java/io/micronaut/starter/feature/build/maven/templates/pom.rocker.raw +++ b/starter-core/src/main/java/io/micronaut/starter/feature/build/maven/templates/pom.rocker.raw @@ -2,6 +2,7 @@ @import io.micronaut.starter.application.Project @import io.micronaut.starter.build.Property @import io.micronaut.starter.build.dependencies.Dependency +@import io.micronaut.starter.build.dependencies.MavenCoordinate @import io.micronaut.starter.build.maven.MavenBuild @import io.micronaut.starter.build.maven.MavenDependency @import io.micronaut.starter.feature.Features @@ -18,7 +19,6 @@ @import io.micronaut.starter.feature.messaging.SharedTestResourceFeature @import io.micronaut.starter.feature.migration.MigrationFeature @import io.micronaut.starter.feature.testresources.TestResources -@import io.micronaut.starter.options.JdkVersion @import io.micronaut.starter.util.VersionInfo @args ( @@ -113,58 +113,40 @@ String jvmArguments || features.isFeaturePresent(HibernateReactiveFeature.class) || features.isFeaturePresent(R2dbc.class))) ) { - + @if (!mavenBuild.getAotDependencies().isEmpty()) { @io.micronaut.starter.feature.build.maven.templates.aotDependencies.template(mavenBuild.getAotDependencies()) } @if (features.isFeaturePresent(SharedTestResourceFeature.class)) { - true -} -@if (features.isFeaturePresent(TestResources.class) && - features.isFeaturePresent(DatabaseDriverFeature.class) && - (!features.isFeaturePresent(Data.class) || features.isFeaturePresent(HibernateReactiveFeature.class) || features.isFeaturePresent(R2dbc.class)) -){ -@with? (String resourceName = features - .getFeature(DatabaseDriverFeature.class) - .flatMap(DatabaseDriverFeature::getDbType) - .map(dbType -> features.isFeaturePresent(R2dbc.class) ? dbType.getR2dbcTestResourcesModuleName() : features.isFeaturePresent(HibernateReactiveFeature.class) ? dbType.getHibernateReactiveTestResourcesModuleName() : dbType.getJdbcTestResourcesModuleName()) - .orElse(null)) { - - - io.micronaut.testresources - micronaut-test-resources-@resourceName - -@if ((features.isFeaturePresent(HibernateReactiveFeature.class) || features.isFeaturePresent(R2dbc.class)) - && features.isFeaturePresent(DatabaseDriverFeature.class) - && !features.isFeaturePresent(MigrationFeature.class) -) { -@with? (Dependency driver = features.getFeature(DatabaseDriverFeature.class) - .flatMap(DatabaseDriverFeatureDependencies::getJavaClientDependency) - .map(Dependency.Builder::build) - .orElse(null)) { -@dependency.template(driver.getGroupId(), driver.getArtifactId(), null, null, false, null) + true } +@if (features.isFeaturePresent(TestResources.class) && !mavenBuild.getTestResourcesDependencies().isEmpty()) { + +@for (MavenCoordinate testResourcesDependency : mavenBuild.getTestResourcesDependencies()) { + + @(testResourcesDependency.groupId()) + @(testResourcesDependency.artifactId()) + } - -} + } @if (jvmArguments != null) { - @(jvmArguments) + @(jvmArguments) } @if (applicationType == ApplicationType.FUNCTION && features.contains("oracle-function")){ - - -H:+StaticExecutableWithDynamicLibC - -Dfn.handler=${function.entrypoint} - --initialize-at-build-time=@project.getPackageName() - - - ${function.entrypoint} - + + -H:+StaticExecutableWithDynamicLibC + -Dfn.handler=${function.entrypoint} + --initialize-at-build-time=@project.getPackageName() + + + ${function.entrypoint} + } @if (features.contains("micronaut-aot")) { - aot-${packaging}.properties + aot-${packaging}.properties } - + } } diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/build/maven/templates/pomGeneric.rocker.raw b/starter-core/src/main/java/io/micronaut/starter/feature/build/maven/templates/pomGeneric.rocker.raw index 7d6fe2ef429..e9ab832c9f7 100644 --- a/starter-core/src/main/java/io/micronaut/starter/feature/build/maven/templates/pomGeneric.rocker.raw +++ b/starter-core/src/main/java/io/micronaut/starter/feature/build/maven/templates/pomGeneric.rocker.raw @@ -6,7 +6,6 @@ @import io.micronaut.starter.build.maven.MavenDependency @import io.micronaut.starter.feature.Features @import io.micronaut.starter.feature.build.maven.templates.dependency -@import io.micronaut.starter.options.JdkVersion @import io.micronaut.starter.util.VersionInfo @args ( diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/ChatBotType.java b/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/ChatBotType.java index 695fa1911f5..2492fa757b5 100644 --- a/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/ChatBotType.java +++ b/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/ChatBotType.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2023 original authors + * Copyright 2017-2024 original authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,6 +18,7 @@ import io.micronaut.core.util.StringUtils; public enum ChatBotType { + BASECAMP, TELEGRAM; @Override diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/ChatBots.java b/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/ChatBots.java index cde677fef3a..cbc367ffced 100644 --- a/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/ChatBots.java +++ b/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/ChatBots.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2023 original authors + * Copyright 2017-2024 original authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,7 +18,6 @@ import io.micronaut.core.annotation.NonNull; import io.micronaut.starter.application.generator.GeneratorContext; import io.micronaut.starter.feature.FeatureContext; -import io.micronaut.starter.feature.chatbots.template.about; import io.micronaut.starter.feature.validator.MicronautValidationFeature; import io.micronaut.starter.feature.validator.ValidationFeature; import io.micronaut.starter.options.BuildTool; @@ -40,12 +39,7 @@ protected ChatBots(MicronautValidationFeature validationFeature) { this.validationFeature = validationFeature; } - protected void renderTemplates(@NonNull GeneratorContext generatorContext) { - generatorContext.addTemplate( - "about-markdown", - new RockerTemplate("src/main/resources/botcommands/about.md", about.template(getChatBotType())) - ); - } + protected abstract void renderTemplates(@NonNull GeneratorContext generatorContext); @Override public void apply(GeneratorContext generatorContext) { @@ -72,7 +66,7 @@ public String getMicronautDocumentation() { protected abstract ChatBotType getChatBotType(); @NonNull - protected abstract String rootReadMeTemplate(@NonNull GeneratorContext generatorContext); + protected abstract RockerTemplate rootReadMeTemplate(@NonNull GeneratorContext generatorContext); @NonNull protected abstract String getBuildCommand(@NonNull BuildTool buildTool); diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/ChatBotsFeature.java b/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/ChatBotsFeature.java index f600bdd77f8..047f9dbfc14 100644 --- a/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/ChatBotsFeature.java +++ b/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/ChatBotsFeature.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2023 original authors + * Copyright 2017-2024 original authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/basecamp/BasecampAwsChatBot.java b/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/basecamp/BasecampAwsChatBot.java new file mode 100644 index 00000000000..081973a719d --- /dev/null +++ b/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/basecamp/BasecampAwsChatBot.java @@ -0,0 +1,117 @@ +/* + * Copyright 2017-2024 original authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.micronaut.starter.feature.chatbots.basecamp; + +import io.micronaut.core.annotation.NonNull; +import io.micronaut.starter.application.ApplicationType; +import io.micronaut.starter.application.Project; +import io.micronaut.starter.application.generator.GeneratorContext; +import io.micronaut.starter.build.dependencies.Dependency; +import io.micronaut.starter.build.dependencies.MicronautDependencyUtils; +import io.micronaut.starter.feature.FeatureContext; +import io.micronaut.starter.feature.aws.AwsFeature; +import io.micronaut.starter.feature.aws.AwsMicronautRuntimeFeature; +import io.micronaut.starter.feature.aws.Cdk; +import io.micronaut.starter.feature.chatbots.basecamp.template.awsCdkReadme; +import io.micronaut.starter.feature.chatbots.basecamp.template.awsReadme; +import io.micronaut.starter.feature.function.HandlerClassFeature; +import io.micronaut.starter.feature.function.awslambda.AwsLambda; +import io.micronaut.starter.feature.validator.MicronautValidationFeature; +import io.micronaut.starter.options.BuildTool; +import io.micronaut.starter.template.RockerTemplate; +import jakarta.inject.Singleton; + +/** + * Adds support for Telegram chatbots as Lambdas. + * + * @author Tim Yates + * @since 4.3.0 + */ +@Singleton +public class BasecampAwsChatBot extends ChatBotsBasecamp implements AwsFeature, AwsMicronautRuntimeFeature, HandlerClassFeature { + + public static final String NAME = "chatbots-basecamp-lambda"; + + public static final Dependency CHATBOTS_BASECAMP_LAMBDA = MicronautDependencyUtils + .chatBotsDependency() + .artifactId("micronaut-chatbots-basecamp-lambda") + .compile() + .build(); + + public static final String HANDLER_CLASS = "io.micronaut.chatbots.basecamp.lambda.Handler"; + private final AwsLambda awsLambda; + + public BasecampAwsChatBot(MicronautValidationFeature validationFeature, AwsLambda awsLambda) { + super(validationFeature); + this.awsLambda = awsLambda; + } + + @Override + public boolean supports(ApplicationType applicationType) { + return applicationType == ApplicationType.FUNCTION; + } + + @NonNull + @Override + public String getName() { + return NAME; + } + + @Override + public String getTitle() { + return "Basecamp ChatBot as AWS Lambda function"; + } + + @Override + public String getDescription() { + return "Generates an application that can be deployed as an AWS Lambda function that implements a Basecamp ChatBot"; + } + + @Override + public void processSelectedFeatures(FeatureContext featureContext) { + super.processSelectedFeatures(featureContext); + featureContext.addFeatureIfNotPresent(AwsLambda.class, awsLambda); + } + + @Override + public void apply(GeneratorContext generatorContext) { + super.apply(generatorContext); + addMicronautRuntimeBuildProperty(generatorContext); + } + + @Override + protected void addDependencies(GeneratorContext generatorContext) { + generatorContext.addDependency(CHATBOTS_BASECAMP_LAMBDA); + } + + @Override + public RockerTemplate rootReadMeTemplate(GeneratorContext generatorContext) { + return new RockerTemplate(generatorContext.isFeaturePresent(Cdk.class) + ? awsCdkReadme.template(generatorContext.getProject(), generatorContext.getFeatures(), getBuildCommand(generatorContext.getBuildTool())) + : awsReadme.template(generatorContext.getProject(), generatorContext.getFeatures(), getBuildCommand(generatorContext.getBuildTool())) + ); + } + + @Override + protected String getBuildCommand(BuildTool buildTool) { + return ""; + } + + @Override + public String handlerClass(ApplicationType applicationType, Project project) { + return HANDLER_CLASS; + } +} diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/basecamp/BasecampAzureChatBot.java b/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/basecamp/BasecampAzureChatBot.java new file mode 100644 index 00000000000..aab5286e78f --- /dev/null +++ b/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/basecamp/BasecampAzureChatBot.java @@ -0,0 +1,105 @@ +/* + * Copyright 2017-2024 original authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.micronaut.starter.feature.chatbots.basecamp; + +import io.micronaut.core.annotation.NonNull; +import io.micronaut.starter.application.ApplicationType; +import io.micronaut.starter.application.generator.GeneratorContext; +import io.micronaut.starter.build.dependencies.Dependency; +import io.micronaut.starter.build.dependencies.MicronautDependencyUtils; +import io.micronaut.starter.feature.FeatureContext; +import io.micronaut.starter.feature.chatbots.basecamp.template.azureReadme; +import io.micronaut.starter.feature.function.azure.AzureBuildCommandUtils; +import io.micronaut.starter.feature.function.azure.AzureCloudFeature; +import io.micronaut.starter.feature.function.azure.AzureMicronautRuntimeFeature; +import io.micronaut.starter.feature.function.azure.AzureRawFunction; +import io.micronaut.starter.feature.validator.MicronautValidationFeature; +import io.micronaut.starter.options.BuildTool; +import io.micronaut.starter.template.RockerTemplate; +import jakarta.inject.Singleton; + +/** + * Adds support for Telegram chatbots as Azure Functions. + * + * @author Tim Yates + * @since 4.3.0 + */ +@Singleton +public class BasecampAzureChatBot extends ChatBotsBasecamp implements AzureCloudFeature, AzureMicronautRuntimeFeature { + + public static final String NAME = "chatbots-basecamp-azure-function"; + + public static final Dependency CHATBOTS_BASECAMP_AZURE_FUNCTION = MicronautDependencyUtils + .chatBotsDependency() + .artifactId("micronaut-chatbots-basecamp-azure-function") + .compile() + .build(); + + private final AzureRawFunction azureRawFunction; + + public BasecampAzureChatBot(MicronautValidationFeature validationFeature, AzureRawFunction azureRawFunction) { + super(validationFeature); + this.azureRawFunction = azureRawFunction; + } + + @Override + public boolean supports(ApplicationType applicationType) { + return applicationType == ApplicationType.FUNCTION; + } + + @NonNull + @Override + public String getName() { + return NAME; + } + + @Override + public String getTitle() { + return "Basecamp ChatBot as an Azure Function"; + } + + @Override + public String getDescription() { + return "Generates an application that can be deployed as an Azure Function that implements a Basecamp ChatBot"; + } + + @Override + public void processSelectedFeatures(FeatureContext featureContext) { + super.processSelectedFeatures(featureContext); + featureContext.addFeatureIfNotPresent(AzureRawFunction.class, azureRawFunction); + } + + @Override + public void apply(GeneratorContext generatorContext) { + super.apply(generatorContext); + addMicronautRuntimeBuildProperty(generatorContext); + } + + @Override + protected String getBuildCommand(BuildTool buildTool) { + return AzureBuildCommandUtils.getBuildCommand(buildTool); + } + + @Override + protected void addDependencies(GeneratorContext generatorContext) { + generatorContext.addDependency(CHATBOTS_BASECAMP_AZURE_FUNCTION); + } + + @Override + public RockerTemplate rootReadMeTemplate(GeneratorContext generatorContext) { + return new RockerTemplate(azureReadme.template(generatorContext.getProject(), generatorContext.getFeatures(), getBuildCommand(generatorContext.getBuildTool()))); + } +} diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/basecamp/BasecampGcpChatBot.java b/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/basecamp/BasecampGcpChatBot.java new file mode 100644 index 00000000000..7f0affd5ac4 --- /dev/null +++ b/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/basecamp/BasecampGcpChatBot.java @@ -0,0 +1,104 @@ +/* + * Copyright 2017-2024 original authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.micronaut.starter.feature.chatbots.basecamp; + +import io.micronaut.core.annotation.NonNull; +import io.micronaut.starter.application.ApplicationType; +import io.micronaut.starter.application.generator.GeneratorContext; +import io.micronaut.starter.build.dependencies.Dependency; +import io.micronaut.starter.build.dependencies.MicronautDependencyUtils; +import io.micronaut.starter.feature.FeatureContext; +import io.micronaut.starter.feature.chatbots.basecamp.template.gcpReadme; +import io.micronaut.starter.feature.function.gcp.GcpCloudFeature; +import io.micronaut.starter.feature.function.gcp.GcpCloudFunctionBuildCommandUtils; +import io.micronaut.starter.feature.function.gcp.GcpMicronautRuntimeFeature; +import io.micronaut.starter.feature.function.gcp.GoogleCloudRawFunction; +import io.micronaut.starter.feature.validator.MicronautValidationFeature; +import io.micronaut.starter.options.BuildTool; +import io.micronaut.starter.template.RockerTemplate; +import jakarta.inject.Singleton; + +/** + * Adds support for Telegram chatbots as Google Cloud Functions. + * + * @author Tim Yates + * @since 4.3.0 + */ +@Singleton +public class BasecampGcpChatBot extends ChatBotsBasecamp implements GcpCloudFeature, GcpMicronautRuntimeFeature { + + public static final String NAME = "chatbots-basecamp-gcp-function"; + + public static final Dependency CHATBOTS_BASECAMP_GCP_FUNCTION = MicronautDependencyUtils + .chatBotsDependency() + .artifactId("micronaut-chatbots-basecamp-gcp-function") + .compile() + .build(); + private final GoogleCloudRawFunction rawFunction; + + public BasecampGcpChatBot(MicronautValidationFeature validationFeature, GoogleCloudRawFunction rawFunction) { + super(validationFeature); + this.rawFunction = rawFunction; + } + + @Override + public boolean supports(ApplicationType applicationType) { + return applicationType == ApplicationType.FUNCTION; + } + + @NonNull + @Override + public String getName() { + return NAME; + } + + @Override + public String getTitle() { + return "Basecamp ChatBot as a Google Cloud Function"; + } + + @Override + public String getDescription() { + return "Generates an application that can be deployed as a Google Cloud Function that implements a Basecamp ChatBot"; + } + + @Override + public void processSelectedFeatures(FeatureContext featureContext) { + super.processSelectedFeatures(featureContext); + featureContext.addFeatureIfNotPresent(GoogleCloudRawFunction.class, rawFunction); + } + + @Override + public void apply(GeneratorContext generatorContext) { + super.apply(generatorContext); + addMicronautRuntimeBuildProperty(generatorContext); + } + + @Override + protected String getBuildCommand(BuildTool buildTool) { + return GcpCloudFunctionBuildCommandUtils.getBuildCommand(buildTool); + } + + @Override + protected void addDependencies(GeneratorContext generatorContext) { + generatorContext.addDependency(CHATBOTS_BASECAMP_GCP_FUNCTION); + } + + @Override + public RockerTemplate rootReadMeTemplate(GeneratorContext generatorContext) { + return new RockerTemplate(gcpReadme.template(generatorContext.getProject(), generatorContext.getFeatures(), getBuildCommand(generatorContext.getBuildTool()))); + } +} diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/basecamp/BasecampHttpChatBot.java b/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/basecamp/BasecampHttpChatBot.java new file mode 100644 index 00000000000..e69241c9280 --- /dev/null +++ b/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/basecamp/BasecampHttpChatBot.java @@ -0,0 +1,109 @@ +/* + * Copyright 2017-2024 original authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.micronaut.starter.feature.chatbots.basecamp; + +import io.micronaut.core.annotation.NonNull; +import io.micronaut.starter.application.ApplicationType; +import io.micronaut.starter.application.generator.GeneratorContext; +import io.micronaut.starter.build.dependencies.Dependency; +import io.micronaut.starter.build.dependencies.MicronautDependencyUtils; +import io.micronaut.starter.feature.chatbots.basecamp.template.controllerGroovyJunit; +import io.micronaut.starter.feature.chatbots.basecamp.template.controllerGroovySpock; +import io.micronaut.starter.feature.chatbots.basecamp.template.controllerJavaJunit; +import io.micronaut.starter.feature.chatbots.basecamp.template.controllerKotlinJunit; +import io.micronaut.starter.feature.chatbots.basecamp.template.controllerReadme; +import io.micronaut.starter.feature.validator.MicronautValidationFeature; +import io.micronaut.starter.options.BuildTool; +import io.micronaut.starter.options.TestFramework; +import io.micronaut.starter.template.RockerTemplate; +import jakarta.inject.Singleton; + +/** + * Adds support for Telegram chatbots as Google Cloud Functions. + * + * @author Tim Yates + * @since 4.3.0 + */ +@Singleton +public class BasecampHttpChatBot extends ChatBotsBasecamp { + + public static final String NAME = "chatbots-basecamp-http"; + + public static final Dependency CHATBOTS_BASECAMP_HTTP = MicronautDependencyUtils + .chatBotsDependency() + .artifactId("micronaut-chatbots-basecamp-http") + .compile() + .build(); + + public BasecampHttpChatBot(MicronautValidationFeature validationFeature) { + super(validationFeature); + } + + @Override + public boolean supports(ApplicationType applicationType) { + return applicationType == ApplicationType.DEFAULT; + } + + @Override + protected void renderTemplates(GeneratorContext generatorContext) { + super.renderTemplates(generatorContext); + if (generatorContext.getTestFramework() == TestFramework.JUNIT) { + generatorContext.addTemplate( + "http-client-command-handler-junit-test", + generatorContext.getTestSourcePath("/{packagePath}/BasecampController"), + controllerJavaJunit.template(generatorContext.getProject()), + controllerKotlinJunit.template(generatorContext.getProject()), + controllerGroovyJunit.template(generatorContext.getProject()) + ); + } else if (generatorContext.getTestFramework() == TestFramework.SPOCK) { + generatorContext.addTemplate( + "http-client-command-handler-spock-test", + new RockerTemplate(generatorContext.getTestSourcePath("/{packagePath}/BasecampController"), controllerGroovySpock.template(generatorContext.getProject())) + ); + } + } + + @NonNull + @Override + public String getName() { + return NAME; + } + + @Override + public String getTitle() { + return "Basecamp ChatBot as a controller"; + } + + @Override + public String getDescription() { + return "Generates an application that implements a Basecamp chatbot controller"; + } + + @Override + protected void addDependencies(GeneratorContext generatorContext) { + generatorContext.addDependency(CHATBOTS_BASECAMP_HTTP); + } + + @Override + public RockerTemplate rootReadMeTemplate(GeneratorContext generatorContext) { + return new RockerTemplate(controllerReadme.template(generatorContext.getProject(), generatorContext.getFeatures(), getBuildCommand(generatorContext.getBuildTool()))); + } + + @Override + protected String getBuildCommand(BuildTool buildTool) { + return ""; + } +} diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/basecamp/ChatBotsBasecamp.java b/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/basecamp/ChatBotsBasecamp.java new file mode 100644 index 00000000000..6232a27d29f --- /dev/null +++ b/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/basecamp/ChatBotsBasecamp.java @@ -0,0 +1,116 @@ +/* + * Copyright 2017-2024 original authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.micronaut.starter.feature.chatbots.basecamp; + +import io.micronaut.starter.application.generator.GeneratorContext; +import io.micronaut.starter.feature.chatbots.ChatBotType; +import io.micronaut.starter.feature.chatbots.ChatBots; +import io.micronaut.starter.feature.chatbots.basecamp.template.aboutCommandHandlerGroovy; +import io.micronaut.starter.feature.chatbots.basecamp.template.aboutCommandHandlerGroovyJunit; +import io.micronaut.starter.feature.chatbots.basecamp.template.aboutCommandHandlerGroovySpock; +import io.micronaut.starter.feature.chatbots.basecamp.template.aboutCommandHandlerJava; +import io.micronaut.starter.feature.chatbots.basecamp.template.aboutCommandHandlerJavaJunit; +import io.micronaut.starter.feature.chatbots.basecamp.template.aboutCommandHandlerKotlin; +import io.micronaut.starter.feature.chatbots.basecamp.template.aboutCommandHandlerKotlinJunit; +import io.micronaut.starter.feature.chatbots.basecamp.template.finalCommandHandlerGroovy; +import io.micronaut.starter.feature.chatbots.basecamp.template.finalCommandHandlerJava; +import io.micronaut.starter.feature.chatbots.basecamp.template.finalCommandHandlerKotlin; +import io.micronaut.starter.feature.chatbots.basecamp.template.mockAboutCommandJson; +import io.micronaut.starter.feature.chatbots.basecamp.template.basecampReadme; +import io.micronaut.starter.feature.chatbots.basecamp.template.about; +import io.micronaut.starter.feature.validator.MicronautValidationFeature; +import io.micronaut.starter.options.TestFramework; +import io.micronaut.starter.template.RockerTemplate; +import io.micronaut.starter.template.RockerWritable; + +/** + * Base class for Telegram chatbot features. + * + * @since 4.3.0 + * @author Tim Yates + */ +abstract class ChatBotsBasecamp extends ChatBots { + + protected ChatBotsBasecamp(MicronautValidationFeature validationFeature) { + super(validationFeature); + } + + @Override + protected void addConfigurations(GeneratorContext generatorContext) { + generatorContext.getConfiguration().put( + "micronaut.chatbots.folder", + "botcommands" + ); + } + + @Override + protected void renderTemplates(GeneratorContext generatorContext) { + generatorContext.addTemplate( + "about-html", + new RockerTemplate("src/main/resources/botcommands/about.html", about.template()) + ); + generatorContext.addTemplate( + "basecamp-about-command-handler", + generatorContext.getSourcePath("/{packagePath}/BasecampAboutCommandHandler"), + aboutCommandHandlerJava.template(generatorContext.getProject()), + aboutCommandHandlerKotlin.template(generatorContext.getProject()), + aboutCommandHandlerGroovy.template(generatorContext.getProject()) + ); + if (!generatorContext.getTestFramework().isKotlinTestFramework()) { + generatorContext.addTemplate( + "mock-basecamp-about-command-json", + new RockerTemplate( + "src/test/resources/mockBasecampAboutCommand.json", + mockAboutCommandJson.template() + ) + ); + } + if (generatorContext.getTestFramework() == TestFramework.JUNIT) { + generatorContext.addTemplate( + "about-command-handler-junit-test", + generatorContext.getTestSourcePath("/{packagePath}/BasecampAboutCommandHandler"), + aboutCommandHandlerJavaJunit.template(generatorContext.getProject()), + aboutCommandHandlerKotlinJunit.template(generatorContext.getProject()), + aboutCommandHandlerGroovyJunit.template(generatorContext.getProject()) + ); + } else if (generatorContext.getTestFramework() == TestFramework.SPOCK) { + generatorContext.addTemplate( + "about-command-handler-spock-groovy-test", + new RockerTemplate(generatorContext.getTestSourcePath("/{packagePath}/BasecampAboutCommandHandler"), aboutCommandHandlerGroovySpock.template(generatorContext.getProject())) + ); + } + + generatorContext.addHelpTemplate(new RockerWritable(basecampReadme.template(rootReadMeTemplate(generatorContext)))); + + generatorContext.addTemplate( + "final-command-handler", + generatorContext.getSourcePath("/{packagePath}/BasecampFinalCommandHandler"), + finalCommandHandlerJava.template(generatorContext.getProject()), + finalCommandHandlerKotlin.template(generatorContext.getProject()), + finalCommandHandlerGroovy.template(generatorContext.getProject()) + ); + } + + @Override + public String getThirdPartyDocumentation() { + return "https://github.com/basecamp/bc3-api/blob/master/sections/chatbots.md"; + } + + @Override + public ChatBotType getChatBotType() { + return ChatBotType.BASECAMP; + } +} diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/basecamp/template/about.rocker.raw b/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/basecamp/template/about.rocker.raw new file mode 100644 index 00000000000..77685a48027 --- /dev/null +++ b/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/basecamp/template/about.rocker.raw @@ -0,0 +1 @@ +Basecamp Bot developed with ๐Ÿ’™ and Micronaut. \ No newline at end of file diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/basecamp/template/aboutCommandHandlerGroovy.rocker.raw b/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/basecamp/template/aboutCommandHandlerGroovy.rocker.raw new file mode 100644 index 00000000000..0899df30012 --- /dev/null +++ b/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/basecamp/template/aboutCommandHandlerGroovy.rocker.raw @@ -0,0 +1,38 @@ +@import io.micronaut.starter.application.Project +@args (Project project) +@if (project.getPackageName() != null) { +package @project.getPackageName() +} + +import io.micronaut.chatbots.basecamp.api.Query +import io.micronaut.chatbots.basecamp.core.BasecampBotConfiguration +import io.micronaut.chatbots.basecamp.core.BasecampHandler +import io.micronaut.chatbots.core.CommandResponse +import io.micronaut.chatbots.core.TextResourceLoader +import io.micronaut.core.annotation.NonNull +import io.micronaut.core.annotation.Nullable +import jakarta.inject.Singleton +import jakarta.validation.constraints.NotNull + +import java.util.Optional + +@@Singleton +class BasecampAboutCommandHandler implements BasecampHandler { + + public static final String ABOUT = "about" + private final TextResourceLoader textResourceLoader + + BasecampAboutCommandHandler(TextResourceLoader textResourceLoader) { + this.textResourceLoader = textResourceLoader + } + + @@Override + public boolean canHandle(@@Nullable BasecampBotConfiguration bot, @@NonNull @@NotNull Query input) { + return input.command.equalsIgnoreCase("/" + ABOUT) + } + + @@Override + public @@NonNull Optional handle(@@Nullable BasecampBotConfiguration bot, @@NonNull @@NotNull Query input) { + return textResourceLoader.composeCommandResponse(ABOUT).map { it.text } + } +} \ No newline at end of file diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/basecamp/template/aboutCommandHandlerGroovyJunit.rocker.raw b/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/basecamp/template/aboutCommandHandlerGroovyJunit.rocker.raw new file mode 100644 index 00000000000..713fb74d073 --- /dev/null +++ b/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/basecamp/template/aboutCommandHandlerGroovyJunit.rocker.raw @@ -0,0 +1,48 @@ +@import io.micronaut.starter.application.Project +@args (Project project) +@if (project.getPackageName() != null) { +package @project.getPackageName() + +} + +import io.micronaut.chatbots.basecamp.api.Query +import io.micronaut.chatbots.basecamp.core.BasecampBotConfiguration +import io.micronaut.chatbots.core.Dispatcher +import io.micronaut.context.BeanContext +import io.micronaut.json.JsonMapper +import io.micronaut.test.extensions.junit5.annotation.MicronautTest +import jakarta.inject.Inject +import org.junit.jupiter.api.Test +import java.io.IOException + +import static org.junit.jupiter.api.Assertions.assertEquals +import static org.junit.jupiter.api.Assertions.assertTrue + +@@MicronautTest(startApplication = false) +class BasecampAboutCommandHandlerTest { + + @@Inject + BeanContext ctx + + @@Inject + Dispatcher dispatcher + + @@Inject + JsonMapper jsonMapper + + @@Test + void beanOfTypeHelloWorldHandlerExists() { + assertTrue(ctx.containsBean(BasecampAboutCommandHandler)) + } + + @@Test + void aboutCommandHandlerExists() throws Exception { + String send = dispatcher.dispatch(null, jsonMapper.readValue(getAboutCommandJson(), Query)).get() + + assertEquals('Basecamp Bot developed with ๐Ÿ’™ and Micronaut.', send.trim()) + } + + private String getAboutCommandJson() { + BasecampAboutCommandHandlerTest.getResourceAsStream("/mockBasecampAboutCommand.json").text + } +} \ No newline at end of file diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/basecamp/template/aboutCommandHandlerGroovySpock.rocker.raw b/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/basecamp/template/aboutCommandHandlerGroovySpock.rocker.raw new file mode 100644 index 00000000000..895eb918002 --- /dev/null +++ b/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/basecamp/template/aboutCommandHandlerGroovySpock.rocker.raw @@ -0,0 +1,45 @@ +@import io.micronaut.starter.application.Project +@args (Project project) +@if (project.getPackageName() != null) { +package @project.getPackageName() + +} + +import io.micronaut.chatbots.basecamp.api.Query +import io.micronaut.chatbots.basecamp.core.BasecampBotConfiguration +import io.micronaut.chatbots.core.Dispatcher +import io.micronaut.context.BeanContext +import io.micronaut.json.JsonMapper +import io.micronaut.test.extensions.spock.annotation.MicronautTest +import jakarta.inject.Inject +import spock.lang.Specification + +@@MicronautTest(startApplication = false) +class BasecampAboutCommandHandlerSpec extends Specification { + + @@Inject + BeanContext ctx + + @@Inject + Dispatcher dispatcher + + @@Inject + JsonMapper jsonMapper + + void "about command handler is in the context"() { + expect: + ctx.containsBean(BasecampAboutCommandHandler) + } + + void "the about command handler works as expected"() { + when: + String send = dispatcher.dispatch(null, jsonMapper.readValue(aboutCommandJson, Query)).get() + + then: + send.trim() == 'Basecamp Bot developed with ๐Ÿ’™ and Micronaut.' + } + + private String getAboutCommandJson() { + BasecampAboutCommandHandlerSpec.getResourceAsStream("/mockBasecampAboutCommand.json").text + } +} \ No newline at end of file diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/basecamp/template/aboutCommandHandlerJava.rocker.raw b/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/basecamp/template/aboutCommandHandlerJava.rocker.raw new file mode 100644 index 00000000000..8b6a0607deb --- /dev/null +++ b/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/basecamp/template/aboutCommandHandlerJava.rocker.raw @@ -0,0 +1,39 @@ +@import io.micronaut.starter.application.Project +@args (Project project) +@if (project.getPackageName() != null) { +package @project.getPackageName(); + +} + +import io.micronaut.chatbots.basecamp.api.Query; +import io.micronaut.chatbots.basecamp.core.BasecampBotConfiguration; +import io.micronaut.chatbots.basecamp.core.BasecampHandler; +import io.micronaut.chatbots.core.CommandResponse; +import io.micronaut.chatbots.core.TextResourceLoader; +import io.micronaut.core.annotation.NonNull; +import io.micronaut.core.annotation.Nullable; +import jakarta.inject.Singleton; +import jakarta.validation.constraints.NotNull; + +import java.util.Optional; + +@@Singleton +class BasecampAboutCommandHandler implements BasecampHandler { + + public static final String ABOUT = "about"; + private final TextResourceLoader textResourceLoader; + + BasecampAboutCommandHandler(TextResourceLoader textResourceLoader) { + this.textResourceLoader = textResourceLoader; + } + + @@Override + public boolean canHandle(@@Nullable BasecampBotConfiguration bot, @@NonNull @@NotNull Query input) { + return input.getCommand().equalsIgnoreCase("/" + ABOUT); + } + + @@Override + public @@NonNull Optional handle(@@Nullable BasecampBotConfiguration bot, @@NonNull @@NotNull Query input) { + return textResourceLoader.composeCommandResponse(ABOUT).map(CommandResponse::text); + } +} \ No newline at end of file diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/basecamp/template/aboutCommandHandlerJavaJunit.rocker.raw b/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/basecamp/template/aboutCommandHandlerJavaJunit.rocker.raw new file mode 100644 index 00000000000..0a75d01a10e --- /dev/null +++ b/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/basecamp/template/aboutCommandHandlerJavaJunit.rocker.raw @@ -0,0 +1,52 @@ +@import io.micronaut.starter.application.Project +@args (Project project) +@if (project.getPackageName() != null) { +package @project.getPackageName(); + +} + +import io.micronaut.chatbots.basecamp.api.Query; +import io.micronaut.chatbots.basecamp.core.BasecampBotConfiguration; +import io.micronaut.chatbots.core.Dispatcher; +import io.micronaut.context.BeanContext; +import io.micronaut.json.JsonMapper; +import io.micronaut.test.extensions.junit5.annotation.MicronautTest; +import jakarta.inject.Inject; +import org.junit.jupiter.api.Test; +import java.io.IOException; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +@@MicronautTest(startApplication = false) +class BasecampAboutCommandHandlerTest { + + @@Inject + BeanContext ctx; + + @@Inject + Dispatcher dispatcher; + + @@Inject + JsonMapper jsonMapper; + + @@Test + void beanOfTypeHelloWorldHandlerExists() { + assertTrue(ctx.containsBean(BasecampAboutCommandHandler.class)); + } + + @@Test + void aboutCommandHandlerExists() throws Exception { + String send = dispatcher.dispatch(null, jsonMapper.readValue(getAboutCommandJson(), Query.class)).get(); + + assertEquals( + """ + Basecamp Bot developed with ๐Ÿ’™ and Micronaut.""", + send.trim() + ); + } + + private String getAboutCommandJson() throws IOException { + return new String(BasecampAboutCommandHandlerTest.class.getResourceAsStream("/mockBasecampAboutCommand.json").readAllBytes()); + } +} \ No newline at end of file diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/basecamp/template/aboutCommandHandlerKotlin.rocker.raw b/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/basecamp/template/aboutCommandHandlerKotlin.rocker.raw new file mode 100644 index 00000000000..f4f06b6c588 --- /dev/null +++ b/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/basecamp/template/aboutCommandHandlerKotlin.rocker.raw @@ -0,0 +1,31 @@ +@import io.micronaut.starter.application.Project +@args (Project project) +@if (project.getPackageName() != null) { +package @project.getPackageName() + +} + +import io.micronaut.chatbots.basecamp.api.Query +import io.micronaut.chatbots.basecamp.core.BasecampBotConfiguration +import io.micronaut.chatbots.basecamp.core.BasecampHandler +import io.micronaut.chatbots.core.CommandResponse +import io.micronaut.chatbots.core.TextResourceLoader +import io.micronaut.core.annotation.NonNull +import io.micronaut.core.annotation.Nullable +import jakarta.inject.Singleton +import jakarta.validation.constraints.NotNull + +import java.util.Optional + +@@Singleton +open class BasecampAboutCommandHandler(private val textResourceLoader: TextResourceLoader): BasecampHandler { + + override fun canHandle(bot: BasecampBotConfiguration?, input: Query) = input.command.equals("/$ABOUT", true) + + override fun handle(bot: BasecampBotConfiguration?, input: Query): Optional = + textResourceLoader.composeCommandResponse(ABOUT).map { r -> r.text } + + companion object { + private const val ABOUT = "about" + } +} \ No newline at end of file diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/basecamp/template/aboutCommandHandlerKotlinJunit.rocker.raw b/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/basecamp/template/aboutCommandHandlerKotlinJunit.rocker.raw new file mode 100644 index 00000000000..b5a7bca026e --- /dev/null +++ b/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/basecamp/template/aboutCommandHandlerKotlinJunit.rocker.raw @@ -0,0 +1,48 @@ +@import io.micronaut.starter.application.Project +@args (Project project) +@if (project.getPackageName() != null) { +package @project.getPackageName() + +} + +import io.micronaut.chatbots.basecamp.api.Query; +import io.micronaut.chatbots.basecamp.core.BasecampBotConfiguration; +import io.micronaut.chatbots.core.Dispatcher +import io.micronaut.context.BeanContext +import io.micronaut.json.JsonMapper +import io.micronaut.test.extensions.junit5.annotation.MicronautTest +import jakarta.inject.Inject +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Assertions.assertTrue +import org.junit.jupiter.api.Test + +@@MicronautTest(startApplication = false) +class BasecampAboutCommandHandlerTest { + + @@Inject + lateinit var ctx: BeanContext + + @@Inject + lateinit var dispatcher: Dispatcher + + @@Inject + lateinit var jsonMapper: JsonMapper + + @@Test + fun beanOfTypeHelloWorldHandlerExists() { + assertTrue(ctx.containsBean(BasecampAboutCommandHandler::class.java)) + } + + @@Test + @@Throws(Exception::class) + fun aboutCommandHandlerExists() { + val send = dispatcher.dispatch(null, jsonMapper.readValue(getAboutCommandJson(), Query::class.java)).get() + + assertEquals( + """Basecamp Bot developed with ๐Ÿ’™ and Micronaut.""", + send.trim() + ) + } + + private fun getAboutCommandJson() = BasecampAboutCommandHandlerTest::class.java.getResource("/mockBasecampAboutCommand.json")!!.readText() +} \ No newline at end of file diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/basecamp/template/awsCdkReadme.rocker.raw b/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/basecamp/template/awsCdkReadme.rocker.raw new file mode 100644 index 00000000000..a8228e106cf --- /dev/null +++ b/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/basecamp/template/awsCdkReadme.rocker.raw @@ -0,0 +1,13 @@ +@import io.micronaut.starter.application.Project +@import io.micronaut.starter.feature.Features +@import io.micronaut.starter.feature.chatbots.basecamp.BasecampAwsChatBot + +@args ( +Project project, +Features features, +String buildCommand +) + +## Lambda handler class + +The Cdk project defined in `infra` is already configured to use `@BasecampAwsChatBot.HANDLER_CLASS` as the handler for your Lambda function. diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/basecamp/template/awsReadme.rocker.raw b/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/basecamp/template/awsReadme.rocker.raw new file mode 100644 index 00000000000..c5ef374418b --- /dev/null +++ b/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/basecamp/template/awsReadme.rocker.raw @@ -0,0 +1,13 @@ +@import io.micronaut.starter.application.Project +@import io.micronaut.starter.feature.Features +@import io.micronaut.starter.feature.chatbots.basecamp.BasecampAwsChatBot + +@args ( +Project project, +Features features, +String buildCommand +) + +## Lambda handler class + +When deployed to AWS Lambda, the lambda handler should be defined as `@BasecampAwsChatBot.HANDLER_CLASS`. diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/template/azureReadme.rocker.raw b/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/basecamp/template/azureReadme.rocker.raw similarity index 100% rename from starter-core/src/main/java/io/micronaut/starter/feature/chatbots/template/azureReadme.rocker.raw rename to starter-core/src/main/java/io/micronaut/starter/feature/chatbots/basecamp/template/azureReadme.rocker.raw diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/basecamp/template/basecampReadme.rocker.raw b/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/basecamp/template/basecampReadme.rocker.raw new file mode 100644 index 00000000000..5debf3dc89e --- /dev/null +++ b/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/basecamp/template/basecampReadme.rocker.raw @@ -0,0 +1,24 @@ +@import io.micronaut.starter.template.RockerTemplate + +@args(RockerTemplate platformTemplate) + +# Basecamp ChatBot + +Follow the instructions in the [Micronaut ChatBot Documentation](https://micronaut-projects.github.io/micronaut-chatbots/latest/guide/) to create a Basecamp ChatBot. + +@platformTemplate.renderModel() + +You can then create a Basecamp webhook by running the following command: + +```bash +curl -s -H "Authorization: Bearer ${ACCESS_TOKEN}" -H "Content-Type: application/json" \ + -d '{"service_name":"${BOTNAME}","command_url":"${YOUR_HTTP_TRIGGER_URL}"}' \ + https://3.basecampapi.com/${APP_ID}/buckets/${BUCKET_ID}/chats/${CHAT_ID}/integrations.json +``` + +Where; +- `BOTNAME` is the name of your bot +- `ACCESS_TOKEN` is your Oauth2 Basecamp access token +- `YOUR_HTTP_TRIGGER_URL` is the https address of your URL of your controller or function +- `APP_ID`, `BUCKET_ID` and `CHAT_ID` are the IDs of your Basecamp application, bucket and chat respectively + diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/basecamp/template/controllerGroovyJunit.rocker.raw b/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/basecamp/template/controllerGroovyJunit.rocker.raw new file mode 100644 index 00000000000..e1997d54bab --- /dev/null +++ b/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/basecamp/template/controllerGroovyJunit.rocker.raw @@ -0,0 +1,42 @@ +@import io.micronaut.starter.application.Project +@args (Project project) +@if (project.getPackageName() != null) { +package @project.getPackageName() + +} + +import io.micronaut.context.BeanContext +import io.micronaut.http.HttpHeaders +import io.micronaut.http.HttpRequest +import io.micronaut.http.HttpResponse +import io.micronaut.http.MutableHttpRequest +import io.micronaut.http.client.HttpClient +import io.micronaut.http.client.annotation.Client +import io.micronaut.test.extensions.junit5.annotation.MicronautTest +import jakarta.inject.Inject +import org.junit.jupiter.api.Test +import java.io.IOException + +import static org.junit.jupiter.api.Assertions.assertEquals + +@@MicronautTest +class BasecampControllerTest { + + @@Client("/") + @@Inject + HttpClient client + + @@Inject + BeanContext ctx + + @@Test + void aboutCommandHandlerExists() { + MutableHttpRequest post = HttpRequest.POST("/basecamp", getAboutCommandJson()).header(HttpHeaders.USER_AGENT, "Mock Basecamp request") + HttpResponse messageResponse = client.toBlocking().exchange(post, String) + assertEquals('Basecamp Bot developed with ๐Ÿ’™ and Micronaut.', messageResponse.body().trim()); + } + + private String getAboutCommandJson() { + BasecampControllerTest.getResourceAsStream("/mockBasecampAboutCommand.json").text + } +} \ No newline at end of file diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/basecamp/template/controllerGroovySpock.rocker.raw b/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/basecamp/template/controllerGroovySpock.rocker.raw new file mode 100644 index 00000000000..df6e64d2067 --- /dev/null +++ b/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/basecamp/template/controllerGroovySpock.rocker.raw @@ -0,0 +1,41 @@ +@import io.micronaut.starter.application.Project +@args (Project project) +@if (project.getPackageName() != null) { +package @project.getPackageName() + +} + +import io.micronaut.context.BeanContext +import io.micronaut.http.HttpHeaders +import io.micronaut.http.HttpRequest +import io.micronaut.http.HttpResponse +import io.micronaut.http.MutableHttpRequest +import io.micronaut.http.client.HttpClient +import io.micronaut.http.client.annotation.Client +import io.micronaut.test.extensions.spock.annotation.MicronautTest +import jakarta.inject.Inject +import spock.lang.Specification + +@@MicronautTest +class BasecampControllerSpec extends Specification { + + @@Client("/") + @@Inject + HttpClient client + + @@Inject + BeanContext ctx + + void "controller is enabled and responsive"() { + when: + MutableHttpRequest post = HttpRequest.POST("/basecamp", aboutCommandJson).header(HttpHeaders.USER_AGENT, "Mock Basecamp request") + HttpResponse messageResponse = client.toBlocking().exchange(post, String) + + then: + messageResponse.body().trim() == 'Basecamp Bot developed with ๐Ÿ’™ and Micronaut.' + } + + private String getAboutCommandJson() { + BasecampControllerSpec.getResourceAsStream("/mockBasecampAboutCommand.json").text + } +} \ No newline at end of file diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/basecamp/template/controllerJavaJunit.rocker.raw b/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/basecamp/template/controllerJavaJunit.rocker.raw new file mode 100644 index 00000000000..b86aa0424ba --- /dev/null +++ b/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/basecamp/template/controllerJavaJunit.rocker.raw @@ -0,0 +1,45 @@ +@import io.micronaut.starter.application.Project +@args (Project project) +@if (project.getPackageName() != null) { +package @project.getPackageName(); + +} + +import io.micronaut.context.BeanContext; +import io.micronaut.http.HttpHeaders; +import io.micronaut.http.HttpRequest; +import io.micronaut.http.HttpResponse; +import io.micronaut.http.MutableHttpRequest; +import io.micronaut.http.client.HttpClient; +import io.micronaut.http.client.annotation.Client; +import io.micronaut.test.extensions.junit5.annotation.MicronautTest; +import jakarta.inject.Inject; +import org.junit.jupiter.api.Test; +import java.io.IOException; +import static org.junit.jupiter.api.Assertions.assertEquals; + +@@MicronautTest +class BasecampControllerTest { + + @@Client("/") + @@Inject + HttpClient client; + + @@Inject + BeanContext ctx; + + @@Test + void aboutCommandHandlerExists() throws Exception { + MutableHttpRequest post = HttpRequest.POST("/basecamp", getAboutCommandJson()).header(HttpHeaders.USER_AGENT, "Mock Basecamp request"); + HttpResponse messageResponse = client.toBlocking().exchange(post, String.class); + assertEquals( + """ + Basecamp Bot developed with ๐Ÿ’™ and Micronaut.""", + messageResponse.body().trim() + ); + } + + private String getAboutCommandJson() throws IOException { + return new String(BasecampControllerTest.class.getResourceAsStream("/mockBasecampAboutCommand.json").readAllBytes()); + } +} \ No newline at end of file diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/basecamp/template/controllerKotlinJunit.rocker.raw b/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/basecamp/template/controllerKotlinJunit.rocker.raw new file mode 100644 index 00000000000..cf848cbb8a9 --- /dev/null +++ b/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/basecamp/template/controllerKotlinJunit.rocker.raw @@ -0,0 +1,39 @@ +@import io.micronaut.starter.application.Project +@args (Project project) +@if (project.getPackageName() != null) { +package @project.getPackageName() + +} + +import io.micronaut.context.BeanContext +import io.micronaut.http.HttpHeaders +import io.micronaut.http.HttpRequest +import io.micronaut.http.client.HttpClient +import io.micronaut.http.client.annotation.Client +import io.micronaut.test.extensions.junit5.annotation.MicronautTest +import jakarta.inject.Inject +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.Assertions.assertEquals + +@@MicronautTest +class BasecampControllerTest { + + @@field:Client("/") + @@Inject + lateinit var client: HttpClient + + @@Inject + lateinit var ctx: BeanContext + + @@Test + fun aboutCommandHandlerExists() { + val post = HttpRequest.POST("/basecamp", getAboutCommandJson()).header(HttpHeaders.USER_AGENT, "Mock Basecamp Request") + val messageResponse = client.toBlocking().exchange(post, String::class.java) + assertEquals( + """Basecamp Bot developed with ๐Ÿ’™ and Micronaut.""", + messageResponse.body().trim() + ) + } + + private fun getAboutCommandJson() = BasecampControllerTest::class.java.getResource("/mockBasecampAboutCommand.json")!!.readText() +} \ No newline at end of file diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/basecamp/template/controllerReadme.rocker.raw b/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/basecamp/template/controllerReadme.rocker.raw new file mode 100644 index 00000000000..43475ddda82 --- /dev/null +++ b/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/basecamp/template/controllerReadme.rocker.raw @@ -0,0 +1,13 @@ +@import io.micronaut.starter.application.Project +@import io.micronaut.starter.feature.Features + +@args ( +Project project, +Features features, +String buildCommand +) + +This project has a dependency on `micronaut-chatbots-basecamp-http` which has added a controller to your application with the path `/basecamp`. + +When registering your bot with Basecamp, you will need to provide the HTTPS URL of your application including this path. +If you are running your application locally, you can use a tool like [ngrok](https://ngrok.com/) to expose your application to the internet. diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/basecamp/template/finalCommandHandlerGroovy.rocker.raw b/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/basecamp/template/finalCommandHandlerGroovy.rocker.raw new file mode 100644 index 00000000000..df934808afb --- /dev/null +++ b/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/basecamp/template/finalCommandHandlerGroovy.rocker.raw @@ -0,0 +1,39 @@ +@import io.micronaut.starter.application.Project +@args (Project project) +@if (project.getPackageName() != null) { +package @project.getPackageName() +} + +import io.micronaut.chatbots.basecamp.api.Query +import io.micronaut.chatbots.basecamp.core.BasecampBotConfiguration +import io.micronaut.chatbots.basecamp.core.BasecampHandler +import io.micronaut.core.annotation.NonNull +import io.micronaut.core.annotation.Nullable +import io.micronaut.core.order.Ordered +import jakarta.inject.Singleton +import jakarta.validation.constraints.NotNull + +@@Singleton +class BasecampFinalCommandHandler implements BasecampHandler { + + @@Override + boolean canHandle( + @@Nullable BasecampBotConfiguration bot, + @@NonNull @@NotNull Query query + ) { + true + } + + @@Override + Optional handle( + @@Nullable BasecampBotConfiguration bot, + @@NonNull @@NotNull Query query + ) { + Optional.of("I don't how to handle your query: ${query.command}".toString()) + } + + @@Override + int getOrder() { + Ordered.LOWEST_PRECEDENCE + } +} diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/basecamp/template/finalCommandHandlerJava.rocker.raw b/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/basecamp/template/finalCommandHandlerJava.rocker.raw new file mode 100644 index 00000000000..06f6dc78bd6 --- /dev/null +++ b/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/basecamp/template/finalCommandHandlerJava.rocker.raw @@ -0,0 +1,42 @@ +@import io.micronaut.starter.application.Project +@args (Project project) +@if (project.getPackageName() != null) { +package @project.getPackageName(); + +} + +import io.micronaut.chatbots.basecamp.api.Query; +import io.micronaut.chatbots.basecamp.core.BasecampBotConfiguration; +import io.micronaut.chatbots.basecamp.core.BasecampHandler; +import io.micronaut.core.annotation.NonNull; +import io.micronaut.core.annotation.Nullable; +import io.micronaut.core.order.Ordered; +import jakarta.inject.Singleton; +import jakarta.validation.constraints.NotNull; + +import java.util.Optional; + +@@Singleton +class BasecampFinalCommandHandler implements BasecampHandler { + + @@Override + public boolean canHandle( + @@Nullable BasecampBotConfiguration bot, + @@NonNull @@NotNull Query query + ) { + return true; + } + + @@Override + public Optional handle( + @@Nullable BasecampBotConfiguration bot, + @@NonNull @@NotNull Query query + ) { + return Optional.of("I don't how to handle your query: %s".formatted(query.getCommand())); + } + + @@Override + public int getOrder() { + return Ordered.LOWEST_PRECEDENCE; + } +} diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/basecamp/template/finalCommandHandlerKotlin.rocker.raw b/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/basecamp/template/finalCommandHandlerKotlin.rocker.raw new file mode 100644 index 00000000000..3e33b094224 --- /dev/null +++ b/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/basecamp/template/finalCommandHandlerKotlin.rocker.raw @@ -0,0 +1,24 @@ +@import io.micronaut.starter.application.Project +@args (Project project) +@if (project.getPackageName() != null) { +package @project.getPackageName() + +} + +import io.micronaut.chatbots.basecamp.api.Query +import io.micronaut.chatbots.basecamp.core.BasecampBotConfiguration +import io.micronaut.chatbots.basecamp.core.BasecampHandler +import io.micronaut.core.order.Ordered +import jakarta.inject.Singleton +import java.util.Optional + +@@Singleton +open class BasecampFinalCommandHandler: BasecampHandler { + + override fun canHandle(bot: BasecampBotConfiguration?, query: Query) = true + + override fun handle(bot: BasecampBotConfiguration?, query: Query): Optional = + Optional.of("I don't how to handle your query: ${query.command}") + + override fun getOrder() = Ordered.LOWEST_PRECEDENCE +} diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/basecamp/template/gcpReadme.rocker.raw b/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/basecamp/template/gcpReadme.rocker.raw new file mode 100644 index 00000000000..7f38f08469f --- /dev/null +++ b/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/basecamp/template/gcpReadme.rocker.raw @@ -0,0 +1,39 @@ +@import io.micronaut.starter.application.Project +@import io.micronaut.starter.feature.Features + +@args ( +Project project, +Features features, +String buildCommand +) + +## Deploying the function to GCP + +Once you have a Google Cloud project selected (with billing enabled), build the function with: + +```bash +$ ./@buildCommand +``` + +Then `cd` into the `@features.build().getJarDirectory()` directory (deployment has to be done from the location where the JAR lives): + +```bash +$ cd @features.build().getJarDirectory() +``` + +Now run: + +```bash +gcloud functions deploy @project.getName() \ + --entry-point io.micronaut.chatbots.basecamp.googlecloud.Handler \ + --runtime java17 \ + --trigger-http +``` + +Choose unauthenticated access when prompted. + +To obtain the trigger URL do the following: + +```bash +$ YOUR_HTTP_TRIGGER_URL=$(gcloud functions describe @project.getName() --format='value(httpsTrigger.url)') +``` diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/basecamp/template/mockAboutCommandJson.rocker.raw b/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/basecamp/template/mockAboutCommandJson.rocker.raw new file mode 100644 index 00000000000..57e18e1342c --- /dev/null +++ b/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/basecamp/template/mockAboutCommandJson.rocker.raw @@ -0,0 +1,23 @@ +{ + "command": "/about", + "creator": { + "id": 1007299143, + "attachable_sgid": "BAh7CEkiCGdpZAY6BkVUSSIrZ2lkOi8vYmMzL1BlcnNvbQQcMDA3Mjk5MTQzP2V4cGlyZXNfaW4GOwBUSSIMcHVycG9zZQY7AFRJIg9hdHRhY2hhYmxlBjsAVEkiD2V4cGlyZXNfYXQGOwBUMA==--919d2c8b11ff403eefcab9db42dd26846d0c3102", + "name": "Victor Cooper", + "email_address": "victor@@honchodesign.com", + "personable_type": "User", + "title": "Chief Strategist", + "bio": "Don't let your dreams be dreams", + "created_at": "2016-09-22T16:21:03.625-05:00", + "updated_at": "2016-09-22T16:21:06.184-05:00", + "admin": true, + "owner": true, + "time_zone": "America/Chicago", + "avatar_url": "https://3.basecamp-static.com/195539477/people/BAhpBEcqCjw=--c632b967cec296b87363a697a67a87f9cc1e5b45/avatar-64-x4", + "company": { + "id": 1033447817, + "name": "Honcho Design" + } + }, + "callback_url": "https://3.basecamp.com/195539477/integrations/2uH9aHLEVhhaXKPaqrj8yw8P/buckets/2085958501/chats/9007199254741775/lines" +} \ No newline at end of file diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/telegram/ChatBotsTelegram.java b/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/telegram/ChatBotsTelegram.java index b62d21134ea..c0a404d9832 100644 --- a/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/telegram/ChatBotsTelegram.java +++ b/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/telegram/ChatBotsTelegram.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2023 original authors + * Copyright 2017-2024 original authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,18 +18,19 @@ import io.micronaut.starter.application.generator.GeneratorContext; import io.micronaut.starter.feature.chatbots.ChatBotType; import io.micronaut.starter.feature.chatbots.ChatBots; -import io.micronaut.starter.feature.chatbots.template.aboutCommandHandlerGroovy; -import io.micronaut.starter.feature.chatbots.template.aboutCommandHandlerGroovyJunit; -import io.micronaut.starter.feature.chatbots.template.aboutCommandHandlerGroovySpock; -import io.micronaut.starter.feature.chatbots.template.aboutCommandHandlerJava; -import io.micronaut.starter.feature.chatbots.template.aboutCommandHandlerJavaJunit; -import io.micronaut.starter.feature.chatbots.template.aboutCommandHandlerKotlin; -import io.micronaut.starter.feature.chatbots.template.aboutCommandHandlerKotlinJunit; -import io.micronaut.starter.feature.chatbots.template.finalCommandHandlerGroovy; -import io.micronaut.starter.feature.chatbots.template.finalCommandHandlerJava; -import io.micronaut.starter.feature.chatbots.template.finalCommandHandlerKotlin; -import io.micronaut.starter.feature.chatbots.template.mockAboutCommandJson; -import io.micronaut.starter.feature.chatbots.template.telegramReadme; +import io.micronaut.starter.feature.chatbots.telegram.template.aboutCommandHandlerGroovy; +import io.micronaut.starter.feature.chatbots.telegram.template.aboutCommandHandlerGroovyJunit; +import io.micronaut.starter.feature.chatbots.telegram.template.aboutCommandHandlerGroovySpock; +import io.micronaut.starter.feature.chatbots.telegram.template.aboutCommandHandlerJava; +import io.micronaut.starter.feature.chatbots.telegram.template.aboutCommandHandlerJavaJunit; +import io.micronaut.starter.feature.chatbots.telegram.template.aboutCommandHandlerKotlin; +import io.micronaut.starter.feature.chatbots.telegram.template.aboutCommandHandlerKotlinJunit; +import io.micronaut.starter.feature.chatbots.telegram.template.finalCommandHandlerGroovy; +import io.micronaut.starter.feature.chatbots.telegram.template.finalCommandHandlerJava; +import io.micronaut.starter.feature.chatbots.telegram.template.finalCommandHandlerKotlin; +import io.micronaut.starter.feature.chatbots.telegram.template.mockAboutCommandJson; +import io.micronaut.starter.feature.chatbots.telegram.template.telegramReadme; +import io.micronaut.starter.feature.chatbots.telegram.template.about; import io.micronaut.starter.feature.validator.MicronautValidationFeature; import io.micronaut.starter.options.TestFramework; import io.micronaut.starter.template.RockerTemplate; @@ -65,7 +66,10 @@ protected void addConfigurations(GeneratorContext generatorContext) { @Override protected void renderTemplates(GeneratorContext generatorContext) { - super.renderTemplates(generatorContext); + generatorContext.addTemplate( + "about-markdown", + new RockerTemplate("src/main/resources/botcommands/about.md", about.template()) + ); generatorContext.addTemplate( "about-command-handler", generatorContext.getSourcePath("/{packagePath}/AboutCommandHandler"), @@ -97,12 +101,7 @@ protected void renderTemplates(GeneratorContext generatorContext) { ); } - generatorContext.addHelpTemplate(new RockerWritable(telegramReadme.template( - rootReadMeTemplate(generatorContext), - generatorContext.getProject(), - generatorContext.getFeatures(), - getBuildCommand(generatorContext.getBuildTool())) - )); + generatorContext.addHelpTemplate(new RockerWritable(telegramReadme.template(rootReadMeTemplate(generatorContext)))); generatorContext.addTemplate( "final-command-handler", diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/telegram/TelegramAwsChatBot.java b/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/telegram/TelegramAwsChatBot.java index c762b9d7e8c..f1bf57def69 100644 --- a/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/telegram/TelegramAwsChatBot.java +++ b/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/telegram/TelegramAwsChatBot.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2023 original authors + * Copyright 2017-2024 original authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,12 +25,13 @@ import io.micronaut.starter.feature.aws.AwsFeature; import io.micronaut.starter.feature.aws.AwsMicronautRuntimeFeature; import io.micronaut.starter.feature.aws.Cdk; -import io.micronaut.starter.feature.chatbots.template.awsCdkReadme; -import io.micronaut.starter.feature.chatbots.template.awsReadme; +import io.micronaut.starter.feature.chatbots.telegram.template.awsCdkReadme; +import io.micronaut.starter.feature.chatbots.telegram.template.awsReadme; import io.micronaut.starter.feature.function.HandlerClassFeature; import io.micronaut.starter.feature.function.awslambda.AwsLambda; import io.micronaut.starter.feature.validator.MicronautValidationFeature; import io.micronaut.starter.options.BuildTool; +import io.micronaut.starter.template.RockerTemplate; import jakarta.inject.Singleton; /** @@ -97,10 +98,11 @@ protected void addDependencies(GeneratorContext generatorContext) { } @Override - public String rootReadMeTemplate(GeneratorContext generatorContext) { - return generatorContext.isFeaturePresent(Cdk.class) ? - awsCdkReadme.class.getName().replace(".", "/") + ".rocker.raw" : - awsReadme.class.getName().replace(".", "/") + ".rocker.raw"; + public RockerTemplate rootReadMeTemplate(GeneratorContext generatorContext) { + return new RockerTemplate(generatorContext.isFeaturePresent(Cdk.class) + ? awsCdkReadme.template(generatorContext.getProject(), generatorContext.getFeatures(), getBuildCommand(generatorContext.getBuildTool())) + : awsReadme.template(generatorContext.getProject(), generatorContext.getFeatures(), getBuildCommand(generatorContext.getBuildTool())) + ); } @Override diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/telegram/TelegramAzureChatBot.java b/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/telegram/TelegramAzureChatBot.java index f74472dc6d0..d3fbed06aa2 100644 --- a/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/telegram/TelegramAzureChatBot.java +++ b/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/telegram/TelegramAzureChatBot.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2023 original authors + * Copyright 2017-2024 original authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,13 +21,14 @@ import io.micronaut.starter.build.dependencies.Dependency; import io.micronaut.starter.build.dependencies.MicronautDependencyUtils; import io.micronaut.starter.feature.FeatureContext; -import io.micronaut.starter.feature.chatbots.template.azureReadme; +import io.micronaut.starter.feature.chatbots.telegram.template.azureReadme; import io.micronaut.starter.feature.function.azure.AzureBuildCommandUtils; import io.micronaut.starter.feature.function.azure.AzureCloudFeature; import io.micronaut.starter.feature.function.azure.AzureMicronautRuntimeFeature; import io.micronaut.starter.feature.function.azure.AzureRawFunction; import io.micronaut.starter.feature.validator.MicronautValidationFeature; import io.micronaut.starter.options.BuildTool; +import io.micronaut.starter.template.RockerTemplate; import jakarta.inject.Singleton; /** @@ -98,7 +99,7 @@ protected void addDependencies(GeneratorContext generatorContext) { } @Override - public String rootReadMeTemplate(GeneratorContext generatorContext) { - return azureReadme.class.getName().replace(".", "/") + ".rocker.raw"; + public RockerTemplate rootReadMeTemplate(GeneratorContext generatorContext) { + return new RockerTemplate(azureReadme.template(generatorContext.getProject(), generatorContext.getFeatures(), getBuildCommand(generatorContext.getBuildTool()))); } } diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/telegram/TelegramGcpChatBot.java b/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/telegram/TelegramGcpChatBot.java index e7f5b8d2f6e..1ba46d90a49 100644 --- a/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/telegram/TelegramGcpChatBot.java +++ b/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/telegram/TelegramGcpChatBot.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2023 original authors + * Copyright 2017-2024 original authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,13 +21,14 @@ import io.micronaut.starter.build.dependencies.Dependency; import io.micronaut.starter.build.dependencies.MicronautDependencyUtils; import io.micronaut.starter.feature.FeatureContext; -import io.micronaut.starter.feature.chatbots.template.gcpReadme; +import io.micronaut.starter.feature.chatbots.telegram.template.gcpReadme; import io.micronaut.starter.feature.function.gcp.GcpCloudFeature; import io.micronaut.starter.feature.function.gcp.GcpCloudFunctionBuildCommandUtils; import io.micronaut.starter.feature.function.gcp.GcpMicronautRuntimeFeature; import io.micronaut.starter.feature.function.gcp.GoogleCloudRawFunction; import io.micronaut.starter.feature.validator.MicronautValidationFeature; import io.micronaut.starter.options.BuildTool; +import io.micronaut.starter.template.RockerTemplate; import jakarta.inject.Singleton; /** @@ -96,7 +97,7 @@ protected void addDependencies(GeneratorContext generatorContext) { } @Override - protected String rootReadMeTemplate(GeneratorContext generatorContext) { - return gcpReadme.class.getName().replace(".", "/") + ".rocker.raw"; + public RockerTemplate rootReadMeTemplate(GeneratorContext generatorContext) { + return new RockerTemplate(gcpReadme.template(generatorContext.getProject(), generatorContext.getFeatures(), getBuildCommand(generatorContext.getBuildTool()))); } } diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/telegram/TelegramHttpChatBot.java b/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/telegram/TelegramHttpChatBot.java index 9982987561a..21347ffbf9f 100644 --- a/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/telegram/TelegramHttpChatBot.java +++ b/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/telegram/TelegramHttpChatBot.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2023 original authors + * Copyright 2017-2024 original authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,7 +20,11 @@ import io.micronaut.starter.application.generator.GeneratorContext; import io.micronaut.starter.build.dependencies.Dependency; import io.micronaut.starter.build.dependencies.MicronautDependencyUtils; -import io.micronaut.starter.feature.chatbots.template.*; +import io.micronaut.starter.feature.chatbots.telegram.template.controllerGroovyJunit; +import io.micronaut.starter.feature.chatbots.telegram.template.controllerGroovySpock; +import io.micronaut.starter.feature.chatbots.telegram.template.controllerJavaJunit; +import io.micronaut.starter.feature.chatbots.telegram.template.controllerKotlinJunit; +import io.micronaut.starter.feature.chatbots.telegram.template.controllerReadme; import io.micronaut.starter.feature.validator.MicronautValidationFeature; import io.micronaut.starter.options.BuildTool; import io.micronaut.starter.options.TestFramework; @@ -94,8 +98,8 @@ protected void addDependencies(GeneratorContext generatorContext) { } @Override - protected String rootReadMeTemplate(GeneratorContext generatorContext) { - return controllerReadme.class.getName().replace(".", "/") + ".rocker.raw"; + public RockerTemplate rootReadMeTemplate(GeneratorContext generatorContext) { + return new RockerTemplate(controllerReadme.template(generatorContext.getProject(), generatorContext.getFeatures(), getBuildCommand(generatorContext.getBuildTool()))); } @Override diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/telegram/template/about.rocker.raw b/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/telegram/template/about.rocker.raw new file mode 100644 index 00000000000..cd87239ac56 --- /dev/null +++ b/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/telegram/template/about.rocker.raw @@ -0,0 +1 @@ +Telegram Bot developed with ๐Ÿ’™ and [Micronaut](https://micronaut.io) \ No newline at end of file diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/template/aboutCommandHandlerGroovy.rocker.raw b/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/telegram/template/aboutCommandHandlerGroovy.rocker.raw similarity index 99% rename from starter-core/src/main/java/io/micronaut/starter/feature/chatbots/template/aboutCommandHandlerGroovy.rocker.raw rename to starter-core/src/main/java/io/micronaut/starter/feature/chatbots/telegram/template/aboutCommandHandlerGroovy.rocker.raw index 531579dddb3..3b2f20fe4d6 100644 --- a/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/template/aboutCommandHandlerGroovy.rocker.raw +++ b/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/telegram/template/aboutCommandHandlerGroovy.rocker.raw @@ -2,6 +2,7 @@ @args (Project project) @if (project.getPackageName() != null) { package @project.getPackageName() + } import io.micronaut.chatbots.core.SpaceParser diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/template/aboutCommandHandlerGroovyJunit.rocker.raw b/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/telegram/template/aboutCommandHandlerGroovyJunit.rocker.raw similarity index 100% rename from starter-core/src/main/java/io/micronaut/starter/feature/chatbots/template/aboutCommandHandlerGroovyJunit.rocker.raw rename to starter-core/src/main/java/io/micronaut/starter/feature/chatbots/telegram/template/aboutCommandHandlerGroovyJunit.rocker.raw diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/template/aboutCommandHandlerGroovySpock.rocker.raw b/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/telegram/template/aboutCommandHandlerGroovySpock.rocker.raw similarity index 100% rename from starter-core/src/main/java/io/micronaut/starter/feature/chatbots/template/aboutCommandHandlerGroovySpock.rocker.raw rename to starter-core/src/main/java/io/micronaut/starter/feature/chatbots/telegram/template/aboutCommandHandlerGroovySpock.rocker.raw diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/template/aboutCommandHandlerJava.rocker.raw b/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/telegram/template/aboutCommandHandlerJava.rocker.raw similarity index 100% rename from starter-core/src/main/java/io/micronaut/starter/feature/chatbots/template/aboutCommandHandlerJava.rocker.raw rename to starter-core/src/main/java/io/micronaut/starter/feature/chatbots/telegram/template/aboutCommandHandlerJava.rocker.raw diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/template/aboutCommandHandlerJavaJunit.rocker.raw b/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/telegram/template/aboutCommandHandlerJavaJunit.rocker.raw similarity index 100% rename from starter-core/src/main/java/io/micronaut/starter/feature/chatbots/template/aboutCommandHandlerJavaJunit.rocker.raw rename to starter-core/src/main/java/io/micronaut/starter/feature/chatbots/telegram/template/aboutCommandHandlerJavaJunit.rocker.raw diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/template/aboutCommandHandlerKotlin.rocker.raw b/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/telegram/template/aboutCommandHandlerKotlin.rocker.raw similarity index 99% rename from starter-core/src/main/java/io/micronaut/starter/feature/chatbots/template/aboutCommandHandlerKotlin.rocker.raw rename to starter-core/src/main/java/io/micronaut/starter/feature/chatbots/telegram/template/aboutCommandHandlerKotlin.rocker.raw index 6bdf0c85742..a646b34de13 100644 --- a/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/template/aboutCommandHandlerKotlin.rocker.raw +++ b/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/telegram/template/aboutCommandHandlerKotlin.rocker.raw @@ -2,6 +2,7 @@ @args (Project project) @if (project.getPackageName() != null) { package @project.getPackageName() + } import io.micronaut.chatbots.core.SpaceParser diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/template/aboutCommandHandlerKotlinJunit.rocker.raw b/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/telegram/template/aboutCommandHandlerKotlinJunit.rocker.raw similarity index 100% rename from starter-core/src/main/java/io/micronaut/starter/feature/chatbots/template/aboutCommandHandlerKotlinJunit.rocker.raw rename to starter-core/src/main/java/io/micronaut/starter/feature/chatbots/telegram/template/aboutCommandHandlerKotlinJunit.rocker.raw diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/template/awsCdkReadme.rocker.raw b/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/telegram/template/awsCdkReadme.rocker.raw similarity index 100% rename from starter-core/src/main/java/io/micronaut/starter/feature/chatbots/template/awsCdkReadme.rocker.raw rename to starter-core/src/main/java/io/micronaut/starter/feature/chatbots/telegram/template/awsCdkReadme.rocker.raw diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/template/awsReadme.rocker.raw b/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/telegram/template/awsReadme.rocker.raw similarity index 100% rename from starter-core/src/main/java/io/micronaut/starter/feature/chatbots/template/awsReadme.rocker.raw rename to starter-core/src/main/java/io/micronaut/starter/feature/chatbots/telegram/template/awsReadme.rocker.raw diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/telegram/template/azureReadme.rocker.raw b/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/telegram/template/azureReadme.rocker.raw new file mode 100644 index 00000000000..52bf7098b6c --- /dev/null +++ b/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/telegram/template/azureReadme.rocker.raw @@ -0,0 +1,16 @@ +@import io.micronaut.starter.application.Project +@import io.micronaut.starter.feature.Features + +@args ( +Project project, +Features features, +String buildCommand +) + +## Deploying the function to Azure + +Once you have an Azure account set up and have logged in via `az login`, deploy the function with: + +```bash +$ ./@buildCommand +``` diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/template/controllerGroovyJunit.rocker.raw b/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/telegram/template/controllerGroovyJunit.rocker.raw similarity index 99% rename from starter-core/src/main/java/io/micronaut/starter/feature/chatbots/template/controllerGroovyJunit.rocker.raw rename to starter-core/src/main/java/io/micronaut/starter/feature/chatbots/telegram/template/controllerGroovyJunit.rocker.raw index 5640d4f9bd0..36b557f1f26 100644 --- a/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/template/controllerGroovyJunit.rocker.raw +++ b/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/telegram/template/controllerGroovyJunit.rocker.raw @@ -2,6 +2,7 @@ @args (Project project) @if (project.getPackageName() != null) { package @project.getPackageName() + } import io.micronaut.chatbots.telegram.api.send.SendMessage diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/template/controllerGroovySpock.rocker.raw b/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/telegram/template/controllerGroovySpock.rocker.raw similarity index 100% rename from starter-core/src/main/java/io/micronaut/starter/feature/chatbots/template/controllerGroovySpock.rocker.raw rename to starter-core/src/main/java/io/micronaut/starter/feature/chatbots/telegram/template/controllerGroovySpock.rocker.raw diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/template/controllerJavaJunit.rocker.raw b/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/telegram/template/controllerJavaJunit.rocker.raw similarity index 100% rename from starter-core/src/main/java/io/micronaut/starter/feature/chatbots/template/controllerJavaJunit.rocker.raw rename to starter-core/src/main/java/io/micronaut/starter/feature/chatbots/telegram/template/controllerJavaJunit.rocker.raw diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/template/controllerKotlinJunit.rocker.raw b/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/telegram/template/controllerKotlinJunit.rocker.raw similarity index 99% rename from starter-core/src/main/java/io/micronaut/starter/feature/chatbots/template/controllerKotlinJunit.rocker.raw rename to starter-core/src/main/java/io/micronaut/starter/feature/chatbots/telegram/template/controllerKotlinJunit.rocker.raw index b98f06c3afd..88063c5e336 100644 --- a/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/template/controllerKotlinJunit.rocker.raw +++ b/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/telegram/template/controllerKotlinJunit.rocker.raw @@ -2,6 +2,7 @@ @args (Project project) @if (project.getPackageName() != null) { package @project.getPackageName() + } import io.micronaut.chatbots.telegram.api.send.SendMessage diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/template/controllerReadme.rocker.raw b/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/telegram/template/controllerReadme.rocker.raw similarity index 100% rename from starter-core/src/main/java/io/micronaut/starter/feature/chatbots/template/controllerReadme.rocker.raw rename to starter-core/src/main/java/io/micronaut/starter/feature/chatbots/telegram/template/controllerReadme.rocker.raw diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/template/finalCommandHandlerGroovy.rocker.raw b/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/telegram/template/finalCommandHandlerGroovy.rocker.raw similarity index 99% rename from starter-core/src/main/java/io/micronaut/starter/feature/chatbots/template/finalCommandHandlerGroovy.rocker.raw rename to starter-core/src/main/java/io/micronaut/starter/feature/chatbots/telegram/template/finalCommandHandlerGroovy.rocker.raw index c6d85989d47..bc455b193d0 100644 --- a/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/template/finalCommandHandlerGroovy.rocker.raw +++ b/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/telegram/template/finalCommandHandlerGroovy.rocker.raw @@ -2,6 +2,7 @@ @args (Project project) @if (project.getPackageName() != null) { package @project.getPackageName() + } import io.micronaut.chatbots.core.SpaceParser diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/template/finalCommandHandlerJava.rocker.raw b/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/telegram/template/finalCommandHandlerJava.rocker.raw similarity index 100% rename from starter-core/src/main/java/io/micronaut/starter/feature/chatbots/template/finalCommandHandlerJava.rocker.raw rename to starter-core/src/main/java/io/micronaut/starter/feature/chatbots/telegram/template/finalCommandHandlerJava.rocker.raw diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/template/finalCommandHandlerKotlin.rocker.raw b/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/telegram/template/finalCommandHandlerKotlin.rocker.raw similarity index 99% rename from starter-core/src/main/java/io/micronaut/starter/feature/chatbots/template/finalCommandHandlerKotlin.rocker.raw rename to starter-core/src/main/java/io/micronaut/starter/feature/chatbots/telegram/template/finalCommandHandlerKotlin.rocker.raw index 785a0a95bdf..10181f7b3c4 100644 --- a/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/template/finalCommandHandlerKotlin.rocker.raw +++ b/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/telegram/template/finalCommandHandlerKotlin.rocker.raw @@ -2,6 +2,7 @@ @args (Project project) @if (project.getPackageName() != null) { package @project.getPackageName() + } import io.micronaut.chatbots.core.SpaceParser diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/template/gcpReadme.rocker.raw b/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/telegram/template/gcpReadme.rocker.raw similarity index 100% rename from starter-core/src/main/java/io/micronaut/starter/feature/chatbots/template/gcpReadme.rocker.raw rename to starter-core/src/main/java/io/micronaut/starter/feature/chatbots/telegram/template/gcpReadme.rocker.raw diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/template/mockAboutCommandJson.rocker.raw b/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/telegram/template/mockAboutCommandJson.rocker.raw similarity index 100% rename from starter-core/src/main/java/io/micronaut/starter/feature/chatbots/template/mockAboutCommandJson.rocker.raw rename to starter-core/src/main/java/io/micronaut/starter/feature/chatbots/telegram/template/mockAboutCommandJson.rocker.raw diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/template/telegramReadme.rocker.raw b/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/telegram/template/telegramReadme.rocker.raw similarity index 73% rename from starter-core/src/main/java/io/micronaut/starter/feature/chatbots/template/telegramReadme.rocker.raw rename to starter-core/src/main/java/io/micronaut/starter/feature/chatbots/telegram/template/telegramReadme.rocker.raw index 3dec8958305..0a80252031e 100644 --- a/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/template/telegramReadme.rocker.raw +++ b/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/telegram/template/telegramReadme.rocker.raw @@ -1,13 +1,6 @@ -@import com.fizzed.rocker.Rocker -@import io.micronaut.starter.application.Project -@import io.micronaut.starter.feature.Features +@import io.micronaut.starter.template.RockerTemplate -@args( - String platformTemplate, - Project project, - Features features, - String buildCommand -) +@args(RockerTemplate platformTemplate) # Telegram ChatBot @@ -15,7 +8,7 @@ Follow the instructions in the [Micronaut ChatBot Documentation](https://microna Once you have a username and HTTP auth key for your new bot, edit the application config in this project to set the bot username and make up a WEBHOOK_TOKEN so you can ensure it's Telegram that's calling your bot. -@Rocker.template(platformTemplate, project, features, buildCommand) +@platformTemplate.renderModel() You can then set up the Telegram webhook by running the following command: diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/template/about.rocker.raw b/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/template/about.rocker.raw deleted file mode 100644 index 0a6fb96b22a..00000000000 --- a/starter-core/src/main/java/io/micronaut/starter/feature/chatbots/template/about.rocker.raw +++ /dev/null @@ -1,4 +0,0 @@ -@import io.micronaut.starter.application.Project -@args(io.micronaut.starter.feature.chatbots.ChatBotType type) - -@type Bot developed with ๐Ÿ’™ and [Micronaut](https://micronaut.io) \ No newline at end of file diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/ci/workflows/oci/OCICiWorkflowFeature.java b/starter-core/src/main/java/io/micronaut/starter/feature/ci/workflows/oci/OCICiWorkflowFeature.java index 1b3b817dd19..41d700783c3 100644 --- a/starter-core/src/main/java/io/micronaut/starter/feature/ci/workflows/oci/OCICiWorkflowFeature.java +++ b/starter-core/src/main/java/io/micronaut/starter/feature/ci/workflows/oci/OCICiWorkflowFeature.java @@ -29,7 +29,7 @@ @Singleton public class OCICiWorkflowFeature extends CIWorkflowFeature { - public static final String NAME = "oci-devops-build-ci"; + public static final String NAME = "oracle-cloud-devops-build-ci"; private static final String WORKFLOW_FILENAME = "build_spec.yml"; @NonNull @@ -79,6 +79,11 @@ private Template workflowRockerTemplate(GeneratorContext generatorContext) { } } + @Override + public boolean isPreview() { + return false; + } + @Override public String getThirdPartyDocumentation() { return "https://docs.oracle.com/en-us/iaas/Content/devops/using/build_specs.htm"; diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/database/Cassandra.java b/starter-core/src/main/java/io/micronaut/starter/feature/database/Cassandra.java index 7d13000d05c..56d811ec96b 100644 --- a/starter-core/src/main/java/io/micronaut/starter/feature/database/Cassandra.java +++ b/starter-core/src/main/java/io/micronaut/starter/feature/database/Cassandra.java @@ -23,14 +23,16 @@ import io.micronaut.starter.feature.Feature; import io.micronaut.starter.feature.config.ApplicationConfiguration; import io.micronaut.starter.feature.micrometer.MicrometerFeature; +import io.micronaut.starter.feature.testcontainers.ContributingTestContainerDependency; import io.micronaut.starter.feature.testresources.TestResources; import jakarta.inject.Singleton; +import java.util.Collections; import java.util.List; import java.util.Map; @Singleton -public class Cassandra implements Feature { +public class Cassandra implements Feature, ContributingTestContainerDependency { public static final String NAME = "cassandra"; @@ -114,4 +116,9 @@ public String getMicronautDocumentation() { public String getThirdPartyDocumentation() { return "https://docs.datastax.com/en/developer/java-driver/latest/"; } + + @Override + public List testContainersDependencies() { + return Collections.singletonList(ContributingTestContainerDependency.testContainerDependency("cassandra")); + } } diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/database/DataMongoFeature.java b/starter-core/src/main/java/io/micronaut/starter/feature/database/DataMongoFeature.java index ed8d76a80a9..040387813b1 100644 --- a/starter-core/src/main/java/io/micronaut/starter/feature/database/DataMongoFeature.java +++ b/starter-core/src/main/java/io/micronaut/starter/feature/database/DataMongoFeature.java @@ -28,7 +28,7 @@ /** * Base class for our data-mongo features. */ -public abstract class DataMongoFeature extends EaseTestingFeature implements DataDocumentFeature { +public abstract class DataMongoFeature extends EaseTestingFeature implements DataDocumentFeature, MongoContributingTestContainerDependency { private static final String MONGODB_GROUP = "org.mongodb"; diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/database/DatabaseDriverFeature.java b/starter-core/src/main/java/io/micronaut/starter/feature/database/DatabaseDriverFeature.java index fc195c1a7cb..71a4833a410 100644 --- a/starter-core/src/main/java/io/micronaut/starter/feature/database/DatabaseDriverFeature.java +++ b/starter-core/src/main/java/io/micronaut/starter/feature/database/DatabaseDriverFeature.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2022 original authors + * Copyright 2017-2024 original authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,6 +19,7 @@ import io.micronaut.starter.application.ApplicationType; import io.micronaut.starter.application.generator.GeneratorContext; import io.micronaut.starter.build.dependencies.Dependency; +import io.micronaut.starter.build.dependencies.MavenCoordinate; import io.micronaut.starter.feature.Category; import io.micronaut.starter.feature.FeatureContext; import io.micronaut.starter.feature.OneOfFeature; @@ -29,14 +30,16 @@ import io.micronaut.starter.feature.testresources.DbType; import io.micronaut.starter.feature.testresources.EaseTestingFeature; import io.micronaut.starter.feature.testresources.TestResources; - +import io.micronaut.starter.feature.testresources.TestResourcesAdditionalModulesProvider; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Optional; -public abstract class DatabaseDriverFeature extends EaseTestingFeature implements OneOfFeature, DatabaseDriverFeatureDependencies { +import static io.micronaut.starter.build.dependencies.MicronautDependencyUtils.GROUP_ID_MICRONAUT_TESTRESOURCES; + +public abstract class DatabaseDriverFeature extends EaseTestingFeature implements OneOfFeature, DatabaseDriverFeatureDependencies, TestResourcesAdditionalModulesProvider { private final JdbcFeature jdbcFeature; @@ -104,6 +107,57 @@ public Optional getDbType() { return Optional.empty(); } + @Override + @NonNull + public List getTestResourcesAdditionalModules(@NonNull GeneratorContext generatorContext) { + if ( + (!generatorContext.isFeaturePresent(Data.class) || generatorContext.isFeaturePresent(HibernateReactiveFeature.class)) + ) { + return getDbType().map(dbType -> { + if (generatorContext.isFeaturePresent(R2dbc.class)) { + return Collections.singletonList(dbType.getR2dbcTestResourcesModuleName()); + } else if (generatorContext.isFeaturePresent(HibernateReactiveFeature.class)) { + return Collections.singletonList(dbType.getHibernateReactiveTestResourcesModuleName()); + } else { + return Collections.singletonList(dbType.getJdbcTestResourcesModuleName()); + } + }).orElseGet(Collections::emptyList); + } + return Collections.emptyList(); + } + + @Override + @NonNull + public List getTestResourcesDependencies(@NonNull GeneratorContext generatorContext) { + List dependencies = new ArrayList<>(); + if ( + (!generatorContext.isFeaturePresent(Data.class) || generatorContext.isFeaturePresent(HibernateReactiveFeature.class) || generatorContext.isFeaturePresent(R2dbc.class)) + ) { + getDbType() + .map(dbType -> { + if (generatorContext.isFeaturePresent(R2dbc.class)) { + return dbType.getR2dbcTestResourcesModuleName(); + } else if (generatorContext.isFeaturePresent(HibernateReactiveFeature.class)) { + return dbType.getHibernateReactiveTestResourcesModuleName(); + } else { + return dbType.getJdbcTestResourcesModuleName(); + } + }) + .map(resourceName -> new MavenCoordinate(GROUP_ID_MICRONAUT_TESTRESOURCES, "micronaut-test-resources-" + resourceName, null)) + .ifPresent(dependencies::add); + } + if ((generatorContext.isFeaturePresent(HibernateReactiveFeature.class) || generatorContext.isFeaturePresent(R2dbc.class)) + && generatorContext.isFeaturePresent(DatabaseDriverFeature.class) + && !generatorContext.isFeaturePresent(MigrationFeature.class) + ) { + generatorContext.getFeature(DatabaseDriverFeature.class) + .flatMap(DatabaseDriverFeatureDependencies::getJavaClientDependency) + .map(Dependency.Builder::build) + .ifPresent(driver -> dependencies.add(new MavenCoordinate(driver.getGroupId(), driver.getArtifactId(), null))); + } + return dependencies; + } + public Map getAdditionalConfig(GeneratorContext generatorContext) { return Collections.emptyMap(); } @@ -122,14 +176,22 @@ protected List parseDependencies(GeneratorContext generatorC return dependencies; } } - if (generatorContext.getFeatures().hasFeature(DataHibernateReactive.class) || generatorContext.getFeatures().hasFeature(HibernateReactiveJpa.class)) { - getHibernateReactiveJavaClientDependency().ifPresent(dependencies::add); - if (generatorContext.isFeaturePresent(MigrationFeature.class)) { - getJavaClientDependency().ifPresent(dependencies::add); - } + if (generatorContext.getFeatures().hasFeature(HibernateReactiveFeature.class)) { + dependencies.addAll(dependenciesForHibernateReactive(generatorContext)); } else { getJavaClientDependency().ifPresent(dependencies::add); } return dependencies; } + + @NonNull + protected List dependenciesForHibernateReactive(@NonNull GeneratorContext generatorContext) { + List dependencies = new ArrayList<>(); + getHibernateReactiveJavaClientDependency().ifPresent(dependencies::add); + if (generatorContext.isFeaturePresent(MigrationFeature.class)) { + getJavaClientDependency().ifPresent(dependencies::add); + } + return dependencies; + } } + diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/database/HibernateGorm.java b/starter-core/src/main/java/io/micronaut/starter/feature/database/HibernateGorm.java deleted file mode 100644 index bfd7282453a..00000000000 --- a/starter-core/src/main/java/io/micronaut/starter/feature/database/HibernateGorm.java +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright 2017-2022 original authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.micronaut.starter.feature.database; - -import io.micronaut.starter.application.ApplicationType; -import io.micronaut.starter.application.generator.GeneratorContext; -import io.micronaut.starter.build.dependencies.Dependency; -import io.micronaut.starter.feature.Category; -import io.micronaut.starter.feature.FeatureContext; -import io.micronaut.starter.feature.GroovySpecificFeature; -import io.micronaut.starter.feature.migration.MigrationFeature; -import io.micronaut.starter.feature.other.HibernateValidator; -import jakarta.inject.Singleton; - -import java.util.Map; - -@Singleton -public class HibernateGorm implements GroovySpecificFeature, DatabaseDriverConfigurationFeature { - - private static final String PREFIX = "dataSource."; - private static final String URL_KEY = PREFIX + "url"; - private static final String DRIVER_KEY = PREFIX + "driver-class-name"; - private static final String USERNAME_KEY = PREFIX + "username"; - private static final String PASSWORD_KEY = PREFIX + "password"; - - private final DatabaseDriverFeature defaultDbFeature; - private final HibernateValidator hibernateValidator; - - public HibernateGorm(DatabaseDriverFeature defaultDbFeature, HibernateValidator hibernateValidator) { - this.defaultDbFeature = defaultDbFeature; - this.hibernateValidator = hibernateValidator; - } - - @Override - public boolean isPreview() { - return true; - } - - @Override - public String getName() { - return "hibernate-gorm"; - } - - @Override - public String getTitle() { - return "GORM for Hibernate"; - } - - @Override - public String getDescription() { - return "Adds support for Hibernate using GORM"; - } - - @Override - public void processSelectedFeatures(FeatureContext featureContext) { - if (!featureContext.isPresent(DatabaseDriverFeature.class)) { - featureContext.addFeature(defaultDbFeature); - } - if (!featureContext.isPresent(HibernateValidator.class)) { - featureContext.addFeature(hibernateValidator); - } - } - - @Override - public void apply(GeneratorContext generatorContext) { - Map config = generatorContext.getConfiguration(); - DatabaseDriverFeature dbFeature = generatorContext.getRequiredFeature(DatabaseDriverFeature.class); - applyDefaultConfig(generatorContext, dbFeature, config); - config.put("dataSource.pooled", true); - config.put("dataSource.jmxExport", true); - config.put("hibernate.hbm2ddl.auto", generatorContext.getFeatures().hasFeature(MigrationFeature.class) ? Hbm2ddlAuto.NONE.toString() : - Hbm2ddlAuto.UPDATE.toString()); - config.put("hibernate.cache.queries", false); - config.put("hibernate.cache.use_second_level_cache", false); - config.put("hibernate.cache.use_query_cache", false); - - generatorContext.addDependency(Dependency.builder() - .groupId("io.micronaut.groovy") - .artifactId("micronaut-hibernate-gorm") - .compile()); - generatorContext.addDependency(Dependency.builder() - .groupId("org.apache.tomcat") - .artifactId("tomcat-jdbc") - .runtime()); - } - - @Override - public boolean supports(ApplicationType applicationType) { - return true; - } - - @Override - public String getUrlKey() { - return URL_KEY; - } - - @Override - public String getDriverKey() { - return DRIVER_KEY; - } - - @Override - public String getUsernameKey() { - return USERNAME_KEY; - } - - @Override - public String getPasswordKey() { - return PASSWORD_KEY; - } - - @Override - public String getCategory() { - return Category.DATABASE; - } -} diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/database/Neo4jGorm.java b/starter-core/src/main/java/io/micronaut/starter/feature/database/HibernateJpaModelgen.java similarity index 58% rename from starter-core/src/main/java/io/micronaut/starter/feature/database/Neo4jGorm.java rename to starter-core/src/main/java/io/micronaut/starter/feature/database/HibernateJpaModelgen.java index b671dfb6bad..ea5f51691d7 100644 --- a/starter-core/src/main/java/io/micronaut/starter/feature/database/Neo4jGorm.java +++ b/starter-core/src/main/java/io/micronaut/starter/feature/database/HibernateJpaModelgen.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2022 original authors + * Copyright 2017-2024 original authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,56 +15,44 @@ */ package io.micronaut.starter.feature.database; +import io.micronaut.core.annotation.NonNull; import io.micronaut.starter.application.ApplicationType; import io.micronaut.starter.application.generator.GeneratorContext; import io.micronaut.starter.build.dependencies.Dependency; import io.micronaut.starter.feature.Category; -import io.micronaut.starter.feature.FeatureContext; -import io.micronaut.starter.feature.GroovySpecificFeature; +import io.micronaut.starter.feature.Feature; import jakarta.inject.Singleton; @Singleton -public class Neo4jGorm implements GroovySpecificFeature { +public class HibernateJpaModelgen implements Feature { - private final Neo4jBolt neo4jBolt; + public static final String NAME = "hibernate-jpamodelgen"; - public Neo4jGorm(Neo4jBolt neo4jBolt) { - this.neo4jBolt = neo4jBolt; - } - - @Override - public boolean isPreview() { - return true; - } + private static final Dependency DEPENDENCY_JPAMODELGEN = Dependency.builder() + .groupId("org.hibernate.orm") + .artifactId("hibernate-jpamodelgen") + .annotationProcessor() + .build(); @Override + @NonNull public String getName() { - return "neo4j-gorm"; + return NAME; } @Override public String getTitle() { - return "GORM for Neo4j"; + return "Hibernate JPA Static Metamodel Generator"; } @Override public String getDescription() { - return "Configures GORM for Neo4j for Groovy applications"; - } - - @Override - public void processSelectedFeatures(FeatureContext featureContext) { - if (!featureContext.isPresent(Neo4jBolt.class)) { - featureContext.addFeature(neo4jBolt); - } + return "Generator for compile time static metamodel classes"; } @Override public void apply(GeneratorContext generatorContext) { - generatorContext.addDependency(Dependency.builder() - .groupId("io.micronaut.groovy") - .artifactId("micronaut-neo4j-gorm") - .compile()); + generatorContext.addDependency(DEPENDENCY_JPAMODELGEN); } @Override @@ -77,4 +65,13 @@ public String getCategory() { return Category.DATABASE; } + @Override + public String getThirdPartyDocumentation() { + return "https://hibernate.org/orm/tooling/"; + } + + @Override + public String getMicronautDocumentation() { + return "https://micronaut-projects.github.io/micronaut-data/latest/guide/#typeSafeJava"; + } } diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/database/HibernateReactiveFeature.java b/starter-core/src/main/java/io/micronaut/starter/feature/database/HibernateReactiveFeature.java index 4a49d24f262..3e714ddc8c4 100644 --- a/starter-core/src/main/java/io/micronaut/starter/feature/database/HibernateReactiveFeature.java +++ b/starter-core/src/main/java/io/micronaut/starter/feature/database/HibernateReactiveFeature.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2022 original authors + * Copyright 2017-2024 original authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -67,7 +67,7 @@ public void apply(GeneratorContext generatorContext) { } if (optionalDbType.isPresent()) { DbType dbType = optionalDbType.get(); - if (dbType == DbType.ORACLEXE) { + if (dbType == DbType.ORACLEFREE) { generatorContext.getConfiguration().put(JPA_HIBERNATE_PROPERTIES_DIALECT, ORACLE_DIALECT); } } diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/database/MongoContributingTestContainerDependency.java b/starter-core/src/main/java/io/micronaut/starter/feature/database/MongoContributingTestContainerDependency.java new file mode 100644 index 00000000000..9e5184e2349 --- /dev/null +++ b/starter-core/src/main/java/io/micronaut/starter/feature/database/MongoContributingTestContainerDependency.java @@ -0,0 +1,29 @@ +/* + * Copyright 2017-2024 original authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.micronaut.starter.feature.database; + +import io.micronaut.starter.build.dependencies.Dependency; +import io.micronaut.starter.feature.testcontainers.ContributingTestContainerDependency; + +import java.util.Collections; +import java.util.List; + +public interface MongoContributingTestContainerDependency extends ContributingTestContainerDependency { + @Override + default List testContainersDependencies() { + return Collections.singletonList(ContributingTestContainerDependency.testContainerDependency("mongodb")); + } +} diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/database/MongoFeature.java b/starter-core/src/main/java/io/micronaut/starter/feature/database/MongoFeature.java index 6fd56dda1a8..9d13a5c6ad1 100644 --- a/starter-core/src/main/java/io/micronaut/starter/feature/database/MongoFeature.java +++ b/starter-core/src/main/java/io/micronaut/starter/feature/database/MongoFeature.java @@ -18,7 +18,7 @@ import io.micronaut.starter.feature.testresources.EaseTestingFeature; import io.micronaut.starter.feature.testresources.TestResources; -public abstract class MongoFeature extends EaseTestingFeature { +public abstract class MongoFeature extends EaseTestingFeature implements MongoContributingTestContainerDependency { protected MongoFeature(TestContainers testContainers, TestResources testResources) { diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/database/MySQL.java b/starter-core/src/main/java/io/micronaut/starter/feature/database/MySQL.java index cbbad7a74ae..766554e069a 100644 --- a/starter-core/src/main/java/io/micronaut/starter/feature/database/MySQL.java +++ b/starter-core/src/main/java/io/micronaut/starter/feature/database/MySQL.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2022 original authors + * Copyright 2017-2024 original authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -34,9 +34,9 @@ public class MySQL extends MySQLCompatibleFeature { .artifactId("r2dbc-mysql") .runtime(); - public static final Dependency.Builder DEPENDENCY_MYSQL_CONNECTOR_JAVA = Dependency.builder() - .groupId(NAME) - .artifactId("mysql-connector-java") + private static final Dependency.Builder DEPENDENCY_MYSQL_CONNECTOR_JAVA = Dependency.builder() + .groupId("com.mysql") + .artifactId("mysql-connector-j") .runtime() .template(); diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/database/Oracle.java b/starter-core/src/main/java/io/micronaut/starter/feature/database/Oracle.java index fe74fe494a6..8612f15d53a 100644 --- a/starter-core/src/main/java/io/micronaut/starter/feature/database/Oracle.java +++ b/starter-core/src/main/java/io/micronaut/starter/feature/database/Oracle.java @@ -31,12 +31,23 @@ public class Oracle extends DatabaseDriverFeature { public static final String NAME = "oracle"; public static final String VERTX_ORACLE_CLIENT = "vertx-oracle-client"; + + //TODO: enable once ojdbc upgrades to 23. See: https://github.com/micronaut-projects/micronaut-sql/pull/1268 + public static final boolean COMPATIBLE_WITH_HIBERNATE_REACTIVE = false; + + @Deprecated(forRemoval = true) public static final Dependency.Builder DEPENDENCY_OJDBC8 = Dependency.builder() .groupId("com.oracle.database.jdbc") .artifactId("ojdbc8") .runtime() .template(); + public static final Dependency.Builder DEPENDENCY_OJDBC11 = Dependency.builder() + .groupId("com.oracle.database.jdbc") + .artifactId("ojdbc11") + .runtime() + .template(); + private static final Dependency.Builder DEPENDENCY_ORACLE_R2DBC = Dependency.builder() .groupId("com.oracle.database.r2dbc") .artifactId("oracle-r2dbc") @@ -88,7 +99,7 @@ public String getDriverClass() { @NonNull @Override public Optional getDbType() { - return Optional.of(DbType.ORACLEXE); + return Optional.of(DbType.ORACLEFREE); } @Override @@ -115,13 +126,13 @@ public Optional getR2DbcDependency() { @Override @NonNull public Optional getHibernateReactiveJavaClientDependency() { - return Optional.of(DEPENDENCY_VERTX_ORACLE_CLIENT); + return COMPATIBLE_WITH_HIBERNATE_REACTIVE ? Optional.of(DEPENDENCY_VERTX_ORACLE_CLIENT) : Optional.empty(); } @Override @NonNull public Optional getJavaClientDependency() { - return Optional.of(DEPENDENCY_OJDBC8); + return Optional.of(DEPENDENCY_OJDBC11); } @Override diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/database/TestContainers.java b/starter-core/src/main/java/io/micronaut/starter/feature/database/TestContainers.java index e05ee42a19f..f0c41e89e00 100644 --- a/starter-core/src/main/java/io/micronaut/starter/feature/database/TestContainers.java +++ b/starter-core/src/main/java/io/micronaut/starter/feature/database/TestContainers.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2022 original authors + * Copyright 2017-2024 original authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,14 +19,13 @@ import io.micronaut.core.annotation.Nullable; import io.micronaut.starter.application.ApplicationType; import io.micronaut.starter.application.generator.GeneratorContext; -import io.micronaut.starter.build.dependencies.Dependency; import io.micronaut.starter.feature.Category; import io.micronaut.starter.feature.Feature; +import io.micronaut.starter.feature.FeaturePhase; import io.micronaut.starter.feature.config.ApplicationConfiguration; import io.micronaut.starter.feature.config.Configuration; import io.micronaut.starter.feature.database.r2dbc.R2dbc; -import io.micronaut.starter.feature.messaging.kafka.Kafka; -import io.micronaut.starter.feature.test.MockServerClient; +import io.micronaut.starter.feature.testcontainers.ContributingTestContainerDependency; import io.micronaut.starter.options.TestFramework; import io.micronaut.starter.template.StringTemplate; import jakarta.inject.Singleton; @@ -35,10 +34,8 @@ @Singleton public class TestContainers implements Feature { - public static final String NAME = "testcontainers"; - - public static final String TESTCONTAINERS_GROUP_ID = "org.testcontainers"; + private static final String ARTIFACT_ID_TESTCONTAINERS = "testcontainers"; @NonNull @Override @@ -58,7 +55,12 @@ public String getDescription() { @Override public void apply(GeneratorContext generatorContext) { - generatorContext.addDependency(testContainerTestDependency("testcontainers")); + generatorContext.getFeatures().getFeatures() + .stream() + .filter(ContributingTestContainerDependency.class::isInstance) + .forEach(f -> ((ContributingTestContainerDependency) f).testContainersDependencies().forEach(generatorContext::addDependency)); + generatorContext.addDependency(ContributingTestContainerDependency.testContainerDependency(ARTIFACT_ID_TESTCONTAINERS)); + generatorContext.getFeature(DatabaseDriverFeature.class).ifPresent(driverFeature -> { generatorContext.getFeature(R2dbc.class).ifPresent(driverConfiguration -> { if (driverFeature instanceof SQLServer) { @@ -68,11 +70,11 @@ public void apply(GeneratorContext generatorContext) { Configuration testConfig = generatorContext.getConfiguration("test", ApplicationConfiguration.testConfig()); testConfig.put(driverConfiguration.getUrlKey(), url); }); - generatorContext.addDependency(testContainerTestDependency("r2dbc")); + generatorContext.addDependency(ContributingTestContainerDependency.testContainerDependency("r2dbc")); // TestContainers requires the database module, a jdbc driver AND the r2dbc module: see https://www.testcontainers.org/modules/databases/r2dbc/ driverFeature.getJavaClientDependency().ifPresent(d -> generatorContext.addDependency(d.testRuntime())); artifactIdForDriverFeature(driverFeature).ifPresent(dependencyArtifactId -> - generatorContext.addDependency(testContainerTestDependency(dependencyArtifactId))); + generatorContext.addDependency(ContributingTestContainerDependency.testContainerDependency(dependencyArtifactId))); }); generatorContext.getFeature(DatabaseDriverConfigurationFeature.class).ifPresent(driverConfiguration -> { String driver = "org.testcontainers.jdbc.ContainerDatabaseDriver"; @@ -85,7 +87,7 @@ public void apply(GeneratorContext generatorContext) { testConfig.put(driverConfiguration.getDriverKey(), driver); }); artifactIdForDriverFeature(driverFeature).ifPresent(dependencyArtifactId -> - generatorContext.addDependency(testContainerTestDependency(dependencyArtifactId))); + generatorContext.addDependency(ContributingTestContainerDependency.testContainerDependency(dependencyArtifactId))); }); generatorContext.getFeature(HibernateReactiveFeature.class).ifPresent(hibernateReactiveFeature -> { urlForDatabaseDriverFeature(driverFeature).ifPresent(url -> { @@ -93,35 +95,12 @@ public void apply(GeneratorContext generatorContext) { testConfig.put(hibernateReactiveFeature.getUrlKey(), url); }); artifactIdForDriverFeature(driverFeature) - .ifPresent(dependencyArtifactId -> generatorContext.addDependency(testContainerTestDependency(dependencyArtifactId))); + .ifPresent(dependencyArtifactId -> generatorContext.addDependency(ContributingTestContainerDependency.testContainerDependency(dependencyArtifactId))); }); }); testContainerArtifactIdByTestFramework(generatorContext.getTestFramework()).ifPresent(testArtifactId -> { - generatorContext.addDependency(testContainerTestDependency(testArtifactId)); + generatorContext.addDependency(ContributingTestContainerDependency.testContainerDependency(testArtifactId)); }); - - if (generatorContext.isFeaturePresent(MongoFeature.class) || - generatorContext.isFeaturePresent(DataMongoFeature.class) || - generatorContext.isFeaturePresent(DataMongoReactive.class)) { - generatorContext.addDependency(testContainerTestDependency("mongodb")); - } - if (generatorContext.isFeaturePresent(Kafka.class)) { - generatorContext.addDependency(testContainerTestDependency("kafka")); - } - if (generatorContext.isFeaturePresent(Cassandra.class)) { - generatorContext.addDependency(testContainerTestDependency("cassandra")); - } - if (generatorContext.isFeaturePresent(MockServerClient.class)) { - generatorContext.addDependency(testContainerTestDependency("mockserver")); - } - } - - @NonNull - private static Dependency.Builder testContainerTestDependency(@NonNull String artifactId) { - return Dependency.builder() - .groupId(TESTCONTAINERS_GROUP_ID) - .artifactId(artifactId) - .test(); } @NonNull @@ -193,6 +172,11 @@ public String getCategory() { return Category.DATABASE; } + @Override + public int getOrder() { + return FeaturePhase.TEST.getOrder(); + } + @Nullable @Override public String getThirdPartyDocumentation() { diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/database/r2dbc/R2dbc.java b/starter-core/src/main/java/io/micronaut/starter/feature/database/r2dbc/R2dbc.java index 69f242e0815..a25c185200d 100644 --- a/starter-core/src/main/java/io/micronaut/starter/feature/database/r2dbc/R2dbc.java +++ b/starter-core/src/main/java/io/micronaut/starter/feature/database/r2dbc/R2dbc.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2023 original authors + * Copyright 2017-2024 original authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/function/AbstractFunctionFeature.java b/starter-core/src/main/java/io/micronaut/starter/feature/function/AbstractFunctionFeature.java index d85bb28bd1e..8a4a758b070 100644 --- a/starter-core/src/main/java/io/micronaut/starter/feature/function/AbstractFunctionFeature.java +++ b/starter-core/src/main/java/io/micronaut/starter/feature/function/AbstractFunctionFeature.java @@ -71,7 +71,7 @@ protected void applyFunction(GeneratorContext generatorContext, ApplicationType if (type == ApplicationType.DEFAULT) { - final String className = StringUtils.capitalize(generatorContext.getProject().getPropertyName()); + final String className = StringUtils.capitalize(generatorContext.getProject().getClassName()); Project project = generatorContext.getProject().withClassName(className); Language language = generatorContext.getLanguage(); diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/function/awslambda/AwsLambda.java b/starter-core/src/main/java/io/micronaut/starter/feature/function/awslambda/AwsLambda.java index b9256b1972a..d9635f1869e 100644 --- a/starter-core/src/main/java/io/micronaut/starter/feature/function/awslambda/AwsLambda.java +++ b/starter-core/src/main/java/io/micronaut/starter/feature/function/awslambda/AwsLambda.java @@ -18,12 +18,17 @@ import com.fizzed.rocker.RockerModel; import io.micronaut.context.env.Environment; import io.micronaut.core.annotation.NonNull; +import io.micronaut.http.client.HttpClient; import io.micronaut.starter.application.ApplicationType; import io.micronaut.starter.application.Project; import io.micronaut.starter.application.generator.GeneratorContext; import io.micronaut.starter.build.dependencies.Dependency; import io.micronaut.starter.build.dependencies.MicronautDependencyUtils; -import io.micronaut.starter.feature.*; +import io.micronaut.starter.feature.Category; +import io.micronaut.starter.feature.CodeContributingFeature; +import io.micronaut.starter.feature.DefaultFeature; +import io.micronaut.starter.feature.Feature; +import io.micronaut.starter.feature.FeatureContext; import io.micronaut.starter.feature.architecture.CpuArchitecture; import io.micronaut.starter.feature.architecture.X86; import io.micronaut.starter.feature.aws.AwsApiFeature; @@ -56,8 +61,8 @@ import io.micronaut.starter.feature.function.awslambda.template.homeControllerSpock; import io.micronaut.starter.feature.graalvm.GraalVM; import io.micronaut.starter.feature.httpclient.HttpClientFeature; +import io.micronaut.starter.feature.httpclient.HttpClientJdk; import io.micronaut.starter.feature.json.SerializationJacksonFeature; -import io.micronaut.starter.feature.other.HttpClient; import io.micronaut.starter.feature.other.ShadePlugin; import io.micronaut.starter.feature.security.SecurityFeature; import io.micronaut.starter.options.BuildTool; @@ -65,6 +70,7 @@ import io.micronaut.starter.options.Options; import io.micronaut.starter.options.TestRockerModelProvider; import io.micronaut.starter.template.RockerWritable; +import jakarta.inject.Inject; import jakarta.inject.Singleton; import java.util.Optional; @@ -111,18 +117,19 @@ public class AwsLambda implements FunctionFeature, DefaultFeature, AwsCloudFeatu private final AwsLambdaCustomRuntime customRuntime; private final CpuArchitecture defaultCpuArchitecture; private final AwsLambdaSnapstart snapstart; - private final HttpClient httpClient; + private final HttpClientJdk httpClientJdk; private final AwsLambdaEventsSerde awsLambdaEventsSerde; private final HandlerClassFeature defaultAwsLambdaHandlerProvider; private final HandlerClassFeature functionAwsLambdaHandlerProvider; + @Inject public AwsLambda(ShadePlugin shadePlugin, AwsLambdaCustomRuntime customRuntime, X86 x86, AwsLambdaSnapstart snapstart, - HttpClient httpClient, + HttpClientJdk httpClientJdk, AwsLambdaEventsSerde awsLambdaEventsSerde, DefaultAwsLambdaHandlerProvider defaultAwsLambdaHandlerProvider, FunctionAwsLambdaHandlerProvider functionAwsLambdaHandlerProvider) { @@ -130,12 +137,34 @@ public AwsLambda(ShadePlugin shadePlugin, this.customRuntime = customRuntime; this.defaultCpuArchitecture = x86; this.snapstart = snapstart; - this.httpClient = httpClient; + this.httpClientJdk = httpClientJdk; this.awsLambdaEventsSerde = awsLambdaEventsSerde; this.defaultAwsLambdaHandlerProvider = defaultAwsLambdaHandlerProvider; this.functionAwsLambdaHandlerProvider = functionAwsLambdaHandlerProvider; } + /** + * @deprecated Use {@link #AwsLambda(ShadePlugin, AwsLambdaCustomRuntime, X86, AwsLambdaSnapstart, HttpClientJdk, AwsLambdaEventsSerde, DefaultAwsLambdaHandlerProvider, FunctionAwsLambdaHandlerProvider)} instead. + */ + @Deprecated + public AwsLambda(ShadePlugin shadePlugin, + AwsLambdaCustomRuntime customRuntime, + X86 x86, + AwsLambdaSnapstart snapstart, + HttpClient httpClient, + AwsLambdaEventsSerde awsLambdaEventsSerde, + DefaultAwsLambdaHandlerProvider defaultAwsLambdaHandlerProvider, + FunctionAwsLambdaHandlerProvider functionAwsLambdaHandlerProvider) { + this(shadePlugin, + customRuntime, + x86, + snapstart, + new HttpClientJdk(), + awsLambdaEventsSerde, + defaultAwsLambdaHandlerProvider, + functionAwsLambdaHandlerProvider); + } + @Override public void processSelectedFeatures(FeatureContext featureContext) { Stream.of(defaultAwsLambdaHandlerProvider, functionAwsLambdaHandlerProvider) @@ -155,7 +184,7 @@ public void processSelectedFeatures(FeatureContext featureContext) { } if (featureContext.isPresent(GraalVM.class) && !featureContext.isPresent(HttpClientFeature.class)) { - featureContext.addFeature(httpClient); + featureContext.addFeature(httpClientJdk); } if (shouldAddSnapstartFeature(featureContext)) { diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/function/azure/AbstractAzureFunction.java b/starter-core/src/main/java/io/micronaut/starter/feature/function/azure/AbstractAzureFunction.java index d734de8e838..74f59de3ebc 100644 --- a/starter-core/src/main/java/io/micronaut/starter/feature/function/azure/AbstractAzureFunction.java +++ b/starter-core/src/main/java/io/micronaut/starter/feature/function/azure/AbstractAzureFunction.java @@ -123,13 +123,13 @@ public void apply(GeneratorContext generatorContext) { @NonNull private Optional javaVersionValue(GeneratorContext generatorContext) { if (generatorContext.getBuildTool().isGradle()) { - if (generatorContext.getJdkVersion() == JdkVersion.JDK_17) { + if (JdkVersion.JDK_17.equals(generatorContext.getJdkVersion())) { return Optional.of("Java 17"); } else { return Optional.empty(); } } - if (generatorContext.getJdkVersion() == JdkVersion.JDK_17) { + if (JdkVersion.JDK_17.equals(generatorContext.getJdkVersion())) { return Optional.of("17"); } else { return Optional.empty(); diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/function/azure/AzureFunctionFeatureValidator.java b/starter-core/src/main/java/io/micronaut/starter/feature/function/azure/AzureFunctionFeatureValidator.java index c2f92b7965d..4dc31503336 100644 --- a/starter-core/src/main/java/io/micronaut/starter/feature/function/azure/AzureFunctionFeatureValidator.java +++ b/starter-core/src/main/java/io/micronaut/starter/feature/function/azure/AzureFunctionFeatureValidator.java @@ -28,7 +28,7 @@ public class AzureFunctionFeatureValidator implements FeatureValidator { public static boolean supports(JdkVersion jdkVersion) { - return jdkVersion == JdkVersion.JDK_8 || jdkVersion == JdkVersion.JDK_11 || jdkVersion == JdkVersion.JDK_17; + return JdkVersion.JDK_8.equals(jdkVersion) || JdkVersion.JDK_11.equals(jdkVersion) || JdkVersion.JDK_17.equals(jdkVersion); } @Override diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/function/azure/template/azurefunctions.rocker.raw b/starter-core/src/main/java/io/micronaut/starter/feature/function/azure/template/azurefunctions.rocker.raw index 13eefa4b0e1..dc1557c72cb 100644 --- a/starter-core/src/main/java/io/micronaut/starter/feature/function/azure/template/azurefunctions.rocker.raw +++ b/starter-core/src/main/java/io/micronaut/starter/feature/function/azure/template/azurefunctions.rocker.raw @@ -2,32 +2,25 @@ @import io.micronaut.starter.build.gradle.GradleDsl; @args (Project project, GradleDsl dsl, String javaVersion) -@if(dsl == GradleDsl.KOTLIN) { -azurefunctions { - resourceGroup = "java-functions-group" - appName = "@project.getName()" - pricingTier = "Consumption" - setRuntime(closureOf { - os("linux") -@if(javaVersion != null) { - javaVersion("@javaVersion") -} - }) - localDebug = "transport=dt_socket,server=y,suspend=n,address=5005" -} -} -@if(dsl == GradleDsl.GROOVY) { azurefunctions { resourceGroup = "java-functions-group" appName = "@project.getName()" pricingTier = "Consumption" region = "westus" +@if(dsl == GradleDsl.KOTLIN) { + setRuntime(closureOf { + os("linux") +@if(javaVersion != null) { + javaVersion("@javaVersion") +} + }) +} else { runtime { os = "linux" @if(javaVersion != null) { - javaVersion = "@javaVersion" + javaVersion = "@javaVersion" } } +} localDebug = "transport=dt_socket,server=y,suspend=n,address=5005" } -} \ No newline at end of file diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/function/gcp/GoogleCloudFunctionFeatureValidator.java b/starter-core/src/main/java/io/micronaut/starter/feature/function/gcp/GoogleCloudFunctionFeatureValidator.java index 9be2a5b4e2b..348514fd9a1 100644 --- a/starter-core/src/main/java/io/micronaut/starter/feature/function/gcp/GoogleCloudFunctionFeatureValidator.java +++ b/starter-core/src/main/java/io/micronaut/starter/feature/function/gcp/GoogleCloudFunctionFeatureValidator.java @@ -29,7 +29,7 @@ public class GoogleCloudFunctionFeatureValidator implements FeatureValidator { private static boolean supports(JdkVersion jdkVersion) { - return jdkVersion == JdkVersion.JDK_11 || jdkVersion == JdkVersion.JDK_17; + return JdkVersion.JDK_11.equals(jdkVersion) || JdkVersion.JDK_17.equals(jdkVersion); } @Override diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/github/workflows/templates/buildAndPushImage.rocker.raw b/starter-core/src/main/java/io/micronaut/starter/feature/github/workflows/templates/buildAndPushImage.rocker.raw index d996a490b61..84dbe5810d0 100644 --- a/starter-core/src/main/java/io/micronaut/starter/feature/github/workflows/templates/buildAndPushImage.rocker.raw +++ b/starter-core/src/main/java/io/micronaut/starter/feature/github/workflows/templates/buildAndPushImage.rocker.raw @@ -1,5 +1,4 @@ @import io.micronaut.starter.options.BuildTool -@import io.micronaut.starter.options.JdkVersion @args ( BuildTool buildTool, diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/httpclient/HttpClientJdk.java b/starter-core/src/main/java/io/micronaut/starter/feature/httpclient/HttpClientJdk.java index dfbd7463e68..79f0aa55fd9 100644 --- a/starter-core/src/main/java/io/micronaut/starter/feature/httpclient/HttpClientJdk.java +++ b/starter-core/src/main/java/io/micronaut/starter/feature/httpclient/HttpClientJdk.java @@ -29,10 +29,14 @@ public class HttpClientJdk implements HttpClientFeature { public static final String NAME = "http-client-jdk"; public static final String ARTIFACT_ID_MICRONAUT_HTTP_CLIENT_JDK = "micronaut-http-client-jdk"; - private static final Dependency DEPENDENCY_MICRONAUT_HTTP_CLIENT_JDK = MicronautDependencyUtils.coreDependency() - .artifactId(ARTIFACT_ID_MICRONAUT_HTTP_CLIENT_JDK) + private static final Dependency.Builder MICRONAUT_HTTP_CLIENT_JDK = MicronautDependencyUtils.coreDependency() + .artifactId(ARTIFACT_ID_MICRONAUT_HTTP_CLIENT_JDK); + public static final Dependency DEPENDENCY_MICRONAUT_HTTP_CLIENT_JDK = MICRONAUT_HTTP_CLIENT_JDK .compile() .build(); + public static final Dependency DEPENDENCY_MICRONAUT_HTTP_CLIENT_JDK_COMPILE_ONLY = MICRONAUT_HTTP_CLIENT_JDK + .compileOnly() + .build(); @Override public String getName() { diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/jaxrs/JaxRs.java b/starter-core/src/main/java/io/micronaut/starter/feature/jaxrs/JaxRs.java index df352f70047..c971b2e10cf 100644 --- a/starter-core/src/main/java/io/micronaut/starter/feature/jaxrs/JaxRs.java +++ b/starter-core/src/main/java/io/micronaut/starter/feature/jaxrs/JaxRs.java @@ -29,11 +29,14 @@ @Singleton public class JaxRs implements Feature, MicronautServerDependent { - public static final String MICRONAUT_JAX_RS_GROUP = "io.micronaut.jaxrs"; public static final String MICRONAUT_JAXRS_VERSION = "micronaut.jaxrs.version"; public static final String MICRONAUT_JAXRS_PROCESSOR = "micronaut-jaxrs-processor"; public static final String NAME = "jax-rs"; - + private static final String ARTIFACT_ID_MICRONAUT_JAXRS_SERVER = "micronaut-jaxrs-server"; + private static final Dependency DEPENDENCY_JAXRS_SERVER_COMPILE = MicronautDependencyUtils.jaxrsDependency() + .artifactId(ARTIFACT_ID_MICRONAUT_JAXRS_SERVER) + .compile() + .build(); private final JaxRsSecurity jaxRsSecurity; public JaxRs(JaxRsSecurity jaxRsSecurity) { @@ -64,22 +67,19 @@ public void processSelectedFeatures(FeatureContext featureContext) { @Override public void apply(GeneratorContext generatorContext) { - Dependency.Builder jaxrs = Dependency.builder() - .groupId(MICRONAUT_JAX_RS_GROUP) - .artifactId(MICRONAUT_JAXRS_PROCESSOR) - .versionProperty(MICRONAUT_JAXRS_VERSION) - .template(); + addDependencies(generatorContext); + } + protected void addDependencies(GeneratorContext generatorContext) { generatorContext.addDependency(MicronautDependencyUtils.annotationProcessor(generatorContext.getBuildTool(), - MICRONAUT_JAX_RS_GROUP, + MicronautDependencyUtils.GROUP_ID_MICRONAUT_JAXRS, MICRONAUT_JAXRS_PROCESSOR, MICRONAUT_JAXRS_VERSION)); - - generatorContext.addDependency(jaxrs.testAnnotationProcessor()); - generatorContext.addDependency(Dependency.builder() - .groupId(MICRONAUT_JAX_RS_GROUP) - .artifactId("micronaut-jaxrs-server") - .compile()); + generatorContext.addDependency(MicronautDependencyUtils.testAnnotationProcessor(generatorContext.getBuildTool(), + MicronautDependencyUtils.GROUP_ID_MICRONAUT_JAXRS, + MICRONAUT_JAXRS_PROCESSOR, + MICRONAUT_JAXRS_VERSION)); + generatorContext.addDependency(DEPENDENCY_JAXRS_SERVER_COMPILE); } @Override diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/jaxrs/JaxRsSecurity.java b/starter-core/src/main/java/io/micronaut/starter/feature/jaxrs/JaxRsSecurity.java index 462acdca039..3dd820a5e06 100644 --- a/starter-core/src/main/java/io/micronaut/starter/feature/jaxrs/JaxRsSecurity.java +++ b/starter-core/src/main/java/io/micronaut/starter/feature/jaxrs/JaxRsSecurity.java @@ -17,7 +17,7 @@ import io.micronaut.starter.application.ApplicationType; import io.micronaut.starter.application.generator.GeneratorContext; -import io.micronaut.starter.build.dependencies.Dependency; +import io.micronaut.starter.build.dependencies.MicronautDependencyUtils; import io.micronaut.starter.feature.Category; import io.micronaut.starter.feature.Feature; import io.micronaut.starter.feature.server.MicronautServerDependent; @@ -25,6 +25,7 @@ @Singleton public class JaxRsSecurity implements Feature, MicronautServerDependent { + private static final String ARTIFACT_ID_MICRONAUT_JAXRS_SERVER_SECURITY = "micronaut-jaxrs-server-security"; @Override public String getName() { @@ -48,9 +49,8 @@ public boolean isVisible() { @Override public void apply(GeneratorContext generatorContext) { - generatorContext.addDependency(Dependency.builder() - .groupId(JaxRs.MICRONAUT_JAX_RS_GROUP) - .artifactId("micronaut-jaxrs-server-security") + generatorContext.addDependency(MicronautDependencyUtils.jaxrsDependency() + .artifactId(ARTIFACT_ID_MICRONAUT_JAXRS_SERVER_SECURITY) .versionProperty("micronaut.jaxrs.version") .compile()); } diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/database/MongoGorm.java b/starter-core/src/main/java/io/micronaut/starter/feature/json/JsonSmart.java similarity index 52% rename from starter-core/src/main/java/io/micronaut/starter/feature/database/MongoGorm.java rename to starter-core/src/main/java/io/micronaut/starter/feature/json/JsonSmart.java index a733fd68d96..d3798549f09 100644 --- a/starter-core/src/main/java/io/micronaut/starter/feature/database/MongoGorm.java +++ b/starter-core/src/main/java/io/micronaut/starter/feature/json/JsonSmart.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2022 original authors + * Copyright 2017-2024 original authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,59 +13,45 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.micronaut.starter.feature.database; +package io.micronaut.starter.feature.json; -import io.micronaut.core.annotation.Nullable; +import io.micronaut.core.annotation.NonNull; import io.micronaut.starter.application.ApplicationType; import io.micronaut.starter.application.generator.GeneratorContext; import io.micronaut.starter.build.dependencies.Dependency; import io.micronaut.starter.feature.Category; -import io.micronaut.starter.feature.FeatureContext; -import io.micronaut.starter.feature.GroovySpecificFeature; +import io.micronaut.starter.feature.Feature; import jakarta.inject.Singleton; @Singleton -public class MongoGorm implements GroovySpecificFeature { +public class JsonSmart implements Feature { - private final MongoReactive mongoReactive; + public static final String NAME = "json-smart"; - public MongoGorm(MongoReactive mongoReactive) { - this.mongoReactive = mongoReactive; - } - - @Override - public boolean isPreview() { - return true; - } + private static final Dependency DEPENDENCY_JSON_SMART = Dependency.builder() + .lookupArtifactId("json-smart") + .test() + .build(); @Override + @NonNull public String getName() { - return "mongo-gorm"; + return NAME; } @Override public String getTitle() { - return "GORM for MongoDB"; + return "Netplex Json-smart"; } @Override public String getDescription() { - return "Configures GORM for MongoDB for Groovy applications"; - } - - @Override - public void processSelectedFeatures(FeatureContext featureContext) { - if (!featureContext.isPresent(MongoReactive.class)) { - featureContext.addFeature(mongoReactive); - } + return "Json-smart is a performance focused, JSON processor library"; } @Override public void apply(GeneratorContext generatorContext) { - generatorContext.addDependency(Dependency.builder() - .groupId("io.micronaut.groovy") - .artifactId("micronaut-mongo-gorm") - .compile()); + generatorContext.addDependency(DEPENDENCY_JSON_SMART); } @Override @@ -75,12 +61,11 @@ public boolean supports(ApplicationType applicationType) { @Override public String getCategory() { - return Category.DATABASE; + return Category.TEST; } - @Nullable @Override public String getThirdPartyDocumentation() { - return "https://gorm.grails.org/latest/mongodb/manual/"; + return "https://netplex.github.io/json-smart/"; } } diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/messaging/jms/SQS.java b/starter-core/src/main/java/io/micronaut/starter/feature/messaging/jms/SQS.java index d8baf368662..9502744f2a8 100644 --- a/starter-core/src/main/java/io/micronaut/starter/feature/messaging/jms/SQS.java +++ b/starter-core/src/main/java/io/micronaut/starter/feature/messaging/jms/SQS.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2021 original authors + * Copyright 2017-2024 original authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,11 +17,19 @@ import io.micronaut.core.annotation.NonNull; import io.micronaut.starter.application.generator.GeneratorContext; +import io.micronaut.starter.build.dependencies.MavenCoordinate; import io.micronaut.starter.build.dependencies.MicronautDependencyUtils; +import io.micronaut.starter.feature.testresources.TestResourcesAdditionalModulesProvider; +import io.micronaut.testresources.buildtools.KnownModules; import jakarta.inject.Singleton; +import java.util.Collections; +import java.util.List; + +import static io.micronaut.starter.build.dependencies.MicronautDependencyUtils.GROUP_ID_MICRONAUT_TESTRESOURCES; + @Singleton -public class SQS extends AbstractJmsFeature { +public class SQS extends AbstractJmsFeature implements TestResourcesAdditionalModulesProvider { public static final String NAME = "jms-sqs"; @@ -48,4 +56,14 @@ public void apply(GeneratorContext generatorContext) { .artifactId("micronaut-jms-sqs") .compile()); } + + @Override + public List getTestResourcesAdditionalModules(GeneratorContext generatorContext) { + return Collections.singletonList(KnownModules.LOCALSTACK_SQS); + } + + @Override + public List getTestResourcesDependencies(GeneratorContext generatorContext) { + return Collections.singletonList(new MavenCoordinate(GROUP_ID_MICRONAUT_TESTRESOURCES, "micronaut-test-resources-localstack-sqs", null)); + } } diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/messaging/kafka/Kafka.java b/starter-core/src/main/java/io/micronaut/starter/feature/messaging/kafka/Kafka.java index 0049e1a9bb9..49386fdd1ca 100644 --- a/starter-core/src/main/java/io/micronaut/starter/feature/messaging/kafka/Kafka.java +++ b/starter-core/src/main/java/io/micronaut/starter/feature/messaging/kafka/Kafka.java @@ -24,6 +24,7 @@ import io.micronaut.starter.feature.database.TestContainers; import io.micronaut.starter.feature.messaging.MessagingFeature; import io.micronaut.starter.feature.messaging.SharedTestResourceFeature; +import io.micronaut.starter.feature.testcontainers.ContributingTestContainerArtifactId; import io.micronaut.starter.feature.testresources.EaseTestingFeature; import io.micronaut.starter.feature.testresources.TestResources; import io.micronaut.starter.options.Options; @@ -32,8 +33,8 @@ import java.util.Set; @Singleton -public class Kafka extends EaseTestingFeature implements DefaultFeature, MessagingFeature, SharedTestResourceFeature { - +public class Kafka extends EaseTestingFeature + implements DefaultFeature, MessagingFeature, SharedTestResourceFeature, ContributingTestContainerArtifactId { public static final Dependency MICRONAUT_KAFKA = MicronautDependencyUtils .kafkaDependency() .artifactId("micronaut-kafka") @@ -41,6 +42,7 @@ public class Kafka extends EaseTestingFeature implements DefaultFeature, Messagi .build(); public static final String NAME = "kafka"; + private static final String TEST_CONTAINERS_ARTIFACT_ID_KAFKA = "kafka"; public Kafka(TestContainers testContainers, TestResources testResources) { super(testContainers, testResources); @@ -76,4 +78,9 @@ public boolean shouldApply(ApplicationType applicationType, Options options, Set public String getMicronautDocumentation() { return "https://micronaut-projects.github.io/micronaut-kafka/latest/guide/index.html"; } + + @Override + public String testContainersArtifactId() { + return TEST_CONTAINERS_ARTIFACT_ID_KAFKA; + } } diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/multitenancy/MultitenancyGorm.java b/starter-core/src/main/java/io/micronaut/starter/feature/multitenancy/MultitenancyGorm.java deleted file mode 100644 index 1c212ffbfe7..00000000000 --- a/starter-core/src/main/java/io/micronaut/starter/feature/multitenancy/MultitenancyGorm.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright 2017-2022 original authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.micronaut.starter.feature.multitenancy; - -import io.micronaut.core.annotation.NonNull; -import io.micronaut.starter.application.ApplicationType; -import io.micronaut.starter.application.generator.GeneratorContext; -import io.micronaut.starter.build.dependencies.Dependency; -import io.micronaut.starter.feature.Category; -import io.micronaut.starter.feature.Feature; -import io.micronaut.starter.feature.FeatureContext; -import io.micronaut.starter.feature.FeaturePredicate; -import io.micronaut.starter.feature.GroovySpecificFeature; -import io.micronaut.starter.options.Language; - -import jakarta.inject.Singleton; -import java.util.Optional; - -@Singleton -public class MultitenancyGorm implements GroovySpecificFeature { - - private final Multitenancy multitenancy; - - public MultitenancyGorm(Multitenancy multitenancy) { - this.multitenancy = multitenancy; - } - - @Override - public boolean isPreview() { - return true; - } - - @Override - public void processSelectedFeatures(FeatureContext featureContext) { - if (featureContext.getLanguage() == Language.GROOVY) { - if (!featureContext.isPresent(Multitenancy.class)) { - featureContext.addFeature(multitenancy); - } - } else { - featureContext.exclude(new FeaturePredicate() { - @Override - public boolean test(Feature feature) { - return feature instanceof MultitenancyGorm; - } - - @Override - public Optional getWarning() { - return Optional.of("multi-tenancy-gorm feature only supports Groovy"); - } - }); - } - } - - @Override - public void apply(GeneratorContext generatorContext) { - generatorContext.addDependency(Dependency.builder() - .groupId("io.micronaut.groovy") - .artifactId("micronaut-multitenancy-gorm") - .compile()); - } - - @NonNull - @Override - public String getName() { - return "multi-tenancy-gorm"; - } - - @Override - public String getTitle() { - return "Multitenancy GORM"; - } - - @Override - public String getDescription() { - return "Integrates Micronaut multitenancy capabilities with GORM multitenancy features"; - } - - @Override - public String getMicronautDocumentation() { - return "https://docs.micronaut.io/latest/guide/index.html#multitenancyGorm"; - } - - @Override - public String getThirdPartyDocumentation() { - return "https://gorm.grails.org/latest/hibernate/manual/index.html#multiTenancy"; - } - - @Override - public boolean supports(ApplicationType applicationType) { - return true; - } - - @Override - public String getCategory() { - return Category.DATABASE; - } -} diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/opensearch/OpenSearchAmazon.java b/starter-core/src/main/java/io/micronaut/starter/feature/opensearch/OpenSearchAmazon.java new file mode 100644 index 00000000000..0bbf895d4c8 --- /dev/null +++ b/starter-core/src/main/java/io/micronaut/starter/feature/opensearch/OpenSearchAmazon.java @@ -0,0 +1,48 @@ +/* + * Copyright 2017-2024 original authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.micronaut.starter.feature.opensearch; + +import io.micronaut.starter.feature.database.TestContainers; +import io.micronaut.starter.feature.testresources.TestResources; +import jakarta.inject.Singleton; + +@Singleton +public class OpenSearchAmazon extends OpenSearchFeature { + + public static final String NAME = "opensearch-amazon"; + + public OpenSearchAmazon( + TestContainers testContainers, + TestResources testResources + ) { + super(testContainers, testResources); + } + + @Override + public String getName() { + return NAME; + } + + @Override + public String getTitle() { + return "Open Search Amazon"; + } + + @Override + public String getDescription() { + return "Adds support for Amazon OpenSearch Service"; + } +} diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/opensearch/OpenSearchContributingTestContainerDependency.java b/starter-core/src/main/java/io/micronaut/starter/feature/opensearch/OpenSearchContributingTestContainerDependency.java new file mode 100644 index 00000000000..a81b625b8de --- /dev/null +++ b/starter-core/src/main/java/io/micronaut/starter/feature/opensearch/OpenSearchContributingTestContainerDependency.java @@ -0,0 +1,34 @@ +/* + * Copyright 2017-2024 original authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.micronaut.starter.feature.opensearch; + +import io.micronaut.starter.build.dependencies.Dependency; +import io.micronaut.starter.feature.testcontainers.ContributingTestContainerDependency; + +import java.util.Collections; +import java.util.List; + +public interface OpenSearchContributingTestContainerDependency extends ContributingTestContainerDependency { + + @Override + default List testContainersDependencies() { + return Collections.singletonList(Dependency.builder() + .groupId("org.opensearch") + .artifactId("opensearch-testcontainers") + .test() + .build()); + } +} diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/opensearch/OpenSearchFeature.java b/starter-core/src/main/java/io/micronaut/starter/feature/opensearch/OpenSearchFeature.java new file mode 100644 index 00000000000..422db77c754 --- /dev/null +++ b/starter-core/src/main/java/io/micronaut/starter/feature/opensearch/OpenSearchFeature.java @@ -0,0 +1,80 @@ +/* + * Copyright 2017-2024 original authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.micronaut.starter.feature.opensearch; + +import io.micronaut.starter.application.ApplicationType; +import io.micronaut.starter.application.generator.GeneratorContext; +import io.micronaut.starter.build.dependencies.MavenCoordinate; +import io.micronaut.starter.build.dependencies.MicronautDependencyUtils; +import io.micronaut.starter.feature.Category; +import io.micronaut.starter.feature.database.TestContainers; +import io.micronaut.starter.feature.testresources.EaseTestingFeature; +import io.micronaut.starter.feature.testresources.TestResources; +import io.micronaut.starter.feature.testresources.TestResourcesAdditionalModulesProvider; +import io.micronaut.testresources.buildtools.KnownModules; + +import java.util.Collections; +import java.util.List; + +import static io.micronaut.starter.build.dependencies.MicronautDependencyUtils.GROUP_ID_MICRONAUT_TESTRESOURCES; + +public abstract class OpenSearchFeature extends EaseTestingFeature implements OpenSearchContributingTestContainerDependency, TestResourcesAdditionalModulesProvider { + + protected OpenSearchFeature( + TestContainers testContainers, + TestResources testResources + ) { + super(testContainers, testResources); + } + + @Override + public boolean supports(ApplicationType applicationType) { + return true; + } + + @Override + public String getMicronautDocumentation() { + return "https://micronaut-projects.github.io/micronaut-opensearch/latest/guide/"; + } + + @Override + public String getThirdPartyDocumentation() { + return "https://opensearch.org/docs/latest/clients/java/"; + } + + @Override + public String getCategory() { + return Category.SEARCH; + } + + @Override + public void apply(GeneratorContext generatorContext) { + generatorContext.addDependency(MicronautDependencyUtils + .opensearchDependency() + .artifactId("micronaut-" + getName()) + .compile()); + } + + @Override + public List getTestResourcesAdditionalModules(GeneratorContext generatorContext) { + return Collections.singletonList(KnownModules.OPENSEARCH); + } + + @Override + public List getTestResourcesDependencies(GeneratorContext generatorContext) { + return Collections.singletonList(new MavenCoordinate(GROUP_ID_MICRONAUT_TESTRESOURCES, "micronaut-test-resources-opensearch", null)); + } +} diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/opensearch/OpenSearchHttpClient5.java b/starter-core/src/main/java/io/micronaut/starter/feature/opensearch/OpenSearchHttpClient5.java new file mode 100644 index 00000000000..057df2a49ec --- /dev/null +++ b/starter-core/src/main/java/io/micronaut/starter/feature/opensearch/OpenSearchHttpClient5.java @@ -0,0 +1,48 @@ +/* + * Copyright 2017-2024 original authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.micronaut.starter.feature.opensearch; + +import io.micronaut.starter.feature.database.TestContainers; +import io.micronaut.starter.feature.testresources.TestResources; +import jakarta.inject.Singleton; + +@Singleton +public class OpenSearchHttpClient5 extends OpenSearchFeature { + + public static final String NAME = "opensearch-httpclient5"; + + public OpenSearchHttpClient5( + TestContainers testContainers, + TestResources testResources + ) { + super(testContainers, testResources); + } + + @Override + public String getName() { + return NAME; + } + + @Override + public String getTitle() { + return "OpenSearch HttpClient 5"; + } + + @Override + public String getDescription() { + return "Adds support for OpenSearch using Apache HttpClient 5 Transport"; + } +} diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/opensearch/OpenSearchRestClient.java b/starter-core/src/main/java/io/micronaut/starter/feature/opensearch/OpenSearchRestClient.java new file mode 100644 index 00000000000..0c7d044b5c5 --- /dev/null +++ b/starter-core/src/main/java/io/micronaut/starter/feature/opensearch/OpenSearchRestClient.java @@ -0,0 +1,68 @@ +/* + * Copyright 2017-2024 original authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.micronaut.starter.feature.opensearch; + +import io.micronaut.starter.application.generator.GeneratorContext; +import io.micronaut.starter.feature.FeatureContext; +import io.micronaut.starter.feature.database.TestContainers; +import io.micronaut.starter.feature.json.JacksonDatabindFeature; +import io.micronaut.starter.feature.testresources.TestResources; +import jakarta.inject.Singleton; + +@Singleton +public class OpenSearchRestClient extends OpenSearchFeature { + + public static final String NAME = "opensearch-restclient"; + + private final JacksonDatabindFeature jacksonDatabindFeature; + + public OpenSearchRestClient( + TestContainers testContainers, + TestResources testResources, + JacksonDatabindFeature jacksonDatabindFeature + ) { + super(testContainers, testResources); + this.jacksonDatabindFeature = jacksonDatabindFeature; + } + + @Override + public String getName() { + return NAME; + } + + @Override + public String getTitle() { + return "OpenSearch REST Client"; + } + + @Override + public void apply(GeneratorContext generatorContext) { + super.apply(generatorContext); + } + + @Override + public void processSelectedFeatures(FeatureContext featureContext) { + super.processSelectedFeatures(featureContext); + if (!featureContext.isPresent(JacksonDatabindFeature.class)) { + featureContext.addFeature(jacksonDatabindFeature); + } + } + + @Override + public String getDescription() { + return "Adds support for OpenSearch RestClient-based transport"; + } +} diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/opentelemetry/OpenTelemetryExporterFeature.java b/starter-core/src/main/java/io/micronaut/starter/feature/opentelemetry/OpenTelemetryExporterFeature.java index f4e78780660..2ad9737a4fd 100644 --- a/starter-core/src/main/java/io/micronaut/starter/feature/opentelemetry/OpenTelemetryExporterFeature.java +++ b/starter-core/src/main/java/io/micronaut/starter/feature/opentelemetry/OpenTelemetryExporterFeature.java @@ -48,6 +48,10 @@ public String getDescription() { @Override public void apply(GeneratorContext generatorContext) { generatorContext.addDependency(exporterDependency()); + addConfiguration(generatorContext); + } + + protected void addConfiguration(GeneratorContext generatorContext) { generatorContext.getConfiguration().addCommaSeparatedValue("otel.traces.exporter", exporterValue()); } diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/opentelemetry/OpenTelemetryExporterJaeger.java b/starter-core/src/main/java/io/micronaut/starter/feature/opentelemetry/OpenTelemetryExporterJaeger.java index 48307bfc754..6032f0216b1 100644 --- a/starter-core/src/main/java/io/micronaut/starter/feature/opentelemetry/OpenTelemetryExporterJaeger.java +++ b/starter-core/src/main/java/io/micronaut/starter/feature/opentelemetry/OpenTelemetryExporterJaeger.java @@ -16,14 +16,35 @@ package io.micronaut.starter.feature.opentelemetry; import io.micronaut.core.annotation.NonNull; +import io.micronaut.starter.application.generator.GeneratorContext; import jakarta.inject.Singleton; +import java.util.Locale; + @Singleton public class OpenTelemetryExporterJaeger extends OpenTelemetryExporterFeature { private static final String EXPORTER_JAEGER = "Jaeger"; + @NonNull + @Override + public String getName() { + return "tracing-opentelemetry-exporter-" + EXPORTER_JAEGER.toLowerCase(Locale.ROOT); + } + + @NonNull + @Override + public String getTitle() { + return "OpenTelemetry Exporter " + EXPORTER_JAEGER; + } + @NonNull public String exporterName() { - return EXPORTER_JAEGER; + return OpenTelemetryExporterOtlp.EXPORTER_OTLP; + } + + @Override + protected void addConfiguration(GeneratorContext generatorContext) { + super.addConfiguration(generatorContext); + generatorContext.getConfiguration().put("otel.exporter.otlp.endpoint", "http://localhost:4317"); } } diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/opentelemetry/OpenTelemetryExporterOtlp.java b/starter-core/src/main/java/io/micronaut/starter/feature/opentelemetry/OpenTelemetryExporterOtlp.java index 1aa27ec5070..030227b4296 100644 --- a/starter-core/src/main/java/io/micronaut/starter/feature/opentelemetry/OpenTelemetryExporterOtlp.java +++ b/starter-core/src/main/java/io/micronaut/starter/feature/opentelemetry/OpenTelemetryExporterOtlp.java @@ -20,7 +20,7 @@ @Singleton public class OpenTelemetryExporterOtlp extends OpenTelemetryExporterFeature { - private static final String EXPORTER_OTLP = "OTLP"; + public static final String EXPORTER_OTLP = "OTLP"; @NonNull public String exporterName() { diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/opentelemetry/OpenTelemetryXray.java b/starter-core/src/main/java/io/micronaut/starter/feature/opentelemetry/OpenTelemetryXray.java index 0766875d4f7..1e2128fdb55 100644 --- a/starter-core/src/main/java/io/micronaut/starter/feature/opentelemetry/OpenTelemetryXray.java +++ b/starter-core/src/main/java/io/micronaut/starter/feature/opentelemetry/OpenTelemetryXray.java @@ -23,26 +23,33 @@ @Singleton public class OpenTelemetryXray extends AbstractOpenTelemetry { - - private static final Dependency.Builder OPEN_TELEMETRY_EXTENSION_AWS = - OpenTelemetryDependencyUtils.openTelemetryDependency() - .artifactId("opentelemetry-extension-aws") - .compile(); - + public static final String NAME = "tracing-opentelemetry-xray"; private static final Dependency.Builder OPEN_TELEMETRY_INSTRUMENTATION_AWS_SDK = OpenTelemetryDependencyUtils.openTelemetryInstrumentationDependency() .artifactId("opentelemetry-aws-sdk-2.2") .compile(); - - private static final Dependency.Builder OPEN_TELEMETRY_CONTRIB_XRAY = Dependency.builder() - .groupId("io.opentelemetry.contrib") + private static final String GROUP_ID_IO_OPENTELEMETRY_CONTRIB = "io.opentelemetry.contrib"; + private static final Dependency OPEN_TELEMETRY_CONTRIB_XRAY = Dependency.builder() + .groupId(GROUP_ID_IO_OPENTELEMETRY_CONTRIB) .artifactId("opentelemetry-aws-xray") - .compile(); - + .compile() + .build(); + private static final String ARTIFACT_ID_OPENTELEMETRY_AWS_RESOURCES = "opentelemetry-aws-resources"; + private static final String ARTIFACT_ID_OPENTELEMETRY_AWS_XRAY_PROPAGATOR = "opentelemetry-aws-xray-propagator"; + private static final Dependency OPEN_TELEMETRY_CONTRIB_XRAY_RESOURCES = Dependency.builder() + .groupId(GROUP_ID_IO_OPENTELEMETRY_CONTRIB) + .artifactId(ARTIFACT_ID_OPENTELEMETRY_AWS_RESOURCES) + .compile() + .build(); + private static final Dependency OPEN_TELEMETRY_CONTRIB_XRAY_PROPAGATOR = Dependency.builder() + .groupId(GROUP_ID_IO_OPENTELEMETRY_CONTRIB) + .artifactId(ARTIFACT_ID_OPENTELEMETRY_AWS_XRAY_PROPAGATOR) + .compile() + .build(); private static final Dependency.Builder OPEN_TELEMETRY_BOM_ALPHA = Dependency.builder() .lookupArtifactId("opentelemetry-instrumentation-bom-alpha") .compile(); - + public OpenTelemetryXray(OpenTelemetry otel, OpenTelemetryHttp otelHttp, OpenTelemetryAnnotations otelAnnotations, @@ -54,7 +61,7 @@ public OpenTelemetryXray(OpenTelemetry otel, @NonNull @Override public String getName() { - return "tracing-opentelemetry-xray"; + return NAME; } @Override @@ -70,8 +77,9 @@ public String getDescription() { @Override public void apply(GeneratorContext generatorContext) { - generatorContext.addDependency(OPEN_TELEMETRY_EXTENSION_AWS); generatorContext.addDependency(OPEN_TELEMETRY_CONTRIB_XRAY); + generatorContext.addDependency(OPEN_TELEMETRY_CONTRIB_XRAY_RESOURCES); + generatorContext.addDependency(OPEN_TELEMETRY_CONTRIB_XRAY_PROPAGATOR); if (generatorContext.getFeatures().isFeaturePresent(AwsV2Sdk.class)) { generatorContext.addDependency(OPEN_TELEMETRY_BOM_ALPHA); generatorContext.addDependency(OPEN_TELEMETRY_INSTRUMENTATION_AWS_SDK); diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/other/HttpClientTest.java b/starter-core/src/main/java/io/micronaut/starter/feature/other/HttpClientTest.java index c7c713e2385..5cfb02563b5 100644 --- a/starter-core/src/main/java/io/micronaut/starter/feature/other/HttpClientTest.java +++ b/starter-core/src/main/java/io/micronaut/starter/feature/other/HttpClientTest.java @@ -34,6 +34,7 @@ import jakarta.inject.Singleton; import java.util.Set; +import static io.micronaut.starter.feature.httpclient.HttpClientJdk.ARTIFACT_ID_MICRONAUT_HTTP_CLIENT_JDK; import static io.micronaut.starter.feature.other.HttpClient.ARTIFACT_ID_MICRONAUT_HTTP_CLIENT; @Singleton @@ -49,6 +50,16 @@ public class HttpClientTest implements DefaultFeature { .compileOnly() .build(); + private static final Dependency DEPENDENCY_MICRONAUT_HTTP_CLIENT_JDK_TEST = MicronautDependencyUtils.coreDependency() + .artifactId(ARTIFACT_ID_MICRONAUT_HTTP_CLIENT_JDK) + .test() + .build(); + + private static final Dependency DEPENDENCY_MICRONAUT_HTTP_CLIENT_JDK_COMPILE_ONLY = MicronautDependencyUtils.coreDependency() + .artifactId(ARTIFACT_ID_MICRONAUT_HTTP_CLIENT_JDK) + .compileOnly() + .build(); + @Override public String getName() { return "http-client-test"; @@ -73,11 +84,15 @@ public boolean supports(ApplicationType applicationType) { public void apply(GeneratorContext generatorContext) { if (!hasHttpClientFeatureDependencyInScope(generatorContext, Scope.COMPILE)) { if (generatorContext.getFeatures().hasFeature(AwsLambdaCustomRuntime.class) || (generatorContext.getFeatures().hasFeature(AwsLambda.class) && generatorContext.getFeatures().hasFeature(GraalVM.class))) { - generatorContext.addDependency(HttpClient.DEPENDENCY_MICRONAUT_HTTP_CLIENT); + generatorContext.addDependency(HttpClientJdk.DEPENDENCY_MICRONAUT_HTTP_CLIENT_JDK); } else if (generatorContext.getApplicationType() == ApplicationType.DEFAULT) { - generatorContext.addDependency(DEPENDENCY_MICRONAUT_HTTP_CLIENT_TEST); + generatorContext.addDependency(generatorContext.getFeatures().hasFeature(AwsLambda.class) + ? DEPENDENCY_MICRONAUT_HTTP_CLIENT_JDK_TEST + : DEPENDENCY_MICRONAUT_HTTP_CLIENT_TEST); if (generatorContext.hasFeature(MicronautHttpValidation.class) && generatorContext.getBuildTool().isGradle()) { - generatorContext.addDependency(DEPENDENCY_MICRONAUT_HTTP_CLIENT_COMPILE_ONLY); + generatorContext.addDependency(generatorContext.getFeatures().hasFeature(AwsLambda.class) + ? DEPENDENCY_MICRONAUT_HTTP_CLIENT_JDK_COMPILE_ONLY + : DEPENDENCY_MICRONAUT_HTTP_CLIENT_COMPILE_ONLY); } } } @@ -85,7 +100,7 @@ public void apply(GeneratorContext generatorContext) { private boolean hasHttpClientFeatureDependencyInScope(@NonNull GeneratorContext generatorContext, @NonNull Scope scope) { return generatorContext.hasDependencyInScope(MicronautDependencyUtils.GROUP_ID_MICRONAUT, ARTIFACT_ID_MICRONAUT_HTTP_CLIENT, scope) || - generatorContext.hasDependencyInScope(MicronautDependencyUtils.GROUP_ID_MICRONAUT, HttpClientJdk.ARTIFACT_ID_MICRONAUT_HTTP_CLIENT_JDK, scope); + generatorContext.hasDependencyInScope(MicronautDependencyUtils.GROUP_ID_MICRONAUT, ARTIFACT_ID_MICRONAUT_HTTP_CLIENT_JDK, scope); } @Override diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/other/OpenApiAdoc.java b/starter-core/src/main/java/io/micronaut/starter/feature/other/OpenApiAdoc.java index 2672c3b6b69..30bc6bcb493 100644 --- a/starter-core/src/main/java/io/micronaut/starter/feature/other/OpenApiAdoc.java +++ b/starter-core/src/main/java/io/micronaut/starter/feature/other/OpenApiAdoc.java @@ -49,12 +49,12 @@ public String getName() { @Override public String getTitle() { - return "OpenAPI Conversion to Asciidoc"; + return "OpenAPI Conversion to AsciiDoc"; } @Override public String getDescription() { - return "Adds and enables document conversion to asciidoc"; + return "Adds and enables document conversion to AsciiDoc"; } @Override diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/other/OpenApiExplorer.java b/starter-core/src/main/java/io/micronaut/starter/feature/other/OpenApiExplorer.java new file mode 100644 index 00000000000..e8e37ea856b --- /dev/null +++ b/starter-core/src/main/java/io/micronaut/starter/feature/other/OpenApiExplorer.java @@ -0,0 +1,74 @@ +/* + * Copyright 2017-2024 original authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.micronaut.starter.feature.other; + +import java.util.ArrayList; +import java.util.List; + +import io.micronaut.starter.feature.InterceptUrlMap; +import io.micronaut.starter.feature.staticResources.ContributingStaticResources; +import io.micronaut.starter.feature.staticResources.StaticResource; + +import jakarta.inject.Singleton; + +@Singleton +public class OpenApiExplorer extends OpenApiView implements ContributingStaticResources { + + public static final String NAME = "openapi-explorer"; + + public OpenApiExplorer(OpenApi openApiFeature) { + super(openApiFeature); + } + + @Override + public String getName() { + return NAME; + } + + @Override + public String getTitle() { + return "OpenAPI Explorer View"; + } + + @Override + public String getDescription() { + return "Adds and enables OpenAPI Explorer view for OpenAPI"; + } + + @Override + public String getThirdPartyDocumentation() { + return "https://github.com/Authress-Engineering/openapi-explorer"; + } + + @Override + public String getMicronautDocumentation() { + return "https://micronaut-projects.github.io/micronaut-openapi/latest/guide/#openapiExplorer"; + } + + @Override + public List staticResources() { + List result = new ArrayList<>(super.staticResources()); + result.add(new StaticResource("openapi-explorer", "/openapi-explorer/**", "classpath:META-INF/swagger/views/openapi-explorer")); + return result; + } + + @Override + public List interceptUrlMaps() { + List result = new ArrayList<>(super.interceptUrlMaps()); + result.add(InterceptUrlMap.anonymousAcccess("/openapi-explorer/**")); + return result; + } +} diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/other/OpenRewrite.java b/starter-core/src/main/java/io/micronaut/starter/feature/other/OpenRewrite.java index c7b29043e20..b1297f5fd68 100644 --- a/starter-core/src/main/java/io/micronaut/starter/feature/other/OpenRewrite.java +++ b/starter-core/src/main/java/io/micronaut/starter/feature/other/OpenRewrite.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2021 original authors + * Copyright 2017-2023 original authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -59,7 +59,7 @@ public String getTitle() { @Override @NonNull public String getDescription() { - return "Adds OpenRewrite plugin and Micronaut upgrade recipe"; + return "Adds OpenRewrite plugin and Micronaut3to4Migration migration recipe"; } @Override @@ -74,6 +74,7 @@ public void apply(GeneratorContext generatorContext) { private void addGradlePlugin(GeneratorContext generatorContext) { generatorContext.addHelpLink("Rewrite Gradle Plugin", "https://plugins.gradle.org/plugin/org.openrewrite.rewrite"); + generatorContext.addHelpLink("Rewrite Micronaut3to4Migration Recipe", "https://docs.openrewrite.org/running-recipes/popular-recipe-guides/migrate-to-micronaut-4-from-micronaut-3"); generatorContext.addBuildPlugin(GradlePlugin.builder() .id("org.openrewrite.rewrite") .lookupArtifactId("plugin") @@ -87,6 +88,7 @@ private void addGradlePlugin(GeneratorContext generatorContext) { } private void addMavenPlugin(GeneratorContext generatorContext) { + generatorContext.addHelpLink("Rewrite Micronaut3to4Migration Recipe", "https://docs.openrewrite.org/running-recipes/popular-recipe-guides/migrate-to-micronaut-4-from-micronaut-3"); String mavenPluginArtifactId = "rewrite-maven-plugin"; generatorContext.addBuildPlugin(MavenPlugin.builder() .artifactId(mavenPluginArtifactId) diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/other/RapiDoc.java b/starter-core/src/main/java/io/micronaut/starter/feature/other/RapiDoc.java index 842f078e54c..2e1c48a2909 100644 --- a/starter-core/src/main/java/io/micronaut/starter/feature/other/RapiDoc.java +++ b/starter-core/src/main/java/io/micronaut/starter/feature/other/RapiDoc.java @@ -43,7 +43,7 @@ public String getTitle() { @Override public String getDescription() { - return "Adds and enables RapiDoc view for OpenApi"; + return "Adds and enables RapiDoc view for OpenAPI"; } @Override diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/other/Redoc.java b/starter-core/src/main/java/io/micronaut/starter/feature/other/Redoc.java index b66e268b5fa..bfb27a3626d 100644 --- a/starter-core/src/main/java/io/micronaut/starter/feature/other/Redoc.java +++ b/starter-core/src/main/java/io/micronaut/starter/feature/other/Redoc.java @@ -43,7 +43,7 @@ public String getTitle() { @Override public String getDescription() { - return "Adds and enables Redoc view for OpenApi"; + return "Adds and enables Redoc view for OpenAPI"; } @Override diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/other/template/openApiProperties.rocker.raw b/starter-core/src/main/java/io/micronaut/starter/feature/other/template/openApiProperties.rocker.raw index c238fc2ab77..06b97be989e 100644 --- a/starter-core/src/main/java/io/micronaut/starter/feature/other/template/openApiProperties.rocker.raw +++ b/starter-core/src/main/java/io/micronaut/starter/feature/other/template/openApiProperties.rocker.raw @@ -4,6 +4,7 @@ Feature feature ) swagger-ui.enabled=@feature.getName().equals("swagger-ui") redoc.enabled=@feature.getName().equals("redoc") +openapi-explorer.enabled=@feature.getName().equals("openapi-explorer") rapidoc.enabled=@feature.getName().equals("rapidoc") rapidoc.bg-color=#14191f rapidoc.text-color=#aec2e0 diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/other/template/openrewriteGradlePlugin.rocker.raw b/starter-core/src/main/java/io/micronaut/starter/feature/other/template/openrewriteGradlePlugin.rocker.raw index d8ba1f8f762..d910d58d0d1 100644 --- a/starter-core/src/main/java/io/micronaut/starter/feature/other/template/openrewriteGradlePlugin.rocker.raw +++ b/starter-core/src/main/java/io/micronaut/starter/feature/other/template/openrewriteGradlePlugin.rocker.raw @@ -1,3 +1,3 @@ rewrite { - activeRecipe("org.openrewrite.java.micronaut.Micronaut2to3Migration") + activeRecipe("org.openrewrite.java.micronaut.Micronaut3to4Migration") } diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/other/template/openrewriteMavenPlugin.rocker.raw b/starter-core/src/main/java/io/micronaut/starter/feature/other/template/openrewriteMavenPlugin.rocker.raw index 238fb6c0643..5b4453590d6 100644 --- a/starter-core/src/main/java/io/micronaut/starter/feature/other/template/openrewriteMavenPlugin.rocker.raw +++ b/starter-core/src/main/java/io/micronaut/starter/feature/other/template/openrewriteMavenPlugin.rocker.raw @@ -1,10 +1,11 @@ +@import io.micronaut.starter.util.VersionInfo org.openrewrite.maven rewrite-maven-plugin ${openrewrite.maven.plugin.version} - org.openrewrite.java.micronaut.Micronaut2to3Migration + org.openrewrite.java.micronaut.Micronaut3to4Migration diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/picocli/lang/kotlin/PicocliKotlinApplication.java b/starter-core/src/main/java/io/micronaut/starter/feature/picocli/lang/kotlin/PicocliKotlinApplication.java index 273e70ec7e6..9f5bbf74898 100644 --- a/starter-core/src/main/java/io/micronaut/starter/feature/picocli/lang/kotlin/PicocliKotlinApplication.java +++ b/starter-core/src/main/java/io/micronaut/starter/feature/picocli/lang/kotlin/PicocliKotlinApplication.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2022 original authors + * Copyright 2017-2024 original authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,13 +19,13 @@ import io.micronaut.starter.application.ApplicationType; import io.micronaut.starter.application.Project; import io.micronaut.starter.application.generator.GeneratorContext; +import io.micronaut.starter.feature.RequireKaptFeature; import io.micronaut.starter.feature.lang.kotlin.KotlinApplicationFeature; import io.micronaut.starter.template.RockerTemplate; - import jakarta.inject.Singleton; @Singleton -public class PicocliKotlinApplication implements KotlinApplicationFeature { +public class PicocliKotlinApplication implements RequireKaptFeature, KotlinApplicationFeature { @Override @Nullable diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/sourcegen/SourcegenFeatureValidator.java b/starter-core/src/main/java/io/micronaut/starter/feature/sourcegen/SourcegenFeatureValidator.java new file mode 100644 index 00000000000..5ae4c8e6383 --- /dev/null +++ b/starter-core/src/main/java/io/micronaut/starter/feature/sourcegen/SourcegenFeatureValidator.java @@ -0,0 +1,56 @@ +/* + * Copyright 2017-2024 original authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.micronaut.starter.feature.sourcegen; + +import io.micronaut.core.util.StringUtils; +import io.micronaut.starter.application.ApplicationType; +import io.micronaut.starter.feature.Feature; +import io.micronaut.starter.feature.validation.FeatureValidator; +import io.micronaut.starter.options.Language; +import io.micronaut.starter.options.Options; +import jakarta.inject.Singleton; + +import java.util.List; +import java.util.Set; +import java.util.stream.Stream; + +@Singleton +public class SourcegenFeatureValidator implements FeatureValidator { + + @Override + public void validatePreProcessing(Options options, ApplicationType applicationType, Set features) { + + } + + @Override + public void validatePostProcessing(Options options, ApplicationType applicationType, Set features) { + if (features.stream().anyMatch(f -> f instanceof SourcegenJava)) { + if (!supports(options.getLanguage())) { + throw new IllegalArgumentException("sourcegen-generator is not supported in " + StringUtils.capitalize(options.getLanguage().getName()) + " applications"); + } + } + } + + public static List supportedLanguages() { + return Stream.of(Language.values()) + .filter(SourcegenFeatureValidator::supports) + .toList(); + } + + public static boolean supports(Language language) { + return language != Language.GROOVY; + } +} diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/sourcegen/SourcegenJava.java b/starter-core/src/main/java/io/micronaut/starter/feature/sourcegen/SourcegenJava.java new file mode 100644 index 00000000000..f99f1d12351 --- /dev/null +++ b/starter-core/src/main/java/io/micronaut/starter/feature/sourcegen/SourcegenJava.java @@ -0,0 +1,93 @@ +/* + * Copyright 2017-2024 original authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.micronaut.starter.feature.sourcegen; + +import io.micronaut.core.annotation.NonNull; +import io.micronaut.starter.application.ApplicationType; +import io.micronaut.starter.application.generator.GeneratorContext; +import io.micronaut.starter.build.dependencies.Dependency; +import io.micronaut.starter.build.dependencies.MicronautDependencyUtils; +import io.micronaut.starter.build.dependencies.Scope; +import io.micronaut.starter.feature.Category; +import io.micronaut.starter.feature.Feature; +import io.micronaut.starter.options.Language; +import jakarta.inject.Singleton; + +@Singleton +public class SourcegenJava implements Feature { + + public static final String NAME = "sourcegen-generator"; + + private static final Dependency DEPENDENCY_MICRONAUT_SOURCEGEN_ANNOTATIONS = MicronautDependencyUtils.sourcegenDependency() + .artifactId("micronaut-sourcegen-annotations") + .scope(Scope.COMPILE) + .build(); + + private static final Dependency DEPENDENCY_MICRONAUT_SOURCEGEN_GENERATOR_JAVA = MicronautDependencyUtils.sourcegenDependency() + .artifactId("micronaut-sourcegen-generator-java") + .scope(Scope.ANNOTATION_PROCESSOR) + .build(); + + private static final Dependency DEPENDENCY_MICRONAUT_SOURCEGEN_GENERATOR_KOTLIN = MicronautDependencyUtils.sourcegenDependency() + .artifactId("micronaut-sourcegen-generator-kotlin") + .scope(Scope.ANNOTATION_PROCESSOR) + .build(); + + @Override + @NonNull + public String getName() { + return NAME; + } + + @Override + public String getTitle() { + return "Micronaut source code generator for Java and Kotlin"; + } + + @Override + public String getDescription() { + return "Micronaut SourceGen exposes a language-neutral API for source code generation"; + } + + @Override + public String getCategory() { + return Category.API; + } + + @Override + public String getMicronautDocumentation() { + return "https://micronaut-projects.github.io/micronaut-sourcegen/latest/guide/"; + } + + @Override + public boolean supports(ApplicationType applicationType) { + return true; + } + + @Override + public void apply(GeneratorContext generatorContext) { + addDependencies(generatorContext); + } + + private void addDependencies(GeneratorContext generatorContext) { + generatorContext.addDependency(DEPENDENCY_MICRONAUT_SOURCEGEN_ANNOTATIONS); + if (generatorContext.getLanguage() == Language.JAVA) { + generatorContext.addDependency(DEPENDENCY_MICRONAUT_SOURCEGEN_GENERATOR_JAVA); + } else if (generatorContext.getLanguage() == Language.KOTLIN) { + generatorContext.addDependency(DEPENDENCY_MICRONAUT_SOURCEGEN_GENERATOR_KOTLIN); + } + } +} diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/test/JunitCompanionFeatureValidator.java b/starter-core/src/main/java/io/micronaut/starter/feature/test/JunitCompanionFeatureValidator.java index 9941de96153..73e24ee1e0c 100644 --- a/starter-core/src/main/java/io/micronaut/starter/feature/test/JunitCompanionFeatureValidator.java +++ b/starter-core/src/main/java/io/micronaut/starter/feature/test/JunitCompanionFeatureValidator.java @@ -32,10 +32,18 @@ */ @Singleton public class JunitCompanionFeatureValidator implements FeatureValidator { + @Override public void validatePreProcessing(Options options, ApplicationType applicationType, Set features) { + + } + + @Override + public void validatePostProcessing(Options options, + ApplicationType applicationType, + Set features) { if (options.getTestFramework() != TestFramework.JUNIT) { features.stream() .filter(JunitCompanionFeature.class::isInstance) @@ -45,11 +53,4 @@ public void validatePreProcessing(Options options, }); } } - - @Override - public void validatePostProcessing(Options options, - ApplicationType applicationType, - Set features) { - - } } diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/test/LocalStack.java b/starter-core/src/main/java/io/micronaut/starter/feature/test/LocalStack.java index a406c2deb9a..97ed9dbaf7d 100644 --- a/starter-core/src/main/java/io/micronaut/starter/feature/test/LocalStack.java +++ b/starter-core/src/main/java/io/micronaut/starter/feature/test/LocalStack.java @@ -24,10 +24,9 @@ import io.micronaut.starter.feature.FeatureContext; import io.micronaut.starter.feature.database.TestContainers; import io.micronaut.starter.feature.messaging.jms.SQS; +import io.micronaut.starter.feature.testcontainers.ContributingTestContainerArtifactId; import jakarta.inject.Singleton; -import static io.micronaut.starter.feature.database.TestContainers.TESTCONTAINERS_GROUP_ID; - /** * Adds support for LocalStack. * @@ -35,8 +34,9 @@ * @since 3.7.1 */ @Singleton -public class LocalStack implements Feature { +public class LocalStack implements Feature, ContributingTestContainerArtifactId { + public static final String ARTIFACT_ID_LOCALSTACK = "localstack"; private final TestContainers testContainers; public LocalStack(TestContainers testContainers) { @@ -84,10 +84,6 @@ public void processSelectedFeatures(FeatureContext featureContext) { @Override public void apply(GeneratorContext generatorContext) { - generatorContext.addDependency(Dependency.builder() - .groupId(TESTCONTAINERS_GROUP_ID) - .artifactId("localstack") - .test()); // SQS pulls this in transitively so this is not required if (!generatorContext.isFeaturePresent(SQS.class)) { generatorContext.addDependency(Dependency.builder() @@ -96,4 +92,9 @@ public void apply(GeneratorContext generatorContext) { .test()); } } + + @Override + public String testContainersArtifactId() { + return ARTIFACT_ID_LOCALSTACK; + } } diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/test/MockServerClient.java b/starter-core/src/main/java/io/micronaut/starter/feature/test/MockServerClient.java index 1e2a5cc1587..5ee3ba7feb0 100644 --- a/starter-core/src/main/java/io/micronaut/starter/feature/test/MockServerClient.java +++ b/starter-core/src/main/java/io/micronaut/starter/feature/test/MockServerClient.java @@ -22,10 +22,11 @@ import io.micronaut.starter.build.dependencies.Dependency; import io.micronaut.starter.feature.Category; import io.micronaut.starter.feature.Feature; +import io.micronaut.starter.feature.testcontainers.ContributingTestContainerArtifactId; import jakarta.inject.Singleton; @Singleton -public class MockServerClient implements Feature { +public class MockServerClient implements Feature, ContributingTestContainerArtifactId { public static final String NAME = "mockserver-client-java"; public static final String ARTIFACT_ID_MOCKSERVER_CLIENT_JAVA = "mockserver-client-java"; @@ -34,6 +35,7 @@ public class MockServerClient implements Feature { .lookupArtifactId(ARTIFACT_ID_MOCKSERVER_CLIENT_JAVA) .test() .build(); + public static final String TEST_CONTAINERS_ARTIFACT_ID_MOCKSERVER = "mockserver"; @Override @NonNull @@ -75,4 +77,9 @@ public void apply(GeneratorContext generatorContext) { protected void addDependencies(GeneratorContext generatorContext) { generatorContext.addDependency(DEPENDENCY_MOCKSERVER_CLIENT_JAVA); } + + @Override + public String testContainersArtifactId() { + return TEST_CONTAINERS_ARTIFACT_ID_MOCKSERVER; + } } diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/testcontainers/ContributingTestContainerArtifactId.java b/starter-core/src/main/java/io/micronaut/starter/feature/testcontainers/ContributingTestContainerArtifactId.java new file mode 100644 index 00000000000..6df66918c02 --- /dev/null +++ b/starter-core/src/main/java/io/micronaut/starter/feature/testcontainers/ContributingTestContainerArtifactId.java @@ -0,0 +1,35 @@ +/* + * Copyright 2017-2024 original authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.micronaut.starter.feature.testcontainers; + +import io.micronaut.starter.build.dependencies.Dependency; +import java.util.Collections; +import java.util.List; + +/** + * API to flag a feature as contributing a Test Container Dependency. + * By implementing this instead of {@link ContributingTestContainerDependency} they only have to provide the artifactId. + * @author Sergio del Amo + * @since 4.4.0 + */ +public interface ContributingTestContainerArtifactId extends ContributingTestContainerDependency { + String testContainersArtifactId(); + + @Override + default List testContainersDependencies() { + return Collections.singletonList(ContributingTestContainerDependency.testContainerDependency(testContainersArtifactId())); + } +} diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/testcontainers/ContributingTestContainerDependency.java b/starter-core/src/main/java/io/micronaut/starter/feature/testcontainers/ContributingTestContainerDependency.java new file mode 100644 index 00000000000..ba6aa30821d --- /dev/null +++ b/starter-core/src/main/java/io/micronaut/starter/feature/testcontainers/ContributingTestContainerDependency.java @@ -0,0 +1,36 @@ +/* + * Copyright 2017-2024 original authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.micronaut.starter.feature.testcontainers; + +import io.micronaut.core.annotation.NonNull; +import io.micronaut.starter.build.dependencies.Dependency; + +import java.util.List; + +public interface ContributingTestContainerDependency { + String TESTCONTAINERS_GROUP_ID = "org.testcontainers"; + + List testContainersDependencies(); + + @NonNull + static Dependency testContainerDependency(@NonNull String artifactId) { + return Dependency.builder() + .groupId(TESTCONTAINERS_GROUP_ID) + .artifactId(artifactId) + .test() + .build(); + } +} diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/testresources/DbType.java b/starter-core/src/main/java/io/micronaut/starter/feature/testresources/DbType.java index 85b263a9d00..b3cdbc836e4 100644 --- a/starter-core/src/main/java/io/micronaut/starter/feature/testresources/DbType.java +++ b/starter-core/src/main/java/io/micronaut/starter/feature/testresources/DbType.java @@ -24,7 +24,12 @@ public enum DbType { MYSQL("mysql", KnownModules.JDBC_MYSQL, KnownModules.R2DBC_MYSQL, KnownModules.HIBERNATE_REACTIVE_MYSQL), POSTGRESQL("postgres", KnownModules.JDBC_POSTGRESQL, KnownModules.R2DBC_POSTGRESQL, KnownModules.HIBERNATE_REACTIVE_POSTGRESQL), SQLSERVER("mssql", KnownModules.JDBC_MSSQL, KnownModules.R2DBC_MSSQL, KnownModules.HIBERNATE_REACTIVE_MSSQL), - ORACLEXE("oracle", KnownModules.JDBC_ORACLE_XE, KnownModules.R2DBC_ORACLE_XE, KnownModules.HIBERNATE_REACTIVE_ORACLE_XE); + /** + * @deprecated Use {@link #ORACLEFREE} instead. + */ + @Deprecated(forRemoval = true, since = "4.4.0") + ORACLEXE("oracle-xe", KnownModules.JDBC_ORACLE_XE, KnownModules.R2DBC_ORACLE_XE, KnownModules.HIBERNATE_REACTIVE_ORACLE_XE), + ORACLEFREE("oracle", KnownModules.JDBC_ORACLE_FREE, KnownModules.R2DBC_ORACLE_FREE, KnownModules.HIBERNATE_REACTIVE_ORACLE_FREE); private final String name; private final String jdbcTestResourcesModuleName; diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/testresources/TestResourcesAdditionalModulesProvider.java b/starter-core/src/main/java/io/micronaut/starter/feature/testresources/TestResourcesAdditionalModulesProvider.java new file mode 100644 index 00000000000..e1c8c1cbfa8 --- /dev/null +++ b/starter-core/src/main/java/io/micronaut/starter/feature/testresources/TestResourcesAdditionalModulesProvider.java @@ -0,0 +1,31 @@ +/* + * Copyright 2017-2024 original authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.micronaut.starter.feature.testresources; + +import io.micronaut.core.annotation.NonNull; +import io.micronaut.starter.application.generator.GeneratorContext; +import io.micronaut.starter.build.dependencies.MavenCoordinate; + +import java.util.List; + +public interface TestResourcesAdditionalModulesProvider { + + @NonNull + List getTestResourcesAdditionalModules(@NonNull GeneratorContext generatorContext); + + @NonNull + List getTestResourcesDependencies(@NonNull GeneratorContext generatorContext); +} diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/view/JTE.java b/starter-core/src/main/java/io/micronaut/starter/feature/view/JTE.java index b7ec3659a4f..785a981e3a3 100644 --- a/starter-core/src/main/java/io/micronaut/starter/feature/view/JTE.java +++ b/starter-core/src/main/java/io/micronaut/starter/feature/view/JTE.java @@ -89,7 +89,7 @@ private BuildPlugin gradlePlugin(GeneratorContext generatorContext) { GradlePlugin.Builder builder = GradlePlugin.builder() .id("gg.jte.gradle") - .extension(new RockerWritable(gradlePluginJTE.template(patchKapt, gradleDsl.orElse(GradleDsl.KOTLIN), JTE_SRC_DIR))) + .extension(new RockerWritable(gradlePluginJTE.template(patchKapt, JTE_SRC_DIR))) .lookupArtifactId("jte-gradle-plugin"); return builder.build(); } diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/view/ViewsFieldset.java b/starter-core/src/main/java/io/micronaut/starter/feature/view/ViewsFieldset.java index 91c367e6e28..6309306cbf2 100644 --- a/starter-core/src/main/java/io/micronaut/starter/feature/view/ViewsFieldset.java +++ b/starter-core/src/main/java/io/micronaut/starter/feature/view/ViewsFieldset.java @@ -43,6 +43,7 @@ public class ViewsFieldset implements Feature { private static final String INPUTDATE_HTML = "inputdate.html"; private static final String INPUTDATETIMELOCAL_HTML = "inputdatetimelocal.html"; private static final String INPUTEMAIL_HTML = "inputemail.html"; + private static final String INPUTFILE_HTML = "inputfile.html"; private static final String INPUTHIDDEN_HTML = "inputhidden.html"; private static final String INPUTNUMBER_HTML = "inputnumber.html"; private static final String INPUTPASSWORD_HTML = "inputpassword.html"; @@ -68,6 +69,7 @@ public class ViewsFieldset implements Feature { INPUTDATE_HTML, INPUTDATETIMELOCAL_HTML, INPUTEMAIL_HTML, + INPUTFILE_HTML, INPUTHIDDEN_HTML, INPUTNUMBER_HTML, INPUTPASSWORD_HTML, diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/view/ViewsFieldsetTck.java b/starter-core/src/main/java/io/micronaut/starter/feature/view/ViewsFieldsetTck.java index 32f27ab3ada..53db8fcac8a 100644 --- a/starter-core/src/main/java/io/micronaut/starter/feature/view/ViewsFieldsetTck.java +++ b/starter-core/src/main/java/io/micronaut/starter/feature/view/ViewsFieldsetTck.java @@ -20,10 +20,10 @@ import io.micronaut.starter.application.generator.GeneratorContext; import io.micronaut.starter.build.dependencies.Dependency; import io.micronaut.starter.build.dependencies.MicronautDependencyUtils; -import io.micronaut.starter.build.dependencies.Scope; import io.micronaut.starter.feature.Category; import io.micronaut.starter.feature.Feature; import io.micronaut.starter.feature.FeatureContext; +import io.micronaut.starter.feature.test.Junit; import io.micronaut.starter.feature.test.JunitPlatformSuiteEngine; import io.micronaut.starter.options.Language; import io.micronaut.starter.template.RockerTemplate; @@ -47,7 +47,9 @@ public ViewsFieldsetTck(JunitPlatformSuiteEngine junitPlatformSuiteEngine) { @Override public void processSelectedFeatures(FeatureContext featureContext) { - featureContext.addFeatureIfNotPresent(JunitPlatformSuiteEngine.class, junitPlatformSuiteEngine); + if (featureContext.isPresent(Junit.class)) { + featureContext.addFeatureIfNotPresent(JunitPlatformSuiteEngine.class, junitPlatformSuiteEngine); + } } @Override @@ -99,7 +101,5 @@ private void addThymeleafSuite(GeneratorContext generatorContext) { private void addDependencies(GeneratorContext generatorContext) { generatorContext.addDependency(DEPENDENCY_VIEWS_FIELDSET_TCK); - //TODO Delete when this is merged https://github.com/micronaut-projects/micronaut-views/pull/656 - generatorContext.addDependency(Dependency.builder().groupId("io.micronaut.data").artifactId("micronaut-data-jdbc").scope(Scope.TEST)); } } diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/view/gradlePluginJTE.rocker.raw b/starter-core/src/main/java/io/micronaut/starter/feature/view/gradlePluginJTE.rocker.raw index 27ec4ac596d..bc8e644bd80 100644 --- a/starter-core/src/main/java/io/micronaut/starter/feature/view/gradlePluginJTE.rocker.raw +++ b/starter-core/src/main/java/io/micronaut/starter/feature/view/gradlePluginJTE.rocker.raw @@ -1,13 +1,7 @@ -@import io.micronaut.starter.build.gradle.GradleDsl -@args(boolean patchKaptOutputs, GradleDsl dsl, String path) +@args(boolean patchKaptOutputs, String path) jte { -@if(dsl == GradleDsl.KOTLIN) { - sourceDirectory.set(file("src/main/jte").toPath()) -} -@if(dsl == GradleDsl.GROOVY) { sourceDirectory = file("@path").toPath() -} generate() } diff --git a/starter-core/src/main/java/io/micronaut/starter/options/JdkVersion.java b/starter-core/src/main/java/io/micronaut/starter/options/JdkVersion.java index b4987b1b89f..94651b78120 100644 --- a/starter-core/src/main/java/io/micronaut/starter/options/JdkVersion.java +++ b/starter-core/src/main/java/io/micronaut/starter/options/JdkVersion.java @@ -15,8 +15,14 @@ */ package io.micronaut.starter.options; -import java.util.Arrays; -import java.util.List; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; +import io.micronaut.core.annotation.NonNull; +import io.micronaut.core.util.StringUtils; +import io.micronaut.serde.annotation.Serdeable; + +import java.util.Map; +import java.util.TreeMap; /** * JDK versions. @@ -24,43 +30,96 @@ * @author graemerocher * @since 1.0.0 */ -public enum JdkVersion { - JDK_8(8), - JDK_9(9), - JDK_10(10), - JDK_11(11), - JDK_12(12), - JDK_13(13), - JDK_14(14), - JDK_15(15), - JDK_16(16), - JDK_17(17), - JDK_18(18), - JDK_19(19), - JDK_20(20), - JDK_21(21); - - private static final List SUPPORTED_JDKS = Arrays.stream(JdkVersion.values()).map(JdkVersion::majorVersion).toList(); - - private final int majorVersion; - - JdkVersion(int majorVersion) { +@Serdeable +public final class JdkVersion { + + private static final Map INSTANCES = new TreeMap<>(); + + public static final JdkVersion JDK_8 = new JdkVersion(8); + public static final JdkVersion JDK_9 = new JdkVersion(9); + public static final JdkVersion JDK_10 = new JdkVersion(10); + public static final JdkVersion JDK_11 = new JdkVersion(11); + public static final JdkVersion JDK_12 = new JdkVersion(12); + public static final JdkVersion JDK_13 = new JdkVersion(13); + public static final JdkVersion JDK_14 = new JdkVersion(14); + public static final JdkVersion JDK_15 = new JdkVersion(15); + public static final JdkVersion JDK_16 = new JdkVersion(16); + public static final JdkVersion JDK_17 = new JdkVersion(17); + public static final JdkVersion JDK_18 = new JdkVersion(18); + public static final JdkVersion JDK_19 = new JdkVersion(19); + public static final JdkVersion JDK_20 = new JdkVersion(20); + public static final JdkVersion JDK_21 = new JdkVersion(21); + private static final String PREFIX_JDK = "JDK_"; + + int majorVersion; + + public JdkVersion(int majorVersion) { this.majorVersion = majorVersion; + INSTANCES.put(majorVersion, this); + } + + /** + * @return the name + */ + @JsonValue + public String name() { + return PREFIX_JDK + majorVersion; + } + + @Override + public String toString() { + return name(); + } + + @Override + public boolean equals(Object o) { + return o instanceof JdkVersion other && other.majorVersion == majorVersion; + } + + @Override + public int hashCode() { + return majorVersion; + } + + @JsonCreator + public static JdkVersion valueOf(String jdkVersion) { + if (StringUtils.isEmpty(jdkVersion)) { + throw new IllegalArgumentException("cannot parse JdkVersion from " + jdkVersion); + } + if (!jdkVersion.startsWith(PREFIX_JDK)) { + throw new IllegalArgumentException("cannot parse JdkVersion from " + jdkVersion); + } + String version = jdkVersion.substring(PREFIX_JDK.length()); + try { + int majorVersion = Integer.parseInt(version); + return valueOf(majorVersion); + } catch (NumberFormatException e) { + throw new IllegalArgumentException("cannot parse JDK major version of " + version); + } } public static JdkVersion valueOf(int majorVersion) { - return Arrays - .stream(JdkVersion.values()) + return INSTANCES.values().stream() .filter(jdkVersion -> jdkVersion.majorVersion == majorVersion) .findFirst() - .orElseThrow(() -> new IllegalArgumentException("Unsupported JDK version: " + majorVersion + ". Supported values are " + SUPPORTED_JDKS)); + .orElseThrow(() -> new IllegalArgumentException( + "Unsupported JDK version: " + majorVersion + ". Supported values are " + INSTANCES.keySet())); } public int majorVersion() { return majorVersion; } - public boolean greaterThanEqual(JdkVersion jdk) { + // for serialization + int getMajorVersion() { + return majorVersion; + } + + public boolean greaterThanEqual(@NonNull JdkVersion jdk) { return majorVersion >= jdk.majorVersion; } + + public String asString() { + return "" + majorVersion; + } } diff --git a/starter-core/src/main/java/io/micronaut/starter/options/MicronautJdkVersionConfiguration.java b/starter-core/src/main/java/io/micronaut/starter/options/MicronautJdkVersionConfiguration.java index 72fdc4d9361..f8bb1597b13 100644 --- a/starter-core/src/main/java/io/micronaut/starter/options/MicronautJdkVersionConfiguration.java +++ b/starter-core/src/main/java/io/micronaut/starter/options/MicronautJdkVersionConfiguration.java @@ -26,7 +26,7 @@ public class MicronautJdkVersionConfiguration implements JdkVersionConfiguration public static final List SUPPORTED_JDKS = List.of(JDK_17, JDK_21); - public static final JdkVersion DEFAULT_OPTION = JDK_17; + public static final JdkVersion DEFAULT_OPTION = JDK_21; @Override public List getSupportedJdkVersions() { diff --git a/starter-core/src/main/java/io/micronaut/starter/template/RockerTemplate.java b/starter-core/src/main/java/io/micronaut/starter/template/RockerTemplate.java index b7376f88075..227848205a3 100644 --- a/starter-core/src/main/java/io/micronaut/starter/template/RockerTemplate.java +++ b/starter-core/src/main/java/io/micronaut/starter/template/RockerTemplate.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2022 original authors + * Copyright 2017-2024 original authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,6 +16,7 @@ package io.micronaut.starter.template; import com.fizzed.rocker.RockerModel; +import com.fizzed.rocker.RockerOutput; import java.io.OutputStream; @@ -60,4 +61,8 @@ public boolean isExecutable() { public RockerWritable getWritable() { return writable; } + + public RockerOutput renderModel() { + return writable.getModel().render(); + } } diff --git a/starter-core/src/main/resources/gradle/gradlew.bat b/starter-core/src/main/resources/gradle/gradlew.bat index 6689b85beec..7101f8e4676 100644 --- a/starter-core/src/main/resources/gradle/gradlew.bat +++ b/starter-core/src/main/resources/gradle/gradlew.bat @@ -43,11 +43,11 @@ set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 if %ERRORLEVEL% equ 0 goto execute -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail @@ -57,11 +57,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe if exist "%JAVA_EXE%" goto execute -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail diff --git a/starter-core/src/main/resources/gradle/wrapper/gradle-wrapper.jar b/starter-core/src/main/resources/gradle/wrapper/gradle-wrapper.jar index 7f93135c49b..e6441136f3d 100644 Binary files a/starter-core/src/main/resources/gradle/wrapper/gradle-wrapper.jar and b/starter-core/src/main/resources/gradle/wrapper/gradle-wrapper.jar differ diff --git a/starter-core/src/main/resources/gradle/wrapper/gradle-wrapper.properties b/starter-core/src/main/resources/gradle/wrapper/gradle-wrapper.properties index 3fa8f862f75..b82aa23a4f0 100644 --- a/starter-core/src/main/resources/gradle/wrapper/gradle-wrapper.properties +++ b/starter-core/src/main/resources/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/starter-core/src/main/resources/views/thymeleaf/fieldset/fieldset.html b/starter-core/src/main/resources/views/thymeleaf/fieldset/fieldset.html index 8dc3dd2343e..5eb8e64f077 100644 --- a/starter-core/src/main/resources/views/thymeleaf/fieldset/fieldset.html +++ b/starter-core/src/main/resources/views/thymeleaf/fieldset/fieldset.html @@ -1 +1 @@ -

\ No newline at end of file +
\ No newline at end of file diff --git a/starter-core/src/main/resources/views/thymeleaf/fieldset/form.html b/starter-core/src/main/resources/views/thymeleaf/fieldset/form.html index 80f00922dd5..58be4785a9b 100644 --- a/starter-core/src/main/resources/views/thymeleaf/fieldset/form.html +++ b/starter-core/src/main/resources/views/thymeleaf/fieldset/form.html @@ -1 +1 @@ -
\ No newline at end of file +
\ No newline at end of file diff --git a/starter-core/src/main/resources/views/thymeleaf/fieldset/inputcheckbox.html b/starter-core/src/main/resources/views/thymeleaf/fieldset/inputcheckbox.html index 155380c7fea..644c59651c0 100644 --- a/starter-core/src/main/resources/views/thymeleaf/fieldset/inputcheckbox.html +++ b/starter-core/src/main/resources/views/thymeleaf/fieldset/inputcheckbox.html @@ -1 +1 @@ -
\ No newline at end of file +
diff --git a/starter-core/src/main/resources/views/thymeleaf/fieldset/inputfile.html b/starter-core/src/main/resources/views/thymeleaf/fieldset/inputfile.html new file mode 100644 index 00000000000..78064a75b1d --- /dev/null +++ b/starter-core/src/main/resources/views/thymeleaf/fieldset/inputfile.html @@ -0,0 +1 @@ +
\ No newline at end of file diff --git a/starter-core/src/main/resources/views/thymeleaf/fieldset/inputradio.html b/starter-core/src/main/resources/views/thymeleaf/fieldset/inputradio.html index 0f78abc6a7a..6d411550cea 100644 --- a/starter-core/src/main/resources/views/thymeleaf/fieldset/inputradio.html +++ b/starter-core/src/main/resources/views/thymeleaf/fieldset/inputradio.html @@ -1 +1 @@ - \ No newline at end of file + diff --git a/starter-core/src/test/groovy/io/micronaut/starter/build/BuildTestUtil.groovy b/starter-core/src/test/groovy/io/micronaut/starter/build/BuildTestUtil.groovy index 9b52c8a8ad3..1778fcdac0b 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/build/BuildTestUtil.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/build/BuildTestUtil.groovy @@ -14,7 +14,7 @@ class BuildTestUtil { Language language, TestFramework testFramework, String template) { - buildTool.isGradle() ? new GradleBuildTestVerifier(template, language, testFramework) : new MavenBuildTestVerifier(template, language) + buildTool.isGradle() ? new GradleBuildTestVerifier(buildTool, template, language, testFramework) : new MavenBuildTestVerifier(template, language) } static BuildTestVerifier verifier(BuildTool buildTool, diff --git a/starter-core/src/test/groovy/io/micronaut/starter/build/BuildTestVerifier.groovy b/starter-core/src/test/groovy/io/micronaut/starter/build/BuildTestVerifier.groovy index 3fe4b0d1302..6c1b549ab43 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/build/BuildTestVerifier.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/build/BuildTestVerifier.groovy @@ -26,6 +26,10 @@ interface BuildTestVerifier { boolean hasDependency(String groupId, String artifactId) + boolean hasExclusion(String groupId, String artifactId, String excludedGroupId, String excludedArtifactId) + + boolean hasExclusion(String groupId, String artifactId, String excludedGroupId, String excludedArtifactId, Scope scope) + boolean hasTestResourceDependency(String groupId, String artifactId) boolean hasTestResourceDependency(String artifactId) diff --git a/starter-core/src/test/groovy/io/micronaut/starter/build/dependencies/GradleDependencyComparatorSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/build/dependencies/GradleDependencyComparatorSpec.groovy index 928f8b6501e..a5e0a091a82 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/build/dependencies/GradleDependencyComparatorSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/build/dependencies/GradleDependencyComparatorSpec.groovy @@ -24,7 +24,7 @@ class GradleDependencyComparatorSpec extends Specification { dep(Dependency.builder().groupId("io.micronaut.openapi").artifactId("micronaut-openapi").annotationProcessor(), ctx), dep(Dependency.builder().groupId("io.micronaut.sql").artifactId("micronaut-jdbc-hikari").compile(), ctx), dep(Dependency.builder().groupId("org.testcontainers").artifactId("testcontainers").test(), ctx), - dep(Dependency.builder().groupId("mysql").artifactId("mysql-connector-java").runtime(), ctx), + dep(Dependency.builder().groupId("com.mysql").artifactId("mysql-connector-j").runtime(), ctx), dep(Dependency.builder().groupId("org.testcontainers").artifactId("junit-jupiter").test(), ctx), dep(Dependency.builder().groupId("org.testcontainers").artifactId("mysql").test(), ctx), dep(Dependency.builder().groupId("ch.qos.logback").artifactId("logback-classic").runtime(), ctx) @@ -42,7 +42,7 @@ class GradleDependencyComparatorSpec extends Specification { "${str(dependencies[5])}" == 'implementation("io.swagger.core.v3:swagger-annotations")' "${str(dependencies[6])}" == 'implementation("jakarta.annotation:jakarta.annotation-api")' "${str(dependencies[7])}" == 'runtimeOnly("ch.qos.logback:logback-classic")' - "${str(dependencies[8])}" == 'runtimeOnly("mysql:mysql-connector-java")' + "${str(dependencies[8])}" == 'runtimeOnly("com.mysql:mysql-connector-j")' "${str(dependencies[9])}" == 'testImplementation("org.testcontainers:junit-jupiter")' "${str(dependencies[10])}" == 'testImplementation("org.testcontainers:mysql")' "${str(dependencies[11])}" == 'testImplementation("org.testcontainers:testcontainers")' diff --git a/starter-core/src/test/groovy/io/micronaut/starter/build/gradle/GradleBuildTestVerifier.groovy b/starter-core/src/test/groovy/io/micronaut/starter/build/gradle/GradleBuildTestVerifier.groovy index 472bf10aa40..a8f6b9de20a 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/build/gradle/GradleBuildTestVerifier.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/build/gradle/GradleBuildTestVerifier.groovy @@ -3,17 +3,21 @@ package io.micronaut.starter.build.gradle import io.micronaut.context.exceptions.ConfigurationException import io.micronaut.starter.build.BuildTestVerifier import io.micronaut.starter.build.dependencies.Scope +import io.micronaut.starter.options.BuildTool import io.micronaut.starter.options.Language import io.micronaut.starter.options.TestFramework import java.util.regex.Pattern class GradleBuildTestVerifier implements BuildTestVerifier { + + final BuildTool buildTool final String template final Language language final TestFramework testFramework - GradleBuildTestVerifier(String template, Language language, TestFramework testFramework) { + GradleBuildTestVerifier(BuildTool buildTool, String template, Language language, TestFramework testFramework) { + this.buildTool = buildTool this.template = template this.language = language this.testFramework = testFramework @@ -86,6 +90,27 @@ class GradleBuildTestVerifier implements BuildTestVerifier { }) } + @Override + boolean hasExclusion(String groupId, String artifactId, String excludedGroupId, String excludedArtifactId) { + hasExclusion(groupId, artifactId, excludedGroupId, excludedArtifactId, Scope.COMPILE) + } + + @Override + boolean hasExclusion(String groupId, String artifactId, String excludedGroupId, String excludedArtifactId, Scope scope) { + Optional gradleConfigurationNameOptional = GradleConfiguration.of(scope, language, testFramework, null).map { it.getConfigurationName() } + if (!gradleConfigurationNameOptional.isPresent()){ + throw new ConfigurationException("cannot match " + scope + " to gradle configuration"); + } + String gradleConfigurationName = gradleConfigurationNameOptional.get() + String pattern = /(?s).*${gradleConfigurationName}\("${groupId.replace(".", "\\.")}:${artifactId}"\)\s*\{(.+?)\}/ + println pattern + def match = template =~ pattern + String assignmentOp = (buildTool == BuildTool.GRADLE) ? ": " : " = " + return match.size() > 0 + ? match[0][1].contains("exclude(group${assignmentOp}\"${excludedGroupId}\", module${assignmentOp}\"${excludedArtifactId}\")") + : false + } + @Override boolean hasTestResourceDependency(String groupId, String artifactId) { hasDependency(groupId, artifactId, Scope.TEST_RESOURCES_SERVICE) diff --git a/starter-core/src/test/groovy/io/micronaut/starter/build/gradle/GradleBuildTestVerifierSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/build/gradle/GradleBuildTestVerifierSpec.groovy index 7e7ae28c710..0531e80b111 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/build/gradle/GradleBuildTestVerifierSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/build/gradle/GradleBuildTestVerifierSpec.groovy @@ -1,16 +1,15 @@ package io.micronaut.starter.build.gradle +import io.micronaut.starter.options.BuildTool import io.micronaut.starter.options.Language import io.micronaut.starter.options.TestFramework import spock.lang.Specification -import spock.lang.Unroll class GradleBuildTestVerifierSpec extends Specification { - @Unroll void "hasDependencyRegex"(boolean expected, String template, String groupId, String artifactId, String scope) { given: - GradleBuildTestVerifier verifier = new GradleBuildTestVerifier(template, Language.JAVA, TestFramework.JUNIT) + GradleBuildTestVerifier verifier = new GradleBuildTestVerifier(BuildTool.GRADLE, template, Language.JAVA, TestFramework.JUNIT) expect: expected == verifier.hasDependency(groupId, artifactId, scope) @@ -22,6 +21,5 @@ class GradleBuildTestVerifierSpec extends Specification { true | 'implementation("io.micronaut.oraclecloud:micronaut-oraclecloud-function-http:2.0.0")' | "io.micronaut.oraclecloud" | "micronaut-oraclecloud-function-http" | GradleConfiguration.IMPLEMENTATION.toString() false | 'implementation("io.micronaut.oraclecloud:micronaut-oraclecloud-function-http")' | "io.micronaut" | "micronaut-oraclecloud-function-http" | GradleConfiguration.IMPLEMENTATION.toString() false | 'implementation("io.micronaut.oraclecloud:micronaut-oraclecloud-function-http")' | "io.micronaut.oraclecloud" | "micronaut-oraclecloud-function" | GradleConfiguration.IMPLEMENTATION.toString() - } } diff --git a/starter-core/src/test/groovy/io/micronaut/starter/build/maven/MavenBuildTestVerifier.groovy b/starter-core/src/test/groovy/io/micronaut/starter/build/maven/MavenBuildTestVerifier.groovy index 1f1a213e9b0..860ed0eece4 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/build/maven/MavenBuildTestVerifier.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/build/maven/MavenBuildTestVerifier.groovy @@ -159,6 +159,31 @@ class MavenBuildTestVerifier implements BuildTestVerifier { } } + @CompileDynamic + @Override + boolean hasExclusion(String groupId, String artifactId, String excludedGroupId, String excludedArtifactId) { + hasExclusion(groupId, artifactId, excludedGroupId, excludedArtifactId, Scope.COMPILE) + } + + @CompileDynamic + @Override + boolean hasExclusion(String groupId, String artifactId, String excludedGroupId, String excludedArtifactId, Scope scope) { + String expectedExclude = "${excludedGroupId}:${excludedArtifactId}" + if ((scope == Scope.ANNOTATION_PROCESSOR || scope == Scope.TEST_ANNOTATION_PROCESSOR) && language != Language.GROOVY) { + project.build.plugins.plugin.find { it.artifactId.text() == "maven-compiler-plugin" }?.with { + configuration.annotationProcessorPaths.path.find {it.artifactId.text() == artifactId && it.groupId.text() == groupId && it.exclusions}?.with { + List excludes = exclusions.exclusion.collect { "${it.groupId.text()}:${it.artifactId.text()}".toString() } + return excludes.contains(expectedExclude) + } + } + } else { + project.dependencies.dependency.find { it.artifactId.text() == artifactId && it.groupId.text() == groupId && it.exclusions}?.with { + List excludes = exclusions.exclusion.collect { "${it.groupId.text()}:${it.artifactId.text()}".toString() } + return excludes.contains(expectedExclude) + } + } + } + @CompileDynamic @Override boolean hasTestResourceDependency(String expectedGroupId, String expectedArtifactId) { diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/FeatureSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/FeatureSpec.groovy index 4cbe59f2798..904c4ed005b 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/FeatureSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/FeatureSpec.groovy @@ -39,7 +39,7 @@ class FeatureSpec extends BeanContextSpec { } @Unroll - void "test #feature does not add an unmodifiable map to config"(Feature feature) { + void "test #feature.name does not add an unmodifiable map to config"(Feature feature) { when: JdkVersion javaVersion = javaVersionForFeature(feature.name) Language language = Language.JAVA @@ -95,7 +95,13 @@ class FeatureSpec extends BeanContextSpec { } private static JdkVersion javaVersionForFeature(String feature) { - MicronautJdkVersionConfiguration.DEFAULT_OPTION + // Azure functions support 21 as a preview for functions version 4.x in Linux. Java 21 is not supported in Windows yet + // https://learn.microsoft.com/en-us/azure/azure-functions/functions-reference-java?tabs=bash%2Cconsumption#supported-versions + return feature in ["azure-function", + "azure-function-http", + "chatbots-basecamp-azure-function", + "chatbots-telegram-azure-function" + ] ? JdkVersion.JDK_17 : MicronautJdkVersionConfiguration.DEFAULT_OPTION } private static ApplicationType applicationTypeForFeature(Feature feature) { diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/KotlinSymbolProcessingSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/KotlinSymbolProcessingSpec.groovy index a03e82f25d9..9d941b6a5db 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/KotlinSymbolProcessingSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/KotlinSymbolProcessingSpec.groovy @@ -5,7 +5,6 @@ import io.micronaut.starter.BuildBuilder import io.micronaut.starter.application.ApplicationType import io.micronaut.starter.build.BuildTestUtil import io.micronaut.starter.build.BuildTestVerifier -import io.micronaut.starter.feature.build.KotlinSupportFeature import io.micronaut.starter.fixture.CommandOutputFixture import io.micronaut.starter.options.BuildTool import io.micronaut.starter.options.JdkVersion @@ -81,8 +80,8 @@ class KotlinSymbolProcessingSpec extends ApplicationContextSpec implements Comma Map output = generate(ApplicationType.DEFAULT, new Options(Language.JAVA, TestFramework.DEFAULT_OPTION, BuildTool.GRADLE_KOTLIN, JdkVersion.JDK_17)) then: - output."gradle.properties".contains("micronautVersion") - !output."gradle.properties".contains("org.gradle.jvmargs") + output."gradle.properties" =~ /(?m)^micronautVersion=.+/ + !(output."gradle.properties" =~ /(?m)^org.gradle.jvmargs=.+/) where: buildTool << BuildTool.valuesGradle() @@ -93,8 +92,8 @@ class KotlinSymbolProcessingSpec extends ApplicationContextSpec implements Comma Map output = generate(ApplicationType.DEFAULT, new Options(Language.KOTLIN, TestFramework.DEFAULT_OPTION, BuildTool.GRADLE_KOTLIN, JdkVersion.JDK_17)) then: - output."gradle.properties".contains("micronautVersion") - output."gradle.properties".contains("org.gradle.jvmargs") + output."gradle.properties" =~ /(?m)^micronautVersion=.+/ + output."gradle.properties" =~ /(?m)^org.gradle.jvmargs=.+/ where: buildTool << BuildTool.valuesGradle() diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/acme/AcmeSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/acme/AcmeSpec.groovy index 5e1e0b5a0ec..a4575ee0c02 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/acme/AcmeSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/acme/AcmeSpec.groovy @@ -12,8 +12,8 @@ class AcmeSpec extends ApplicationContextSpec implements CommandOutputFixture { void 'test readme.md with feature acme contains links to micronaut docs'() { when: - def output = generate(['acme']) - def readme = output["README.md"] + Map output = generate(['acme']) + String readme = output["README.md"] then: readme diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/aws/AmazonApiGatewayHttpSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/aws/AmazonApiGatewayHttpSpec.groovy index c587f4d0c7a..886029c6737 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/aws/AmazonApiGatewayHttpSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/aws/AmazonApiGatewayHttpSpec.groovy @@ -48,17 +48,11 @@ class AmazonApiGatewayHttpSpec extends ApplicationContextSpec implements Command void 'lambda runtime main class configuration is present for amazon-api-gateway-http and build #buildTool'(BuildTool buildTool) { when: Map output = generate(ApplicationType.DEFAULT, options.withBuildTool(buildTool), [AmazonApiGatewayHttp.NAME]) + def build = output[buildTool.buildFileName] then: - if (buildTool == BuildTool.GRADLE) { - assert output['build.gradle'] - assert output['build.gradle'].contains('nativeLambda {') - assert output['build.gradle'].contains('lambdaRuntimeClassName = "io.micronaut.function.aws.runtime.APIGatewayV2HTTPEventMicronautLambdaRuntime"') - } else if (buildTool == BuildTool.GRADLE_KOTLIN) { - assert output['build.gradle.kts'] - assert output['build.gradle.kts'].contains('nativeLambda {') - assert output['build.gradle.kts'].contains('lambdaRuntimeClassName.set("io.micronaut.function.aws.runtime.APIGatewayV2HTTPEventMicronautLambdaRuntime")') - } + build.contains('nativeLambda {') + build.contains('lambdaRuntimeClassName = "io.micronaut.function.aws.runtime.APIGatewayV2HTTPEventMicronautLambdaRuntime"') where: buildTool << BuildTool.valuesGradle() diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/aws/AmazonApiGatewaySpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/aws/AmazonApiGatewaySpec.groovy index 968041344c9..050e8a0dba0 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/aws/AmazonApiGatewaySpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/aws/AmazonApiGatewaySpec.groovy @@ -78,18 +78,12 @@ class AmazonApiGatewaySpec extends ApplicationContextSpec implements CommandOutp void 'lambda runtime main class configuration is present for amazon-api-gateway and build #buildTool'(BuildTool buildTool) { when: - Map output = generate(ApplicationType.DEFAULT, options, [AmazonApiGateway.NAME]) + Map output = generate(ApplicationType.DEFAULT, options.withBuildTool(buildTool), [AmazonApiGateway.NAME]) + def build = output[buildTool.buildFileName] then: - if (buildTool == BuildTool.GRADLE) { - assert output['build.gradle'] - assert output['build.gradle'].contains('nativeLambda {') - assert output['build.gradle'].contains('lambdaRuntimeClassName = "io.micronaut.function.aws.runtime.MicronautLambdaRuntime"') - } else if (buildTool == BuildTool.GRADLE) { - assert output['build.gradle.kts'] - assert output['build.gradle.kts'].contains('nativeLambda {') - assert output['build.gradle.kts'].contains('lambdaRuntimeClassName.set("io.micronaut.function.aws.runtime.MicronautLambdaRuntime")') - } + build.contains('nativeLambda {') + build.contains('lambdaRuntimeClassName = "io.micronaut.function.aws.runtime.MicronautLambdaRuntime"') where: buildTool << BuildTool.valuesGradle() diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/aws/AwsV2SdkSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/aws/AwsV2SdkSpec.groovy index e897b03cce3..347cdfa2517 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/aws/AwsV2SdkSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/aws/AwsV2SdkSpec.groovy @@ -12,8 +12,8 @@ class AwsV2SdkSpec extends ApplicationContextSpec implements CommandOutputFixtur void 'test readme.md with feature aws-v2-sdk contains links to micronaut docs'() { when: - def output = generate(['aws-v2-sdk']) - def readme = output["README.md"] + Map output = generate(['aws-v2-sdk']) + String readme = output["README.md"] then: readme.contains("[Micronaut AWS SDK 2.x documentation](https://micronaut-projects.github.io/micronaut-aws/latest/guide/)") diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/aws/CdkFeatureSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/aws/CdkFeatureSpec.groovy index 841b9dc4c3c..94282c1a6de 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/aws/CdkFeatureSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/aws/CdkFeatureSpec.groovy @@ -55,6 +55,7 @@ class CdkFeatureSpec extends ApplicationContextSpec implements CommandOutputFixt then: output.'infra/src/main/java/example/micronaut/AppStack.java'.contains('import software.amazon.awscdk.services.logs.RetentionDays;') output.'infra/src/main/java/example/micronaut/AppStack.java'.contains('.logRetention(RetentionDays.ONE_WEEK)') + output.'infra/src/main/java/example/micronaut/AppStack.java'.contains('.tracing(Tracing.ACTIVE)') where: buildTool << BuildTool.values() diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/aws/DynamoDbSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/aws/DynamoDbSpec.groovy index 39f70cbef11..ce17157f2b1 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/aws/DynamoDbSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/aws/DynamoDbSpec.groovy @@ -17,8 +17,8 @@ class DynamoDbSpec extends ApplicationContextSpec implements CommandOutputFixtur void 'test readme.md with feature dynamodb contains links to micronaut docs'() { when: - def output = generate([DynamoDb.NAME]) - def readme = output["README.md"] + Map output = generate([DynamoDb.NAME]) + String readme = output["README.md"] then: readme.contains("[Micronaut Amazon DynamoDB documentation](https://micronaut-projects.github.io/micronaut-aws/latest/guide/#dynamodb)") @@ -56,10 +56,8 @@ class DynamoDbSpec extends ApplicationContextSpec implements CommandOutputFixtur then: verifier.hasDependency("io.micronaut.aws", "micronaut-aws-sdk-v2", Scope.COMPILE) - template.contains(""" implementation("software.amazon.awssdk:dynamodb") { - | exclude(group$mapNotation "software.amazon.awssdk", module$mapNotation "apache-client") - | exclude(group$mapNotation "software.amazon.awssdk", module$mapNotation "netty-nio-client") - | }""".stripMargin()) + verifier.hasExclusion("software.amazon.awssdk", "dynamodb", "software.amazon.awssdk", "apache-client") + verifier.hasExclusion("software.amazon.awssdk", "dynamodb", "software.amazon.awssdk", "netty-nio-client") verifier.hasDependency("software.amazon.awssdk", "url-connection-client", Scope.COMPILE) where: @@ -77,26 +75,13 @@ class DynamoDbSpec extends ApplicationContextSpec implements CommandOutputFixtur then: verifier.hasDependency("io.micronaut.aws", "micronaut-aws-sdk-v2", Scope.COMPILE) - template.contains(""" - - software.amazon.awssdk - dynamodb - compile - - - software.amazon.awssdk - apache-client - - - software.amazon.awssdk - netty-nio-client - - - -""") verifier.hasDependency("io.micronaut.aws", "micronaut-aws-sdk-v2", Scope.COMPILE) verifier.hasDependency("software.amazon.awssdk", "url-connection-client", Scope.COMPILE) + verifier.hasDependency("software.amazon.awssdk", "dynamodb", Scope.COMPILE) + verifier.hasExclusion("software.amazon.awssdk", "dynamodb", "software.amazon.awssdk", "apache-client") + verifier.hasExclusion("software.amazon.awssdk", "dynamodb", "software.amazon.awssdk", "netty-nio-client") + where: language << GraalVMFeatureValidator.supportedLanguages() } diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/aws/LambdaFunctionUrlSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/aws/LambdaFunctionUrlSpec.groovy index fa27b113311..3eeea1c4545 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/aws/LambdaFunctionUrlSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/aws/LambdaFunctionUrlSpec.groovy @@ -53,17 +53,11 @@ class LambdaFunctionUrlSpec extends ApplicationContextSpec implements CommandOut void 'lambda runtime main class configuration is present for #buildTool'(BuildTool buildTool) { when: Map output = generate(ApplicationType.FUNCTION, createOptions(buildTool), [LambdaFunctionUrl.NAME]) + def build = output["app/$buildTool.buildFileName"] then: - if (buildTool == BuildTool.GRADLE) { - assert output['app/build.gradle'] - assert output['app/build.gradle'].contains('nativeLambda {') - assert output['app/build.gradle'].contains('lambdaRuntimeClassName = "io.micronaut.function.aws.runtime.MicronautLambdaRuntime"') - } else if (buildTool == BuildTool.GRADLE_KOTLIN) { - assert output['app/build.gradle.kts'] - assert output['app/build.gradle.kts'].contains('nativeLambda {') - assert output['app/build.gradle.kts'].contains('lambdaRuntimeClassName.set("io.micronaut.function.aws.runtime.MicronautLambdaRuntime")') - } + build.contains('nativeLambda {') + build.contains('lambdaRuntimeClassName = "io.micronaut.function.aws.runtime.MicronautLambdaRuntime"') where: buildTool << BuildTool.valuesGradle() diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/awsalexa/AwsAlexaSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/awsalexa/AwsAlexaSpec.groovy index d539faff798..5827bccce08 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/awsalexa/AwsAlexaSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/awsalexa/AwsAlexaSpec.groovy @@ -22,8 +22,8 @@ class AwsAlexaSpec extends ApplicationContextSpec implements CommandOutputFixtur void 'test readme.md with feature aws-alexa contains links to micronaut docs'() { when: - def output = generate(['aws-alexa']) - def readme = output["README.md"] + Map output = generate(['aws-alexa']) + String readme = output["README.md"] then: readme diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/awslambdacustomruntime/AwsLambdaCustomRuntimeSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/awslambdacustomruntime/AwsLambdaCustomRuntimeSpec.groovy index a132eeb6da9..b3a23b13447 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/awslambdacustomruntime/AwsLambdaCustomRuntimeSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/awslambdacustomruntime/AwsLambdaCustomRuntimeSpec.groovy @@ -22,8 +22,8 @@ class AwsLambdaCustomRuntimeSpec extends ApplicationContextSpec implements Comm void 'test readme.md with feature aws-lambda-custom-runtime contains links to micronaut docs'() { when: - def output = generate(['aws-lambda-custom-runtime']) - def readme = output["README.md"] + Map output = generate(['aws-lambda-custom-runtime']) + String readme = output["README.md"] then: readme @@ -33,13 +33,13 @@ class AwsLambdaCustomRuntimeSpec extends ApplicationContextSpec implements Comm @Issue("https://github.com/micronaut-projects/micronaut-starter/issues/723") void 'test readme.md with feature aws-lambda-custom-runtime and graalvm contains extra documentation. language = #language'() { when: - def output = generate( + Map output = generate( ApplicationType.DEFAULT, new Options(language, TestFramework.JUNIT, BuildTool.GRADLE, MicronautJdkVersionConfiguration.DEFAULT_OPTION), ['aws-lambda-custom-runtime', 'graalvm'] ) - def readme = output["README.md"] + String readme = output["README.md"] then: readme @@ -115,7 +115,7 @@ class AwsLambdaCustomRuntimeSpec extends ApplicationContextSpec implements Comm then: verifier.hasDependency("io.micronaut.aws", "micronaut-function-aws-custom-runtime", Scope.COMPILE) and: 'http-client dependency is in compile scope' - verifier.hasDependency("io.micronaut", "micronaut-http-client", Scope.COMPILE) + verifier.hasDependency("io.micronaut", "micronaut-http-client-jdk", Scope.COMPILE) where: language | applicationType @@ -138,7 +138,7 @@ class AwsLambdaCustomRuntimeSpec extends ApplicationContextSpec implements Comm BuildTestVerifier verifier = BuildTestUtil.verifier(buildTool, template) then: - verifier.hasDependency("io.micronaut", "micronaut-http-client", Scope.COMPILE) + verifier.hasDependency("io.micronaut", "micronaut-http-client-jdk", Scope.COMPILE) where: language | applicationType diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/awsparameterstore/AwsParameterStoreSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/awsparameterstore/AwsParameterStoreSpec.groovy index 77dce3c185f..02bd7ab6bff 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/awsparameterstore/AwsParameterStoreSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/awsparameterstore/AwsParameterStoreSpec.groovy @@ -2,6 +2,9 @@ package io.micronaut.starter.feature.awsparameterstore import io.micronaut.starter.ApplicationContextSpec import io.micronaut.starter.BuildBuilder +import io.micronaut.starter.build.BuildTestUtil +import io.micronaut.starter.build.BuildTestVerifier +import io.micronaut.starter.build.dependencies.Scope import io.micronaut.starter.feature.config.Yaml import io.micronaut.starter.fixture.CommandOutputFixture import io.micronaut.starter.options.BuildTool @@ -11,8 +14,8 @@ import spock.lang.Unroll class AwsParameterStoreSpec extends ApplicationContextSpec implements CommandOutputFixture { void 'test readme.md with feature aws-parameter-store contains links to micronaut docs'() { when: - def output = generate(['aws-parameter-store']) - def readme = output["README.md"] + Map output = generate(['aws-parameter-store']) + String readme = output["README.md"] then: readme @@ -27,54 +30,32 @@ class AwsParameterStoreSpec extends ApplicationContextSpec implements CommandOut then: bootstrap - bootstrap.contains('''\ -micronaut: - application: - name: foo - config-client: - enabled: true -''') - bootstrap.contains('''\ -aws.client.system-manager.parameterstore.enabled: true -''') - } - @Unroll - void 'test gradle aws-parameter-store feature for language=#language'() { when: - String template = new BuildBuilder(beanContext, BuildTool.GRADLE) - .language(language) - .features(['aws-parameter-store']) - .render() + Map bootstrapYml = new org.yaml.snakeyaml.Yaml().load(bootstrap) then: - template.count('implementation("io.micronaut.aws:micronaut-aws-parameter-store")') == 1 - - and: 'micronaut-aws-parameter-store exposes aws-sdk-v2 transitively' - !template.contains('implementation("io.micronaut.aws:aws-sdk-v2")') - - where: - language << Language.values().toList() + 'foo' == bootstrapYml['micronaut']['application']['name'] + true == bootstrapYml['micronaut']['config-client']['enabled'] + true == bootstrapYml['aws']['client']['system-manager']['parameterstore']['enabled'] + false == bootstrapYml['aws']['distributed-configuration']['search-active-environments'] + false == bootstrapYml['aws']['distributed-configuration']['search-common-application'] } @Unroll - void 'test maven aws-parameter-store feature for language=#language'() { + void 'test #buildTool aws-parameter-store feature for language=#language'(BuildTool buildTool, Language language) { when: - String template = new BuildBuilder(beanContext, BuildTool.MAVEN) + String template = new BuildBuilder(beanContext, buildTool) .language(language) .features(['aws-parameter-store']) .render() + BuildTestVerifier verifier = BuildTestUtil.verifier(buildTool, language, template) then: - template.count(''' - - io.micronaut.aws - micronaut-aws-parameter-store - compile - -''') == 1 + verifier.hasDependency("io.micronaut.aws", "micronaut-aws-parameter-store", Scope.COMPILE) + !verifier.hasDependency("io.micronaut.aws", ":aws-sdk-v2", Scope.COMPILE) where: - language << Language.values().toList() + [buildTool, language] << [BuildTool.values(), Language.values().toList()].combinations() } } diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/awssecretsmanager/AwsSecretsManagerSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/awssecretsmanager/AwsSecretsManagerSpec.groovy index 1873ca9b93c..9e669d35754 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/awssecretsmanager/AwsSecretsManagerSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/awssecretsmanager/AwsSecretsManagerSpec.groovy @@ -2,6 +2,9 @@ package io.micronaut.starter.feature.awssecretsmanager import io.micronaut.starter.ApplicationContextSpec import io.micronaut.starter.BuildBuilder +import io.micronaut.starter.build.BuildTestUtil +import io.micronaut.starter.build.BuildTestVerifier +import io.micronaut.starter.build.dependencies.Scope import io.micronaut.starter.feature.config.Yaml import io.micronaut.starter.fixture.CommandOutputFixture import io.micronaut.starter.options.BuildTool @@ -11,8 +14,8 @@ import spock.lang.Unroll class AwsSecretsManagerSpec extends ApplicationContextSpec implements CommandOutputFixture { void 'test readme.md with feature aws-secrets-manager contains links to micronaut docs'() { when: - def output = generate(['aws-secrets-manager']) - def readme = output["README.md"] + Map output = generate(['aws-secrets-manager']) + String readme = output["README.md"] then: readme @@ -27,51 +30,31 @@ class AwsSecretsManagerSpec extends ApplicationContextSpec implements CommandOut then: bootstrap - bootstrap.contains('''\ -micronaut: - application: - name: foo - config-client: - enabled: true -''') - } - - @Unroll - void 'test gradle aws-secrets-manager feature for language=#language'() { when: - String template = new BuildBuilder(beanContext, BuildTool.GRADLE) - .language(language) - .features(['aws-secrets-manager']) - .render() + Map bootstrapYml = new org.yaml.snakeyaml.Yaml().load(bootstrap) then: - template.count('implementation("io.micronaut.aws:micronaut-aws-secretsmanager")') == 1 - - and: 'micronaut-aws-secretsmanager exposes aws-sdk-v2 transitively' - !template.contains('implementation("io.micronaut.aws:aws-sdk-v2")') - - where: - language << Language.values().toList() + 'foo' == bootstrapYml['micronaut']['application']['name'] + true == bootstrapYml['micronaut']['config-client']['enabled'] + true == bootstrapYml['aws']['client']['system-manager']['parameterstore']['enabled'] + false == bootstrapYml['aws']['distributed-configuration']['search-active-environments'] + false == bootstrapYml['aws']['distributed-configuration']['search-common-application'] } @Unroll - void 'test maven aws-secrets-manager feature for language=#language'() { + void 'test #buildTool aws-secrets-manager feature for language=#language'(BuildTool buildTool, Language language) { when: - String template = new BuildBuilder(beanContext, BuildTool.MAVEN) + String template = new BuildBuilder(beanContext, buildTool) .language(language) .features(['aws-secrets-manager']) .render() + BuildTestVerifier verifier = BuildTestUtil.verifier(buildTool, language, template) then: - template.count(''' - - io.micronaut.aws - micronaut-aws-secretsmanager - compile - -''') == 1 + verifier.hasDependency("io.micronaut.aws", "micronaut-aws-secretsmanager", Scope.COMPILE) + !verifier.hasDependency("io.micronaut.aws", ":aws-sdk-v2", Scope.COMPILE) where: - language << Language.values().toList() + [buildTool, language] << [BuildTool.values(), Language.values().toList()].combinations() } } diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/azure/AzureCosmosDbFeatureSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/azure/AzureCosmosDbFeatureSpec.groovy index 7318754d767..6fde828bd0e 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/azure/AzureCosmosDbFeatureSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/azure/AzureCosmosDbFeatureSpec.groovy @@ -16,8 +16,8 @@ class AzureCosmosDbFeatureSpec extends ApplicationContextSpec implements Command void 'test README.md with feature azure-cosmos-db contains links to micronaut and microsoft docs'() { when: - def output = generate(['azure-cosmos-db']) - def readme = output["README.md"] + Map output = generate(['azure-cosmos-db']) + String readme = output["README.md"] then: readme.contains("[Micronaut Azure Cosmos DB documentation](https://micronaut-projects.github.io/micronaut-azure/latest/guide/#azureCosmosClient)") diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/azure/AzureKeyVaultFeatureSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/azure/AzureKeyVaultFeatureSpec.groovy index 2a7ff9aa29b..b6c894dad43 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/azure/AzureKeyVaultFeatureSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/azure/AzureKeyVaultFeatureSpec.groovy @@ -1,8 +1,9 @@ package io.micronaut.starter.feature.azure -import groovy.xml.XmlSlurper import io.micronaut.starter.ApplicationContextSpec import io.micronaut.starter.BuildBuilder +import io.micronaut.starter.build.BuildTestUtil +import io.micronaut.starter.build.BuildTestVerifier import io.micronaut.starter.fixture.CommandOutputFixture import io.micronaut.starter.options.BuildTool @@ -10,8 +11,8 @@ class AzureKeyVaultFeatureSpec extends ApplicationContextSpec implements Command void 'test readme.md with feature azure-key-vault contains links to micronaut and microsoft docs'() { when: - def output = generate(['azure-key-vault']) - def readme = output["README.md"] + Map output = generate(['azure-key-vault']) + String readme = output["README.md"] then: readme @@ -19,28 +20,19 @@ class AzureKeyVaultFeatureSpec extends ApplicationContextSpec implements Command readme.contains("https://azure.microsoft.com/en-us/services/key-vault/#product-overview") } - void "test maven azure-key-vault feature adds dependency"() { + void "test azure-key-vault feature adds dependencies for buildTool=#buildTool"(BuildTool buildTool) { when: - String template = new BuildBuilder(beanContext, BuildTool.MAVEN) + String template = new BuildBuilder(beanContext, buildTool) .features(["azure-key-vault"]) .render() - def pom = new XmlSlurper().parseText(template) + BuildTestVerifier verifier = BuildTestUtil.verifier(buildTool, template) then: - with(pom.dependencies.dependency.find { it.artifactId == "micronaut-azure-secret-manager" }) { - scope.text() == 'compile' - groupId.text() == 'io.micronaut.azure' - } - } - - void "test gradle azure-key-vault feature adds dependency"() { - when: - String template = new BuildBuilder(beanContext, BuildTool.GRADLE) - .features(["azure-key-vault"]) - .render() + verifier.hasDependency("io.micronaut.azure", "micronaut-azure-secret-manager") + verifier.hasDependency("io.micronaut.discovery", "micronaut-discovery-client") - then: - template.contains('implementation("io.micronaut.azure:micronaut-azure-secret-manager")') + where: + buildTool << BuildTool.values() } void "test azure-key-vault feature configuration"() { diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/build/GradleEnterpriseSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/build/GradleEnterpriseSpec.groovy index c642bfc35e3..d5f274989f9 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/build/GradleEnterpriseSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/build/GradleEnterpriseSpec.groovy @@ -36,11 +36,7 @@ class GradleEnterpriseSpec extends ApplicationContextSpec implements CommandOutp settings.contains('buildScan {') settings.contains('termsOfServiceUrl = "https://gradle.com/terms-of-service"') settings.contains('termsOfServiceAgree = "yes"') - if (buildTool == BuildTool.GRADLE_KOTLIN) { - assert settings.contains($/id("com.gradle.enterprise") version("$expectedVersion")/$) - } else if (buildTool == BuildTool.GRADLE) { - assert settings.contains($/id "com.gradle.enterprise" version "$expectedVersion"/$) - } + settings.contains($/id("com.gradle.enterprise") version("$expectedVersion")/$) where: buildTool << BuildTool.valuesGradle() diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/build/KaptSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/build/KaptSpec.groovy index 3890fb3c8ca..e123714c8ae 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/build/KaptSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/build/KaptSpec.groovy @@ -145,4 +145,29 @@ class KaptSpec extends ApplicationContextSpec implements CommandOutputFixture { and: 'the config file is added in the right place' output.".mvn/jvm.config" == KotlinSupportFeature.JDK_21_KAPT_MODULES } + + void 'Corrected jdk21 = jdk17 is specified in build = #buildTool for kapt'(BuildTool buildTool) { + when: + def output = generate(ApplicationType.DEFAULT, new Options(Language.KOTLIN, TestFramework.DEFAULT_OPTION, buildTool, JdkVersion.JDK_21),['kapt']) + def buildFile = buildTool == BuildTool.GRADLE ? output["build.gradle"] : output["build.gradle.kts"] + + then: + buildFile + buildFile.contains('sourceCompatibility = JavaVersion.toVersion("17")') + !buildFile.contains('targetCompatibility = JavaVersion.toVersion("17")') + !buildFile.contains('targetCompatibility = JavaVersion.toVersion("21")') + + where: + buildTool << BuildTool.valuesGradle() + } + + void 'Corrected jdk21 = jdk17 is specified in Maven build for kapt'() { + when: + def output = generate(ApplicationType.DEFAULT, new Options(Language.KOTLIN, TestFramework.DEFAULT_OPTION, BuildTool.MAVEN, JdkVersion.JDK_21),['kapt']) + def buildFile = output["pom.xml"] + + then: + buildFile + buildFile.contains('17') + } } diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/build/MicronautAotSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/build/MicronautAotSpec.groovy index c7d7b4e5d99..c24ae8ad405 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/build/MicronautAotSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/build/MicronautAotSpec.groovy @@ -81,10 +81,9 @@ class MicronautAotSpec extends ApplicationContextSpec implements CommandOutputFi language << Language.values().toList() } - @Unroll - void 'application with gradle and feature micronaut-aot for language=#language'() { + void 'application with #buildTool and feature micronaut-aot for language=#language'(BuildTool buildTool, Language language) { when: - String output = build(GRADLE, language) + String output = build(buildTool, language) then: output.contains(AOT_PLUGIN) @@ -96,9 +95,10 @@ class MicronautAotSpec extends ApplicationContextSpec implements CommandOutputFi output.contains('optimizeClassLoading = true') output.contains('deduceEnvironment = true') output.contains('optimizeNetty = true') + output.contains('replaceLogbackXml = true') where: - language << Language.values().toList() + [buildTool, language] << [BuildTool.valuesGradle(), Language.values().toList()].combinations() } @Unroll @@ -111,26 +111,6 @@ class MicronautAotSpec extends ApplicationContextSpec implements CommandOutputFi output.contains('aot {') } - @Unroll - void 'application with gradle and feature micronaut-aot for language=#language and Kotlin DSL'() { - when: - String output = build(GRADLE_KOTLIN, language) - - then: - output.contains(AOT_PLUGIN) - output.contains('aot {') - output.contains('optimizeServiceLoading.set(false)') - output.contains('convertYamlToJava.set(false)') - output.contains('precomputeOperations.set(true)') - output.contains('cacheEnvironment.set(true)') - output.contains('optimizeClassLoading.set(true)') - output.contains('deduceEnvironment.set(true)') - output.contains('optimizeNetty.set(true)') - - where: - language << Language.values().toList() - } - @Unroll void 'order is correct in application with gradle and feature micronaut-aot for language=#language'() { when: diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/build/MicronautGradleEnterpriseSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/build/MicronautGradleEnterpriseSpec.groovy index 52ce5ffff0c..6556ef3638e 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/build/MicronautGradleEnterpriseSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/build/MicronautGradleEnterpriseSpec.groovy @@ -54,11 +54,7 @@ class MicronautGradleEnterpriseSpec extends ApplicationContextSpec implements Co |}'''.stripMargin()) settings.contains('plugins {') - if (buildTool == BuildTool.GRADLE_KOTLIN) { - assert settings.contains(' id("io.micronaut.build.internal.gradle-enterprise") version("') - } else if (buildTool == BuildTool.GRADLE) { - assert settings.contains(' id "io.micronaut.build.internal.gradle-enterprise" version "') - } + settings.contains(' id("io.micronaut.build.internal.gradle-enterprise") version("') where: buildTool << BuildTool.valuesGradle() diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/build/gradle/GradleSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/build/gradle/GradleSpec.groovy index 9a536671f64..2cf7f5daaf5 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/build/gradle/GradleSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/build/gradle/GradleSpec.groovy @@ -5,12 +5,14 @@ import io.micronaut.starter.application.ApplicationType import io.micronaut.starter.build.Property import io.micronaut.starter.build.gradle.GradleBuild import io.micronaut.starter.feature.aws.AwsLambdaFeatureValidator +import io.micronaut.starter.feature.build.Kapt import io.micronaut.starter.feature.build.MicronautBuildPlugin import io.micronaut.starter.feature.build.gradle.templates.gradleProperties import io.micronaut.starter.feature.build.gradle.templates.settingsGradle import io.micronaut.starter.feature.graalvm.GraalVMFeatureValidator import io.micronaut.starter.fixture.CommandOutputFixture import io.micronaut.starter.options.BuildTool +import io.micronaut.starter.options.JdkVersion import io.micronaut.starter.options.Language import io.micronaut.starter.options.Options import io.micronaut.starter.options.TestFramework @@ -78,7 +80,7 @@ class GradleSpec extends BeanContextSpec implements CommandOutputFixture { then: buildGradle - !buildGradle.contains("tasks") + !buildGradle.contains("tasks {") where: language << [Language.JAVA, Language.GROOVY] @@ -91,12 +93,12 @@ class GradleSpec extends BeanContextSpec implements CommandOutputFixture { then: buildGradle - buildGradle.contains(configuration) + buildGradle.contains('graalvmNative.toolchainDetection = false') where: - dsl | fileName | configuration - BuildTool.GRADLE | 'build.gradle' | 'graalvmNative.toolchainDetection = false' - BuildTool.GRADLE_KOTLIN | 'build.gradle.kts' | 'graalvmNative.toolchainDetection.set(false)' + dsl | fileName + BuildTool.GRADLE | 'build.gradle' + BuildTool.GRADLE_KOTLIN | 'build.gradle.kts' } void 'ignoredAutomaticDependencies not output by default'() { @@ -114,20 +116,21 @@ class GradleSpec extends BeanContextSpec implements CommandOutputFixture { then: buildGradle - buildGradle.contains(configuration) + buildGradle.contains('graalvmNative.toolchainDetection = false') where: - dsl | fileName | configuration - BuildTool.GRADLE | 'build.gradle' | 'graalvmNative.toolchainDetection = false' - BuildTool.GRADLE_KOTLIN | 'build.gradle.kts' | 'graalvmNative.toolchainDetection.set(false)' + dsl | fileName + BuildTool.GRADLE | 'build.gradle' + BuildTool.GRADLE_KOTLIN | 'build.gradle.kts' } void 'Supported languages have both Gradle and Graalvm plugin docs (lang = #lang, buildTool = #buildTool, apptype = #apptype)'( ApplicationType apptype, Language lang, BuildTool buildTool ) { when: - def output = generate(apptype, new Options(lang, TestFramework.DEFAULT_OPTION, buildTool, jdk)) - def readme = output["README.md"] + List features = (apptype == ApplicationType.CLI && lang == Language.KOTLIN) ? [Kapt.NAME] : [] + Map output = generate(apptype, new Options(lang, TestFramework.DEFAULT_OPTION, buildTool, jdk), features) + String readme = output["README.md"] then: readme @@ -143,12 +146,36 @@ class GradleSpec extends BeanContextSpec implements CommandOutputFixture { ].combinations() } + void 'Selected jdk = #jdk is specified in build = #buildTool for lang = #lang'( + Language lang, JdkVersion jdk, BuildTool buildTool + ) { + when: + def output = generate(ApplicationType.DEFAULT, new Options(lang, TestFramework.DEFAULT_OPTION, buildTool, jdk)) + def buildFile = buildTool == BuildTool.GRADLE ? output["build.gradle"] : output["build.gradle.kts"] + + then: + buildFile + buildFile.contains("sourceCompatibility = JavaVersion.toVersion(\"${jdk.majorVersion()}\")") + if (lang == Language.KOTLIN) { + assert !buildFile.contains("targetCompatibility = JavaVersion.toVersion(\"${jdk.majorVersion()}\")") + } else { + assert buildFile.contains("targetCompatibility = JavaVersion.toVersion(\"${jdk.majorVersion()}\")") + } + + where: + [lang, jdk, buildTool] << [ + Language.values(), + [JdkVersion.JDK_17, JdkVersion.JDK_21], + BuildTool.valuesGradle() + ].combinations() + } + void 'Unsupported languages have Gradle but omit GraalVM plugin docs (lang = #lang, buildTool = #buildTool, apptype = #apptype)'( ApplicationType apptype, Language lang, BuildTool buildTool ) { when: - def output = generate(apptype, new Options(lang, TestFramework.DEFAULT_OPTION, buildTool, jdk)) - def readme = output["README.md"] + Map output = generate(apptype, new Options(lang, TestFramework.DEFAULT_OPTION, buildTool, jdk)) + String readme = output["README.md"] then: readme diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/build/maven/EnforcerPluginSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/build/maven/EnforcerPluginSpec.groovy index bb2ba52d373..8937809da1f 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/build/maven/EnforcerPluginSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/build/maven/EnforcerPluginSpec.groovy @@ -13,8 +13,8 @@ class EnforcerPluginSpec extends ApplicationContextSpec implements CommandOutpu void 'test readme.md with feature kubernetes-informer contains links to docs'() { when: - def output = generate(['kubernetes-informer']) - def readme = output["README.md"] + Map output = generate(['kubernetes-informer']) + String readme = output["README.md"] then: readme diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/build/maven/MavenSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/build/maven/MavenSpec.groovy index fd2bc6a11bb..097d6c9ec55 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/build/maven/MavenSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/build/maven/MavenSpec.groovy @@ -30,7 +30,7 @@ class MavenSpec extends ApplicationContextSpec implements CommandOutputFixture { void 'Readme has Maven plugin docs (lang = #lang, apptype = #apptype)'(ApplicationType apptype, Language lang) { when: Map output = generate(apptype, createOptions(lang, BuildTool.MAVEN)) - def readme = output["README.md"] + String readme = output["README.md"] then: readme @@ -164,9 +164,9 @@ class MavenSpec extends ApplicationContextSpec implements CommandOutputFixture { org.apache.groovy groovy ''') - template.contains('''\ - 4.0.16 -''') + template.contains("""\ + ${VersionInfo.getBomVersion("groovy")} +""") } @Unroll @@ -177,7 +177,7 @@ class MavenSpec extends ApplicationContextSpec implements CommandOutputFixture { String template = new BuildBuilder(beanContext, BuildTool.MAVEN) .features(chosenFeatures) .language(Language.JAVA) - .jdkVersion(MicronautJdkVersionConfiguration.DEFAULT_OPTION) + .jdkVersion(javaVersionForRuntime(runtime)) .render() then: template.contains("${runtime}") @@ -195,7 +195,41 @@ class MavenSpec extends ApplicationContextSpec implements CommandOutputFixture { ApplicationType.DEFAULT | ["undertow-server"] | "undertow" } + private static JdkVersion javaVersionForRuntime(String runtime) { + // Azure functions support 21 as a preview for functions version 4.x in Linux. Java 21 is not supported in Windows yet + // https://learn.microsoft.com/en-us/azure/azure-functions/functions-reference-java?tabs=bash%2Cconsumption#supported-versions + // Google Cloud Function execution environment supports 21 in preview only + // https://cloud.google.com/functions/docs/concepts/execution-environment#runtimes + return runtime in ["azure_function", + "google_function" + ] ? JdkVersion.JDK_17 : + MicronautJdkVersionConfiguration.DEFAULT_OPTION + } + private static Options createOptions(Language language, BuildTool buildTool = BuildTool.DEFAULT_OPTION) { new Options(language, language.getDefaults().getTest(), buildTool, AwsLambdaFeatureValidator.firstSupportedJdk()) } + + void 'Selected jdk = #jdk is specified in Maven for lang = #lang'( + Language lang, JdkVersion jdk + ) { + when: + def output = generate(ApplicationType.DEFAULT, new Options(lang, TestFramework.DEFAULT_OPTION, BuildTool.MAVEN, jdk)) + def buildFile = output["pom.xml"] + + then: + buildFile + if (lang == Language.KOTLIN) { + // has kapt so has to be 17 + assert buildFile.contains("17") + } else { + assert buildFile.contains("$jdk.majorVersion") + } + + where: + [lang, jdk] << [ + Language.values(), + [JdkVersion.JDK_17, JdkVersion.JDK_21] + ].combinations() + } } diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/buildless/BuildlessSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/buildless/BuildlessSpec.groovy index 42f70ab46c1..b4143daf2a3 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/buildless/BuildlessSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/buildless/BuildlessSpec.groovy @@ -17,8 +17,8 @@ class BuildlessSpec extends ApplicationContextSpec implements CommandOutputFixtu void 'test README.md with buildless feature contains links to docs'() { when: - def output = generate([Buildless.NAME]) - def readme = output["README.md"] + Map output = generate([Buildless.NAME]) + String readme = output["README.md"] then: readme.contains("[https://docs.less.build/](https://docs.less.build/)") @@ -54,7 +54,7 @@ class BuildlessSpec extends ApplicationContextSpec implements CommandOutputFixtu def output = generate(ApplicationType.DEFAULT, new Options(Language.JAVA, buildTool), [Buildless.NAME]) def version = beanContext.getBean(CoordinateResolver).resolve(Buildless.BUILDLESS_PLUGIN_ARTIFACT).get().version def settings = buildTool == BuildTool.GRADLE ? output['settings.gradle'] : output['settings.gradle.kts'] - def expectedPlugin = buildTool == BuildTool.GRADLE ? """id "build.less" version "$version\"""" : """id("build.less") version("$version")""" + def expectedPlugin = """id("build.less") version("$version\"""" then: 'we have the plugin in the settings file' settings.contains(" $expectedPlugin") diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/cache/CaffeineSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/cache/CaffeineSpec.groovy index f9ada8bba1b..4878d2eddc4 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/cache/CaffeineSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/cache/CaffeineSpec.groovy @@ -11,8 +11,8 @@ class CaffeineSpec extends ApplicationContextSpec implements CommandOutputFixtur void 'test readme.md with feature cache-caffeine contains links to micronaut docs'() { when: - def output = generate(['cache-caffeine']) - def readme = output["README.md"] + Map output = generate(['cache-caffeine']) + String readme = output["README.md"] then: readme diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/cache/CoherenceSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/cache/CoherenceSpec.groovy index a083fb87dfd..b6dccd4d962 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/cache/CoherenceSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/cache/CoherenceSpec.groovy @@ -11,8 +11,8 @@ class CoherenceSpec extends BeanContextSpec implements CommandOutputFixture { void 'test readme.md with feature cache-coherence contains links to micronaut docs'() { when: - def output = generate([Coherence.NAME]) - def readme = output["README.md"] + Map output = generate([Coherence.NAME]) + String readme = output["README.md"] then: readme diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/cache/EHCacheSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/cache/EHCacheSpec.groovy index aecd665107c..9e5d7d5b006 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/cache/EHCacheSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/cache/EHCacheSpec.groovy @@ -12,8 +12,8 @@ class EHCacheSpec extends ApplicationContextSpec implements CommandOutputFixture void 'test readme.md with feature cache-ehcache contains links to micronaut docs'() { when: - def output = generate(['cache-ehcache']) - def readme = output["README.md"] + Map output = generate(['cache-ehcache']) + String readme = output["README.md"] then: readme diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/cache/HazelcastSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/cache/HazelcastSpec.groovy index e74c3ea5ff5..cc83af0c8a2 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/cache/HazelcastSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/cache/HazelcastSpec.groovy @@ -13,8 +13,8 @@ class HazelcastSpec extends ApplicationContextSpec implements CommandOutputFixtu @Unroll void 'test readme.md contains links to hazelcast and micronaut docs'() { when: - def output = generate(['cache-hazelcast']) - def readme = output["README.md"] + Map output = generate(['cache-hazelcast']) + String readme = output["README.md"] then: readme diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/cache/InfinispanSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/cache/InfinispanSpec.groovy index 057df2ff791..e0786d76a6d 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/cache/InfinispanSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/cache/InfinispanSpec.groovy @@ -12,8 +12,8 @@ class InfinispanSpec extends ApplicationContextSpec implements CommandOutputFix void 'test readme.md with feature cache-infinispan contains links to micronaut docs'() { when: - def output = generate(['cache-infinispan']) - def readme = output["README.md"] + Map output = generate(['cache-infinispan']) + String readme = output["README.md"] then: readme diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/camunda/ExternalWorkerSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/camunda/ExternalWorkerSpec.groovy index 8a5f6dcd780..ce13f41213a 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/camunda/ExternalWorkerSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/camunda/ExternalWorkerSpec.groovy @@ -30,8 +30,8 @@ class ExternalWorkerSpec extends ApplicationContextSpec implements CommandOutput @PendingFeature(reason = "camunda community features do not support Micronaut Framework 4 yet") void 'test readme.md with feature camunda-external-worker contains links to micronaut docs'() { when: - def output = generate(['camunda-external-worker']) - def readme = output["README.md"] + Map output = generate(['camunda-external-worker']) + String readme = output["README.md"] then: readme diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/camunda/Platform7Spec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/camunda/Platform7Spec.groovy index 5f4a448d0f2..db3e340df68 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/camunda/Platform7Spec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/camunda/Platform7Spec.groovy @@ -30,8 +30,8 @@ class Platform7Spec extends ApplicationContextSpec implements CommandOutputFixtu @PendingFeature(reason = "camunda community features do not support Micronaut Framework 4 yet") void 'test readme.md with feature camunda-platform7 contains links to micronaut docs'() { when: - def output = generate(['camunda-platform7']) - def readme = output["README.md"] + Map output = generate(['camunda-platform7']) + String readme = output["README.md"] then: readme diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/camunda/ZeebeSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/camunda/ZeebeSpec.groovy index 28d5a451727..619d02bcaec 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/camunda/ZeebeSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/camunda/ZeebeSpec.groovy @@ -29,8 +29,8 @@ class ZeebeSpec extends ApplicationContextSpec implements CommandOutputFixture { @PendingFeature(reason = "camunda community features do not support Micronaut Framework 4 yet") void 'test readme.md with feature camunda-zeebe contains links to micronaut docs'() { when: - def output = generate(['camunda-zeebe']) - def readme = output["README.md"] + Map output = generate(['camunda-zeebe']) + String readme = output["README.md"] then: readme diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/chatbots/BaseChatBotSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/chatbots/BaseChatBotSpec.groovy index fd1362b9664..0a581b1cc0d 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/chatbots/BaseChatBotSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/chatbots/BaseChatBotSpec.groovy @@ -13,18 +13,4 @@ abstract class BaseChatBotSpec extends ApplicationContextSpec implements Command abstract Class getFeature() abstract String getFeatureName() - - void 'example chat commands are generated in #language'(Language language) { - when: - ApplicationType applicationType = getSupportedApplicationTypes().contains(ApplicationType.FUNCTION) ? ApplicationType.FUNCTION : getSupportedApplicationTypes().stream().findFirst().orElseThrow() - def output = generate(applicationType, new Options(language), [featureName]) - - then: - output.containsKey("src/main/$language.name/example/micronaut/AboutCommandHandler.$language.extension".toString()) - output.containsKey("src/main/$language.name/example/micronaut/FinalCommandHandler.$language.extension".toString()) - output.containsKey("src/main/resources/botcommands/about.md") - - where: - language << Language.values() - } } diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/chatbots/basecamp/BaseBasecampChatBotSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/chatbots/basecamp/BaseBasecampChatBotSpec.groovy new file mode 100644 index 00000000000..20b20d35932 --- /dev/null +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/chatbots/basecamp/BaseBasecampChatBotSpec.groovy @@ -0,0 +1,47 @@ +package io.micronaut.starter.feature.chatbots.basecamp + +import io.micronaut.starter.application.ApplicationType +import io.micronaut.starter.feature.chatbots.BaseChatBotSpec +import io.micronaut.starter.options.Language +import io.micronaut.starter.options.Options +import io.micronaut.starter.options.TestFramework + +abstract class BaseBasecampChatBotSpec extends BaseChatBotSpec { + + void 'feature #supportMsg ApplicationType #type'(ApplicationType type, boolean supports) { + expect: + beanContext.getBean(feature).supports(type) == supports + + where: + type << ApplicationType.values() + supports = type in supportedApplicationTypes + supportMsg = supports ? 'supports' : 'does not support' + } + + void 'configuration is generated for #applicationType apps'() { + when: + def output = generate(applicationType, [featureName]) + def cfg = output["src/main/resources/application.properties"] + + then: + cfg.contains("micronaut.chatbots.folder=botcommands") + + where: + applicationType << supportedApplicationTypes + } + + void 'example chat commands are generated in #language for #applicationType apps'(Language language, ApplicationType applicationType) { + when: + def output = generate(applicationType, new Options(language, TestFramework.JUNIT), [featureName]) + + then: + output.containsKey("src/main/$language.name/example/micronaut/BasecampAboutCommandHandler.$language.extension".toString()) + output.containsKey("src/main/$language.name/example/micronaut/BasecampFinalCommandHandler.$language.extension".toString()) + output.containsKey("src/main/resources/botcommands/about.html") + output.containsKey(language.getTestSourcePath("/example/micronaut/BasecampAboutCommandHandlerTest")) + output.containsKey("src/test/resources/mockBasecampAboutCommand.json") + + where: + [language, applicationType] << [Language.values(), supportedApplicationTypes].combinations() + } +} diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/chatbots/basecamp/BasecampAwsChatBotSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/chatbots/basecamp/BasecampAwsChatBotSpec.groovy new file mode 100644 index 00000000000..84841534235 --- /dev/null +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/chatbots/basecamp/BasecampAwsChatBotSpec.groovy @@ -0,0 +1,83 @@ +package io.micronaut.starter.feature.chatbots.basecamp + +import io.micronaut.starter.application.ApplicationType +import io.micronaut.starter.feature.aws.AwsLambdaFeatureValidator +import io.micronaut.starter.feature.aws.Cdk +import io.micronaut.starter.feature.chatbots.ChatBotsFeature +import io.micronaut.starter.feature.function.Cloud +import io.micronaut.starter.options.BuildTool +import io.micronaut.starter.options.Language +import io.micronaut.starter.options.Options +import io.micronaut.starter.options.TestFramework + +class BasecampAwsChatBotSpec extends BaseBasecampChatBotSpec { + + @Override + List getSupportedApplicationTypes() { + [ApplicationType.FUNCTION] + } + + @Override + Class getFeature() { + BasecampAwsChatBot + } + + @Override + String getFeatureName() { + BasecampAwsChatBot.NAME + } + + void 'chatbots-basecamp-lambda feature is an AWS cloud feature'() { + expect: + Cloud.AWS == beanContext.getBean(feature).getCloud() + } + + void 'test README contains docs for #buildTool'(BuildTool buildTool) { + when: + Map output = generate(ApplicationType.FUNCTION, new Options(Language.JAVA, buildTool), [featureName]) + String readme = output["README.md"] + + then: + readme.contains("Basecamp ChatBot") + readme.contains("## Lambda handler class") + readme.contains("When deployed to AWS Lambda, the lambda handler should be defined as `io.micronaut.chatbots.basecamp.lambda.Handler`.") + readme.contains("- [Micronaut Validation documentation](https://micronaut-projects.github.io/micronaut-validation/latest/guide/)") + readme.contains("- [Micronaut AWS Lambda Function documentation](https://micronaut-projects.github.io/micronaut-aws/latest/guide/index.html#lambda)") + readme.contains("- [Micronaut Basecamp ChatBot as AWS Lambda function documentation](https://micronaut-projects.github.io/micronaut-chatbots/latest/guide/)") + + where: + buildTool << BuildTool.values() + } + + void 'test README contains docs for #buildTool with CDK'(BuildTool buildTool) { + when: + Map output = generate(ApplicationType.FUNCTION, new Options(Language.JAVA, buildTool), [featureName, 'aws-cdk']) + String readme = output["README.md"] + + then: + readme.contains("Basecamp ChatBot") + readme.contains("## Lambda handler class") + readme.contains("The Cdk project defined in `infra` is already configured to use `io.micronaut.chatbots.basecamp.lambda.Handler` as the handler for your Lambda function.") + readme.contains("## How to deploy") + readme.contains("- [Micronaut Validation documentation](https://micronaut-projects.github.io/micronaut-validation/latest/guide/)") + readme.contains("- [Micronaut AWS Lambda Function documentation](https://micronaut-projects.github.io/micronaut-aws/latest/guide/index.html#lambda)") + readme.contains("- [Micronaut Basecamp ChatBot as AWS Lambda function documentation](https://micronaut-projects.github.io/micronaut-chatbots/latest/guide/)") + readme.contains("## Feature aws-cdk documentation") + readme.contains("- [https://docs.aws.amazon.com/cdk/v2/guide/home.html](https://docs.aws.amazon.com/cdk/v2/guide/home.html)") + + where: + buildTool << BuildTool.values() + } + + void 'Handler is is set to io.micronaut.chatbots.basecamp.lambda.Handler in CDK when features chatbots-basecamp-lambda and aws-cdk'() { + when: + Options options = new Options(Language.JAVA, TestFramework.JUNIT, BuildTool.GRADLE_KOTLIN, AwsLambdaFeatureValidator.firstSupportedJdk()) + Map output = generate(ApplicationType.FUNCTION, options, [BasecampAwsChatBot.NAME, Cdk.NAME]) + + then: + output.'infra/src/main/java/example/micronaut/AppStack.java'.contains('io.micronaut.chatbots.basecamp.lambda.Handler') + + where: + buildTool << BuildTool.values() + } +} diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/chatbots/basecamp/BasecampAzureChatBotSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/chatbots/basecamp/BasecampAzureChatBotSpec.groovy new file mode 100644 index 00000000000..51753680631 --- /dev/null +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/chatbots/basecamp/BasecampAzureChatBotSpec.groovy @@ -0,0 +1,50 @@ +package io.micronaut.starter.feature.chatbots.basecamp + +import io.micronaut.starter.application.ApplicationType +import io.micronaut.starter.feature.chatbots.ChatBotsFeature +import io.micronaut.starter.feature.function.Cloud +import io.micronaut.starter.feature.function.azure.AzureBuildCommandUtils +import io.micronaut.starter.options.BuildTool +import io.micronaut.starter.options.Language +import io.micronaut.starter.options.Options + +class BasecampAzureChatBotSpec extends BaseBasecampChatBotSpec { + + @Override + Class getFeature() { + BasecampAzureChatBot + } + + @Override + String getFeatureName() { + BasecampAzureChatBot.NAME + } + + @Override + List getSupportedApplicationTypes() { + [ApplicationType.FUNCTION] + } + + void 'chatbots-basecamp-azure-function feature is an Azure cloud feature'() { + expect: + Cloud.AZURE == beanContext.getBean(feature).getCloud() + } + + void 'test README contains docs for #buildTool and command "#command"'(BuildTool buildTool, String command) { + when: + Map output = generate(ApplicationType.FUNCTION, new Options(Language.JAVA, buildTool), [featureName]) + String readme = output["README.md"] + + then: + readme.contains("Basecamp ChatBot") + readme.contains("./$command") + readme.contains("- [Micronaut Azure Function documentation](https://micronaut-projects.github.io/micronaut-azure/latest/guide/index.html#simpleAzureFunctions)") + readme.contains("- [https://docs.microsoft.com/azure](https://docs.microsoft.com/azure)") + readme.contains("- [Micronaut Validation documentation](https://micronaut-projects.github.io/micronaut-validation/latest/guide/)") + readme.contains("- [Micronaut Basecamp ChatBot as an Azure Function documentation](https://micronaut-projects.github.io/micronaut-chatbots/latest/guide/)") + + where: + buildTool << BuildTool.values() + command = buildTool.isGradle() ? AzureBuildCommandUtils.GRADLE_AZURE_DEPLOY_COMMAND : AzureBuildCommandUtils.MAVEN_AZURE_DEPLOY_COMMAND + } +} diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/chatbots/basecamp/BasecampGcpChatBotSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/chatbots/basecamp/BasecampGcpChatBotSpec.groovy new file mode 100644 index 00000000000..850fb5d4806 --- /dev/null +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/chatbots/basecamp/BasecampGcpChatBotSpec.groovy @@ -0,0 +1,48 @@ +package io.micronaut.starter.feature.chatbots.basecamp + +import io.micronaut.starter.application.ApplicationType +import io.micronaut.starter.feature.chatbots.ChatBotsFeature +import io.micronaut.starter.feature.function.Cloud +import io.micronaut.starter.feature.function.gcp.GcpCloudFunctionBuildCommandUtils +import io.micronaut.starter.options.BuildTool +import io.micronaut.starter.options.Language +import io.micronaut.starter.options.Options + +class BasecampGcpChatBotSpec extends BaseBasecampChatBotSpec { + + @Override + Class getFeature() { + BasecampGcpChatBot + } + + @Override + String getFeatureName() { + BasecampGcpChatBot.NAME + } + + List getSupportedApplicationTypes() { + [ApplicationType.FUNCTION] + } + + void 'chatbots-basecamp-gcp-function feature is an GCP cloud feature'() { + expect: + Cloud.GCP == beanContext.getBean(feature).getCloud() + } + + void 'test README contains docs for #buildTool and command "#command"'(BuildTool buildTool, String command) { + when: + Map output = generate(ApplicationType.FUNCTION, new Options(Language.JAVA, buildTool), [featureName]) + String readme = output["README.md"] + + then: + readme.contains("Basecamp ChatBot") + readme.contains("./$command") + readme.contains("- [Micronaut Google Cloud Function documentation](https://micronaut-projects.github.io/micronaut-gcp/latest/guide/index.html#simpleFunctions)") + readme.contains("- [Micronaut Validation documentation](https://micronaut-projects.github.io/micronaut-validation/latest/guide/)") + readme.contains("- [Micronaut Basecamp ChatBot as a Google Cloud Function documentation](https://micronaut-projects.github.io/micronaut-chatbots/latest/guide/)") + + where: + buildTool << BuildTool.values() + command = buildTool.isGradle() ? GcpCloudFunctionBuildCommandUtils.GRADLE_PACKAGE_COMMAND : GcpCloudFunctionBuildCommandUtils.MAVEN_PACKAGE_COMMAND + } +} diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/chatbots/basecamp/BasecampHttpChatBotSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/chatbots/basecamp/BasecampHttpChatBotSpec.groovy new file mode 100644 index 00000000000..3ea081f8be7 --- /dev/null +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/chatbots/basecamp/BasecampHttpChatBotSpec.groovy @@ -0,0 +1,40 @@ +package io.micronaut.starter.feature.chatbots.basecamp + +import io.micronaut.starter.application.ApplicationType +import io.micronaut.starter.feature.chatbots.ChatBotsFeature +import io.micronaut.starter.options.BuildTool +import io.micronaut.starter.options.Language +import io.micronaut.starter.options.Options + +class BasecampHttpChatBotSpec extends BaseBasecampChatBotSpec { + + @Override + List getSupportedApplicationTypes() { + [ApplicationType.DEFAULT] + } + + @Override + Class getFeature() { + BasecampHttpChatBot + } + + @Override + String getFeatureName() { + BasecampHttpChatBot.NAME + } + + void 'test README contains docs for #buildTool'(BuildTool buildTool) { + when: + Map output = generate(ApplicationType.DEFAULT, new Options(Language.JAVA, buildTool), [featureName]) + String readme = output["README.md"] + + then: + readme.contains("Basecamp ChatBot") + readme.contains("This project has a dependency on `micronaut-chatbots-basecamp-http` which has added a controller to your application with the path `/basecamp`.") + readme.contains("- [Micronaut Validation documentation](https://micronaut-projects.github.io/micronaut-validation/latest/guide/)") + readme.contains("- [Micronaut Basecamp ChatBot as a controller documentation](https://micronaut-projects.github.io/micronaut-chatbots/latest/guide/)") + + where: + buildTool << BuildTool.values() + } +} diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/chatbots/telegram/TelegramAwsChatBotSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/chatbots/telegram/TelegramAwsChatBotSpec.groovy index fdb326633e0..75daaabb329 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/chatbots/telegram/TelegramAwsChatBotSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/chatbots/telegram/TelegramAwsChatBotSpec.groovy @@ -35,8 +35,8 @@ class TelegramAwsChatBotSpec extends BaseTelegramChatBotSpec { void 'test README contains docs for #buildTool'(BuildTool buildTool) { when: - def output = generate(ApplicationType.FUNCTION, new Options(Language.JAVA, buildTool), [featureName]) - def readme = output["README.md"] + Map output = generate(ApplicationType.FUNCTION, new Options(Language.JAVA, buildTool), [featureName]) + String readme = output["README.md"] then: readme.contains("Telegram ChatBot") @@ -52,8 +52,8 @@ class TelegramAwsChatBotSpec extends BaseTelegramChatBotSpec { void 'test README contains docs for #buildTool with CDK'(BuildTool buildTool) { when: - def output = generate(ApplicationType.FUNCTION, new Options(Language.JAVA, buildTool), [featureName, 'aws-cdk']) - def readme = output["README.md"] + Map output = generate(ApplicationType.FUNCTION, new Options(Language.JAVA, buildTool), [featureName, 'aws-cdk']) + String readme = output["README.md"] then: readme.contains("Telegram ChatBot") diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/chatbots/telegram/TelegramAzureChatBotSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/chatbots/telegram/TelegramAzureChatBotSpec.groovy index e05215712e2..1fccb1e2fdc 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/chatbots/telegram/TelegramAzureChatBotSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/chatbots/telegram/TelegramAzureChatBotSpec.groovy @@ -33,8 +33,8 @@ class TelegramAzureChatBotSpec extends BaseTelegramChatBotSpec { void 'test README contains docs for #buildTool and command "#command"'(BuildTool buildTool, String command) { when: - def output = generate(ApplicationType.FUNCTION, new Options(Language.JAVA, buildTool), [featureName]) - def readme = output["README.md"] + Map output = generate(ApplicationType.FUNCTION, new Options(Language.JAVA, buildTool), [featureName]) + String readme = output["README.md"] then: readme.contains("Telegram ChatBot") diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/chatbots/telegram/TelegramGcpChatBotSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/chatbots/telegram/TelegramGcpChatBotSpec.groovy index 3ea41173739..81c177238a8 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/chatbots/telegram/TelegramGcpChatBotSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/chatbots/telegram/TelegramGcpChatBotSpec.groovy @@ -35,8 +35,8 @@ class TelegramGcpChatBotSpec extends BaseTelegramChatBotSpec { void 'test README contains docs for #buildTool and command "#command"'(BuildTool buildTool, String command) { when: - def output = generate(ApplicationType.FUNCTION, new Options(Language.JAVA, buildTool), [featureName]) - def readme = output["README.md"] + Map output = generate(ApplicationType.FUNCTION, new Options(Language.JAVA, buildTool), [featureName]) + String readme = output["README.md"] then: readme.contains("Telegram ChatBot") diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/chatbots/telegram/TelegramHttpChatBotSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/chatbots/telegram/TelegramHttpChatBotSpec.groovy index be70b2bd83f..4de1f5bf30f 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/chatbots/telegram/TelegramHttpChatBotSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/chatbots/telegram/TelegramHttpChatBotSpec.groovy @@ -25,8 +25,8 @@ class TelegramHttpChatBotSpec extends BaseTelegramChatBotSpec { void 'test README contains docs for #buildTool'(BuildTool buildTool) { when: - def output = generate(ApplicationType.DEFAULT, new Options(Language.JAVA, buildTool), [featureName]) - def readme = output["README.md"] + Map output = generate(ApplicationType.DEFAULT, new Options(Language.JAVA, buildTool), [featureName]) + String readme = output["README.md"] then: readme.contains("Telegram ChatBot") diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/ci/workflows/oci/OCIWorkflowCISpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/ci/workflows/oci/OCIWorkflowCISpec.groovy index d05ef2a3952..43a1b184bd0 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/ci/workflows/oci/OCIWorkflowCISpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/ci/workflows/oci/OCIWorkflowCISpec.groovy @@ -14,8 +14,16 @@ import spock.lang.Unroll class OCIWorkflowCISpec extends BeanContextSpec implements CommandOutputFixture { + void "test oracle-cloud-devops-build-ci is a not a preview feature"() { + given: + OCICiWorkflowFeature feature = beanContext.getBean(OCICiWorkflowFeature) + + expect: + !feature.isPreview() + } + @Unroll - void 'test oci-devops-build-ci is created for #buildTool and #jdkVersion'(BuildTool buildTool, JdkVersion jdkVersion) { + void 'test oracle-cloud-devops-build-ci is created for #buildTool and #jdkVersion'(BuildTool buildTool, JdkVersion jdkVersion) { when: def output = generate(ApplicationType.DEFAULT, new Options(Language.JAVA, TestFramework.JUNIT, buildTool, jdkVersion), @@ -54,7 +62,7 @@ class OCIWorkflowCISpec extends BeanContextSpec implements CommandOutputFixture } @Unroll - void 'test oci-devops-build-ci and graalvm is created for #buildTool and #jdkVersion'(BuildTool buildTool, JdkVersion jdkVersion) { + void 'test oracle-cloud-devops-build-ci and graalvm is created for #buildTool and #jdkVersion'(BuildTool buildTool, JdkVersion jdkVersion) { when: def output = generate(ApplicationType.DEFAULT, new Options(Language.JAVA, TestFramework.JUNIT, buildTool, JdkVersion.valueOf(jdkVersion.majorVersion())), diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/coherence/CoherenceDataSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/coherence/CoherenceDataSpec.groovy index 61b35cf2476..cd6e323fd4a 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/coherence/CoherenceDataSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/coherence/CoherenceDataSpec.groovy @@ -13,8 +13,8 @@ class CoherenceDataSpec extends BeanContextSpec implements CommandOutputFixture void 'test readme.md with feature coherence-data contains links to micronaut docs'() { when: - def output = generate([CoherenceData.NAME]) - def readme = output["README.md"] + Map output = generate([CoherenceData.NAME]) + String readme = output["README.md"] then: readme diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/coherence/CoherenceDistributedConfigurationSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/coherence/CoherenceDistributedConfigurationSpec.groovy index 0255205c9c4..e09c153e061 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/coherence/CoherenceDistributedConfigurationSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/coherence/CoherenceDistributedConfigurationSpec.groovy @@ -12,8 +12,8 @@ class CoherenceDistributedConfigurationSpec extends BeanContextSpec implements C void 'test readme.md with feature coherence-distributed-configuration contains links to micronaut docs'() { when: - def output = generate([CoherenceDistributedConfiguration.NAME]) - def readme = output["README.md"] + Map output = generate([CoherenceDistributedConfiguration.NAME]) + String readme = output["README.md"] then: readme diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/coherence/CoherenceFeatureSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/coherence/CoherenceFeatureSpec.groovy index 2b46afdd8af..49d0bcafd21 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/coherence/CoherenceFeatureSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/coherence/CoherenceFeatureSpec.groovy @@ -11,8 +11,8 @@ class CoherenceFeatureSpec extends BeanContextSpec implements CommandOutputFixtu void 'test readme.md with feature coherence contains links to micronaut docs'() { when: - def output = generate([CoherenceFeature.NAME]) - def readme = output["README.md"] + Map output = generate([CoherenceFeature.NAME]) + String readme = output["README.md"] then: readme diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/coherence/CoherenceGrpcClientSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/coherence/CoherenceGrpcClientSpec.groovy index 023f53a052d..9ee032f05f6 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/coherence/CoherenceGrpcClientSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/coherence/CoherenceGrpcClientSpec.groovy @@ -12,8 +12,8 @@ class CoherenceGrpcClientSpec extends BeanContextSpec implements CommandOutputFi void 'test readme.md with feature coherence-grpc-client contains links to micronaut docs'() { when: - def output = generate([CoherenceGrpcClient.NAME]) - def readme = output["README.md"] + Map output = generate([CoherenceGrpcClient.NAME]) + String readme = output["README.md"] then: readme diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/coherence/CoherenceSessionSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/coherence/CoherenceSessionSpec.groovy index bcf69d7b90e..dd3ad640b71 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/coherence/CoherenceSessionSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/coherence/CoherenceSessionSpec.groovy @@ -12,8 +12,8 @@ class CoherenceSessionSpec extends BeanContextSpec implements CommandOutputFixtu void 'test readme.md with feature coherence-session contains links to micronaut docs'() { when: - def output = generate([CoherenceSessionStore.NAME]) - def readme = output["README.md"] + Map output = generate([CoherenceSessionStore.NAME]) + String readme = output["README.md"] then: readme diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/crac/CracSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/crac/CracSpec.groovy index 69108630a0d..91506c1d005 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/crac/CracSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/crac/CracSpec.groovy @@ -23,8 +23,8 @@ class CracSpec extends ApplicationContextSpec implements CommandOutputFixture { void 'test readme.md with feature crac contains links to micronaut docs'() { when: - def output = generate([Crac.NAME]) - def readme = output["README.md"] + Map output = generate([Crac.NAME]) + String readme = output["README.md"] then: readme.contains("[Micronaut Support for CRaC (Coordinated Restore at Checkpoint) documentation](https://micronaut-projects.github.io/micronaut-crac/latest/guide)") diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/database/CassandraSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/database/CassandraSpec.groovy index 06abf2e4d66..6a4f8fd6871 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/database/CassandraSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/database/CassandraSpec.groovy @@ -85,8 +85,8 @@ class CassandraSpec extends ApplicationContextSpec implements CommandOutputFixtu void 'test readme has docs'() { when: - def output = generate([Cassandra.NAME]) - def readme = output["README.md"] + Map output = generate([Cassandra.NAME]) + String readme = output["README.md"] then: readme diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/database/DataAzureCosmosFeatureSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/database/DataAzureCosmosFeatureSpec.groovy index 4f5706d6cd4..27eade17021 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/database/DataAzureCosmosFeatureSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/database/DataAzureCosmosFeatureSpec.groovy @@ -20,8 +20,8 @@ class DataAzureCosmosFeatureSpec extends ApplicationContextSpec implements Comma void 'test README.md with feature data-azure-cosmos contains links to micronaut and microsoft docs'() { when: - def output = generate(['data-azure-cosmos']) - def readme = output["README.md"] + Map output = generate(['data-azure-cosmos']) + String readme = output["README.md"] then: readme.contains("[Micronaut Data Azure Cosmos documentation](https://micronaut-projects.github.io/micronaut-data/latest/guide/#azureCosmos)") diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/database/DataHibernateReactiveSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/database/DataHibernateReactiveSpec.groovy index 18b2d3fe23e..03a472b0be5 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/database/DataHibernateReactiveSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/database/DataHibernateReactiveSpec.groovy @@ -1,26 +1,25 @@ package io.micronaut.starter.feature.database +import groovy.transform.Canonical import groovy.xml.XmlSlurper import io.micronaut.starter.BuildBuilder import io.micronaut.starter.application.generator.GeneratorContext import io.micronaut.starter.build.BuildTestUtil import io.micronaut.starter.build.BuildTestVerifier +import io.micronaut.starter.build.dependencies.Dependency import io.micronaut.starter.build.dependencies.Scope import io.micronaut.starter.feature.Features import io.micronaut.starter.feature.migration.Flyway import io.micronaut.starter.feature.migration.Liquibase import io.micronaut.starter.feature.testresources.DbType import io.micronaut.starter.options.BuildTool -import io.micronaut.starter.options.JdkVersion import io.micronaut.starter.options.Language import io.micronaut.starter.options.MicronautJdkVersionConfiguration import spock.lang.Issue -import spock.lang.Requires import static io.micronaut.starter.build.dependencies.MicronautDependencyUtils.ARTIFACT_ID_MICRONAUT_DATA_PROCESSOR_ARTIFACT import static io.micronaut.starter.build.dependencies.MicronautDependencyUtils.GROUP_ID_MICRONAUT_DATA -@Requires({ jvm.current.isJava11Compatible() }) class DataHibernateReactiveSpec extends BaseHibernateReactiveSpec { void "test data jpa reactive requires db"() { @@ -31,10 +30,10 @@ class DataHibernateReactiveSpec extends BaseHibernateReactiveSpec { IllegalArgumentException exception = thrown() and: - exception.message == "Hibernate Reactive requires $MariaDB.NAME, $MySQL.NAME, $Oracle.NAME, $PostgreSQL.NAME, or $SQLServer.NAME" + exception.message == "Hibernate Reactive requires $MariaDB.NAME, $MySQL.NAME, $PostgreSQL.NAME, or $SQLServer.NAME" } - void "test data jpa reactive features for #db"() { + void "test data jpa reactive features for #db"(String db) { when: Features features = getFeatures([DataHibernateReactive.NAME, db]) @@ -45,7 +44,7 @@ class DataHibernateReactiveSpec extends BaseHibernateReactiveSpec { features.contains(DataHibernateReactive.NAME) where: - db << [MySQL.NAME, MariaDB.NAME, PostgreSQL.NAME, Oracle.NAME, SQLServer.NAME] + db << databases() } void "test data jpa reactive features with #migration for #db"(String db, String migration) { @@ -60,44 +59,20 @@ class DataHibernateReactiveSpec extends BaseHibernateReactiveSpec { features.contains(DataHibernateReactive.NAME) where: - [db, migration] << [[MySQL.NAME, MariaDB.NAME, PostgreSQL.NAME, Oracle.NAME, SQLServer.NAME], [Liquibase.NAME, Flyway.NAME]].combinations() + [db, migration] << [databases(), [Liquibase.NAME, Flyway.NAME]].combinations() } - void "data hibernate reactive requires java 11"() { - when: - new BuildBuilder(beanContext, BuildTool.GRADLE) - .jdkVersion(JdkVersion.JDK_8) - .features([DataHibernateReactive.NAME, MySQL.NAME]) - .render() - - then: - IllegalArgumentException ex = thrown() - ex.message == "Hibernate Reactive requires at least JDK 11" - - when: - new BuildBuilder(beanContext, BuildTool.GRADLE) - .jdkVersion(MicronautJdkVersionConfiguration.DEFAULT_OPTION) - .features([DataHibernateReactive.NAME, MySQL.NAME]) - .render() - - then: - noExceptionThrown() - - when: - new BuildBuilder(beanContext, BuildTool.GRADLE) - .jdkVersion(JdkVersion.JDK_17) - .features([DataHibernateReactive.NAME, MySQL.NAME]) - .render() - - then: - noExceptionThrown() + private List databases() { + Oracle.COMPATIBLE_WITH_HIBERNATE_REACTIVE + ? [MySQL.NAME, MariaDB.NAME, PostgreSQL.NAME, Oracle.NAME, SQLServer.NAME] + : [MySQL.NAME, MariaDB.NAME, PostgreSQL.NAME, SQLServer.NAME] } - void "test dependencies are present for gradle with #db (#client)"() { + void "test dependencies are present for gradle with #testScenario.db (#testScenario.client)"(TestScenario testScenario) { when: String template = new BuildBuilder(beanContext, BuildTool.GRADLE) .jdkVersion(MicronautJdkVersionConfiguration.DEFAULT_OPTION) - .features([DataHibernateReactive.NAME, db]) + .features([DataHibernateReactive.NAME, testScenario.db]) .render() then: @@ -106,33 +81,38 @@ class DataHibernateReactiveSpec extends BaseHibernateReactiveSpec { template.contains('implementation("io.micronaut.data:micronaut-data-hibernate-reactive")') !template.contains('implementation("io.micronaut.sql:micronaut-hibernate-reactive")') !template.contains('implementation("io.micronaut.sql:micronaut-jdbc-hikari")') - template.contains($/implementation("$HibernateReactiveFeature.IO_VERTX_DEPENDENCY_GROUP:$client")/$) + template.contains($/implementation("$HibernateReactiveFeature.IO_VERTX_DEPENDENCY_GROUP:$testScenario.client")/$) !template.contains('testImplementation("org.testcontainers:testcontainers")') - !template.contains($/testImplementation("org.testcontainers:$container")/$) + !template.contains($/testImplementation("org.testcontainers:$testScenario.container")/$) and: "postgres needs another dependency with vert.x" - template.contains('implementation("com.ongres.scram:client:') == (db == PostgreSQL.NAME) + template.contains('implementation("com.ongres.scram:client:') == (testScenario.db == PostgreSQL.NAME) and: 'the driver and correct module are included for test-resources' - !template.contains($/runtimeOnly("$driver.groupId:$driver.artifactId")/$) - template.contains($/testResourcesService("$driver.groupId:$driver.artifactId")/$) - template.contains($/additionalModules.add("$testResourcesModule")/$) + !template.contains($/runtimeOnly("$testScenario.driver.groupId:$testScenario.driver.artifactId")/$) + template.contains($/testResourcesService("$testScenario.driver.groupId:$testScenario.driver.artifactId")/$) + template.contains($/additionalModules.add("$testScenario.testResourcesModule")/$) where: - db | client | container | testResourcesModule | driver - MySQL.NAME | MySQLCompatibleFeature.VERTX_MYSQL_CLIENT | 'mysql' | DbType.MYSQL.hibernateReactiveTestResourcesModuleName | MySQL.DEPENDENCY_MYSQL_CONNECTOR_JAVA.build() - MariaDB.NAME | MySQLCompatibleFeature.VERTX_MYSQL_CLIENT | 'mariadb' | DbType.MARIADB.hibernateReactiveTestResourcesModuleName | MariaDB.DEPENDENCY_MARIADB_JAVA_CLIENT.build() - PostgreSQL.NAME | PostgreSQL.VERTX_PG_CLIENT | 'postgresql' | DbType.POSTGRESQL.hibernateReactiveTestResourcesModuleName | PostgreSQL.DEPENDENCY_POSTGRESQL.build() - Oracle.NAME | Oracle.VERTX_ORACLE_CLIENT | 'oracle-xe' | DbType.ORACLEXE.hibernateReactiveTestResourcesModuleName | Oracle.DEPENDENCY_OJDBC8.build() - SQLServer.NAME | SQLServer.VERTX_MSSQL_CLIENT | 'mssqlserver' | DbType.SQLSERVER.hibernateReactiveTestResourcesModuleName | SQLServer.DEPENDENCY_MSSQL_JDBC.build() + testScenario << testScenarios() + } + + private List testScenarios() { + filter([ + new TestScenario(MySQL.NAME, MySQLCompatibleFeature.VERTX_MYSQL_CLIENT, 'mysql', null, DbType.MYSQL.hibernateReactiveTestResourcesModuleName, MySQL.DEPENDENCY_MYSQL_CONNECTOR_JAVA.build()), + new TestScenario(MariaDB.NAME, MySQLCompatibleFeature.VERTX_MYSQL_CLIENT, 'mariadb', null, DbType.MARIADB.hibernateReactiveTestResourcesModuleName, MariaDB.DEPENDENCY_MARIADB_JAVA_CLIENT.build()), + new TestScenario(PostgreSQL.NAME, PostgreSQL.VERTX_PG_CLIENT, 'postgresql', null, DbType.POSTGRESQL.hibernateReactiveTestResourcesModuleName, PostgreSQL.DEPENDENCY_POSTGRESQL.build()), + new TestScenario(Oracle.NAME, Oracle.VERTX_ORACLE_CLIENT, 'oracle-free', null, DbType.ORACLEFREE.hibernateReactiveTestResourcesModuleName, Oracle.DEPENDENCY_OJDBC11.build()), + new TestScenario(SQLServer.NAME, SQLServer.VERTX_MSSQL_CLIENT, 'mssqlserver', null, DbType.SQLSERVER.hibernateReactiveTestResourcesModuleName, SQLServer.DEPENDENCY_MSSQL_JDBC.build()) + ]) } - void "test dependencies are present for gradle with #db (#client) and #migration"() { + void "test dependencies are present for gradle with #testScenario.db (#testScenario.client) and #testScenario.migration"(TestScenario testScenario) { when: String template = new BuildBuilder(beanContext, BuildTool.GRADLE) .jdkVersion(MicronautJdkVersionConfiguration.DEFAULT_OPTION) - .features([DataHibernateReactive.NAME, db, migration]) + .features([DataHibernateReactive.NAME, testScenario.db, testScenario.migration]) .render() then: @@ -140,33 +120,38 @@ class DataHibernateReactiveSpec extends BaseHibernateReactiveSpec { template.contains('implementation("io.micronaut.data:micronaut-data-hibernate-reactive")') !template.contains('implementation("io.micronaut.sql:micronaut-hibernate-reactive")') template.contains('implementation("io.micronaut.sql:micronaut-jdbc-hikari")') - template.contains($/implementation("io.micronaut.$migration:micronaut-$migration")/$) - template.contains($/runtimeOnly("$migrationDriver.groupId:$migrationDriver.artifactId")/$) - template.contains('runtimeOnly("org.flywaydb:flyway-mysql")') == (migration == Flyway.NAME && db in [MySQL.NAME, MariaDB.NAME]) - template.contains($/implementation("$HibernateReactiveFeature.IO_VERTX_DEPENDENCY_GROUP:$client")/$) + template.contains($/implementation("io.micronaut.$testScenario.migration:micronaut-$testScenario.migration")/$) + template.contains($/runtimeOnly("$testScenario.driver.groupId:$testScenario.driver.artifactId")/$) + template.contains('runtimeOnly("org.flywaydb:flyway-mysql")') == (testScenario.migration == Flyway.NAME && testScenario.db in [MySQL.NAME, MariaDB.NAME]) + template.contains($/implementation("$HibernateReactiveFeature.IO_VERTX_DEPENDENCY_GROUP:$testScenario.client")/$) !template.contains('testImplementation("org.testcontainers:testcontainers")') - !template.contains($/testImplementation("org.testcontainers:$container")/$) + !template.contains($/testImplementation("org.testcontainers:$testScenario.container")/$) and: "postgres needs another dependency with vert.x" - template.contains('implementation("com.ongres.scram:client:') == (db == PostgreSQL.NAME) + template.contains('implementation("com.ongres.scram:client:') == (testScenario.db == PostgreSQL.NAME) and: 'the correct module is included for test-resources' - !template.contains($/testResourcesService("$migrationDriver.groupId:$migrationDriver.artifactId")/$) - template.contains($/additionalModules.add("$testResourcesModule")/$) + !template.contains($/testResourcesService("$testScenario.driver.groupId:$testScenario.driver.artifactId")/$) + template.contains($/additionalModules.add("$testScenario.testResourcesModule")/$) where: - db | client | container | migration | testResourcesModule | migrationDriver - MySQL.NAME | MySQLCompatibleFeature.VERTX_MYSQL_CLIENT | 'mysql' | Liquibase.NAME | DbType.MYSQL.hibernateReactiveTestResourcesModuleName | MySQL.DEPENDENCY_MYSQL_CONNECTOR_JAVA.build() - MariaDB.NAME | MySQLCompatibleFeature.VERTX_MYSQL_CLIENT | 'mariadb' | Liquibase.NAME | DbType.MARIADB.hibernateReactiveTestResourcesModuleName | MariaDB.DEPENDENCY_MARIADB_JAVA_CLIENT.build() - PostgreSQL.NAME | PostgreSQL.VERTX_PG_CLIENT | 'postgresql' | Liquibase.NAME | DbType.POSTGRESQL.hibernateReactiveTestResourcesModuleName | PostgreSQL.DEPENDENCY_POSTGRESQL.build() - Oracle.NAME | Oracle.VERTX_ORACLE_CLIENT | 'oracle-xe' | Liquibase.NAME | DbType.ORACLEXE.hibernateReactiveTestResourcesModuleName | Oracle.DEPENDENCY_OJDBC8.build() - SQLServer.NAME | SQLServer.VERTX_MSSQL_CLIENT | 'mssqlserver' | Liquibase.NAME | DbType.SQLSERVER.hibernateReactiveTestResourcesModuleName | SQLServer.DEPENDENCY_MSSQL_JDBC.build() - MySQL.NAME | MySQLCompatibleFeature.VERTX_MYSQL_CLIENT | 'mysql' | Flyway.NAME | DbType.MYSQL.hibernateReactiveTestResourcesModuleName | MySQL.DEPENDENCY_MYSQL_CONNECTOR_JAVA.build() - MariaDB.NAME | MySQLCompatibleFeature.VERTX_MYSQL_CLIENT | 'mariadb' | Flyway.NAME | DbType.MARIADB.hibernateReactiveTestResourcesModuleName | MariaDB.DEPENDENCY_MARIADB_JAVA_CLIENT.build() - PostgreSQL.NAME | PostgreSQL.VERTX_PG_CLIENT | 'postgresql' | Flyway.NAME | DbType.POSTGRESQL.hibernateReactiveTestResourcesModuleName | PostgreSQL.DEPENDENCY_POSTGRESQL.build() - Oracle.NAME | Oracle.VERTX_ORACLE_CLIENT | 'oracle-xe' | Flyway.NAME | DbType.ORACLEXE.hibernateReactiveTestResourcesModuleName | Oracle.DEPENDENCY_OJDBC8.build() - SQLServer.NAME | SQLServer.VERTX_MSSQL_CLIENT | 'mssqlserver' | Flyway.NAME | DbType.SQLSERVER.hibernateReactiveTestResourcesModuleName | SQLServer.DEPENDENCY_MSSQL_JDBC.build() + testScenario << migrationTestScenarios() + } + + List migrationTestScenarios() { + filter([ + new TestScenario(MySQL.NAME, MySQLCompatibleFeature.VERTX_MYSQL_CLIENT, 'mysql', Liquibase.NAME, DbType.MYSQL.hibernateReactiveTestResourcesModuleName, MySQL.DEPENDENCY_MYSQL_CONNECTOR_JAVA.build()), + new TestScenario(MariaDB.NAME, MySQLCompatibleFeature.VERTX_MYSQL_CLIENT, 'mariadb', Liquibase.NAME, DbType.MARIADB.hibernateReactiveTestResourcesModuleName, MariaDB.DEPENDENCY_MARIADB_JAVA_CLIENT.build()), + new TestScenario(PostgreSQL.NAME, PostgreSQL.VERTX_PG_CLIENT, 'postgresql', Liquibase.NAME, DbType.POSTGRESQL.hibernateReactiveTestResourcesModuleName, PostgreSQL.DEPENDENCY_POSTGRESQL.build()), + new TestScenario(Oracle.NAME, Oracle.VERTX_ORACLE_CLIENT, 'oracle-xe', Liquibase.NAME, DbType.ORACLEFREE.hibernateReactiveTestResourcesModuleName, Oracle.DEPENDENCY_OJDBC11.build()), + new TestScenario(SQLServer.NAME, SQLServer.VERTX_MSSQL_CLIENT, 'mssqlserver', Liquibase.NAME, DbType.SQLSERVER.hibernateReactiveTestResourcesModuleName, SQLServer.DEPENDENCY_MSSQL_JDBC.build()), + new TestScenario(MySQL.NAME, MySQLCompatibleFeature.VERTX_MYSQL_CLIENT, 'mysql', Flyway.NAME, DbType.MYSQL.hibernateReactiveTestResourcesModuleName, MySQL.DEPENDENCY_MYSQL_CONNECTOR_JAVA.build()), + new TestScenario(MariaDB.NAME, MySQLCompatibleFeature.VERTX_MYSQL_CLIENT, 'mariadb', Flyway.NAME, DbType.MARIADB.hibernateReactiveTestResourcesModuleName, MariaDB.DEPENDENCY_MARIADB_JAVA_CLIENT.build()), + new TestScenario(PostgreSQL.NAME, PostgreSQL.VERTX_PG_CLIENT, 'postgresql', Flyway.NAME, DbType.POSTGRESQL.hibernateReactiveTestResourcesModuleName, PostgreSQL.DEPENDENCY_POSTGRESQL.build()), + new TestScenario(Oracle.NAME, Oracle.VERTX_ORACLE_CLIENT, 'oracle-xe', Flyway.NAME, DbType.ORACLEFREE.hibernateReactiveTestResourcesModuleName, Oracle.DEPENDENCY_OJDBC11.build()), + new TestScenario(SQLServer.NAME, SQLServer.VERTX_MSSQL_CLIENT, 'mssqlserver', Flyway.NAME, DbType.SQLSERVER.hibernateReactiveTestResourcesModuleName, SQLServer.DEPENDENCY_MSSQL_JDBC.build()) + ]) } void "test kotlin jpa plugin is present for gradle kotlin project"() { @@ -181,10 +166,10 @@ class DataHibernateReactiveSpec extends BaseHibernateReactiveSpec { template.contains('id("org.jetbrains.kotlin.plugin.jpa")') } - void "test dependencies are present for maven with #db (#client)"() { + void "test dependencies are present for maven with #testScenario.db (#testScenario.client)"(TestScenario testScenario) { when: String template = new BuildBuilder(beanContext, BuildTool.MAVEN) - .features([DataHibernateReactive.NAME, db]) + .features([DataHibernateReactive.NAME, testScenario.db]) .jdkVersion(MicronautJdkVersionConfiguration.DEFAULT_OPTION) .render() BuildTestVerifier verifier = BuildTestUtil.verifier(BuildTool.MAVEN, template) @@ -194,32 +179,37 @@ class DataHibernateReactiveSpec extends BaseHibernateReactiveSpec { !containsDataHibernateJpa(template) containsDataHibernateReactive(template) !containsHikariDependency(template) - containsVertXDriver(template, client) - !containsJdbcDriver(template, migrationDriver) + containsVertXDriver(template, testScenario.client) + !containsJdbcDriver(template, testScenario.driver) and: "postgres needs another dependency with vert.x" - db != PostgreSQL.NAME || verifier.hasDependency('com.ongres.scram', "client") + testScenario.db != PostgreSQL.NAME || verifier.hasDependency('com.ongres.scram', "client") and: 'test resources module is correct, and driver is added to the plugin dependencies' - verifier.hasTestResourceDependency("micronaut-test-resources-$testResourcesModule") - verifier.hasTestResourceDependency(migrationDriver.groupId, migrationDriver.artifactId) + verifier.hasTestResourceDependency("micronaut-test-resources-$testScenario.testResourcesModule") + verifier.hasTestResourceDependency(testScenario.driver.groupId, testScenario.driver.artifactId) and: DataJdbcSpec.assertTemplateDoesNotContainMicronautDataVersionProperty(template) where: - db | client | testResourcesModule | migrationDriver - MySQL.NAME | MySQLCompatibleFeature.VERTX_MYSQL_CLIENT | DbType.MYSQL.hibernateReactiveTestResourcesModuleName | MySQL.DEPENDENCY_MYSQL_CONNECTOR_JAVA.build() - MariaDB.NAME | MySQLCompatibleFeature.VERTX_MYSQL_CLIENT | DbType.MARIADB.hibernateReactiveTestResourcesModuleName | MariaDB.DEPENDENCY_MARIADB_JAVA_CLIENT.build() - PostgreSQL.NAME | PostgreSQL.VERTX_PG_CLIENT | DbType.POSTGRESQL.hibernateReactiveTestResourcesModuleName | PostgreSQL.DEPENDENCY_POSTGRESQL.build() - Oracle.NAME | Oracle.VERTX_ORACLE_CLIENT | DbType.ORACLEXE.hibernateReactiveTestResourcesModuleName | Oracle.DEPENDENCY_OJDBC8.build() - SQLServer.NAME | SQLServer.VERTX_MSSQL_CLIENT | DbType.SQLSERVER.hibernateReactiveTestResourcesModuleName | SQLServer.DEPENDENCY_MSSQL_JDBC.build() + testScenario << mavenTestScenarios() } - void "test dependencies are present for maven with #db (#client) and #migration"() { + List mavenTestScenarios() { + filter([ + new TestScenario(MySQL.NAME, MySQLCompatibleFeature.VERTX_MYSQL_CLIENT, null, null, DbType.MYSQL.hibernateReactiveTestResourcesModuleName, MySQL.DEPENDENCY_MYSQL_CONNECTOR_JAVA.build()), + new TestScenario(MariaDB.NAME, MySQLCompatibleFeature.VERTX_MYSQL_CLIENT , null, null, DbType.MARIADB.hibernateReactiveTestResourcesModuleName, MariaDB.DEPENDENCY_MARIADB_JAVA_CLIENT.build()), + new TestScenario(PostgreSQL.NAME , PostgreSQL.VERTX_PG_CLIENT, null, null, DbType.POSTGRESQL.hibernateReactiveTestResourcesModuleName, PostgreSQL.DEPENDENCY_POSTGRESQL.build()), + new TestScenario(Oracle.NAME, Oracle.VERTX_ORACLE_CLIENT, null, null, DbType.ORACLEFREE.hibernateReactiveTestResourcesModuleName, Oracle.DEPENDENCY_OJDBC11.build()), + new TestScenario(SQLServer.NAME, SQLServer.VERTX_MSSQL_CLIENT, null, null, DbType.SQLSERVER.hibernateReactiveTestResourcesModuleName, SQLServer.DEPENDENCY_MSSQL_JDBC.build()), + ]) + } + + void "test dependencies are present for maven with #testScenario.db (#testScenario.client) and #testScenario.migration"(TestScenario testScenario) { when: BuildTool buildTool = BuildTool.MAVEN String template = new BuildBuilder(beanContext, buildTool) - .features([DataHibernateReactive.NAME, db, migration]) + .features([DataHibernateReactive.NAME, testScenario.db, testScenario.migration]) .jdkVersion(MicronautJdkVersionConfiguration.DEFAULT_OPTION) .render() BuildTestVerifier verifier = BuildTestUtil.verifier(buildTool, template) @@ -229,31 +219,36 @@ class DataHibernateReactiveSpec extends BaseHibernateReactiveSpec { !containsDataHibernateJpa(template) containsDataHibernateReactive(template) containsHikariDependency(template) - containsVertXDriver(template, client) - containsMigrationLibrary(template, migration) - containsJdbcDriver(template, migrationDriver) + containsVertXDriver(template, testScenario.client) + containsMigrationLibrary(template, testScenario.migration) + containsJdbcDriver(template, testScenario.driver) and: "postgres needs another dependency with vert.x" - db != PostgreSQL.NAME || verifier.hasDependency('com.ongres.scram', "client") + testScenario.db != PostgreSQL.NAME || verifier.hasDependency('com.ongres.scram', "client") and: 'test resources module is correct, and driver is not added to the plugin dependencies' - verifier.hasTestResourceDependency("micronaut-test-resources-$testResourcesModule") - !verifier.hasTestResourceDependencyWithGroupId(migrationDriver.groupId) + verifier.hasTestResourceDependency("micronaut-test-resources-$testScenario.testResourcesModule") + !verifier.hasTestResourceDependencyWithGroupId(testScenario.driver.groupId) and: DataJdbcSpec.assertTemplateDoesNotContainMicronautDataVersionProperty(template) where: - db | client | migration | testResourcesModule | migrationDriver - MySQL.NAME | MySQLCompatibleFeature.VERTX_MYSQL_CLIENT | Liquibase.NAME | DbType.MYSQL.hibernateReactiveTestResourcesModuleName | MySQL.DEPENDENCY_MYSQL_CONNECTOR_JAVA.build() - MariaDB.NAME | MySQLCompatibleFeature.VERTX_MYSQL_CLIENT | Liquibase.NAME | DbType.MARIADB.hibernateReactiveTestResourcesModuleName | MariaDB.DEPENDENCY_MARIADB_JAVA_CLIENT.build() - PostgreSQL.NAME | PostgreSQL.VERTX_PG_CLIENT | Liquibase.NAME | DbType.POSTGRESQL.hibernateReactiveTestResourcesModuleName | PostgreSQL.DEPENDENCY_POSTGRESQL.build() - Oracle.NAME | Oracle.VERTX_ORACLE_CLIENT | Liquibase.NAME | DbType.ORACLEXE.hibernateReactiveTestResourcesModuleName | Oracle.DEPENDENCY_OJDBC8.build() - SQLServer.NAME | SQLServer.VERTX_MSSQL_CLIENT | Liquibase.NAME | DbType.SQLSERVER.hibernateReactiveTestResourcesModuleName | SQLServer.DEPENDENCY_MSSQL_JDBC.build() - MySQL.NAME | MySQLCompatibleFeature.VERTX_MYSQL_CLIENT | Flyway.NAME | DbType.MYSQL.hibernateReactiveTestResourcesModuleName | MySQL.DEPENDENCY_MYSQL_CONNECTOR_JAVA.build() - MariaDB.NAME | MySQLCompatibleFeature.VERTX_MYSQL_CLIENT | Flyway.NAME | DbType.MARIADB.hibernateReactiveTestResourcesModuleName | MariaDB.DEPENDENCY_MARIADB_JAVA_CLIENT.build() - PostgreSQL.NAME | PostgreSQL.VERTX_PG_CLIENT | Flyway.NAME | DbType.POSTGRESQL.hibernateReactiveTestResourcesModuleName | PostgreSQL.DEPENDENCY_POSTGRESQL.build() - Oracle.NAME | Oracle.VERTX_ORACLE_CLIENT | Flyway.NAME | DbType.ORACLEXE.hibernateReactiveTestResourcesModuleName | Oracle.DEPENDENCY_OJDBC8.build() - SQLServer.NAME | SQLServer.VERTX_MSSQL_CLIENT | Flyway.NAME | DbType.SQLSERVER.hibernateReactiveTestResourcesModuleName | SQLServer.DEPENDENCY_MSSQL_JDBC.build() + testScenario << mavenMigrationTestScenarios() + } + + List mavenMigrationTestScenarios() { + filter([ + new TestScenario(MySQL.NAME, MySQLCompatibleFeature.VERTX_MYSQL_CLIENT,null, Liquibase.NAME, DbType.MYSQL.hibernateReactiveTestResourcesModuleName, MySQL.DEPENDENCY_MYSQL_CONNECTOR_JAVA.build()), + new TestScenario(MariaDB.NAME, MySQLCompatibleFeature.VERTX_MYSQL_CLIENT,null, Liquibase.NAME, DbType.MARIADB.hibernateReactiveTestResourcesModuleName, MariaDB.DEPENDENCY_MARIADB_JAVA_CLIENT.build()), + new TestScenario(PostgreSQL.NAME, PostgreSQL.VERTX_PG_CLIENT,null, Liquibase.NAME, DbType.POSTGRESQL.hibernateReactiveTestResourcesModuleName, PostgreSQL.DEPENDENCY_POSTGRESQL.build()), + new TestScenario(Oracle.NAME, Oracle.VERTX_ORACLE_CLIENT,null, Liquibase.NAME, DbType.ORACLEFREE.hibernateReactiveTestResourcesModuleName, Oracle.DEPENDENCY_OJDBC11.build()), + new TestScenario(SQLServer.NAME, SQLServer.VERTX_MSSQL_CLIENT,null, Liquibase.NAME, DbType.SQLSERVER.hibernateReactiveTestResourcesModuleName, SQLServer.DEPENDENCY_MSSQL_JDBC.build()), + new TestScenario(MySQL.NAME, MySQLCompatibleFeature.VERTX_MYSQL_CLIENT , null, Flyway.NAME, DbType.MYSQL.hibernateReactiveTestResourcesModuleName, MySQL.DEPENDENCY_MYSQL_CONNECTOR_JAVA.build()), + new TestScenario(MariaDB.NAME, MySQLCompatibleFeature.VERTX_MYSQL_CLIENT , null, Flyway.NAME, DbType.MARIADB.hibernateReactiveTestResourcesModuleName, MariaDB.DEPENDENCY_MARIADB_JAVA_CLIENT.build()), + new TestScenario(PostgreSQL.NAME, PostgreSQL.VERTX_PG_CLIENT, null, Flyway.NAME, DbType.POSTGRESQL.hibernateReactiveTestResourcesModuleName, PostgreSQL.DEPENDENCY_POSTGRESQL.build()), + new TestScenario(Oracle.NAME, Oracle.VERTX_ORACLE_CLIENT, null, Flyway.NAME, DbType.ORACLEFREE.hibernateReactiveTestResourcesModuleName, Oracle.DEPENDENCY_OJDBC11.build()), + new TestScenario(SQLServer.NAME, SQLServer.VERTX_MSSQL_CLIENT, null, Flyway.NAME, DbType.SQLSERVER.hibernateReactiveTestResourcesModuleName, SQLServer.DEPENDENCY_MSSQL_JDBC.build()), + ]) } void "test kotlin jpa plugin is present for maven kotlin project"() { @@ -277,9 +272,9 @@ class DataHibernateReactiveSpec extends BaseHibernateReactiveSpec { } } - void "test config for #db"() { + void "test config for #testScenario.db"(DbConfigTestScenario testScenario) { when: - GeneratorContext ctx = buildGeneratorContext([DataHibernateReactive.NAME, db]) + GeneratorContext ctx = buildGeneratorContext([DataHibernateReactive.NAME, testScenario.db]) then: !ctx.configuration.containsKey("datasources.default.url") @@ -287,51 +282,62 @@ class DataHibernateReactiveSpec extends BaseHibernateReactiveSpec { !ctx.configuration.containsKey("datasources.default.password") !ctx.configuration.containsKey("datasources.default.dialect") ctx.configuration."jpa.default.reactive" == true - ctx.configuration."jpa.default.properties.hibernate.connection.db-type" == dbType + ctx.configuration."jpa.default.properties.hibernate.connection.db-type" == testScenario.dbType !ctx.configuration.containsKey("jpa.default.properties.hibernate.connection.url") !ctx.configuration.containsKey("jpa.default.properties.hibernate.connection.username") !ctx.configuration.containsKey("jpa.default.properties.hibernate.connection.password") where: - db | dbType - MySQL.NAME | 'mysql' - MariaDB.NAME | 'mariadb' - PostgreSQL.NAME | 'postgres' - Oracle.NAME | 'oracle' - SQLServer.NAME | 'mssql' + testScenario << dbConfigScenarios() + } + + List dbConfigScenarios() { + filterDbConfigTestScenario([ + new DbConfigTestScenario(MySQL.NAME, 'mysql'), + new DbConfigTestScenario(MariaDB.NAME, 'mariadb'), + new DbConfigTestScenario(PostgreSQL.NAME, 'postgres'), + new DbConfigTestScenario(Oracle.NAME, 'oracle'), + new DbConfigTestScenario(SQLServer.NAME, 'mssql'), + ]) } - void "test config for #db with #migration"() { + void "test config for #testScenario.db with #testScenario.migration"(DbConfigTestScenario testScenario) { when: - GeneratorContext ctx = buildGeneratorContext([DataHibernateReactive.NAME, db, migration]) + GeneratorContext ctx = buildGeneratorContext([DataHibernateReactive.NAME, testScenario.db, testScenario.migration]) then: !ctx.configuration.containsKey("datasources.default.url") !ctx.configuration.containsKey("datasources.default.username") !ctx.configuration.containsKey("datasources.default.password") !ctx.configuration.containsKey("datasources.default.dialect") - ctx.configuration."datasources.default.db-type" == type + ctx.configuration."datasources.default.db-type" == testScenario.dbType ctx.configuration."jpa.default.reactive" == true - ctx.configuration."jpa.default.properties.hibernate.connection.db-type" == type + ctx.configuration."jpa.default.properties.hibernate.connection.db-type" == testScenario.dbType !ctx.configuration.containsKey("jpa.default.properties.hibernate.connection.url") !ctx.configuration.containsKey("jpa.default.properties.hibernate.connection.username") !ctx.configuration.containsKey("jpa.default.properties.hibernate.connection.password") where: - db | type | migration - MySQL.NAME | 'mysql' | Flyway.NAME - MariaDB.NAME | 'mariadb' | Flyway.NAME - PostgreSQL.NAME | 'postgres' | Flyway.NAME - Oracle.NAME | 'oracle' | Flyway.NAME - SQLServer.NAME | 'mssql' | Flyway.NAME - MySQL.NAME | 'mysql' | Liquibase.NAME - MariaDB.NAME | 'mariadb' | Liquibase.NAME - PostgreSQL.NAME | 'postgres' | Liquibase.NAME - Oracle.NAME | 'oracle' | Liquibase.NAME - SQLServer.NAME | 'mssql' | Liquibase.NAME + testScenario << dbConfigWithMigrationScenarios() + } + + List dbConfigWithMigrationScenarios() { + filterDbConfigTestScenario([ + new DbConfigTestScenario(MySQL.NAME , 'mysql' , Flyway.NAME), + new DbConfigTestScenario(MariaDB.NAME , 'mariadb' , Flyway.NAME), + new DbConfigTestScenario(PostgreSQL.NAME , 'postgres' , Flyway.NAME), + new DbConfigTestScenario(Oracle.NAME , 'oracle' , Flyway.NAME), + new DbConfigTestScenario(SQLServer.NAME , 'mssql' , Flyway.NAME), + new DbConfigTestScenario(MySQL.NAME , 'mysql' , Liquibase.NAME), + new DbConfigTestScenario(MariaDB.NAME , 'mariadb' , Liquibase.NAME), + new DbConfigTestScenario(PostgreSQL.NAME , 'postgres' , Liquibase.NAME), + new DbConfigTestScenario(Oracle.NAME , 'oracle' , Liquibase.NAME), + new DbConfigTestScenario(SQLServer.NAME , 'mssql' , Liquibase.NAME), + ]) } - @Issue("https://github.com/micronaut-projects/micronaut-starter/issues/686") + + @Issue("https://github.com/micronaut-projects/micronaut-starter/issues/686") void 'test data-processor dependency is in provided scope for Groovy and Maven'() { when: String template = new BuildBuilder(beanContext, BuildTool.MAVEN) @@ -344,4 +350,33 @@ class DataHibernateReactiveSpec extends BaseHibernateReactiveSpec { then: verifier.hasDependency(GROUP_ID_MICRONAUT_DATA, ARTIFACT_ID_MICRONAUT_DATA_PROCESSOR_ARTIFACT, Scope.COMPILE_ONLY) } + + @Canonical + class DbConfigTestScenario { + String db + String dbType + String migration + } + + @Canonical + class TestScenario { + String db + String client + String container + String migration + String testResourcesModule + Dependency driver + } + + private List filterDbConfigTestScenario(List scenarios) { + scenarios.stream() + .filter(ts -> ts.db != Oracle.NAME || Oracle.COMPATIBLE_WITH_HIBERNATE_REACTIVE) + .toList() + } + + private List filter(List scenarios) { + scenarios.stream() + .filter(ts -> ts.db != Oracle.NAME || Oracle.COMPATIBLE_WITH_HIBERNATE_REACTIVE) + .toList() + } } diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/database/DataJdbcSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/database/DataJdbcSpec.groovy index 7ba9430b0ec..5eeb4b67595 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/database/DataJdbcSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/database/DataJdbcSpec.groovy @@ -25,8 +25,8 @@ class DataJdbcSpec extends ApplicationContextSpec implements CommandOutputFixtu void 'test readme.md with feature data-jdbc contains links to micronaut docs'() { when: - def output = generate(['data-jdbc']) - def readme = output["README.md"] + Map output = generate(['data-jdbc']) + String readme = output["README.md"] then: readme diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/database/DataJpaSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/database/DataJpaSpec.groovy index ff885fc3089..1f3fcd742d8 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/database/DataJpaSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/database/DataJpaSpec.groovy @@ -130,20 +130,20 @@ class DataJpaSpec extends ApplicationContextSpec implements CommandOutputFixture @Issue("https://github.com/micronaut-projects/micronaut-starter/issues/686") void 'test data-processor dependency is in provided scope for Groovy and Maven'() { + given: + BuildTool buildTool = BuildTool.MAVEN + Language language = Language.GROOVY + when: - String template = new BuildBuilder(beanContext, BuildTool.MAVEN) - .language(Language.GROOVY) + String template = new BuildBuilder(beanContext, buildTool) + .language(language) .features(["data-jpa"]) .render() + BuildTestVerifier verifier = BuildTestUtil.verifier(buildTool, language, template) then: - template.contains(''' - - io.micronaut.data - micronaut-data-processor - provided - -''') + println(template) + verifier.hasAnnotationProcessor("io.micronaut.data", "micronaut-data-processor") } void 'feature data-jpa contains correct hbm2ddl.auto values'(List features, String prod, String test) { diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/database/DataMongoSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/database/DataMongoSpec.groovy index 1ea54cf8647..3f5a8650ae5 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/database/DataMongoSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/database/DataMongoSpec.groovy @@ -14,9 +14,9 @@ class DataMongoSpec extends ApplicationContextSpec implements CommandOutputFixtu void "test adding #feature results in the correct build for a #buildTool app in #language"() { when: - def output = generate(ApplicationType.DEFAULT, new Options(language, buildTool), [feature, 'kapt']) - def readme = output["README.md"] - def build = output["build.gradle${buildTool == BuildTool.GRADLE_KOTLIN ? ".kts" : ""}".toString()] + Map output = generate(ApplicationType.DEFAULT, new Options(language, buildTool), [feature, 'kapt']) + String readme = output["README.md"] + String build = output["build.gradle${buildTool == BuildTool.GRADLE_KOTLIN ? ".kts" : ""}".toString()] then: readme @@ -56,8 +56,8 @@ class DataMongoSpec extends ApplicationContextSpec implements CommandOutputFixtu void "test adding #feature results in the correct build for a Maven app in #language"() { when: - def output = generate(ApplicationType.DEFAULT, new Options(language, BuildTool.MAVEN), [feature]) - def readme = output["README.md"] + Map output = generate(ApplicationType.DEFAULT, new Options(language, BuildTool.MAVEN), [feature]) + String readme = output["README.md"] def project = new XmlParser().parseText(output['pom.xml']) then: diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/database/DataSpringJdbcSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/database/DataSpringJdbcSpec.groovy index 439743dc5e4..f37aeacb9a9 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/database/DataSpringJdbcSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/database/DataSpringJdbcSpec.groovy @@ -22,8 +22,8 @@ class DataSpringJdbcSpec extends ApplicationContextSpec implements CommandOutpu void 'test readme.md with feature data-jdbc contains links to micronaut docs'() { when: - def output = generate(['data-spring-jdbc']) - def readme = output["README.md"] + Map output = generate(['data-spring-jdbc']) + String readme = output["README.md"] then: readme diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/database/HibernateGormSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/database/HibernateGormSpec.groovy deleted file mode 100644 index f9191d683f2..00000000000 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/database/HibernateGormSpec.groovy +++ /dev/null @@ -1,85 +0,0 @@ -package io.micronaut.starter.feature.database - -import io.micronaut.starter.ApplicationContextSpec -import io.micronaut.starter.BuildBuilder -import io.micronaut.starter.application.generator.GeneratorContext -import io.micronaut.starter.feature.Features -import io.micronaut.starter.options.BuildTool -import io.micronaut.starter.options.Language - -class HibernateGormSpec extends ApplicationContextSpec { - - void "test hibernate gorm features"() { - when: - Features features = getFeatures(['hibernate-gorm']) - - then: - features.contains("groovy") - features.contains("h2") - features.contains("hibernate-validator") - features.contains("hibernate-gorm") - } - - void "test dependencies are present for gradle"() { - when: - String template = new BuildBuilder(beanContext, BuildTool.GRADLE) - .features(["hibernate-gorm"]) - .language(Language.GROOVY) - .render() - - then: - template.contains('implementation("io.micronaut.groovy:micronaut-hibernate-gorm")') - template.contains('implementation("io.micronaut.beanvalidation:micronaut-hibernate-validator")') - template.contains("runtimeOnly(\"com.h2database:h2\")") - template.contains("runtimeOnly(\"org.apache.tomcat:tomcat-jdbc\")") - } - - void "test dependencies are present for maven"() { - when: - String template = new BuildBuilder(beanContext, BuildTool.MAVEN) - .features(['hibernate-gorm']) - .language(Language.GROOVY) - .render() - - then: - template.contains(""" - - io.micronaut.groovy - micronaut-hibernate-gorm - compile - -""") - template.contains(""" - - io.micronaut.beanvalidation - micronaut-hibernate-validator - compile - -""") - template.contains(""" - - com.h2database - h2 - runtime - -""") - template.contains(""" - - org.apache.tomcat - tomcat-jdbc - runtime - -""") - } - - void "test config"() { - when: - GeneratorContext ctx = buildGeneratorContext(['hibernate-gorm']) - - then: - ctx.configuration.containsKey("dataSource.url") - ctx.configuration.containsKey("dataSource.driver-class-name") - ctx.configuration.containsKey("hibernate.hbm2ddl.auto") - ctx.configuration.containsKey("hibernate.cache.queries") - } -} \ No newline at end of file diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/database/HibernateJpaModelgenSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/database/HibernateJpaModelgenSpec.groovy new file mode 100644 index 00000000000..90bf9a2096e --- /dev/null +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/database/HibernateJpaModelgenSpec.groovy @@ -0,0 +1,57 @@ +package io.micronaut.starter.feature.database + +import io.micronaut.starter.ApplicationContextSpec +import io.micronaut.starter.BuildBuilder +import io.micronaut.starter.application.ApplicationType +import io.micronaut.starter.build.BuildTestUtil +import io.micronaut.starter.build.BuildTestVerifier +import io.micronaut.starter.feature.Category +import io.micronaut.starter.fixture.CommandOutputFixture +import io.micronaut.starter.options.BuildTool +import io.micronaut.starter.options.Language +import spock.lang.Shared + +class HibernateJpaModelgenSpec extends ApplicationContextSpec implements CommandOutputFixture { + + @Shared + HibernateJpaModelgen hibernateJpaModelgen = beanContext.getBean(HibernateJpaModelgen) + + void 'test readme.md with feature hibernate-jpamodelgen contains links to docs'() { + when: + Map output = generate([HibernateJpaModelgen.NAME]) + String readme = output["README.md"] + + then: + readme + readme.contains("https://hibernate.org/orm/tooling/") + readme.contains("https://micronaut-projects.github.io/micronaut-data/latest/guide/#typeSafeJava") + } + + void "feature hibernate-jpamodelgen supports applicationType=#applicationType"(ApplicationType applicationType) { + expect: + hibernateJpaModelgen.supports(applicationType) + + where: + applicationType << ApplicationType.values() + } + + void "feature hibernate-jpamodelgen feature is DATABASE category"() { + expect: + hibernateJpaModelgen.category == Category.DATABASE + } + + void "dependencies are present for #buildTool and #language"(BuildTool buildTool, Language language) { + when: + String template = new BuildBuilder(beanContext, buildTool) + .features([HibernateJpaModelgen.NAME]) + .language(language) + .render() + BuildTestVerifier verifier = BuildTestUtil.verifier(buildTool, language, template) + + then: + verifier.hasAnnotationProcessor("org.hibernate.orm", "hibernate-jpamodelgen") + + where: + [buildTool, language] << [BuildTool.values(), Language.values()].combinations() + } +} diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/database/HibernateReactiveJpaSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/database/HibernateReactiveJpaSpec.groovy index ff3065ca482..ee833d99944 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/database/HibernateReactiveJpaSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/database/HibernateReactiveJpaSpec.groovy @@ -1,10 +1,12 @@ package io.micronaut.starter.feature.database +import groovy.transform.Canonical import io.micronaut.core.version.SemanticVersion import io.micronaut.starter.BuildBuilder import io.micronaut.starter.application.generator.GeneratorContext import io.micronaut.starter.build.BuildTestUtil import io.micronaut.starter.build.BuildTestVerifier +import io.micronaut.starter.build.dependencies.Dependency import io.micronaut.starter.feature.Features import io.micronaut.starter.feature.migration.Flyway import io.micronaut.starter.feature.migration.Liquibase @@ -26,7 +28,7 @@ class HibernateReactiveJpaSpec extends BaseHibernateReactiveSpec { IllegalArgumentException exception = thrown() and: - exception.message == "Hibernate Reactive requires $MariaDB.NAME, $MySQL.NAME, $Oracle.NAME, $PostgreSQL.NAME, or $SQLServer.NAME" + exception.message == "Hibernate Reactive requires $MariaDB.NAME, $MySQL.NAME, $PostgreSQL.NAME, or $SQLServer.NAME" } void "test hibernate reactive jpa features for #db"() { @@ -41,7 +43,7 @@ class HibernateReactiveJpaSpec extends BaseHibernateReactiveSpec { features.contains(HibernateReactiveJpa.NAME) where: - db << [MySQL.NAME, MariaDB.NAME, PostgreSQL.NAME, Oracle.NAME, SQLServer.NAME] + db << databases() } void "test hibernate reactive jpa features for #db with #migration"(String db, String migration) { @@ -57,7 +59,13 @@ class HibernateReactiveJpaSpec extends BaseHibernateReactiveSpec { features.contains(HibernateReactiveJpa.NAME) where: - [db, migration] << [[MySQL.NAME, MariaDB.NAME, PostgreSQL.NAME, Oracle.NAME, SQLServer.NAME], [Liquibase.NAME, Flyway.NAME]].combinations() + [db, migration] << [databases(), [Liquibase.NAME, Flyway.NAME]].combinations() + } + + private List databases() { + Oracle.COMPATIBLE_WITH_HIBERNATE_REACTIVE + ? [MySQL.NAME, MariaDB.NAME, PostgreSQL.NAME, Oracle.NAME, SQLServer.NAME] + : [MySQL.NAME, MariaDB.NAME, PostgreSQL.NAME, SQLServer.NAME] } void "data hibernate reactive requires java 11"() { @@ -90,10 +98,10 @@ class HibernateReactiveJpaSpec extends BaseHibernateReactiveSpec { noExceptionThrown() } - void "test dependencies are present for gradle with #db (#client)"() { + void "test dependencies are present for gradle with #testScenario.db (#testScenario.client)"(TestScenario testScenario) { when: String template = new BuildBuilder(beanContext, BuildTool.GRADLE) - .features([HibernateReactiveJpa.NAME, db]) + .features([HibernateReactiveJpa.NAME, testScenario.db]) .jdkVersion(MicronautJdkVersionConfiguration.DEFAULT_OPTION) .render() @@ -103,32 +111,37 @@ class HibernateReactiveJpaSpec extends BaseHibernateReactiveSpec { !template.contains('implementation("io.micronaut.data:micronaut-data-hibernate-reactive")') template.contains('implementation("io.micronaut.sql:micronaut-hibernate-reactive")') !template.contains('implementation("io.micronaut.sql:micronaut-jdbc-hikari")') - template.contains($/implementation("$HibernateReactiveFeature.IO_VERTX_DEPENDENCY_GROUP:$client")/$) + template.contains($/implementation("$HibernateReactiveFeature.IO_VERTX_DEPENDENCY_GROUP:$testScenario.client")/$) !template.contains('testImplementation("org.testcontainers:testcontainers")') - !template.contains($/testImplementation("org.testcontainers:$container")/$) + !template.contains($/testImplementation("org.testcontainers:$testScenario.container")/$) and: "postgres needs another dependency with vert.x" - template.contains('implementation("com.ongres.scram:client:') == (db == PostgreSQL.NAME) + template.contains('implementation("com.ongres.scram:client:') == (testScenario.db == PostgreSQL.NAME) and: 'the driver and correct module are included for test-resources' - !template.contains($/runtimeOnly("$driver.groupId:$driver.artifactId")/$) - template.contains($/testResourcesService("$driver.groupId:$driver.artifactId")/$) - template.contains($/additionalModules.add("$testResourcesModule")/$) + !template.contains($/runtimeOnly("$testScenario.driver.groupId:$testScenario.driver.artifactId")/$) + template.contains($/testResourcesService("$testScenario.driver.groupId:$testScenario.driver.artifactId")/$) + template.contains($/additionalModules.add("$testScenario.testResourcesModule")/$) where: - db | client | container | testResourcesModule | driver - MySQL.NAME | MySQLCompatibleFeature.VERTX_MYSQL_CLIENT | 'mysql' | DbType.MYSQL.hibernateReactiveTestResourcesModuleName | MySQL.DEPENDENCY_MYSQL_CONNECTOR_JAVA.build() - MariaDB.NAME | MySQLCompatibleFeature.VERTX_MYSQL_CLIENT | 'mariadb' | DbType.MARIADB.hibernateReactiveTestResourcesModuleName | MariaDB.DEPENDENCY_MARIADB_JAVA_CLIENT.build() - PostgreSQL.NAME | PostgreSQL.VERTX_PG_CLIENT | 'postgresql' | DbType.POSTGRESQL.hibernateReactiveTestResourcesModuleName | PostgreSQL.DEPENDENCY_POSTGRESQL.build() - Oracle.NAME | Oracle.VERTX_ORACLE_CLIENT | 'oracle-xe' | DbType.ORACLEXE.hibernateReactiveTestResourcesModuleName | Oracle.DEPENDENCY_OJDBC8.build() - SQLServer.NAME | SQLServer.VERTX_MSSQL_CLIENT | 'mssqlserver' | DbType.SQLSERVER.hibernateReactiveTestResourcesModuleName | SQLServer.DEPENDENCY_MSSQL_JDBC.build() + testScenario << gradleScenarios() + } + + List gradleScenarios() { + filter([ + new TestScenario(MySQL.NAME , MySQLCompatibleFeature.VERTX_MYSQL_CLIENT , 'mysql', null, DbType.MYSQL.hibernateReactiveTestResourcesModuleName, MySQL.DEPENDENCY_MYSQL_CONNECTOR_JAVA.build()), + new TestScenario(MariaDB.NAME, MySQLCompatibleFeature.VERTX_MYSQL_CLIENT , 'mariadb', null, DbType.MARIADB.hibernateReactiveTestResourcesModuleName, MariaDB.DEPENDENCY_MARIADB_JAVA_CLIENT.build()), + new TestScenario(PostgreSQL.NAME , PostgreSQL.VERTX_PG_CLIENT, 'postgresql' , null, DbType.POSTGRESQL.hibernateReactiveTestResourcesModuleName , PostgreSQL.DEPENDENCY_POSTGRESQL.build()), + new TestScenario(Oracle.NAME, Oracle.VERTX_ORACLE_CLIENT, 'oracle-xe', null, DbType.ORACLEFREE.hibernateReactiveTestResourcesModuleName, Oracle.DEPENDENCY_OJDBC11.build()), + new TestScenario(SQLServer.NAME, SQLServer.VERTX_MSSQL_CLIENT, 'mssqlserver' , null, DbType.SQLSERVER.hibernateReactiveTestResourcesModuleName, SQLServer.DEPENDENCY_MSSQL_JDBC.build()), + ]) } - void "test dependencies are present for gradle with #db (#client) and #migration"() { + void "test dependencies are present for gradle with #testScenario.db (#testScenario.client) and #testScenario.migration"(TestScenario testScenario) { when: String template = new BuildBuilder(beanContext, BuildTool.GRADLE) - .features([HibernateReactiveJpa.NAME, db, migration]) + .features([HibernateReactiveJpa.NAME, testScenario.db, testScenario.migration]) .jdkVersion(MicronautJdkVersionConfiguration.DEFAULT_OPTION) .render() @@ -137,32 +150,37 @@ class HibernateReactiveJpaSpec extends BaseHibernateReactiveSpec { !template.contains('implementation("io.micronaut.data:micronaut-data-hibernate-reactive")') template.contains('implementation("io.micronaut.sql:micronaut-hibernate-reactive")') template.contains('implementation("io.micronaut.sql:micronaut-jdbc-hikari")') - template.contains($/implementation("$HibernateReactiveFeature.IO_VERTX_DEPENDENCY_GROUP:$client")/$) - template.contains($/runtimeOnly("$migrationDriver.groupId:$migrationDriver.artifactId")/$) - template.contains('runtimeOnly("org.flywaydb:flyway-mysql")') == (migration == Flyway.NAME && db in [MySQL.NAME, MariaDB.NAME]) + template.contains($/implementation("$HibernateReactiveFeature.IO_VERTX_DEPENDENCY_GROUP:$testScenario.client")/$) + template.contains($/runtimeOnly("$testScenario.driver.groupId:$testScenario.driver.artifactId")/$) + template.contains('runtimeOnly("org.flywaydb:flyway-mysql")') == (testScenario.migration == Flyway.NAME && testScenario.db in [MySQL.NAME, MariaDB.NAME]) !template.contains('testImplementation("org.testcontainers:testcontainers")') - !template.contains($/testImplementation("org.testcontainers:$container")/$) + !template.contains($/testImplementation("org.testcontainers:$testScenario.container")/$) and: "postgres needs another dependency with vert.x" - template.contains('implementation("com.ongres.scram:client:') == (db == PostgreSQL.NAME) + template.contains('implementation("com.ongres.scram:client:') == (testScenario.db == PostgreSQL.NAME) and: 'the correct module is included for test-resources' - !template.contains($/testResourcesService("$migrationDriver.groupId:$migrationDriver.artifactId")/$) - template.contains($/additionalModules.add("$testResourcesModule")/$) + !template.contains($/testResourcesService("$testScenario.driver.groupId:$testScenario.driver.artifactId")/$) + template.contains($/additionalModules.add("$testScenario.testResourcesModule")/$) where: - db | client | container | migration | testResourcesModule | migrationDriver - MySQL.NAME | MySQLCompatibleFeature.VERTX_MYSQL_CLIENT | 'mysql' | Liquibase.NAME | DbType.MYSQL.hibernateReactiveTestResourcesModuleName | MySQL.DEPENDENCY_MYSQL_CONNECTOR_JAVA.build() - MariaDB.NAME | MySQLCompatibleFeature.VERTX_MYSQL_CLIENT | 'mariadb' | Liquibase.NAME | DbType.MARIADB.hibernateReactiveTestResourcesModuleName | MariaDB.DEPENDENCY_MARIADB_JAVA_CLIENT.build() - PostgreSQL.NAME | PostgreSQL.VERTX_PG_CLIENT | 'postgresql' | Liquibase.NAME | DbType.POSTGRESQL.hibernateReactiveTestResourcesModuleName | PostgreSQL.DEPENDENCY_POSTGRESQL.build() - Oracle.NAME | Oracle.VERTX_ORACLE_CLIENT | 'oracle-xe' | Liquibase.NAME | DbType.ORACLEXE.hibernateReactiveTestResourcesModuleName | Oracle.DEPENDENCY_OJDBC8.build() - SQLServer.NAME | SQLServer.VERTX_MSSQL_CLIENT | 'mssqlserver' | Liquibase.NAME | DbType.SQLSERVER.hibernateReactiveTestResourcesModuleName | SQLServer.DEPENDENCY_MSSQL_JDBC.build() - MySQL.NAME | MySQLCompatibleFeature.VERTX_MYSQL_CLIENT | 'mysql' | Flyway.NAME | DbType.MYSQL.hibernateReactiveTestResourcesModuleName | MySQL.DEPENDENCY_MYSQL_CONNECTOR_JAVA.build() - MariaDB.NAME | MySQLCompatibleFeature.VERTX_MYSQL_CLIENT | 'mariadb' | Flyway.NAME | DbType.MARIADB.hibernateReactiveTestResourcesModuleName | MariaDB.DEPENDENCY_MARIADB_JAVA_CLIENT.build() - PostgreSQL.NAME | PostgreSQL.VERTX_PG_CLIENT | 'postgresql' | Flyway.NAME | DbType.POSTGRESQL.hibernateReactiveTestResourcesModuleName | PostgreSQL.DEPENDENCY_POSTGRESQL.build() - Oracle.NAME | Oracle.VERTX_ORACLE_CLIENT | 'oracle-xe' | Flyway.NAME | DbType.ORACLEXE.hibernateReactiveTestResourcesModuleName | Oracle.DEPENDENCY_OJDBC8.build() - SQLServer.NAME | SQLServer.VERTX_MSSQL_CLIENT | 'mssqlserver' | Flyway.NAME | DbType.SQLSERVER.hibernateReactiveTestResourcesModuleName | SQLServer.DEPENDENCY_MSSQL_JDBC.build() + testScenario << gradleMigrationScenarios() + } + + List gradleMigrationScenarios() { + filter([ + new TestScenario(MySQL.NAME, MySQLCompatibleFeature.VERTX_MYSQL_CLIENT, 'mysql', Liquibase.NAME , DbType.MYSQL.hibernateReactiveTestResourcesModuleName, MySQL.DEPENDENCY_MYSQL_CONNECTOR_JAVA.build()), + new TestScenario(MariaDB.NAME, MySQLCompatibleFeature.VERTX_MYSQL_CLIENT, 'mariadb', Liquibase.NAME , DbType.MARIADB.hibernateReactiveTestResourcesModuleName, MariaDB.DEPENDENCY_MARIADB_JAVA_CLIENT.build()), + new TestScenario(PostgreSQL.NAME, PostgreSQL.VERTX_PG_CLIENT, 'postgresql' , Liquibase.NAME , DbType.POSTGRESQL.hibernateReactiveTestResourcesModuleName, PostgreSQL.DEPENDENCY_POSTGRESQL.build()), + new TestScenario(Oracle.NAME, Oracle.VERTX_ORACLE_CLIENT, 'oracle-xe' , Liquibase.NAME , DbType.ORACLEFREE.hibernateReactiveTestResourcesModuleName, Oracle.DEPENDENCY_OJDBC11.build()), + new TestScenario(SQLServer.NAME, SQLServer.VERTX_MSSQL_CLIENT, 'mssqlserver' , Liquibase.NAME , DbType.SQLSERVER.hibernateReactiveTestResourcesModuleName, SQLServer.DEPENDENCY_MSSQL_JDBC.build()), + new TestScenario(MySQL.NAME, MySQLCompatibleFeature.VERTX_MYSQL_CLIENT, 'mysql', Flyway.NAME, DbType.MYSQL.hibernateReactiveTestResourcesModuleName, MySQL.DEPENDENCY_MYSQL_CONNECTOR_JAVA.build()), + new TestScenario(MariaDB.NAME, MySQLCompatibleFeature.VERTX_MYSQL_CLIENT, 'mariadb', Flyway.NAME, DbType.MARIADB.hibernateReactiveTestResourcesModuleName, MariaDB.DEPENDENCY_MARIADB_JAVA_CLIENT.build()), + new TestScenario(PostgreSQL.NAME, PostgreSQL.VERTX_PG_CLIENT, 'postgresql', Flyway.NAME, DbType.POSTGRESQL.hibernateReactiveTestResourcesModuleName, PostgreSQL.DEPENDENCY_POSTGRESQL.build()), + new TestScenario(Oracle.NAME, Oracle.VERTX_ORACLE_CLIENT, 'oracle-xe', Flyway.NAME, DbType.ORACLEFREE.hibernateReactiveTestResourcesModuleName, Oracle.DEPENDENCY_OJDBC11.build()), + new TestScenario(SQLServer.NAME, SQLServer.VERTX_MSSQL_CLIENT, 'mssqlserver' , Flyway.NAME, DbType.SQLSERVER.hibernateReactiveTestResourcesModuleName , SQLServer.DEPENDENCY_MSSQL_JDBC.build()), + ]) } void "test kotlin jpa plugin is present for gradle kotlin project"() { @@ -177,10 +195,10 @@ class HibernateReactiveJpaSpec extends BaseHibernateReactiveSpec { template.contains('id("org.jetbrains.kotlin.plugin.jpa")') } - void "test dependencies are present for maven with #db (#client)"() { + void "test dependencies are present for maven with #testScenario.db (#testScenario.client)"(TestScenario testScenario) { when: String template = new BuildBuilder(beanContext, BuildTool.MAVEN) - .features([HibernateReactiveJpa.NAME, db]) + .features([HibernateReactiveJpa.NAME, testScenario.db]) .jdkVersion(MicronautJdkVersionConfiguration.DEFAULT_OPTION) .render() BuildTestVerifier verifier = BuildTestUtil.verifier(BuildTool.MAVEN, template) @@ -191,15 +209,15 @@ class HibernateReactiveJpaSpec extends BaseHibernateReactiveSpec { !containsDataHibernateReactive(template) contansSqlHibernateReactive(template) !containsHikariDependency(template) - containsVertXDriver(template, client) - !containsJdbcDriver(template, migrationDriver) + containsVertXDriver(template, testScenario.client) + !containsJdbcDriver(template, testScenario.driver) and: "postgres needs another dependency with vert.x" - db != PostgreSQL.NAME || verifier.hasDependency('com.ongres.scram', "client") + testScenario.db != PostgreSQL.NAME || verifier.hasDependency('com.ongres.scram', "client") and: 'test resources module is correct, and driver is added to the plugin dependencies' - verifier.hasTestResourceDependency("micronaut-test-resources-$testResourcesModule") - verifier.hasTestResourceDependency(migrationDriver.groupId, migrationDriver.artifactId) + verifier.hasTestResourceDependency("micronaut-test-resources-$testScenario.testResourcesModule") + verifier.hasTestResourceDependency(testScenario.driver.groupId, testScenario.driver.artifactId) when: Optional semanticVersionOptional = parsePropertySemanticVersion(template, "micronaut.data.version") @@ -209,19 +227,24 @@ class HibernateReactiveJpaSpec extends BaseHibernateReactiveSpec { !semanticVersionOptional.isPresent() where: - db | client | testResourcesModule | migrationDriver - MySQL.NAME | MySQLCompatibleFeature.VERTX_MYSQL_CLIENT | DbType.MYSQL.hibernateReactiveTestResourcesModuleName | MySQL.DEPENDENCY_MYSQL_CONNECTOR_JAVA.build() - MariaDB.NAME | MySQLCompatibleFeature.VERTX_MYSQL_CLIENT | DbType.MARIADB.hibernateReactiveTestResourcesModuleName | MariaDB.DEPENDENCY_MARIADB_JAVA_CLIENT.build() - PostgreSQL.NAME | PostgreSQL.VERTX_PG_CLIENT | DbType.POSTGRESQL.hibernateReactiveTestResourcesModuleName | PostgreSQL.DEPENDENCY_POSTGRESQL.build() - Oracle.NAME | Oracle.VERTX_ORACLE_CLIENT | DbType.ORACLEXE.hibernateReactiveTestResourcesModuleName | Oracle.DEPENDENCY_OJDBC8.build() - SQLServer.NAME | SQLServer.VERTX_MSSQL_CLIENT | DbType.SQLSERVER.hibernateReactiveTestResourcesModuleName | SQLServer.DEPENDENCY_MSSQL_JDBC.build() + testScenario << mavenScenarios() } - void "test dependencies are present for maven with #db (#client) and #migration"() { + List mavenScenarios() { + filter([ + new TestScenario(MySQL.NAME, MySQLCompatibleFeature.VERTX_MYSQL_CLIENT, null, null, DbType.MYSQL.hibernateReactiveTestResourcesModuleName, MySQL.DEPENDENCY_MYSQL_CONNECTOR_JAVA.build()), + new TestScenario(MariaDB.NAME, MySQLCompatibleFeature.VERTX_MYSQL_CLIENT , null, null, DbType.MARIADB.hibernateReactiveTestResourcesModuleName, MariaDB.DEPENDENCY_MARIADB_JAVA_CLIENT.build()), + new TestScenario(PostgreSQL.NAME, PostgreSQL.VERTX_PG_CLIENT, null, null, DbType.POSTGRESQL.hibernateReactiveTestResourcesModuleName, PostgreSQL.DEPENDENCY_POSTGRESQL.build()), + new TestScenario(Oracle.NAME, Oracle.VERTX_ORACLE_CLIENT, null, null, DbType.ORACLEFREE.hibernateReactiveTestResourcesModuleName, Oracle.DEPENDENCY_OJDBC11.build()), + new TestScenario(SQLServer.NAME, SQLServer.VERTX_MSSQL_CLIENT, null, null, DbType.SQLSERVER.hibernateReactiveTestResourcesModuleName, SQLServer.DEPENDENCY_MSSQL_JDBC.build()), + ]) + } + + void "test dependencies are present for maven with #testScenario.db (#testScenario.client) and #testScenario.migration"(TestScenario testScenario) { when: BuildTool buildTool = BuildTool.MAVEN String template = new BuildBuilder(beanContext, buildTool) - .features([HibernateReactiveJpa.NAME, db, migration]) + .features([HibernateReactiveJpa.NAME, testScenario.db, testScenario.migration]) .jdkVersion(MicronautJdkVersionConfiguration.DEFAULT_OPTION) .render() BuildTestVerifier verifier = BuildTestUtil.verifier(buildTool, template) @@ -232,16 +255,16 @@ class HibernateReactiveJpaSpec extends BaseHibernateReactiveSpec { !containsDataHibernateReactive(template) contansSqlHibernateReactive(template) containsHikariDependency(template) - containsVertXDriver(template, client) - containsMigrationLibrary(template, migration) - containsJdbcDriver(template, migrationDriver) + containsVertXDriver(template, testScenario.client) + containsMigrationLibrary(template, testScenario.migration) + containsJdbcDriver(template, testScenario.driver) and: "postgres needs another dependency with vert.x" - db != PostgreSQL.NAME || verifier.hasDependency('com.ongres.scram', "client") + testScenario.db != PostgreSQL.NAME || verifier.hasDependency('com.ongres.scram', "client") and: 'test resources module is correct, and driver is not added to the plugin dependencies' - verifier.hasTestResourceDependency("io.micronaut.testresources", "micronaut-test-resources-$testResourcesModule") - !verifier.hasTestResourceDependencyWithGroupId(migrationDriver.groupId) + verifier.hasTestResourceDependency("io.micronaut.testresources", "micronaut-test-resources-$testScenario.testResourcesModule") + !verifier.hasTestResourceDependencyWithGroupId(testScenario.driver.groupId) when: Optional semanticVersionOptional = parsePropertySemanticVersion(template, "micronaut.data.version") @@ -251,17 +274,22 @@ class HibernateReactiveJpaSpec extends BaseHibernateReactiveSpec { !semanticVersionOptional.isPresent() where: - db | client | migration | testResourcesModule | migrationDriver - MySQL.NAME | MySQLCompatibleFeature.VERTX_MYSQL_CLIENT | Liquibase.NAME | DbType.MYSQL.hibernateReactiveTestResourcesModuleName | MySQL.DEPENDENCY_MYSQL_CONNECTOR_JAVA.build() - MariaDB.NAME | MySQLCompatibleFeature.VERTX_MYSQL_CLIENT | Liquibase.NAME | DbType.MARIADB.hibernateReactiveTestResourcesModuleName | MariaDB.DEPENDENCY_MARIADB_JAVA_CLIENT.build() - PostgreSQL.NAME | PostgreSQL.VERTX_PG_CLIENT | Liquibase.NAME | DbType.POSTGRESQL.hibernateReactiveTestResourcesModuleName | PostgreSQL.DEPENDENCY_POSTGRESQL.build() - Oracle.NAME | Oracle.VERTX_ORACLE_CLIENT | Liquibase.NAME | DbType.ORACLEXE.hibernateReactiveTestResourcesModuleName | Oracle.DEPENDENCY_OJDBC8.build() - SQLServer.NAME | SQLServer.VERTX_MSSQL_CLIENT | Liquibase.NAME | DbType.SQLSERVER.hibernateReactiveTestResourcesModuleName | SQLServer.DEPENDENCY_MSSQL_JDBC.build() - MySQL.NAME | MySQLCompatibleFeature.VERTX_MYSQL_CLIENT | Flyway.NAME | DbType.MYSQL.hibernateReactiveTestResourcesModuleName | MySQL.DEPENDENCY_MYSQL_CONNECTOR_JAVA.build() - MariaDB.NAME | MySQLCompatibleFeature.VERTX_MYSQL_CLIENT | Flyway.NAME | DbType.MARIADB.hibernateReactiveTestResourcesModuleName | MariaDB.DEPENDENCY_MARIADB_JAVA_CLIENT.build() - PostgreSQL.NAME | PostgreSQL.VERTX_PG_CLIENT | Flyway.NAME | DbType.POSTGRESQL.hibernateReactiveTestResourcesModuleName | PostgreSQL.DEPENDENCY_POSTGRESQL.build() - Oracle.NAME | Oracle.VERTX_ORACLE_CLIENT | Flyway.NAME | DbType.ORACLEXE.hibernateReactiveTestResourcesModuleName | Oracle.DEPENDENCY_OJDBC8.build() - SQLServer.NAME | SQLServer.VERTX_MSSQL_CLIENT | Flyway.NAME | DbType.SQLSERVER.hibernateReactiveTestResourcesModuleName | SQLServer.DEPENDENCY_MSSQL_JDBC.build() + testScenario << mavenMigrationScenarios() + } + + List mavenMigrationScenarios() { + filter([ + new TestScenario(MySQL.NAME, MySQLCompatibleFeature.VERTX_MYSQL_CLIENT,null, Liquibase.NAME , DbType.MYSQL.hibernateReactiveTestResourcesModuleName, MySQL.DEPENDENCY_MYSQL_CONNECTOR_JAVA.build()), + new TestScenario(MariaDB.NAME, MySQLCompatibleFeature.VERTX_MYSQL_CLIENT ,null, Liquibase.NAME , DbType.MARIADB.hibernateReactiveTestResourcesModuleName, MariaDB.DEPENDENCY_MARIADB_JAVA_CLIENT.build()), + new TestScenario(PostgreSQL.NAME, PostgreSQL.VERTX_PG_CLIENT,null, Liquibase.NAME , DbType.POSTGRESQL.hibernateReactiveTestResourcesModuleName, PostgreSQL.DEPENDENCY_POSTGRESQL.build()), + new TestScenario(Oracle.NAME, Oracle.VERTX_ORACLE_CLIENT,null, Liquibase.NAME , DbType.ORACLEFREE.hibernateReactiveTestResourcesModuleName, Oracle.DEPENDENCY_OJDBC11.build()), + new TestScenario(SQLServer.NAME, SQLServer.VERTX_MSSQL_CLIENT,null, Liquibase.NAME , DbType.SQLSERVER.hibernateReactiveTestResourcesModuleName, SQLServer.DEPENDENCY_MSSQL_JDBC.build()), + new TestScenario(MySQL.NAME, MySQLCompatibleFeature.VERTX_MYSQL_CLIENT , null, Flyway.NAME , DbType.MYSQL.hibernateReactiveTestResourcesModuleName, MySQL.DEPENDENCY_MYSQL_CONNECTOR_JAVA.build()), + new TestScenario(MariaDB.NAME, MySQLCompatibleFeature.VERTX_MYSQL_CLIENT , null, Flyway.NAME , DbType.MARIADB.hibernateReactiveTestResourcesModuleName, MariaDB.DEPENDENCY_MARIADB_JAVA_CLIENT.build()), + new TestScenario(PostgreSQL.NAME, PostgreSQL.VERTX_PG_CLIENT, null, Flyway.NAME , DbType.POSTGRESQL.hibernateReactiveTestResourcesModuleName, PostgreSQL.DEPENDENCY_POSTGRESQL.build()), + new TestScenario(Oracle.NAME, Oracle.VERTX_ORACLE_CLIENT, null, Flyway.NAME , DbType.ORACLEFREE.hibernateReactiveTestResourcesModuleName, Oracle.DEPENDENCY_OJDBC11.build()), + new TestScenario(SQLServer.NAME, SQLServer.VERTX_MSSQL_CLIENT, null, Flyway.NAME , DbType.SQLSERVER.hibernateReactiveTestResourcesModuleName, SQLServer.DEPENDENCY_MSSQL_JDBC.build()), + ]) } void "test kotlin jpa plugin is present for maven kotlin project"() { @@ -282,9 +310,9 @@ class HibernateReactiveJpaSpec extends BaseHibernateReactiveSpec { ''') } - void "test config for #db"() { + void "test config for #testScenario.db"(DbConfigTestScenario testScenario) { when: - GeneratorContext ctx = buildGeneratorContext([HibernateReactiveJpa.NAME, db]) + GeneratorContext ctx = buildGeneratorContext([HibernateReactiveJpa.NAME, testScenario.db]) then: !ctx.configuration.containsKey("datasources.default.url") @@ -292,47 +320,88 @@ class HibernateReactiveJpaSpec extends BaseHibernateReactiveSpec { !ctx.configuration.containsKey("datasources.default.password") !ctx.configuration.containsKey("datasources.default.dialect") ctx.configuration."jpa.default.reactive" == true - ctx.configuration."jpa.default.properties.hibernate.connection.db-type" == dbType + ctx.configuration."jpa.default.properties.hibernate.connection.db-type" == testScenario.dbType !ctx.configuration.containsKey("jpa.default.properties.hibernate.connection.url") !ctx.configuration.containsKey("jpa.default.properties.hibernate.connection.username") !ctx.configuration.containsKey("jpa.default.properties.hibernate.connection.password") where: - db | dbType - MySQL.NAME | 'mysql' - MariaDB.NAME | 'mariadb' - PostgreSQL.NAME | 'postgres' - Oracle.NAME | 'oracle' - SQLServer.NAME | 'mssql' + testScenario << dbConfigScenarios() + } + + List dbConfigScenarios() { + filterDbConfigTestScenario([ + new DbConfigTestScenario(MySQL.NAME, 'mysql'), + new DbConfigTestScenario(MariaDB.NAME, 'mariadb'), + new DbConfigTestScenario(PostgreSQL.NAME, 'postgres'), + new DbConfigTestScenario(Oracle.NAME, 'oracle'), + new DbConfigTestScenario(SQLServer.NAME, 'mssql'), + ]) } - void "test config for #db with #migration"() { + + void "test config for #testScenario.db with #testScenario.migration"(DbConfigTestScenario testScenario) { when: - GeneratorContext ctx = buildGeneratorContext([HibernateReactiveJpa.NAME, db, migration]) + GeneratorContext ctx = buildGeneratorContext([HibernateReactiveJpa.NAME, testScenario.db, testScenario.migration]) then: !ctx.configuration.containsKey("datasources.default.url") !ctx.configuration.containsKey("datasources.default.username") !ctx.configuration.containsKey("datasources.default.password") !ctx.configuration.containsKey("datasources.default.dialect") - ctx.configuration."datasources.default.db-type" == type + ctx.configuration."datasources.default.db-type" == testScenario.dbType ctx.configuration."jpa.default.reactive" == true - ctx.configuration."jpa.default.properties.hibernate.connection.db-type" == type + ctx.configuration."jpa.default.properties.hibernate.connection.db-type" == testScenario.dbType !ctx.configuration.containsKey("jpa.default.properties.hibernate.connection.url") !ctx.configuration.containsKey("jpa.default.properties.hibernate.connection.username") !ctx.configuration.containsKey("jpa.default.properties.hibernate.connection.password") where: - db | type | migration - MySQL.NAME | 'mysql' | Flyway.NAME - MariaDB.NAME | 'mariadb' | Flyway.NAME - PostgreSQL.NAME | 'postgres' | Flyway.NAME - Oracle.NAME | 'oracle' | Flyway.NAME - SQLServer.NAME | 'mssql' | Flyway.NAME - MySQL.NAME | 'mysql' | Liquibase.NAME - MariaDB.NAME | 'mariadb' | Liquibase.NAME - PostgreSQL.NAME | 'postgres' | Liquibase.NAME - Oracle.NAME | 'oracle' | Liquibase.NAME - SQLServer.NAME | 'mssql' | Liquibase.NAME + testScenario << dbConfigMigrationScenarios() + + } + + List dbConfigMigrationScenarios() { + filterDbConfigTestScenario([ + new DbConfigTestScenario(MySQL.NAME, 'mysql', Flyway.NAME), + new DbConfigTestScenario(MariaDB.NAME, 'mariadb', Flyway.NAME), + new DbConfigTestScenario(PostgreSQL.NAME, 'postgres', Flyway.NAME), + new DbConfigTestScenario(Oracle.NAME, 'oracle', Flyway.NAME), + new DbConfigTestScenario(SQLServer.NAME, 'mssql', Flyway.NAME), + new DbConfigTestScenario(MySQL.NAME, 'mysql', Liquibase.NAME), + new DbConfigTestScenario(MariaDB.NAME, 'mariadb', Liquibase.NAME), + new DbConfigTestScenario(PostgreSQL.NAME, 'postgres', Liquibase.NAME), + new DbConfigTestScenario(Oracle.NAME, 'oracle', Liquibase.NAME), + new DbConfigTestScenario(SQLServer.NAME, 'mssql', Liquibase.NAME), + ]) + } + + @Canonical + class DbConfigTestScenario { + String db + String dbType + String migration + } + + @Canonical + class TestScenario { + String db + String client + String container + String migration + String testResourcesModule + Dependency driver + } + + private List filterDbConfigTestScenario(List scenarios) { + scenarios.stream() + .filter(ts -> ts.db != Oracle.NAME || Oracle.COMPATIBLE_WITH_HIBERNATE_REACTIVE) + .toList() + } + + private List filter(List scenarios) { + scenarios.stream() + .filter(ts -> ts.db != Oracle.NAME || Oracle.COMPATIBLE_WITH_HIBERNATE_REACTIVE) + .toList() } } diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/database/JAsyncSQLSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/database/JAsyncSQLSpec.groovy index d3e99acbdd3..23d42b9f3b4 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/database/JAsyncSQLSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/database/JAsyncSQLSpec.groovy @@ -12,8 +12,8 @@ class JAsyncSQLSpec extends ApplicationContextSpec implements CommandOutputFixtu void 'test readme.md with feature jasync-sql contains links to micronaut and 3rd party docs'() { when: - def output = generate(['jasync-sql','mysql']) - def readme = output["README.md"] + Map output = generate(['jasync-sql','mysql']) + String readme = output["README.md"] then: readme diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/database/JooqSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/database/JooqSpec.groovy index c59f1dbed3f..b0c24817915 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/database/JooqSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/database/JooqSpec.groovy @@ -16,8 +16,8 @@ class JooqSpec extends ApplicationContextSpec implements CommandOutputFixture { void 'test readme.md with feature jooq contains links to micronaut docs'() { when: - def output = generate(ApplicationType.DEFAULT, new Options().withJavaVersion(MicronautJdkVersionConfiguration.DEFAULT_OPTION), ['jooq']) - def readme = output["README.md"] + Map output = generate(ApplicationType.DEFAULT, new Options().withJavaVersion(MicronautJdkVersionConfiguration.DEFAULT_OPTION), ['jooq']) + String readme = output["README.md"] then: readme diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/database/MongoGormSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/database/MongoGormSpec.groovy deleted file mode 100644 index f9cd908c152..00000000000 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/database/MongoGormSpec.groovy +++ /dev/null @@ -1,110 +0,0 @@ -package io.micronaut.starter.feature.database - -import io.micronaut.starter.ApplicationContextSpec -import io.micronaut.starter.BuildBuilder -import io.micronaut.starter.application.ApplicationType -import io.micronaut.starter.application.generator.GeneratorContext -import io.micronaut.starter.feature.Features -import io.micronaut.starter.fixture.CommandOutputFixture -import io.micronaut.starter.options.BuildTool -import io.micronaut.starter.options.Language -import io.micronaut.starter.options.Options - -class MongoGormSpec extends ApplicationContextSpec implements CommandOutputFixture { - - void 'test readme.md with feature mongo-sync contains links to micronaut and 3rd party docs'() { - when: - Options options = new Options(Language.GROOVY, BuildTool.DEFAULT_OPTION) - def output = generate(ApplicationType.DEFAULT,options, ['mongo-gorm']) - def readme = output["README.md"] - - then: - readme - readme.contains("https://micronaut-projects.github.io/micronaut-mongodb/latest/guide/index.html") - readme.contains("https://gorm.grails.org/latest/mongodb/manual/") - readme.contains("https://docs.mongodb.com") - } - - void "test mongo gorm features"() { - when: - Features features = getFeatures(['mongo-gorm']) - - then: - features.contains("groovy") - features.contains("mongo-reactive") - features.contains("mongo-gorm") - } - - void "test dependencies are present for gradle"() { - when: - String template = new BuildBuilder(beanContext, BuildTool.GRADLE) - .features(["mongo-gorm"]) - .language(Language.GROOVY) - .render() - - then: - template.contains('implementation("io.micronaut.groovy:micronaut-mongo-gorm")') - template.contains('implementation("io.micronaut.mongodb:micronaut-mongo-reactive")') - } - - void "test testcontainers dependencies are present for gradle"() { - when: - String template = new BuildBuilder(beanContext, BuildTool.GRADLE) - .features([TestContainers.NAME, 'mongo-gorm']) - .language(Language.GROOVY) - .render() - - then: - template.contains('implementation("io.micronaut.groovy:micronaut-mongo-gorm")') - template.contains('implementation("io.micronaut.mongodb:micronaut-mongo-reactive")') - template.contains('testImplementation("org.testcontainers:mongodb")') - template.contains('testImplementation("org.testcontainers:spock")') - - } - - void "test dependencies are present for maven"() { - when: - String template = new BuildBuilder(beanContext, BuildTool.MAVEN) - .features([TestContainers.NAME, 'mongo-gorm']) - .language(Language.GROOVY) - .render() - - then: - template.contains(""" - - io.micronaut.groovy - micronaut-mongo-gorm - compile - -""") - template.contains(""" - - io.micronaut.mongodb - micronaut-mongo-reactive - compile - -""") - template.contains(""" - - org.testcontainers - mongodb - test - -""") - template.contains(""" - - org.testcontainers - spock - test - -""") - } - - void "test config"() { - when: - GeneratorContext ctx = buildGeneratorContext(['mongo-gorm']) - - then: - !ctx.getConfiguration().get("mongodb.uri") - } -} diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/database/MongoSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/database/MongoSpec.groovy index 86314354987..b16a07ad500 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/database/MongoSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/database/MongoSpec.groovy @@ -17,8 +17,8 @@ class MongoSpec extends ApplicationContextSpec implements CommandOutputFixture { @Unroll void 'test readme.md with feature #feature contains links to micronaut and 3rd party docs'(String feature) { when: - def output = generate([feature]) - def readme = output["README.md"] + Map output = generate([feature]) + String readme = output["README.md"] then: readme diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/database/MySQLSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/database/MySQLSpec.groovy index da6e5280f3f..2f6e6f0ac01 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/database/MySQLSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/database/MySQLSpec.groovy @@ -2,20 +2,25 @@ package io.micronaut.starter.feature.database import io.micronaut.starter.ApplicationContextSpec import io.micronaut.starter.BuildBuilder +import io.micronaut.starter.build.BuildTestUtil +import io.micronaut.starter.build.BuildTestVerifier +import io.micronaut.starter.build.dependencies.Scope import io.micronaut.starter.options.BuildTool import io.micronaut.starter.options.Language +import static io.micronaut.starter.options.BuildTool.GRADLE + class MySQLSpec extends ApplicationContextSpec { void 'test gradle mysql feature for language=#language'() { when: - String template = new BuildBuilder(beanContext, BuildTool.GRADLE) + String template = new BuildBuilder(beanContext, GRADLE) .features(['mysql']) .language(language) .render() then: - template.contains('runtimeOnly("mysql:mysql-connector-java")') + template.contains('runtimeOnly("com.mysql:mysql-connector-j")') and: template.contains(""" @@ -29,13 +34,13 @@ class MySQLSpec extends ApplicationContextSpec { void 'testresources not configured for Gradle with testContainers feature and language=#language'() { when: - String template = new BuildBuilder(beanContext, BuildTool.GRADLE) + String template = new BuildBuilder(beanContext, GRADLE) .features(['mysql', 'testcontainers']) .language(language) .render() then: - template.contains('runtimeOnly("mysql:mysql-connector-java")') + template.contains('runtimeOnly("com.mysql:mysql-connector-j")') and: !template.contains(""" @@ -48,32 +53,22 @@ class MySQLSpec extends ApplicationContextSpec { } void 'test maven mysql feature for language=#language'() { + given: + BuildTool buildTool = BuildTool.MAVEN when: - String template = new BuildBuilder(beanContext, BuildTool.MAVEN) + + String template = new BuildBuilder(beanContext, buildTool) .features(['mysql']) .language(language) .render() + BuildTestVerifier verifier = BuildTestUtil.verifier(buildTool, template) + then: - template.contains(""" - - mysql - mysql-connector-java - runtime - -""") + verifier.hasDependency('com.mysql', "mysql-connector-j", Scope.RUNTIME) + verifier.hasTestResourceDependency("micronaut-test-resources-jdbc-mysql") - and: - template.contains(""" - - - io.micronaut.testresources - micronaut-test-resources-jdbc-mysql - - -""") where: language << Language.values().toList() } - } diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/database/Neo4jBoltSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/database/Neo4jBoltSpec.groovy index 4cae528b21b..8f4a0052a6b 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/database/Neo4jBoltSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/database/Neo4jBoltSpec.groovy @@ -14,8 +14,8 @@ class Neo4jBoltSpec extends ApplicationContextSpec implements CommandOutputFixt void 'test readme.md with feature neo4j-bolt contains links to micronaut docs'() { when: - def output = generate(['neo4j-bolt']) - def readme = output["README.md"] + Map output = generate(['neo4j-bolt']) + String readme = output["README.md"] then: readme diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/database/Neo4jGormSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/database/Neo4jGormSpec.groovy deleted file mode 100644 index 8e0bb9cafe8..00000000000 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/database/Neo4jGormSpec.groovy +++ /dev/null @@ -1,73 +0,0 @@ -package io.micronaut.starter.feature.database - -import io.micronaut.starter.ApplicationContextSpec -import io.micronaut.starter.BuildBuilder -import io.micronaut.starter.application.generator.GeneratorContext -import io.micronaut.starter.feature.Features -import io.micronaut.starter.options.BuildTool -import io.micronaut.starter.options.Language - -class Neo4jGormSpec extends ApplicationContextSpec { - - void "test neo4j gorm features"() { - when: - Features features = getFeatures(['neo4j-gorm']) - - then: - features.contains("groovy") - features.contains("neo4j-bolt") - features.contains("neo4j-gorm") - } - - void "test dependencies are present for gradle"() { - when: - String template = new BuildBuilder(beanContext, BuildTool.GRADLE) - .features(["neo4j-gorm"]) - .language(Language.GROOVY) - .render() - - then: - template.contains('implementation("io.micronaut.groovy:micronaut-neo4j-gorm")') - template.contains('implementation("io.micronaut.neo4j:micronaut-neo4j-bolt")') - template.contains("testRuntimeOnly(\"org.neo4j.test:neo4j-harness\")") - } - - void "test dependencies are present for maven"() { - when: - String template = new BuildBuilder(beanContext, BuildTool.MAVEN) - .features(['neo4j-gorm']) - .language(Language.GROOVY) - .render() - - then: - template.contains(""" - - io.micronaut.groovy - micronaut-neo4j-gorm - compile - -""") - template.contains(""" - - io.micronaut.neo4j - micronaut-neo4j-bolt - compile - -""") - template.contains(""" - - org.neo4j.test - neo4j-harness - test - -""") - } - - void "test config"() { - when: - GeneratorContext ctx = buildGeneratorContext(['neo4j-gorm']) - - then: - ctx.getConfiguration().get("neo4j.uri") == "bolt://\${NEO4J_HOST:localhost}" - } -} diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/database/OracleSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/database/OracleSpec.groovy index d065e7861f5..eb4ed7c1c0d 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/database/OracleSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/database/OracleSpec.groovy @@ -2,50 +2,28 @@ package io.micronaut.starter.feature.database import io.micronaut.starter.ApplicationContextSpec import io.micronaut.starter.BuildBuilder -import io.micronaut.starter.feature.database.r2dbc.R2dbcFeature +import io.micronaut.starter.build.BuildTestUtil +import io.micronaut.starter.build.BuildTestVerifier +import io.micronaut.starter.build.dependencies.Scope import io.micronaut.starter.fixture.CommandOutputFixture import io.micronaut.starter.options.BuildTool import io.micronaut.starter.options.Language import spock.lang.Unroll -import java.util.stream.Collectors - class OracleSpec extends ApplicationContextSpec implements CommandOutputFixture { @Unroll - void 'test gradle oracle feature for language=#language'() { - when: - String template = new BuildBuilder(beanContext, BuildTool.GRADLE) - .features(['oracle']) - .language(language) - .render() - - then: - template.contains('runtimeOnly("com.oracle.database.jdbc:ojdbc8")') - - where: - language << Language.values().toList() - } - - @Unroll - void 'test maven oracle feature for language=#language'() { + void 'test #buildTool oracle feature for language=#language'(BuildTool buildTool, Language language) { when: - String template = new BuildBuilder(beanContext, BuildTool.MAVEN) + String template = new BuildBuilder(beanContext, buildTool) .features(['oracle']) .language(language) .render() - + BuildTestVerifier verifier = BuildTestUtil.verifier(buildTool, language, template) then: - template.contains(""" - - com.oracle.database.jdbc - ojdbc8 - runtime - -""") + verifier.hasDependency("com.oracle.database.jdbc", "ojdbc11", Scope.RUNTIME) where: - language << Language.values().toList() + [buildTool, language] << [BuildTool.values(), Language.values()].combinations() } - } diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/database/TestContainersSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/database/TestContainersSpec.groovy index 9ccd26f36dc..0600b9c0a6f 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/database/TestContainersSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/database/TestContainersSpec.groovy @@ -7,8 +7,6 @@ import io.micronaut.starter.build.BuildTestVerifier import io.micronaut.starter.build.dependencies.Scope import io.micronaut.starter.feature.Features import io.micronaut.starter.options.BuildTool -import io.micronaut.starter.options.JdkVersion -import io.micronaut.starter.options.Language import io.micronaut.starter.options.MicronautJdkVersionConfiguration import io.micronaut.starter.options.TestFramework @@ -93,18 +91,6 @@ class TestContainersSpec extends ApplicationContextSpec { template.contains('testImplementation("org.testcontainers:testcontainers")') } - void "test mongo-gorm dependency is present for gradle"() { - when: - String template = new BuildBuilder(beanContext, BuildTool.GRADLE) - .features([TestContainers.NAME, 'mongo-gorm']) - .language(Language.GROOVY) - .render() - - then: - template.contains('testImplementation("org.testcontainers:mongodb")') - template.contains('testImplementation("org.testcontainers:testcontainers")') - } - void "test testcontainers core is present when no testcontainer modules are present for gradle"() { when: String template = new BuildBuilder(beanContext, BuildTool.GRADLE) @@ -305,30 +291,6 @@ class TestContainersSpec extends ApplicationContextSpec { """) } - void "test mongo-gorm dependency is present for maven"() { - when: - String template = new BuildBuilder(beanContext, BuildTool.MAVEN) - .features([TestContainers.NAME, 'mongo-gorm']) - .language(Language.GROOVY) - .render() - - then: - template.contains(""" - - org.testcontainers - mongodb - test - -""") - template.contains(""" - - org.testcontainers - testcontainers - test - -""") - } - void "test testcontainers dependency is present and no testcontainer modules are present for maven"() { when: String template = new BuildBuilder(beanContext, BuildTool.MAVEN) diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/database/jdbc/JdbcSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/database/jdbc/JdbcSpec.groovy index 71483e6c1d9..16700e80f34 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/database/jdbc/JdbcSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/database/jdbc/JdbcSpec.groovy @@ -81,8 +81,8 @@ class JdbcSpec extends ApplicationContextSpec implements CommandOutputFixture { @Unroll void 'test readme.md with feature #jdbcFeature contains links to micronaut docs'() { when: - def output = generate([jdbcFeature]) - def readme = output["README.md"] + Map output = generate([jdbcFeature]) + String readme = output["README.md"] then: readme diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/database/r2dbc/DataR2dbcSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/database/r2dbc/DataR2dbcSpec.groovy index 1851553ebab..30f9b72a9c4 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/database/r2dbc/DataR2dbcSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/database/r2dbc/DataR2dbcSpec.groovy @@ -32,8 +32,8 @@ class DataR2dbcSpec extends ApplicationContextSpec implements CommandOutputFixtu void 'test readme.md with feature data-jdbc contains links to micronaut docs'() { when: - def output = generate(['data-r2dbc']) - def readme = output["README.md"] + Map output = generate(['data-r2dbc']) + String readme = output["README.md"] then: readme diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/dekorate/DekorateSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/dekorate/DekorateSpec.groovy index 217b41576f5..30672c71620 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/dekorate/DekorateSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/dekorate/DekorateSpec.groovy @@ -13,8 +13,8 @@ class DekorateSpec extends ApplicationContextSpec implements CommandOutputFixtur void 'test readme.md with feature dekorate-kubernetes contains links to micronaut docs'() { when: - def output = generate(['dekorate-kubernetes']) - def readme = output["README.md"] + Map output = generate(['dekorate-kubernetes']) + String readme = output["README.md"] then: readme diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/dev/ControlPanelSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/dev/ControlPanelSpec.groovy index 546e087296c..8762ea66b7b 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/dev/ControlPanelSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/dev/ControlPanelSpec.groovy @@ -32,8 +32,8 @@ class ControlPanelSpec extends ApplicationContextSpec implements CommandOutputFi void 'test readme.md with feature control-panel contains links to micronaut docs'() { when: - def output = generate([ControlPanel.NAME]) - def readme = output["README.md"] + Map output = generate([ControlPanel.NAME]) + String readme = output["README.md"] then: readme diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/discovery/DiscoveryConsulSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/discovery/DiscoveryConsulSpec.groovy index 58e5d20d36f..9f8268ec288 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/discovery/DiscoveryConsulSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/discovery/DiscoveryConsulSpec.groovy @@ -16,8 +16,8 @@ class DiscoveryConsulSpec extends ApplicationContextSpec implements CommandOutp void 'test readme.md with feature discovery-consul contains links to micronaut docs'() { when: - def output = generate(['discovery-consul']) - def readme = output["README.md"] + Map output = generate(['discovery-consul']) + String readme = output["README.md"] then: readme diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/discovery/DiscoveryKubernetesSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/discovery/DiscoveryKubernetesSpec.groovy index 08e3959fa34..f6bf6b09aee 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/discovery/DiscoveryKubernetesSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/discovery/DiscoveryKubernetesSpec.groovy @@ -15,8 +15,8 @@ class DiscoveryKubernetesSpec extends ApplicationContextSpec implements CommandO void 'test readme.md with feature discovery-kubernetes contains links to micronaut docs'() { when: - def output = generate(['discovery-kubernetes']) - def readme = output["README.md"] + Map output = generate(['discovery-kubernetes']) + String readme = output["README.md"] then: readme diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/discovery/EurekaSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/discovery/EurekaSpec.groovy index 69ea1be7628..b849452d5ca 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/discovery/EurekaSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/discovery/EurekaSpec.groovy @@ -15,8 +15,8 @@ class EurekaSpec extends ApplicationContextSpec implements CommandOutputFixture void 'test readme.md with feature discovery-eureka contains links to micronaut docs'() { when: - def output = generate(['discovery-eureka']) - def readme = output["README.md"] + Map output = generate(['discovery-eureka']) + String readme = output["README.md"] then: readme diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/distributedconfig/DistributedConfigConsulSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/distributedconfig/DistributedConfigConsulSpec.groovy index 45092cc6780..83ead52ce69 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/distributedconfig/DistributedConfigConsulSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/distributedconfig/DistributedConfigConsulSpec.groovy @@ -12,8 +12,8 @@ class DistributedConfigConsulSpec extends ApplicationContextSpec implements Com void 'test readme.md with feature discovery-consul contains links to micronaut docs'() { when: - def output = generate(['config-consul']) - def readme = output["README.md"] + Map output = generate(['config-consul']) + String readme = output["README.md"] then: readme diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/distributedconfig/KubernetesConfigSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/distributedconfig/KubernetesConfigSpec.groovy index 1bf292a944b..df37eb0653b 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/distributedconfig/KubernetesConfigSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/distributedconfig/KubernetesConfigSpec.groovy @@ -13,8 +13,8 @@ class KubernetesConfigSpec extends ApplicationContextSpec implements CommandOut void 'test readme.md with feature kubernetes contains links to micronaut docs'() { when: - def output = generate(['config-kubernetes']) - def readme = output["README.md"] + Map output = generate(['config-kubernetes']) + String readme = output["README.md"] then: readme diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/eclipsestore/EclipseStoreSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/eclipsestore/EclipseStoreSpec.groovy index 37dc5a08efd..88498c9b340 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/eclipsestore/EclipseStoreSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/eclipsestore/EclipseStoreSpec.groovy @@ -15,8 +15,8 @@ class EclipseStoreSpec extends BeanContextSpec implements CommandOutputFixture { void 'test readme.md with feature eclipsestore contains links to micronaut docs'() { when: - def output = generate(['eclipsestore']) - def readme = output["README.md"] + Map output = generate(['eclipsestore']) + String readme = output["README.md"] then: readme.contains("[Micronaut EclipseStore documentation](https://micronaut-projects.github.io/micronaut-eclipsestore/latest/guide)") @@ -25,8 +25,8 @@ class EclipseStoreSpec extends BeanContextSpec implements CommandOutputFixture { void 'test readme.md with feature eclipsestore-rest contains links to micronaut docs'() { when: - def output = generate(['eclipsestore-rest']) - def readme = output["README.md"] + Map output = generate(['eclipsestore-rest']) + String readme = output["README.md"] then: readme.contains("[Micronaut EclipseStore documentation](https://micronaut-projects.github.io/micronaut-eclipsestore/latest/guide)") diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/elasticsearch/ElasticsearchSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/elasticsearch/ElasticsearchSpec.groovy index 4f50e6327c8..6616c357318 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/elasticsearch/ElasticsearchSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/elasticsearch/ElasticsearchSpec.groovy @@ -13,8 +13,8 @@ class ElasticsearchSpec extends ApplicationContextSpec implements CommandOutput void 'test readme.md with feature elasticsearch contains links to micronaut docs'() { when: - def output = generate(['elasticsearch']) - def readme = output["README.md"] + Map output = generate(['elasticsearch']) + String readme = output["README.md"] then: readme diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/function/awslambda/AwsLambdaSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/function/awslambda/AwsLambdaSpec.groovy index c925d9af6bb..4fac8383d7f 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/function/awslambda/AwsLambdaSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/function/awslambda/AwsLambdaSpec.groovy @@ -293,15 +293,15 @@ class AwsLambdaSpec extends ApplicationContextSpec implements CommandOutputFixtu then: !buildGradle.contains('id "application"') if (applicationType == ApplicationType.DEFAULT) { - assert buildGradle.contains('mainClass.set') + assert buildGradle.contains('mainClass = ') } buildGradle.contains('id("io.micronaut.application")') if (buildTool == BuildTool.GRADLE_KOTLIN) { assert buildGradle.contains("""\ tasks.named("dockerfileNative") { - baseImage.set("amazonlinux:2") - jdkVersion.set("${javaVersion}") + baseImage = "amazonlinux:2023" + jdkVersion = "${javaVersion}" args( "-XX:MaximumHeapSizePercent=80", "-Dio.netty.allocator.numDirectArenas=0", @@ -311,7 +311,7 @@ tasks.named("dockerfileNative" } else if (buildTool == BuildTool.GRADLE) { assert buildGradle.contains("""\ tasks.named("dockerfileNative") { - baseImage = "amazonlinux:2" + baseImage = "amazonlinux:2023" jdkVersion = "${javaVersion}" args( "-XX:MaximumHeapSizePercent=80", @@ -363,12 +363,12 @@ tasks.named("dockerfileNative") { then: !buildGradle.contains('id "application"') - buildGradle.contains('mainClass.set') + buildGradle.contains('mainClass = ') buildGradle.contains('id("io.micronaut.application")') buildGradle.contains("""\ tasks.named("dockerfileNative") { - baseImage.set("amazonlinux:2") - jdkVersion.set("${javaVersion}") + baseImage = "amazonlinux:2023" + jdkVersion = "${javaVersion}" args( "-XX:MaximumHeapSizePercent=80", "-Dio.netty.allocator.numDirectArenas=0", @@ -411,7 +411,7 @@ tasks.named("dockerfileNative" def buildGradle = output['build.gradle'] then: - buildGradle.contains('mainClass.set("io.micronaut.function.aws.runtime.MicronautLambdaRuntime")') + buildGradle.contains('mainClass = "io.micronaut.function.aws.runtime.MicronautLambdaRuntime"') where: language << Language.values().toList() @@ -428,7 +428,7 @@ tasks.named("dockerfileNative" then: template.contains('runtime("lambda_java")') !template.contains('implementation("io.micronaut:micronaut-http-server-netty")') - !template.contains('implementation("io.micronaut:micronaut-http-client")') + !template.contains('implementation("io.micronaut:micronaut-http-client-jdk")') where: language << Language.values() @@ -444,7 +444,7 @@ tasks.named("dockerfileNative" then: template.contains('runtime("lambda_provided")') !template.contains('implementation("io.micronaut:micronaut-http-server-netty")') - template.contains('implementation("io.micronaut:micronaut-http-client")') + template.contains('implementation("io.micronaut:micronaut-http-client-jdk")') where: language << GraalVMFeatureValidator.supportedLanguages() @@ -490,7 +490,7 @@ tasks.named("dockerfileNative" !verifier.hasDependency("io.micronaut", "micronaut-http-server-netty", Scope.COMPILE) // Specifically added in io.micronaut.starter.feature.other.HttpClientTest.apply - verifier.hasDependency("io.micronaut", "micronaut-http-client") + verifier.hasDependency("io.micronaut", "micronaut-http-client-jdk") where: [applicationType, language] << [ @@ -516,9 +516,8 @@ tasks.named("dockerfileNative" !verifier.hasDependency("io.micronaut.aws", "micronaut-function-aws-custom-runtime") !verifier.hasDependency("io.micronaut", "micronaut-http-server-netty", Scope.COMPILE) verifier.hasDependency('io.micronaut.aws', 'micronaut-function-aws-api-proxy', Scope.COMPILE) - - // Specifically added in io.micronaut.starter.feature.other.HttpClientTest.apply - verifier.hasDependency("io.micronaut", "micronaut-http-client") + verifier.hasDependency("io.micronaut", "micronaut-http-client-jdk", Scope.TEST) + !verifier.hasDependency("io.micronaut", "micronaut-http-client-jdk", Scope.COMPILE) where: language << Language.values().toList() @@ -542,7 +541,7 @@ tasks.named("dockerfileNative" !verifier.hasDependency("io.micronaut", "micronaut-http-server-netty", Scope.COMPILE) // Specifically added in io.micronaut.starter.feature.other.HttpClientTest.apply - verifier.hasDependency("io.micronaut", "micronaut-http-client") + verifier.hasDependency("io.micronaut", "micronaut-http-client-jdk") where: language << GraalVMFeatureValidator.supportedLanguages() @@ -560,7 +559,7 @@ tasks.named("dockerfileNative" then: build.contains('runtime("lambda_java")') !build.contains('implementation("io.micronaut:micronaut-http-server-netty")') - !build.contains('implementation("io.micronaut:micronaut-http-client")') + !build.contains('implementation("io.micronaut:micronaut-http-client-jdk")') output.containsKey("$srcDir/example/micronaut/HomeController.$extension".toString()) output.containsKey(language.getDefaults().getTest().getSourcePath("/example/micronaut/HomeController", language)) diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/function/azure/AzureCloudFunctionSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/function/azure/AzureCloudFunctionSpec.groovy index 8cadeaaf8a7..a4382ed5b75 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/function/azure/AzureCloudFunctionSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/function/azure/AzureCloudFunctionSpec.groovy @@ -51,13 +51,13 @@ class AzureCloudFunctionSpec extends ApplicationContextSpec implements CommandOu void 'test gradle raw azure function feature for language=#language'() { when: - def output = generate( + Map output = generate( ApplicationType.FUNCTION, new Options(language, TestFramework.JUNIT, BuildTool.GRADLE, JdkVersion.JDK_8), ['azure-function'] ) String build = output['build.gradle'] - def readme = output["README.md"] + String readme = output["README.md"] then: build.contains('id("com.microsoft.azure.azurefunctions")') @@ -134,12 +134,12 @@ class AzureCloudFunctionSpec extends ApplicationContextSpec implements CommandOu void 'test sources generated for azure function feature gradle and language=#language (using serde #useSerde)'(Language language, boolean useSerde) { when: - def output = generate( + Map output = generate( ApplicationType.DEFAULT, new Options(language, TestFramework.JUNIT, BuildTool.GRADLE, JdkVersion.JDK_8), ['azure-function'] + (useSerde ? ['serialization-jackson'] : ['jackson-databind']) ) - def readme = output["README.md"] + String readme = output["README.md"] then: output.containsKey("${language.srcDir}/example/micronaut/Application.${language.extension}".toString()) @@ -164,13 +164,13 @@ class AzureCloudFunctionSpec extends ApplicationContextSpec implements CommandOu void 'test azure function feature for language=#language (using serde #useSerde) - maven'(Language language, boolean useSerde) { when: - def output = generate( + Map output = generate( ApplicationType.DEFAULT, new Options(language, TestFramework.JUNIT, BuildTool.MAVEN, JdkVersion.JDK_8), ['azure-function'] + (useSerde ? ['serialization-jackson'] : ['jackson-databind']) ) String build = output['pom.xml'] - def readme = output["README.md"] + String readme = output["README.md"] then: build.count('azure-functions-maven-plugin') == 1 diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/function/azure/AzureHttpFunctionSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/function/azure/AzureHttpFunctionSpec.groovy index 4e72eb6f355..d1af4720e2c 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/function/azure/AzureHttpFunctionSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/function/azure/AzureHttpFunctionSpec.groovy @@ -14,8 +14,8 @@ class AzureHttpFunctionSpec extends BeanContextSpec implements CommandOutputFix void 'test readme.md with feature azure-function and Maven does not contain link to Azure Gradle plugin'() { when: Options options = new Options(Language.JAVA, TestFramework.JUNIT, BuildTool.MAVEN, JdkVersion.JDK_8) - def output = generate(ApplicationType.DEFAULT, options, ['azure-function']) - def readme = output["README.md"] + Map output = generate(ApplicationType.DEFAULT, options, ['azure-function']) + String readme = output["README.md"] then: readme @@ -28,8 +28,8 @@ class AzureHttpFunctionSpec extends BeanContextSpec implements CommandOutputFix void 'test readme.md with feature azure-function contains links to docs'() { when: Options options = new Options(Language.JAVA, TestFramework.JUNIT, BuildTool.GRADLE, JdkVersion.JDK_8) - def output = generate(ApplicationType.DEFAULT, options, ['azure-function']) - def readme = output["README.md"] + Map output = generate(ApplicationType.DEFAULT, options, ['azure-function']) + String readme = output["README.md"] then: readme @@ -69,6 +69,7 @@ class AzureHttpFunctionSpec extends BeanContextSpec implements CommandOutputFix .applicationType(ApplicationType.DEFAULT) .features(['azure-function']) .language(language) + .jdkVersion(JdkVersion.JDK_17) .render() BuildTestVerifier verifier = BuildTestUtil.verifier(buildTool, template) @@ -94,6 +95,7 @@ class AzureHttpFunctionSpec extends BeanContextSpec implements CommandOutputFix .applicationType(ApplicationType.FUNCTION) .features(['azure-function']) .language(language) + .jdkVersion(JdkVersion.JDK_17) .render() BuildTestVerifier verifier = BuildTestUtil.verifier(buildTool, template) diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/function/azure/AzureRawFunctionSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/function/azure/AzureRawFunctionSpec.groovy index bca68f01476..a169b274159 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/function/azure/AzureRawFunctionSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/function/azure/AzureRawFunctionSpec.groovy @@ -10,8 +10,8 @@ class AzureRawFunctionSpec extends BeanContextSpec implements CommandOutputFixt void 'test readme.md with feature azure-function and Maven does not contain link to Azure Gradle plugin'() { when: Options options = new Options(Language.JAVA, TestFramework.JUNIT, BuildTool.MAVEN, JdkVersion.JDK_8) - def output = generate(ApplicationType.FUNCTION, options, ['azure-function']) - def readme = output["README.md"] + Map output = generate(ApplicationType.FUNCTION, options, ['azure-function']) + String readme = output["README.md"] then: readme @@ -24,8 +24,8 @@ class AzureRawFunctionSpec extends BeanContextSpec implements CommandOutputFixt void 'test readme.md with feature azure-function contains links to docs'() { when: Options options = new Options(Language.JAVA, TestFramework.JUNIT, BuildTool.GRADLE, JdkVersion.JDK_8) - def output = generate(ApplicationType.FUNCTION, options, ['azure-function']) - def readme = output["README.md"] + Map output = generate(ApplicationType.FUNCTION, options, ['azure-function']) + String readme = output["README.md"] then: readme diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/function/gcp/GoogleCloudEventsFunctionSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/function/gcp/GoogleCloudEventsFunctionSpec.groovy index 266b28b52e3..b22b19bd4c7 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/function/gcp/GoogleCloudEventsFunctionSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/function/gcp/GoogleCloudEventsFunctionSpec.groovy @@ -51,9 +51,9 @@ class GoogleCloudEventsFunctionSpec extends BeanContextSpec implements CommandOu void 'test readme.md and function for #buildTool build with feature google-cloud-function'(BuildTool buildTool) { when: Options options = new Options(Language.JAVA, TestFramework.JUNIT, buildTool, JdkVersion.JDK_8) - def output = generate(ApplicationType.FUNCTION, options, ['google-cloud-function-cloudevents']) - def function = output['src/main/java/example/micronaut/Function.java'] - def readme = output['README.md'] + Map output = generate(ApplicationType.FUNCTION, options, ['google-cloud-function-cloudevents']) + String function = output['src/main/java/example/micronaut/Function.java'] + String readme = output['README.md'] then: function diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/function/gcp/GoogleCloudFunctionSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/function/gcp/GoogleCloudFunctionSpec.groovy index 950074265db..271dba59f77 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/function/gcp/GoogleCloudFunctionSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/function/gcp/GoogleCloudFunctionSpec.groovy @@ -29,12 +29,12 @@ class GoogleCloudFunctionSpec extends BeanContextSpec implements CommandOutputF void 'test readme.md with feature google-cloud-function contains links to docs'() { when: - def output = generate( + Map output = generate( ApplicationType.DEFAULT, - new Options(language, TestFramework.JUNIT, BuildTool.GRADLE, MicronautJdkVersionConfiguration.DEFAULT_OPTION), + new Options(language, TestFramework.JUNIT, BuildTool.GRADLE, JdkVersion.JDK_17), ['google-cloud-function'] ) - def readme = output["README.md"] + String readme = output["README.md"] then: readme @@ -79,12 +79,12 @@ class GoogleCloudFunctionSpec extends BeanContextSpec implements CommandOutputF void 'test gradle google cloud function feature for language=#language'() { when: - def output = generate( + Map output = generate( ApplicationType.DEFAULT, - new Options(language, TestFramework.JUNIT, BuildTool.GRADLE, MicronautJdkVersionConfiguration.DEFAULT_OPTION), + new Options(language, TestFramework.JUNIT, BuildTool.GRADLE, JdkVersion.JDK_17), ['google-cloud-function'] ) - def readme = output["README.md"] + String readme = output["README.md"] then: output.containsKey("${language.srcDir}/example/micronaut/Application.${extension}".toString()) @@ -124,7 +124,7 @@ class GoogleCloudFunctionSpec extends BeanContextSpec implements CommandOutputF String build = new BuildBuilder(beanContext, buildTool) .features(['google-cloud-function']) .testFramework(TestFramework.JUNIT) - .jdkVersion(MicronautJdkVersionConfiguration.DEFAULT_OPTION) + .jdkVersion(JdkVersion.JDK_17) .render() BuildTestVerifier verifier = BuildTestUtil.verifier(buildTool, build) @@ -141,13 +141,13 @@ class GoogleCloudFunctionSpec extends BeanContextSpec implements CommandOutputF void 'test gradle google cloud function feature for language=#language - raw function'() { when: - def output = generate( + Map output = generate( ApplicationType.FUNCTION, new Options(language, BuildTool.GRADLE), ['google-cloud-function'] ) String build = output['build.gradle'] - def readme = output["README.md"] + String readme = output["README.md"] then: !build.contains('implementation("io.micronaut.gcp:micronaut-gcp-function-http")') @@ -205,7 +205,7 @@ class GoogleCloudFunctionSpec extends BeanContextSpec implements CommandOutputF .applicationType(ApplicationType.DEFAULT) .features(['google-cloud-function']) .language(language) - .jdkVersion(MicronautJdkVersionConfiguration.DEFAULT_OPTION) + .jdkVersion(JdkVersion.JDK_17) .render() BuildTestVerifier verifier = BuildTestUtil.verifier(buildTool, template) diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/function/gcp/GoogleCloudRawFunctionSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/function/gcp/GoogleCloudRawFunctionSpec.groovy index 22f0aef1728..c0652d7f8ea 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/function/gcp/GoogleCloudRawFunctionSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/function/gcp/GoogleCloudRawFunctionSpec.groovy @@ -12,8 +12,8 @@ class GoogleCloudRawFunctionSpec extends BeanContextSpec implements CommandOutp void 'test readme.md with feature google-cloud-function contains links to micronaut docs'() { when: Options options = new Options(Language.JAVA, TestFramework.JUNIT, BuildTool.GRADLE, JdkVersion.JDK_8) - def output = generate(ApplicationType.FUNCTION, options, ['google-cloud-function']) - def readme = output["README.md"] + Map output = generate(ApplicationType.FUNCTION, options, ['google-cloud-function']) + String readme = output["README.md"] then: readme diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/function/oraclefunction/OracleFunctionSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/function/oraclefunction/OracleFunctionSpec.groovy index a84692984bd..fb6ac7f581b 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/function/oraclefunction/OracleFunctionSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/function/oraclefunction/OracleFunctionSpec.groovy @@ -42,13 +42,13 @@ class OracleFunctionSpec extends BeanContextSpec implements CommandOutputFixtur void 'test gradle oracle cloud function feature for language=#language (using serde #useSerde)'(Language language, boolean useSerde) { when: - def output = generate( + Map output = generate( ApplicationType.DEFAULT, new Options(language, TestFramework.JUNIT, BuildTool.GRADLE, MicronautJdkVersionConfiguration.DEFAULT_OPTION), ['oracle-function'] + (useSerde ? ['serialization-jackson'] : ['jackson-databind']) ) - def readme = output["README.md"] - def funcYaml = output["func.yml"] + String readme = output["README.md"] + String funcYaml = output["func.yml"] then: readme @@ -84,14 +84,14 @@ class OracleFunctionSpec extends BeanContextSpec implements CommandOutputFixtur void 'test maven oracle cloud function feature for language=#language (using serde #useSerde)'(Language language, boolean useSerde) { when: - def output = generate( + Map output = generate( ApplicationType.DEFAULT, new Options(language, TestFramework.JUNIT, BuildTool.MAVEN, MicronautJdkVersionConfiguration.DEFAULT_OPTION), ['oracle-function'] + (useSerde ? ['serialization-jackson'] : ['jackson-databind']) ) String build = output['pom.xml'] - def readme = output["README.md"] - def funcYaml = output["func.yml"] + String readme = output["README.md"] + String funcYaml = output["func.yml"] then: readme @@ -129,17 +129,22 @@ class OracleFunctionSpec extends BeanContextSpec implements CommandOutputFixtur build.contains('com.fnproject.fn.runtime.EntryPoint') build.contains('[REGION].ocir.io/[TENANCY]/[REPO]/${project.artifactId}') build.contains('example.micronaut.Function::handleRequest') - build.contains(''' - - - -H:+StaticExecutableWithDynamicLibC - -Dfn.handler=${function.entrypoint} - --initialize-at-build-time=example.micronaut - - - ${function.entrypoint} - - ''') + build.contains('''\ + + io.micronaut.maven + micronaut-maven-plugin + + + -H:+StaticExecutableWithDynamicLibC + -Dfn.handler=${function.entrypoint} + --initialize-at-build-time=example.micronaut + + + ${function.entrypoint} + + + +''') build.contains(''' @@ -156,6 +161,40 @@ class OracleFunctionSpec extends BeanContextSpec implements CommandOutputFixtur [language, useSerde] << [Language.values().toList(), [true, false]].combinations() } + void 'test oracle cloud function image config for #buildTool'(BuildTool buildTool) { + when: + String template = new BuildBuilder(beanContext, buildTool) + .features(['oracle-function']) + .applicationType(ApplicationType.FUNCTION) + .render() + + then: + if (buildTool == BuildTool.GRADLE) { + assert template.contains(''' String region = "region-key" + | String tenancy = "tenancy" + | String repo = "my-app"'''.stripMargin()) + assert template.contains(''' dockerBuild { + | images = ["${region}.ocir.io/${tenancy}/${repo}/${project.name}:${project.version}"] + | }'''.stripMargin()) + assert template.contains(''' dockerBuildNative { + | images = ["${region}.ocir.io/${tenancy}/${repo}/${project.name}:${project.version}"] + | }'''.stripMargin()) + } else { + assert template.contains(''' val region = "region-key" + | val tenancy = "tenancy" + | val repo = "my-app"'''.stripMargin()) + assert template.contains(''' dockerBuild { + | images = listOf("${region}.ocir.io/${tenancy}/${repo}/${project.name}:${project.version}") + | }'''.stripMargin()) + assert template.contains(''' dockerBuildNative { + | images = listOf("${region}.ocir.io/${tenancy}/${repo}/${project.name}:${project.version}") + | }'''.stripMargin()) + } + + where: + buildTool << BuildTool.valuesGradle() + } + void 'test oracle cloud function dependencies for language=#language and buildtool=#buildTool'(Language language, BuildTool buildTool) { when: String template = new BuildBuilder(beanContext, buildTool) diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/github/workflows/azure/AzureContainerInstanceWorkflowSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/github/workflows/azure/AzureContainerInstanceWorkflowSpec.groovy index f6f49acb7df..ed5ac46004c 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/github/workflows/azure/AzureContainerInstanceWorkflowSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/github/workflows/azure/AzureContainerInstanceWorkflowSpec.groovy @@ -3,16 +3,20 @@ package io.micronaut.starter.feature.github.workflows.azure import io.micronaut.starter.BeanContextSpec import io.micronaut.starter.application.ApplicationType import io.micronaut.starter.fixture.CommandOutputFixture -import io.micronaut.starter.options.* +import io.micronaut.starter.options.BuildTool +import io.micronaut.starter.options.JdkVersion +import io.micronaut.starter.options.Language +import io.micronaut.starter.options.MicronautJdkVersionConfiguration +import io.micronaut.starter.options.Options +import io.micronaut.starter.options.TestFramework import io.micronaut.starter.util.VersionInfo -import spock.lang.Unroll class AzureContainerInstanceWorkflowSpec extends BeanContextSpec implements CommandOutputFixture { void 'test github java workflow readme'() { when: - def output = generate([AzureContainerInstanceJavaWorkflow.NAME]) - def readme = output['README.md'] + Map output = generate([AzureContainerInstanceJavaWorkflow.NAME]) + String readme = output['README.md'] then: readme @@ -21,15 +25,14 @@ class AzureContainerInstanceWorkflowSpec extends BeanContextSpec implements Comm void 'test github graalvm workflow readme'() { when: - def output = generate([AzureContainerInstanceGraalWorkflow.NAME]) - def readme = output['README.md'] + Map output = generate([AzureContainerInstanceGraalWorkflow.NAME]) + String readme = output['README.md'] then: readme readme.contains("Azure Container Instance GraalVM Workflow") } - @Unroll void 'test java github workflow is created for #buildTool'(BuildTool buildTool) { when: def output = generate(ApplicationType.DEFAULT, @@ -45,29 +48,39 @@ class AzureContainerInstanceWorkflowSpec extends BeanContextSpec implements Comm buildTool << BuildTool.values() } - @Unroll - void 'test docker image is configured in build.gradle for #name'(String name) { + void 'test docker image is configured in #buildFileName for #feature'(BuildTool buildTool, String feature) { when: - def output = generate([name]) - def gradle = output['build.gradle.kts'] + def output = generate(ApplicationType.DEFAULT, new Options(Language.JAVA, buildTool), [feature]) + def gradle = output[buildTool.buildFileName] then: - gradle - gradle.contains(""" + if (buildTool == BuildTool.GRADLE) { + assert gradle.contains(''' dockerBuild { - images = [\"\${System.env.DOCKER_IMAGE ?: project.name}:\$project.version"] - }""") + images = ["${System.env.DOCKER_IMAGE ?: project.name}:$project.version"] + }''') - gradle.contains(""" + assert gradle.contains(''' dockerBuildNative { - images = [\"\${System.env.DOCKER_IMAGE ?: project.name}:\$project.version"] - }""") + images = ["${System.env.DOCKER_IMAGE ?: project.name}:$project.version"] + }''') + } else { + assert gradle.contains(''' + dockerBuild { + images = listOf("${System.getenv("DOCKER_IMAGE") ?: project.name}:${project.version}") + }''') + + assert gradle.contains(''' + dockerBuildNative { + images = listOf("${System.getenv("DOCKER_IMAGE") ?: project.name}:${project.version}") + }''') + } where: - name << [AzureContainerInstanceJavaWorkflow.NAME, AzureContainerInstanceGraalWorkflow.NAME] + [buildTool, feature] << [BuildTool.valuesGradle(), [AzureContainerInstanceJavaWorkflow.NAME, AzureContainerInstanceGraalWorkflow.NAME]].combinations() + buildFileName = buildTool.buildFileName } - @Unroll void 'test github gradle graal #graalVersion workflow for #jdkVersion'(JdkVersion jdkVersion, JdkVersion graalVersion){ given: diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/github/workflows/docker/DockerRegistryWorkflowSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/github/workflows/docker/DockerRegistryWorkflowSpec.groovy index 18cfb5e6a69..3648a02b72c 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/github/workflows/docker/DockerRegistryWorkflowSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/github/workflows/docker/DockerRegistryWorkflowSpec.groovy @@ -3,15 +3,19 @@ package io.micronaut.starter.feature.github.workflows.docker import io.micronaut.starter.BeanContextSpec import io.micronaut.starter.application.ApplicationType import io.micronaut.starter.fixture.CommandOutputFixture -import io.micronaut.starter.options.* -import spock.lang.Unroll +import io.micronaut.starter.options.BuildTool +import io.micronaut.starter.options.JdkVersion +import io.micronaut.starter.options.Language +import io.micronaut.starter.options.MicronautJdkVersionConfiguration +import io.micronaut.starter.options.Options +import io.micronaut.starter.options.TestFramework class DockerRegistryWorkflowSpec extends BeanContextSpec implements CommandOutputFixture{ void 'test github workflow readme'(){ when: - def output = generate([DockerRegistryWorkflow.NAME]) - def readme = output['README.md'] + Map output = generate([DockerRegistryWorkflow.NAME]) + String readme = output['README.md'] then: readme @@ -27,7 +31,6 @@ Add the following GitHub secrets: """) } - @Unroll void 'test github workflow is created for #buildTool'(BuildTool buildTool, String workflowName) { when: def output = generate(ApplicationType.DEFAULT, @@ -57,20 +60,29 @@ Add the following GitHub secrets: maven.contains("DOCKER_IMAGE=`echo \"\${DOCKER_REGISTRY_URL}/\${DOCKER_REPOSITORY_PATH}/foo") } - void 'test docker image is configured in build.gradle'() { + void 'test docker image is configured in #buildFileName'(BuildTool buildTool) { when: - def output = generate([DockerRegistryWorkflow.NAME]) - def gradle = output['build.gradle.kts'] + def output = generate(ApplicationType.DEFAULT, new Options(Language.JAVA, buildTool), [DockerRegistryWorkflow.NAME]) + def gradle = output[buildTool.buildFileName] then: - gradle - gradle.contains(""" + if (buildTool == BuildTool.GRADLE) { + assert gradle.contains(''' dockerBuild { - images = [\"\${System.env.DOCKER_IMAGE ?: project.name}:\$project.version"] - }""") + images = ["${System.env.DOCKER_IMAGE ?: project.name}:$project.version"] + }''') + } else { + assert gradle.contains(''' + dockerBuild { + images = listOf("${System.getenv("DOCKER_IMAGE") ?: project.name}:${project.version}") + }''') + } + + where: + buildTool << BuildTool.valuesGradle() + buildFileName = buildTool.buildFileName } - @Unroll void 'test github gradle workflow java version for #version'(JdkVersion version){ when: def output = generate(ApplicationType.DEFAULT, diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/github/workflows/docker/GraalVMDockerRegistryWorkflowSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/github/workflows/docker/GraalVMDockerRegistryWorkflowSpec.groovy index d9e5a99e8a4..35f53975500 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/github/workflows/docker/GraalVMDockerRegistryWorkflowSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/github/workflows/docker/GraalVMDockerRegistryWorkflowSpec.groovy @@ -11,8 +11,8 @@ class GraalVMDockerRegistryWorkflowSpec extends BeanContextSpec implements Comma void 'test github workflow readme'() { when: - def output = generate([GraalVMDockerRegistryWorkflow.NAME]) - def readme = output['README.md'] + Map output = generate([GraalVMDockerRegistryWorkflow.NAME]) + String readme = output['README.md'] then: readme @@ -43,17 +43,27 @@ Add the following GitHub secrets: buildTool << BuildTool.values() } - void 'test docker image configured in build.gradle'() { + void 'test docker image is configured in #buildFileName'(BuildTool buildTool) { when: - def output = generate([GraalVMDockerRegistryWorkflow.NAME]) - def gradle = output['build.gradle.kts'] + def output = generate(ApplicationType.DEFAULT, new Options(Language.JAVA, buildTool), [GraalVMDockerRegistryWorkflow.NAME]) + def gradle = output[buildTool.buildFileName] then: - gradle - gradle.contains(""" + if (buildTool == BuildTool.GRADLE) { + assert gradle.contains(''' dockerBuildNative { - images = [\"\${System.env.DOCKER_IMAGE ?: project.name}:\$project.version"] - }""") + images = ["${System.env.DOCKER_IMAGE ?: project.name}:$project.version"] + }''') + } else { + assert gradle.contains(''' + dockerBuildNative { + images = listOf("${System.getenv("DOCKER_IMAGE") ?: project.name}:${project.version}") + }''') + } + + where: + buildTool << BuildTool.valuesGradle() + buildFileName = buildTool.buildFileName } void 'test push to docker workflow for maven'() { diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/github/workflows/gcloud/GoogleCloudRunWorkflowSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/github/workflows/gcloud/GoogleCloudRunWorkflowSpec.groovy index 6b6c7281c2c..d10f04d6d12 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/github/workflows/gcloud/GoogleCloudRunWorkflowSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/github/workflows/gcloud/GoogleCloudRunWorkflowSpec.groovy @@ -3,16 +3,20 @@ package io.micronaut.starter.feature.github.workflows.gcloud import io.micronaut.starter.BeanContextSpec import io.micronaut.starter.application.ApplicationType import io.micronaut.starter.fixture.CommandOutputFixture -import io.micronaut.starter.options.* +import io.micronaut.starter.options.BuildTool +import io.micronaut.starter.options.JdkVersion +import io.micronaut.starter.options.Language +import io.micronaut.starter.options.MicronautJdkVersionConfiguration +import io.micronaut.starter.options.Options +import io.micronaut.starter.options.TestFramework import io.micronaut.starter.util.VersionInfo -import spock.lang.Unroll class GoogleCloudRunWorkflowSpec extends BeanContextSpec implements CommandOutputFixture { void 'test github workflow readme'() { when: - def output = generate([GoogleCloudRunGraalWorkflow.NAME]) - def readme = output['README.md'] + Map output = generate([GoogleCloudRunGraalWorkflow.NAME]) + String readme = output['README.md'] then: readme @@ -20,7 +24,6 @@ class GoogleCloudRunWorkflowSpec extends BeanContextSpec implements CommandOutpu readme.contains("GCLOUD_PROJECT_ID") } - @Unroll void 'test graalvm github workflow is created for #buildTool'(BuildTool buildTool) { when: def output = generate(ApplicationType.DEFAULT, @@ -36,7 +39,6 @@ class GoogleCloudRunWorkflowSpec extends BeanContextSpec implements CommandOutpu buildTool << BuildTool.values() } - @Unroll void 'test github workflow is created for #buildTool'(BuildTool buildTool) { when: def output = generate(ApplicationType.DEFAULT, @@ -53,25 +55,39 @@ class GoogleCloudRunWorkflowSpec extends BeanContextSpec implements CommandOutpu buildTool << BuildTool.values() } - void 'test docker image is configured in build.gradle'() { + void 'test docker image is configured in #buildFileName'(BuildTool buildTool) { when: - def output = generate([GoogleCloudRunGraalWorkflow.NAME]) - def gradle = output['build.gradle.kts'] + def output = generate(ApplicationType.DEFAULT, new Options(Language.JAVA, buildTool), [GoogleCloudRunGraalWorkflow.NAME]) + def gradle = output[buildTool.buildFileName] then: - gradle - gradle.contains(""" + if (buildTool == BuildTool.GRADLE) { + assert gradle.contains(''' dockerBuild { - images = [\"\${System.env.DOCKER_IMAGE ?: project.name}:\$project.version"] - }""") + images = ["${System.env.DOCKER_IMAGE ?: project.name}:$project.version"] + }''') - gradle.contains(""" + assert gradle.contains(''' dockerBuildNative { - images = [\"\${System.env.DOCKER_IMAGE ?: project.name}:\$project.version"] - }""") + images = ["${System.env.DOCKER_IMAGE ?: project.name}:$project.version"] + }''') + } else { + assert gradle.contains(''' + dockerBuild { + images = listOf("${System.getenv("DOCKER_IMAGE") ?: project.name}:${project.version}") + }''') + + assert gradle.contains(''' + dockerBuildNative { + images = listOf("${System.getenv("DOCKER_IMAGE") ?: project.name}:${project.version}") + }''') + } + + where: + buildTool << BuildTool.valuesGradle() + buildFileName = buildTool.buildFileName } - @Unroll void 'test github gradle graal #graalVersion workflow for #jdkVersion'(JdkVersion jdkVersion, JdkVersion graalVersion){ given: @@ -93,7 +109,6 @@ class GoogleCloudRunWorkflowSpec extends BeanContextSpec implements CommandOutpu JdkVersion.JDK_17 | JdkVersion.JDK_17 } - @Unroll void 'test github #buildTool with java #jdkVersion workflow'(BuildTool buildTool, JdkVersion jdkVersion) { when: def output = generate(ApplicationType.DEFAULT, diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/github/workflows/oci/OracleFunctionsWorkflowSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/github/workflows/oci/OracleFunctionsWorkflowSpec.groovy index 1dd03d56f26..2632587497f 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/github/workflows/oci/OracleFunctionsWorkflowSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/github/workflows/oci/OracleFunctionsWorkflowSpec.groovy @@ -3,16 +3,20 @@ package io.micronaut.starter.feature.github.workflows.oci import io.micronaut.starter.BeanContextSpec import io.micronaut.starter.application.ApplicationType import io.micronaut.starter.fixture.CommandOutputFixture -import io.micronaut.starter.options.* +import io.micronaut.starter.options.BuildTool +import io.micronaut.starter.options.JdkVersion +import io.micronaut.starter.options.Language +import io.micronaut.starter.options.MicronautJdkVersionConfiguration +import io.micronaut.starter.options.Options +import io.micronaut.starter.options.TestFramework import io.micronaut.starter.util.VersionInfo -import spock.lang.Unroll class OracleFunctionsWorkflowSpec extends BeanContextSpec implements CommandOutputFixture { void 'test github workflow readme'() { when: - def output = generate([OracleFunctionsJavaWorkflow.NAME]) - def readme = output['README.md'] + Map output = generate([OracleFunctionsJavaWorkflow.NAME]) + String readme = output['README.md'] then: readme @@ -21,15 +25,14 @@ class OracleFunctionsWorkflowSpec extends BeanContextSpec implements CommandOutp void 'test github graalvm workflow readme'() { when: - def output = generate([OracleFunctionsGraalWorkflow.NAME]) - def readme = output['README.md'] + Map output = generate([OracleFunctionsGraalWorkflow.NAME]) + String readme = output['README.md'] then: readme readme.contains("Oracle Functions GraalVM GitHub Workflow") } - @Unroll void 'test github workflow is created for #buildTool with #jdkVersion'(BuildTool buildTool, JdkVersion jdkVersion) { when: def output = generate(ApplicationType.DEFAULT, @@ -52,7 +55,6 @@ class OracleFunctionsWorkflowSpec extends BeanContextSpec implements CommandOutp ].combinations() } - @Unroll void 'test github graalvm workflow is created for #buildTool'(BuildTool buildTool) { when: def output = generate(ApplicationType.DEFAULT, @@ -69,7 +71,6 @@ class OracleFunctionsWorkflowSpec extends BeanContextSpec implements CommandOutp buildTool << BuildTool.values() } - @Unroll void 'test http function pom.xml configuration for #feature'(String feature) { when: def output = generate(ApplicationType.DEFAULT, @@ -118,28 +119,39 @@ class OracleFunctionsWorkflowSpec extends BeanContextSpec implements CommandOutp """) } - void 'test docker image is configured in build.gradle for #feature'(String feature) { + void 'test docker image is configured in #buildFileName for #feature'(BuildTool buildTool, String feature) { when: - def output = generate([feature]) - def gradle = output['build.gradle.kts'] + def output = generate(ApplicationType.DEFAULT, new Options(Language.JAVA, buildTool), [feature]) + def gradle = output[buildTool.buildFileName] then: - gradle - gradle.contains(""" + if (buildTool == BuildTool.GRADLE) { + assert gradle.contains(''' dockerBuild { - images = [\"\${System.env.DOCKER_IMAGE ?: project.name}:\$project.version\"] - }""") + images = ["${System.env.DOCKER_IMAGE ?: project.name}:$project.version"] + }''') - gradle.contains(""" + assert gradle.contains(''' dockerBuildNative { - images = [\"\${System.env.DOCKER_IMAGE ?: project.name}:\$project.version\"] - }""") + images = ["${System.env.DOCKER_IMAGE ?: project.name}:$project.version"] + }''') + } else { + assert gradle.contains(''' + dockerBuild { + images = listOf("${System.getenv("DOCKER_IMAGE") ?: project.name}:${project.version}") + }''') + + assert gradle.contains(''' + dockerBuildNative { + images = listOf("${System.getenv("DOCKER_IMAGE") ?: project.name}:${project.version}") + }''') + } where: - feature << [OracleFunctionsJavaWorkflow.NAME, OracleFunctionsGraalWorkflow.NAME] + [buildTool, feature] << [BuildTool.valuesGradle(), [OracleFunctionsJavaWorkflow.NAME, OracleFunctionsGraalWorkflow.NAME]].combinations() + buildFileName = buildTool.buildFileName } - @Unroll void 'test github gradle graal #graalVersion workflow for #jdkVersion'(JdkVersion jdkVersion, JdkVersion graalVersion) { given: diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/graphql/GraphQLSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/graphql/GraphQLSpec.groovy index cc4b172d7e9..e1acc2148a3 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/graphql/GraphQLSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/graphql/GraphQLSpec.groovy @@ -14,8 +14,8 @@ class GraphQLSpec extends ApplicationContextSpec implements CommandOutputFixtur void 'test readme.md with feature graphql contains links to micronaut docs'() { when: - def output = generate(['graphql']) - def readme = output["README.md"] + Map output = generate(['graphql']) + String readme = output["README.md"] then: readme diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/jaxrs/JaxRsSecuritySpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/jaxrs/JaxRsSecuritySpec.groovy index 1764bdbf9e5..d4b068af8e3 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/jaxrs/JaxRsSecuritySpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/jaxrs/JaxRsSecuritySpec.groovy @@ -2,17 +2,22 @@ package io.micronaut.starter.feature.jaxrs import io.micronaut.starter.ApplicationContextSpec import io.micronaut.starter.BuildBuilder +import io.micronaut.starter.build.BuildTestUtil +import io.micronaut.starter.build.BuildTestVerifier + +import io.micronaut.starter.build.dependencies.Scope import io.micronaut.starter.fixture.CommandOutputFixture import io.micronaut.starter.options.BuildTool import io.micronaut.starter.options.Language +import spock.lang.Issue import spock.lang.Unroll class JaxRsSecuritySpec extends ApplicationContextSpec implements CommandOutputFixture { void 'test readme.md with feature jax-rs-security contains links to micronaut docs'() { when: - def output = generate(['security', JaxRs.NAME]) - def readme = output["README.md"] + Map output = generate(['security', JaxRs.NAME]) + String readme = output["README.md"] then: readme @@ -26,11 +31,12 @@ class JaxRsSecuritySpec extends ApplicationContextSpec implements CommandOutputF .features(['security', JaxRs.NAME, 'kapt']) .language(language) .render() + BuildTestVerifier verifier = BuildTestUtil.verifier(BuildTool.GRADLE, language, template) then: - template.contains('implementation("io.micronaut.jaxrs:micronaut-jaxrs-server-security")') - template.contains('implementation("io.micronaut.jaxrs:micronaut-jaxrs-server")') - template.contains("$scope(\"io.micronaut.jaxrs:micronaut-jaxrs-processor\")") + verifier.hasDependency("io.micronaut.jaxrs", "micronaut-jaxrs-server-security") + verifier.hasDependency("io.micronaut.jaxrs", "micronaut-jaxrs-server") + verifier.hasDependency("io.micronaut.jaxrs", "micronaut-jaxrs-processor", scope) where: language | scope @@ -45,98 +51,34 @@ class JaxRsSecuritySpec extends ApplicationContextSpec implements CommandOutputF .features([JaxRs.NAME]) .language(Language.JAVA) .render() + BuildTestVerifier verifier = BuildTestUtil.verifier(BuildTool.GRADLE, template) then: - !template.contains('implementation("io.micronaut.jaxrs:micronaut-jaxrs-server-security")') + !verifier.hasDependency("io.micronaut.jaxrs", "micronaut-jaxrs-server-security") } - void 'test maven jax-rs-security feature'() { + void 'test maven jax-rs-security feature for language=#language'() { when: String template = new BuildBuilder(beanContext, BuildTool.MAVEN) + .language(language) .features(['security', JaxRs.NAME]) .render() + BuildTestVerifier verifier = BuildTestUtil.verifier(BuildTool.MAVEN, language, template) then: - template.contains(""" - - io.micronaut.jaxrs - micronaut-jaxrs-server-security - compile - -""") - - template.contains(""" - - io.micronaut.jaxrs - micronaut-jaxrs-server - compile - -""") - template.contains(""" - - io.micronaut.jaxrs - micronaut-jaxrs-processor - \${micronaut.jaxrs.version} - - - io.micronaut - micronaut-inject - - - -""") - - when: - template = new BuildBuilder(beanContext, BuildTool.MAVEN) - .language(Language.KOTLIN) - .features(['security', JaxRs.NAME]) - .render() - - then: - template.contains(""" - - io.micronaut.jaxrs - micronaut-jaxrs-server-security - compile - -""") - - template.contains(""" - - io.micronaut.jaxrs - micronaut-jaxrs-server - compile - -""") - template.count('''\ - - io.micronaut.jaxrs - micronaut-jaxrs-processor - ${micronaut.jaxrs.version} - -''') == 2 - - when: - template = new BuildBuilder(beanContext, BuildTool.MAVEN) - .language(Language.GROOVY) - .features(['security', JaxRs.NAME]) - .render() - - then: - template.contains(""" - - io.micronaut.jaxrs - micronaut-jaxrs-server-security - compile - -""") + verifier.hasDependency("io.micronaut.jaxrs", "micronaut-jaxrs-server-security") + verifier.hasDependency("io.micronaut.jaxrs", "micronaut-jaxrs-server") + verifier.hasAnnotationProcessor("io.micronaut.jaxrs", "micronaut-jaxrs-processor") + + and: + if (language == Language.KOTLIN) { + assert verifier.hasTestAnnotationProcessor("io.micronaut.jaxrs", "micronaut-jaxrs-processor") + } else { + assert verifier.hasExclusion("io.micronaut.jaxrs", "micronaut-jaxrs-processor", + "io.micronaut", "micronaut-inject", Scope.ANNOTATION_PROCESSOR) + } - template.contains(""" - - io.micronaut.jaxrs - micronaut-jaxrs-server - compile - -""") + where: + language << Language.values() } } diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/jaxrs/JaxRsSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/jaxrs/JaxRsSpec.groovy index 304ccbe66be..d10d841ff91 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/jaxrs/JaxRsSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/jaxrs/JaxRsSpec.groovy @@ -2,6 +2,9 @@ package io.micronaut.starter.feature.jaxrs import io.micronaut.starter.ApplicationContextSpec import io.micronaut.starter.BuildBuilder +import io.micronaut.starter.build.BuildTestUtil +import io.micronaut.starter.build.BuildTestVerifier +import io.micronaut.starter.build.dependencies.Scope import io.micronaut.starter.fixture.CommandOutputFixture import io.micronaut.starter.options.BuildTool import io.micronaut.starter.options.Language @@ -11,8 +14,8 @@ class JaxRsSpec extends ApplicationContextSpec implements CommandOutputFixture void 'test readme.md with feature jax-rs contains links to micronaut docs'() { when: - def output = generate([JaxRs.NAME]) - def readme = output["README.md"] + Map output = generate([JaxRs.NAME]) + String readme = output["README.md"] then: readme @@ -26,10 +29,11 @@ class JaxRsSpec extends ApplicationContextSpec implements CommandOutputFixture .features([JaxRs.NAME, 'kapt']) .language(language) .render() + BuildTestVerifier verifier = BuildTestUtil.verifier(BuildTool.GRADLE, language, template) then: - template.contains('implementation("io.micronaut.jaxrs:micronaut-jaxrs-server")') - template.contains("$scope(\"io.micronaut.jaxrs:micronaut-jaxrs-processor\")") + verifier.hasDependency("io.micronaut.jaxrs", "micronaut-jaxrs-server") + verifier.hasDependency("io.micronaut.jaxrs", "micronaut-jaxrs-processor", scope) where: language | scope @@ -38,70 +42,29 @@ class JaxRsSpec extends ApplicationContextSpec implements CommandOutputFixture Language.GROOVY | "compileOnly" } - void 'test maven jax-rs feature'() { + void 'test maven jax-rs feature for language=#language'(Language language) { + given: + BuildTool buildTool = BuildTool.MAVEN when: - String template = new BuildBuilder(beanContext, BuildTool.MAVEN) - .features([JaxRs.NAME]) - .render() - - then: - template.contains(""" - - io.micronaut.jaxrs - micronaut-jaxrs-server - compile - -""") - template.contains(""" - - io.micronaut.jaxrs - micronaut-jaxrs-processor - \${micronaut.jaxrs.version} - - - io.micronaut - micronaut-inject - - - -""") - - when: - template = new BuildBuilder(beanContext, BuildTool.MAVEN) - .language(Language.KOTLIN) - .features([JaxRs.NAME]) - .render() - - then: - template.contains(""" - - io.micronaut.jaxrs - micronaut-jaxrs-server - compile - -""") - template.count('''\ - - io.micronaut.jaxrs - micronaut-jaxrs-processor - ${micronaut.jaxrs.version} - -''') == 2 - - when: - template = new BuildBuilder(beanContext, BuildTool.MAVEN) - .language(Language.GROOVY) + String template = new BuildBuilder(beanContext, buildTool) + .language(language) .features([JaxRs.NAME]) .render() + BuildTestVerifier verifier = BuildTestUtil.verifier(buildTool, language, template) then: - template.contains(""" - - io.micronaut.jaxrs - micronaut-jaxrs-server - compile - -""") + verifier.hasDependency("io.micronaut.jaxrs", "micronaut-jaxrs-server") + verifier.hasAnnotationProcessor("io.micronaut.jaxrs", "micronaut-jaxrs-processor") + and: + if (language == Language.KOTLIN) { + assert verifier.hasTestAnnotationProcessor("io.micronaut.jaxrs", "micronaut-jaxrs-processor") + } else { + assert verifier.hasExclusion("io.micronaut.jaxrs", "micronaut-jaxrs-processor", + "io.micronaut", "micronaut-inject", Scope.ANNOTATION_PROCESSOR) + } + where: + language << Language.values() } + } diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/jdbi/JdbiFeatureSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/jdbi/JdbiFeatureSpec.groovy index d533353be32..e138365fd7d 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/jdbi/JdbiFeatureSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/jdbi/JdbiFeatureSpec.groovy @@ -14,8 +14,8 @@ class JdbiFeatureSpec extends ApplicationContextSpec implements CommandOutputFi void 'test readme.md with feature sql-jdbi contains links to micronaut docs'() { when: - def output = generate(['sql-jdbi']) - def readme = output["README.md"] + Map output = generate(['sql-jdbi']) + String readme = output["README.md"] then: readme diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/jmx/JmxSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/jmx/JmxSpec.groovy index 42d28104224..6cdd6520329 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/jmx/JmxSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/jmx/JmxSpec.groovy @@ -12,8 +12,8 @@ class JmxSpec extends ApplicationContextSpec implements CommandOutputFixture { @Unroll void 'test readme.md contains links to jmx and micronaut docs'() { when: - def output = generate(['jmx']) - def readme = output["README.md"] + Map output = generate(['jmx']) + String readme = output["README.md"] then: readme diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/json/JsonSmartSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/json/JsonSmartSpec.groovy new file mode 100644 index 00000000000..56069fba972 --- /dev/null +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/json/JsonSmartSpec.groovy @@ -0,0 +1,57 @@ +package io.micronaut.starter.feature.json + +import io.micronaut.starter.ApplicationContextSpec +import io.micronaut.starter.BuildBuilder +import io.micronaut.starter.application.ApplicationType +import io.micronaut.starter.build.BuildTestUtil +import io.micronaut.starter.build.BuildTestVerifier +import io.micronaut.starter.build.dependencies.Scope +import io.micronaut.starter.feature.Category +import io.micronaut.starter.fixture.CommandOutputFixture +import io.micronaut.starter.options.BuildTool +import io.micronaut.starter.options.Language +import spock.lang.Shared + +class JsonSmartSpec extends ApplicationContextSpec implements CommandOutputFixture { + + @Shared + JsonSmart jsonSmart = beanContext.getBean(JsonSmart) + + void 'test readme.md with feature json-smart contains links to third party docs'() { + when: + Map output = generate([JsonSmart.NAME]) + String readme = output["README.md"] + + then: + readme + readme.contains('https://netplex.github.io/json-smart/') + } + + void "feature json-smart supports applicationType=#applicationType"(ApplicationType applicationType) { + expect: + jsonSmart.supports(applicationType) + + where: + applicationType << ApplicationType.values() + } + + void "feature json-smart feature is TEST category"() { + expect: + jsonSmart.category == Category.TEST + } + + void "dependencies are present for #buildTool and #language"(BuildTool buildTool, Language language) { + when: + String template = new BuildBuilder(beanContext, buildTool) + .features([JsonSmart.NAME]) + .language(language) + .render() + BuildTestVerifier verifier = BuildTestUtil.verifier(buildTool, language, template) + + then: + verifier.hasDependency("net.minidev", "json-smart", Scope.TEST) + + where: + [buildTool, language] << [BuildTool.values(), Language.values()].combinations() + } +} diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/k8s/KubernetesClientSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/k8s/KubernetesClientSpec.groovy index 0b552b65570..3691ddd41f6 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/k8s/KubernetesClientSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/k8s/KubernetesClientSpec.groovy @@ -15,8 +15,8 @@ class KubernetesClientSpec extends ApplicationContextSpec implements CommandOut void 'test readme.md with feature kubernetes-client contains links to docs'() { when: - def output = generate(['kubernetes-client']) - def readme = output["README.md"] + Map output = generate(['kubernetes-client']) + String readme = output["README.md"] then: readme diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/k8s/KubernetesInformerSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/k8s/KubernetesInformerSpec.groovy index 47b1f16787f..2749eca6d89 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/k8s/KubernetesInformerSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/k8s/KubernetesInformerSpec.groovy @@ -15,8 +15,8 @@ class KubernetesInformerSpec extends ApplicationContextSpec implements CommandO void 'test readme.md with feature kubernetes-informer contains links to docs'() { when: - def output = generate(['kubernetes-informer']) - def readme = output["README.md"] + Map output = generate(['kubernetes-informer']) + String readme = output["README.md"] then: readme diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/k8s/KubernetesReactorClientSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/k8s/KubernetesReactorClientSpec.groovy index b96ce06b42f..e9ce7fb13c6 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/k8s/KubernetesReactorClientSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/k8s/KubernetesReactorClientSpec.groovy @@ -15,8 +15,8 @@ class KubernetesReactorClientSpec extends ApplicationContextSpec implements Com void 'test readme.md with feature kubernetes-reactor-client contains links to docs'() { when: - def output = generate(['kubernetes-reactor-client']) - def readme = output["README.md"] + Map output = generate(['kubernetes-reactor-client']) + String readme = output["README.md"] then: readme diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/k8s/KubernetesRxJava2ClientSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/k8s/KubernetesRxJava2ClientSpec.groovy index f5bc2610622..00f0b378fd5 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/k8s/KubernetesRxJava2ClientSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/k8s/KubernetesRxJava2ClientSpec.groovy @@ -15,8 +15,8 @@ class KubernetesRxJava2ClientSpec extends ApplicationContextSpec implements Com void 'test readme.md with feature kubernetes-rxjava2-client contains links to docs'() { when: - def output = generate(['kubernetes-rxjava2-client']) - def readme = output["README.md"] + Map output = generate(['kubernetes-rxjava2-client']) + String readme = output["README.md"] then: readme diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/knative/KnativeSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/knative/KnativeSpec.groovy index 86ca1a431fe..d82d5fcbd43 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/knative/KnativeSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/knative/KnativeSpec.groovy @@ -8,8 +8,8 @@ class KnativeSpec extends BeanContextSpec implements CommandOutputFixture { void 'test readme.md with feature knative contains links to micronaut and knative docs'() { when: - def output = generate(['knative']) - def readme = output["README.md"] + Map output = generate(['knative']) + String readme = output["README.md"] then: readme diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/kotlin/KtorSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/kotlin/KtorSpec.groovy index 7a7874f0eb7..abfbb8b3b6f 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/kotlin/KtorSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/kotlin/KtorSpec.groovy @@ -26,8 +26,8 @@ class KtorSpec extends ApplicationContextSpec implements CommandOutputFixture { void 'test readme.md with feature ktor contains links to micronaut docs'() { when: Options options = new Options(Language.KOTLIN, TestFramework.JUNIT, BuildTool.GRADLE) - def output = generate(ApplicationType.DEFAULT, options, [Ktor.NAME]) - def readme = output["README.md"] + Map output = generate(ApplicationType.DEFAULT, options, [Ktor.NAME]) + String readme = output["README.md"] then: readme @@ -125,7 +125,7 @@ class KtorSpec extends ApplicationContextSpec implements CommandOutputFixture { .render() then: - template.contains("mainClass.set(\"example.micronaut.Application\")") + template.contains('mainClass = "example.micronaut.Application"') where: language << supportedLanguages() diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/lang/GroovyApplicationSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/lang/GroovyApplicationSpec.groovy index 67ed2c73d5e..9885de8e5b4 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/lang/GroovyApplicationSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/lang/GroovyApplicationSpec.groovy @@ -25,7 +25,7 @@ class GroovyApplicationSpec extends BeanContextSpec implements CommandOutputFixt def buildGradle = output['build.gradle'] then: - buildGradle.contains('mainClass.set("example.micronaut.Application")') + buildGradle.contains('mainClass = "example.micronaut.Application"') } @Unroll diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/lang/JavaApplicationSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/lang/JavaApplicationSpec.groovy index 3005cc3b73b..cd40b51f4be 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/lang/JavaApplicationSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/lang/JavaApplicationSpec.groovy @@ -31,7 +31,7 @@ class JavaApplicationSpec extends BeanContextSpec implements CommandOutputFixtur def buildGradle = output['build.gradle'] then: - buildGradle.contains('mainClass.set("example.micronaut.Application")') + buildGradle.contains('mainClass = "example.micronaut.Application"') } void "test java application"() { diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/lang/kotlin/KotlinApplicationSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/lang/kotlin/KotlinApplicationSpec.groovy index 43263aa1930..f2a709ddaa3 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/lang/kotlin/KotlinApplicationSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/lang/kotlin/KotlinApplicationSpec.groovy @@ -36,7 +36,7 @@ class KotlinApplicationSpec extends ApplicationContextSpec implements CommandOut buildGradle.contains('id("org.jetbrains.kotlin.jvm")') !buildGradle.contains('kapt') buildGradle.contains('id("com.google.devtools.ksp")') - buildGradle.contains('mainClass.set("example.micronaut.ApplicationKt")') + buildGradle.contains('mainClass = "example.micronaut.ApplicationKt"') buildGradle.contains('implementation("io.micronaut.kotlin:micronaut-kotlin-runtime")') buildGradle.contains("ksp(\"io.micronaut.security:micronaut-security-annotations\")") } @@ -63,7 +63,7 @@ class KotlinApplicationSpec extends ApplicationContextSpec implements CommandOut assert buildGradle assert buildGradle.contains('id("org.jetbrains.kotlin.jvm")') assert buildGradle.contains('id("com.google.devtools.ksp")') - assert buildGradle.contains('mainClass.set("example.micronaut.ApplicationKt")') + assert buildGradle.contains('mainClass = "example.micronaut.ApplicationKt"') } BuildTestVerifier verifier = BuildTestUtil.verifier(buildTool, template) diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/logging/Slf4jJulBridgeSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/logging/Slf4jJulBridgeSpec.groovy index 5f1aef16cf7..ed2dc8ad9b5 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/logging/Slf4jJulBridgeSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/logging/Slf4jJulBridgeSpec.groovy @@ -44,7 +44,7 @@ class Slf4jJulBridgeSpec extends ApplicationContextSpec implements CommandOutp then: verifier.hasDependency("ch.qos.logback", "logback-classic", Scope.RUNTIME) - verifier.hasDependency("org.slf4j", "jul-to-slf4j", Scope.RUNTIME, "2.0.9", false) + verifier.hasDependency("org.slf4j", "jul-to-slf4j", Scope.RUNTIME) where: buildTool << BuildTool.values() diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/messaging/jms/JmsSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/messaging/jms/JmsSpec.groovy index 1f6b4555ad2..d4696c7fa83 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/messaging/jms/JmsSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/messaging/jms/JmsSpec.groovy @@ -12,8 +12,8 @@ class JmsSpec extends ApplicationContextSpec implements CommandOutputFixture { void 'test README.md with feature jms contains links to micronaut docs'() { when: - def output = generate([feature]) - def readme = output['README.md'] + Map output = generate([feature]) + String readme = output['README.md'] then: readme diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/messaging/jms/OracleAdvancedQueuingSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/messaging/jms/OracleAdvancedQueuingSpec.groovy index 797b4cc1192..d7cc147a4f2 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/messaging/jms/OracleAdvancedQueuingSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/messaging/jms/OracleAdvancedQueuingSpec.groovy @@ -11,8 +11,8 @@ class OracleAdvancedQueuingSpec extends ApplicationContextSpec implements Comma void 'test readme.md with feature jms-oracle-aq contains links to micronaut jms docs'() { when: - def output = generate(['jms-oracle-aq']) - def readme = output["README.md"] + Map output = generate(['jms-oracle-aq']) + String readme = output["README.md"] then: readme @@ -49,7 +49,7 @@ class OracleAdvancedQueuingSpec extends ApplicationContextSpec implements Comma template.contains('implementation("io.micronaut.jms:micronaut-jms-core")') template.contains('implementation("javax.transaction:jta:1.1")') template.contains('implementation("com.oracle.database.messaging:aqapi:19.3.0.0")') - template.contains('runtimeOnly("com.oracle.database.jdbc:ojdbc8")') + template.contains('runtimeOnly("com.oracle.database.jdbc:ojdbc11")') } void 'test jms-oracle-aq with Maven'() { @@ -87,7 +87,7 @@ class OracleAdvancedQueuingSpec extends ApplicationContextSpec implements Comma template.contains(""" com.oracle.database.jdbc - ojdbc8 + ojdbc11 runtime """) diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/messaging/jms/SQSSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/messaging/jms/SQSSpec.groovy new file mode 100644 index 00000000000..11ef20c6ef8 --- /dev/null +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/messaging/jms/SQSSpec.groovy @@ -0,0 +1,44 @@ +package io.micronaut.starter.feature.messaging.jms + +import io.micronaut.starter.ApplicationContextSpec +import io.micronaut.starter.BuildBuilder +import io.micronaut.starter.build.BuildTestUtil +import io.micronaut.starter.build.BuildTestVerifier +import io.micronaut.starter.options.BuildTool +import io.micronaut.starter.options.Language + +class SQSSpec extends ApplicationContextSpec { + + void 'test localstack-sqs test-resources module is added'(Language language) { + when: + String template = new BuildBuilder(beanContext, BuildTool.GRADLE) + .features(['jms-sqs', 'test-resources']) + .language(language) + .render() + + then: + template.contains(""" + testResources { + additionalModules.add("localstack-sqs") + }""") + + where: + language << Language.values().toList() + } + + void 'test localstack-sqs test-resources module is added for Maven'() { + given: + BuildTool buildTool = BuildTool.MAVEN + + when: + String template = new BuildBuilder(beanContext, buildTool) + .features(['jms-sqs', 'test-resources']) + .language(Language.JAVA) + .render() + BuildTestVerifier verifier = BuildTestUtil.verifier(buildTool, template) + + then: + verifier.hasTestResourceDependency("micronaut-test-resources-localstack-sqs") + } +} + diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/messaging/kafka/KafkaSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/messaging/kafka/KafkaSpec.groovy index 1676b14a04a..e5acdf8be74 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/messaging/kafka/KafkaSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/messaging/kafka/KafkaSpec.groovy @@ -13,8 +13,8 @@ class KafkaSpec extends ApplicationContextSpec implements CommandOutputFixture { void 'test readme.md with feature kafka contains links to micronaut docs'() { when: - def output = generate(['kafka']) - def readme = output["README.md"] + Map output = generate(['kafka']) + String readme = output["README.md"] then: readme @@ -76,9 +76,13 @@ class KafkaSpec extends ApplicationContextSpec implements CommandOutputFixture { compile """) - template.contains('''micronaut-maven-plugin - - true + template.contains('''\ + + + io.micronaut.maven + micronaut-maven-plugin + + true ''') } diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/messaging/kafka/KafkaStreamsSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/messaging/kafka/KafkaStreamsSpec.groovy index 822b074fe4a..d521907f906 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/messaging/kafka/KafkaStreamsSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/messaging/kafka/KafkaStreamsSpec.groovy @@ -14,8 +14,8 @@ class KafkaStreamsSpec extends ApplicationContextSpec implements CommandOutputFi void 'test readme.md with feature kafka-streams contains links to micronaut docs'() { when: - def output = generate(['kafka-streams']) - def readme = output["README.md"] + Map output = generate(['kafka-streams']) + String readme = output["README.md"] then: readme @@ -80,9 +80,13 @@ class KafkaStreamsSpec extends ApplicationContextSpec implements CommandOutputFi compile """) - template.contains('''micronaut-maven-plugin - - true + template.contains('''\ + + + io.micronaut.maven + micronaut-maven-plugin + + true ''') } diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/messaging/mqtt/MqttSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/messaging/mqtt/MqttSpec.groovy index 7fd15c0fcb6..1f007c95d82 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/messaging/mqtt/MqttSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/messaging/mqtt/MqttSpec.groovy @@ -44,9 +44,13 @@ class MqttSpec extends ApplicationContextSpec implements CommandOutputFixture { assert verifier.hasBuildPlugin("io.micronaut.test-resources") } else if (buildTool == BuildTool.MAVEN) { assert template.contains("<$TestResources.MICRONAUT_TEST_RESOURCES_ENABLED>true") - assert template.contains('''micronaut-maven-plugin - - true + template.contains('''\ + + + io.micronaut.maven + micronaut-maven-plugin + + true ''') } } diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/messaging/rabbitmq/RabbitMQSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/messaging/rabbitmq/RabbitMQSpec.groovy index 30c637b02d9..0cff71dd0c9 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/messaging/rabbitmq/RabbitMQSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/messaging/rabbitmq/RabbitMQSpec.groovy @@ -10,8 +10,8 @@ class RabbitMQSpec extends ApplicationContextSpec implements CommandOutputFixtur void 'test readme.md with feature rabbitmq contains links to micronaut docs'() { when: - def output = generate(['rabbitmq']) - def readme = output["README.md"] + Map output = generate(['rabbitmq']) + String readme = output["README.md"] then: readme @@ -43,9 +43,13 @@ class RabbitMQSpec extends ApplicationContextSpec implements CommandOutputFixtur compile """) - template.contains('''micronaut-maven-plugin - - true + template.contains('''\ + + + io.micronaut.maven + micronaut-maven-plugin + + true ''') } diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/microstream/MicroStreamSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/microstream/MicroStreamSpec.groovy index 06590efb89e..d79f85f76f3 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/microstream/MicroStreamSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/microstream/MicroStreamSpec.groovy @@ -15,8 +15,8 @@ class MicroStreamSpec extends BeanContextSpec implements CommandOutputFixture { void 'test readme.md with feature microstream contains links to micronaut docs'() { when: - def output = generate(['microstream']) - def readme = output["README.md"] + Map output = generate(['microstream']) + String readme = output["README.md"] then: readme.contains("[Micronaut MicroStream documentation](https://micronaut-projects.github.io/micronaut-microstream/latest/guide)") @@ -25,8 +25,8 @@ class MicroStreamSpec extends BeanContextSpec implements CommandOutputFixture { void 'test readme.md with feature microstream-rest contains links to micronaut docs'() { when: - def output = generate(['microstream-rest']) - def readme = output["README.md"] + Map output = generate(['microstream-rest']) + String readme = output["README.md"] then: readme.contains("[Micronaut MicroStream documentation](https://micronaut-projects.github.io/micronaut-microstream/latest/guide)") @@ -37,8 +37,8 @@ class MicroStreamSpec extends BeanContextSpec implements CommandOutputFixture { void 'test readme.md with feature microstream-cache contains links to micronaut docs'() { when: - def output = generate(['microstream-cache']) - def readme = output["README.md"] + Map output = generate(['microstream-cache']) + String readme = output["README.md"] then: !readme.contains("[Micronaut MicroStream documentation](https://micronaut-projects.github.io/micronaut-microstream/latest/guide)") diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/migration/FlywaySpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/migration/FlywaySpec.groovy index 5a59c2fa911..d24fb951781 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/migration/FlywaySpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/migration/FlywaySpec.groovy @@ -8,14 +8,13 @@ import io.micronaut.starter.build.dependencies.Scope import io.micronaut.starter.feature.config.Yaml import io.micronaut.starter.fixture.CommandOutputFixture import io.micronaut.starter.options.BuildTool -import spock.lang.PendingFeature class FlywaySpec extends ApplicationContextSpec implements CommandOutputFixture { void 'test readme.md with feature flyway contains links to micronaut docs'() { when: - def output = generate(['flyway']) - def readme = output["README.md"] + Map output = generate(['flyway']) + String readme = output["README.md"] then: readme @@ -117,7 +116,6 @@ flyway: buildTool << BuildTool.values() } - @PendingFeature void "test the flyway-database-postgresql dependency is added to the gradle build when postgres is selected"(BuildTool buildTool) { when: BuildTestVerifier verifier = verifier(buildTool, ['flyway', 'postgres']) diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/migration/LiquibaseSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/migration/LiquibaseSpec.groovy index 843faf3965c..a8f7bd16fd5 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/migration/LiquibaseSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/migration/LiquibaseSpec.groovy @@ -10,8 +10,8 @@ class LiquibaseSpec extends ApplicationContextSpec implements CommandOutputFixt void 'test readme.md with feature liquibase contains links to micronaut docs'() { when: - def output = generate(['liquibase']) - def readme = output["README.md"] + Map output = generate(['liquibase']) + String readme = output["README.md"] then: readme diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/multitenancy/MultitenancyGormSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/multitenancy/MultitenancyGormSpec.groovy deleted file mode 100644 index 1957d71a292..00000000000 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/multitenancy/MultitenancyGormSpec.groovy +++ /dev/null @@ -1,92 +0,0 @@ -package io.micronaut.starter.feature.multitenancy - -import io.micronaut.starter.ApplicationContextSpec -import io.micronaut.starter.BuildBuilder -import io.micronaut.starter.application.ApplicationType -import io.micronaut.starter.feature.Category -import io.micronaut.starter.fixture.CommandOutputFixture -import io.micronaut.starter.options.BuildTool -import io.micronaut.starter.options.Language -import io.micronaut.starter.options.Options -import io.micronaut.starter.options.TestFramework -import spock.lang.Shared -import spock.lang.Subject -import spock.lang.Unroll - -class MultitenancyGormSpec extends ApplicationContextSpec implements CommandOutputFixture { - - @Subject - @Shared - MultitenancyGorm multitenancy = beanContext.getBean(MultitenancyGorm) - - void 'test readme.md with feature multi-tenancy-gorm contains links to micronaut docs'() { - when: - Options options = new Options(Language.GROOVY, TestFramework.SPOCK) - def output = generate(ApplicationType.DEFAULT, options, ['multi-tenancy-gorm']) - def readme = output["README.md"] - - then: - readme - readme.contains("https://docs.micronaut.io/latest/guide/index.html#multitenancyGorm") - readme.contains("https://gorm.grails.org/latest/hibernate/manual/index.html#multiTenancy") - } - - void "multi-tenancy-gorm belongs to Database category"() { - expect: - Category.DATABASE == multitenancy.category - } - - void "multi-tenancy-gorm title and description are different"() { - expect: - multitenancy.getTitle() - multitenancy.getDescription() - multitenancy.getTitle() != multitenancy.getDescription() - } - - @Unroll("feature multi-tenancy-gorm works for application type: #applicationType") - void "feature multi-tenancy-gorm works for every type of application type"(ApplicationType applicationType) { - expect: - multitenancy.supports(applicationType) - - where: - applicationType << ApplicationType.values() - } - - void 'dependency is included with maven and feature multi-tenancy-gorm for groovy'() { - when: - String template = new BuildBuilder(beanContext, BuildTool.MAVEN) - .features(['multi-tenancy-gorm']) - .language(Language.GROOVY) - .render() - - then: - template.contains(""" - - io.micronaut.groovy - micronaut-multitenancy-gorm - compile - -""") - and: - template.contains(""" - - io.micronaut.multitenancy - micronaut-multitenancy - compile - -""") - } - - void 'dependency is included with gradle and feature multi-tenancy-gorm for groovy'() { - when: - String template = new BuildBuilder(beanContext, BuildTool.GRADLE) - .features(['multi-tenancy-gorm']) - .language(Language.GROOVY) - .render() - - then: - template.contains('implementation("io.micronaut.groovy:micronaut-multitenancy-gorm")') - and: - template.contains('implementation("io.micronaut.multitenancy:micronaut-multitenancy")') - } -} diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/multitenancy/MultitenancySpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/multitenancy/MultitenancySpec.groovy index 31a2af506b6..3cf445f88cd 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/multitenancy/MultitenancySpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/multitenancy/MultitenancySpec.groovy @@ -19,8 +19,8 @@ class MultitenancySpec extends ApplicationContextSpec implements CommandOutputF void 'test readme.md with feature multi-tenancy contains links to micronaut docs'() { when: - def output = generate(['multi-tenancy']) - def readme = output["README.md"] + Map output = generate(['multi-tenancy']) + String readme = output["README.md"] then: readme diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/netflix/HystrixSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/netflix/HystrixSpec.groovy index 3215e293fd1..1d4919333be 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/netflix/HystrixSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/netflix/HystrixSpec.groovy @@ -12,8 +12,8 @@ class HystrixSpec extends ApplicationContextSpec implements CommandOutputFixture void 'test readme.md with feature netflix-hystrix contains links to micronaut docs'() { when: - def output = generate(['netflix-hystrix']) - def readme = output["README.md"] + Map output = generate(['netflix-hystrix']) + String readme = output["README.md"] then: readme diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/netflix/RibbonSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/netflix/RibbonSpec.groovy index aed045abb34..e828897422f 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/netflix/RibbonSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/netflix/RibbonSpec.groovy @@ -12,8 +12,8 @@ class RibbonSpec extends ApplicationContextSpec implements CommandOutputFixture void 'test readme.md with feature netflix-ribbon contains links to micronaut docs'() { when: - def output = generate(['netflix-ribbon']) - def readme = output["README.md"] + Map output = generate(['netflix-ribbon']) + String readme = output["README.md"] then: readme diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/opensearch/OpenSearchFeatureSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/opensearch/OpenSearchFeatureSpec.groovy new file mode 100644 index 00000000000..34a52d312f7 --- /dev/null +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/opensearch/OpenSearchFeatureSpec.groovy @@ -0,0 +1,82 @@ +package io.micronaut.starter.feature.opensearch + +import io.micronaut.starter.ApplicationContextSpec +import io.micronaut.starter.BuildBuilder +import io.micronaut.starter.build.BuildTestUtil +import io.micronaut.starter.build.BuildTestVerifier +import io.micronaut.starter.build.dependencies.MicronautDependencyUtils +import io.micronaut.starter.build.dependencies.Scope +import io.micronaut.starter.feature.Category +import io.micronaut.starter.feature.database.TestContainers +import io.micronaut.starter.fixture.CommandOutputFixture +import io.micronaut.starter.options.BuildTool + +class OpenSearchFeatureSpec extends ApplicationContextSpec implements CommandOutputFixture { + + void 'test opensearch feature #opensearchFeature.name contributes dependencies for #buildTool'(OpenSearchFeature opensearchFeature, BuildTool buildTool) { + given: + String template = new BuildBuilder(beanContext, buildTool) + .features([opensearchFeature.name]) + .render() + when: + String groupId = MicronautDependencyUtils.GROUP_ID_MICRONAUT_OPENSEARCH + String artifactId = "micronaut-" + opensearchFeature.getName() + BuildTestVerifier verifier = BuildTestUtil.verifier(buildTool, template) + + then: + verifier.hasDependency(groupId, artifactId) + if (opensearchFeature instanceof OpenSearchRestClient) { + assert verifier.hasDependency("io.micronaut", "micronaut-jackson-databind") + } + + and: + isConfiguredForTestResources(buildTool, verifier, template) + + where: + [opensearchFeature, buildTool] << [beanContext.getBeansOfType(OpenSearchFeature), BuildTool.values()].combinations() + } + + void 'test opensearch feature #opensearchFeature.name contributes testcontainers dependencies for #buildTool'(OpenSearchFeature opensearchFeature, BuildTool buildTool) { + given: + String template = new BuildBuilder(beanContext, buildTool) + .features([opensearchFeature.name, TestContainers.NAME]) + .render() + when: + BuildTestVerifier verifier = BuildTestUtil.verifier(buildTool, template) + + then: + verifier.hasDependency("org.opensearch", "opensearch-testcontainers", Scope.TEST) + verifier.hasDependency("org.testcontainers", "testcontainers", Scope.TEST) + + and: + !isConfiguredForTestResources(buildTool, verifier, template) + + where: + [opensearchFeature, buildTool] << [beanContext.getBeansOfType(OpenSearchFeature), BuildTool.values()].combinations() + } + + void "test opensearch feature #opensearchFeature.name is search engine category"(OpenSearchFeature opensearchFeature) { + expect: + Category.SEARCH == opensearchFeature.getCategory() + where: + [opensearchFeature, buildTool] << [beanContext.getBeansOfType(OpenSearchFeature), BuildTool.values()].combinations() + } + + void "test opensearch feature #opensearchFeature.name documentation links"(OpenSearchFeature opensearchFeature) { + expect: + opensearchFeature.getMicronautDocumentation() == 'https://micronaut-projects.github.io/micronaut-opensearch/latest/guide/' + opensearchFeature.getThirdPartyDocumentation() == 'https://opensearch.org/docs/latest/clients/java/' + + where: + [opensearchFeature, buildTool] << [beanContext.getBeansOfType(OpenSearchFeature), BuildTool.values()].combinations() + } + + boolean isConfiguredForTestResources(BuildTool buildTool, BuildTestVerifier verifier, String template) { + buildTool == BuildTool.MAVEN ? + verifier.hasTestResourceDependency("micronaut-test-resources-opensearch") : + verifier.hasBuildPlugin("io.micronaut.test-resources") && + template.contains('''testResources { + | additionalModules.add("opensearch") + | }'''.stripMargin()) + } +} diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/opentelemetry/OpenTelemetryExporterJaegerSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/opentelemetry/OpenTelemetryExporterJaegerSpec.groovy index 328c2ddafe5..70b8b213139 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/opentelemetry/OpenTelemetryExporterJaegerSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/opentelemetry/OpenTelemetryExporterJaegerSpec.groovy @@ -4,6 +4,8 @@ import io.micronaut.starter.ApplicationContextSpec import io.micronaut.starter.BuildBuilder import io.micronaut.starter.application.ApplicationType import io.micronaut.starter.application.generator.GeneratorContext +import io.micronaut.starter.build.BuildTestUtil +import io.micronaut.starter.build.BuildTestVerifier import io.micronaut.starter.feature.Category import io.micronaut.starter.fixture.CommandOutputFixture import io.micronaut.starter.options.BuildTool @@ -31,7 +33,9 @@ class OpenTelemetryExporterJaegerSpec extends ApplicationContextSpec implements GeneratorContext commandContext = buildGeneratorContext(['tracing-opentelemetry-exporter-jaeger']) then: - commandContext.configuration.get('otel.traces.exporter') == 'jaeger' + commandContext.configuration.get('otel.traces.exporter') == 'otlp' + commandContext.configuration.get('otel.exporter.otlp.endpoint') == 'http://localhost:4317' + } @Unroll @@ -52,36 +56,19 @@ class OpenTelemetryExporterJaegerSpec extends ApplicationContextSpec implements applicationType << (ApplicationType.values().toList() - ApplicationType.CLI) } - void 'test gradle tracing-opentelemetry-exporter-jaeger feature for language=#language'(Language language) { + void 'test gradle tracing-opentelemetry-exporter-jaeger feature for language=#language'(Language language, BuildTool buildTool) { when: - String template = new BuildBuilder(beanContext, BuildTool.GRADLE) + String template = new BuildBuilder(beanContext, buildTool) .language(language) .features(['tracing-opentelemetry-exporter-jaeger']) .render() + BuildTestVerifier verifier = BuildTestUtil.verifier(buildTool, language, template) then: - template.contains('implementation("io.opentelemetry:opentelemetry-exporter-jaeger")') - - where: - language << Language.values().toList() - } - - void 'test maven tracing-opentelemetry-exporter-jaeger feature for language=#language'(Language language) { - when: - String template = new BuildBuilder(beanContext, BuildTool.MAVEN) - .language(language) - .features(['tracing-opentelemetry-exporter-jaeger']) - .render() + verifier.hasDependency("io.opentelemetry", "opentelemetry-exporter-otlp") + !verifier.hasDependency("io.opentelemetry", "opentelemetry-exporter-jaeger") - then: - template.contains(""" - - io.opentelemetry - opentelemetry-exporter-jaeger - compile - - """) where: - language << Language.values().toList() + [language, buildTool] << [Language.values().toList(), BuildTool.values()].combinations() } } diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/opentelemetry/OpenTelemetryJaegerSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/opentelemetry/OpenTelemetryJaegerSpec.groovy index abb7b023eff..9a329d1c03d 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/opentelemetry/OpenTelemetryJaegerSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/opentelemetry/OpenTelemetryJaegerSpec.groovy @@ -3,6 +3,8 @@ package io.micronaut.starter.feature.opentelemetry import io.micronaut.starter.ApplicationContextSpec import io.micronaut.starter.BuildBuilder import io.micronaut.starter.application.ApplicationType +import io.micronaut.starter.build.BuildTestUtil +import io.micronaut.starter.build.BuildTestVerifier import io.micronaut.starter.feature.Category import io.micronaut.starter.options.BuildTool import io.micronaut.starter.options.Language @@ -33,7 +35,7 @@ class OpenTelemetryJaegerSpec extends ApplicationContextSpec { then: assertAnnotationProcessorInGradleTemplate(template, "io.micronaut.tracing:micronaut-tracing-opentelemetry-annotation", language) - template.contains('implementation("io.opentelemetry:opentelemetry-exporter-jaeger")') + template.contains('implementation("io.opentelemetry:opentelemetry-exporter-otlp")') template.contains('implementation("io.micronaut.tracing:micronaut-tracing-opentelemetry-grpc")') !template.contains('implementation("io.micronaut.tracing:micronaut-tracing-opentelemetry")') !template.contains('implementation("io.micronaut.tracing:micronaut-tracing-opentelemetry-http")') @@ -52,7 +54,7 @@ class OpenTelemetryJaegerSpec extends ApplicationContextSpec { then: assertAnnotationProcessorInGradleTemplate(template, "io.micronaut.tracing:micronaut-tracing-opentelemetry-annotation", language) - template.contains('implementation("io.opentelemetry:opentelemetry-exporter-jaeger")') + template.contains('implementation("io.opentelemetry:opentelemetry-exporter-otlp")') !template.contains('implementation("io.micronaut.tracing:micronaut-tracing-opentelemetry")') template.contains('implementation("io.micronaut.tracing:micronaut-tracing-opentelemetry-http")') !template.contains('implementation("io.micronaut.tracing:micronaut-tracing-opentelemetry-grpc")') @@ -73,7 +75,7 @@ class OpenTelemetryJaegerSpec extends ApplicationContextSpec { then: assertAnnotationProcessorInGradleTemplate(template, "io.micronaut.tracing:micronaut-tracing-opentelemetry-annotation", language) - template.contains('implementation("io.opentelemetry:opentelemetry-exporter-jaeger")') + template.contains('implementation("io.opentelemetry:opentelemetry-exporter-otlp")') template.contains('implementation("io.micronaut.tracing:micronaut-tracing-opentelemetry")') !template.contains('implementation("io.micronaut.tracing:micronaut-tracing-opentelemetry-http")') @@ -87,67 +89,39 @@ class OpenTelemetryJaegerSpec extends ApplicationContextSpec { void 'test maven tracing-opentelemetry-jaeger feature for language=#language'(Language language) { when: - String template = new BuildBuilder(beanContext, BuildTool.MAVEN) + BuildTool buildTool = BuildTool.MAVEN + String template = new BuildBuilder(beanContext, buildTool) .language(language) .features(['tracing-opentelemetry-jaeger']) .render() + BuildTestVerifier verifier = BuildTestUtil.verifier(buildTool, template) then: - template.contains(""" - - io.opentelemetry - opentelemetry-exporter-jaeger - compile - - """) - !template.contains(""" - - io.micronaut.tracing - micronaut-tracing-opentelemetry - compile - - """) - template.contains(""" - - io.micronaut.tracing - micronaut-tracing-opentelemetry-http - compile - - """) + !verifier.hasDependency("io.opentelemetry", "opentelemetry-exporter-jaeger") + verifier.hasDependency("io.opentelemetry", "opentelemetry-exporter-otlp") + !verifier.hasDependency("io.micronaut.tracing", "micronaut-tracing-opentelemetry") + verifier.hasDependency("io.micronaut.tracing", "micronaut-tracing-opentelemetry-http") + where: language << Language.values().toList() } void 'for function test maven tracing-opentelemetry-jaeger feature for language=#language'(Language language) { when: + BuildTool buildTool = BuildTool.MAVEN String template = new BuildBuilder(beanContext, BuildTool.MAVEN) .applicationType(ApplicationType.FUNCTION) .language(language) .features(['tracing-opentelemetry-jaeger']) .render() + BuildTestVerifier verifier = BuildTestUtil.verifier(buildTool, template) then: - template.contains(""" - - io.opentelemetry - opentelemetry-exporter-jaeger - compile - - """) - template.contains(""" - - io.micronaut.tracing - micronaut-tracing-opentelemetry - compile - - """) - !template.contains(""" - - io.micronaut.tracing - micronaut-tracing-opentelemetry-http - compile - - """) + !verifier.hasDependency("io.opentelemetry", "opentelemetry-exporter-jaeger") + verifier.hasDependency("io.opentelemetry", "opentelemetry-exporter-otlp") + verifier.hasDependency("io.micronaut.tracing", "micronaut-tracing-opentelemetry") + !verifier.hasDependency("io.micronaut.tracing", "micronaut-tracing-opentelemetry-http") + where: language << Language.values().toList() } diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/opentelemetry/OpenTelemetryXraySpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/opentelemetry/OpenTelemetryXraySpec.groovy index 4b8a40645de..f7127236beb 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/opentelemetry/OpenTelemetryXraySpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/opentelemetry/OpenTelemetryXraySpec.groovy @@ -4,6 +4,8 @@ import io.micronaut.starter.ApplicationContextSpec import io.micronaut.starter.BuildBuilder import io.micronaut.starter.application.ApplicationType import io.micronaut.starter.application.generator.GeneratorContext +import io.micronaut.starter.build.BuildTestUtil +import io.micronaut.starter.build.BuildTestVerifier import io.micronaut.starter.feature.Category import io.micronaut.starter.fixture.CommandOutputFixture import io.micronaut.starter.options.BuildTool @@ -58,7 +60,7 @@ class OpenTelemetryXraySpec extends ApplicationContextSpec implements CommandOut then: template.contains('implementation("io.opentelemetry.contrib:opentelemetry-aws-xray")') - template.contains('implementation("io.opentelemetry:opentelemetry-extension-aws")') + !template.contains('implementation("io.opentelemetry:opentelemetry-extension-aws")') where: language << Language.values().toList() @@ -67,16 +69,20 @@ class OpenTelemetryXraySpec extends ApplicationContextSpec implements CommandOut @See("https://aws-otel.github.io/docs/getting-started/java-sdk/trace-manual-instr#instrumenting-the-aws-sdk") void 'test gradle tracing-opentelemetry-xray dynamodb features for language=#language include aws-sdk instrumentation opentelemetry dependency'(Language language) { when: - String template = new BuildBuilder(beanContext, BuildTool.GRADLE) + BuildTool buildTool = BuildTool.GRADLE + String template = new BuildBuilder(beanContext, buildTool) .language(language) .features(['tracing-opentelemetry-xray', 'dynamodb']) .render() + BuildTestVerifier verifier = BuildTestUtil.verifier(buildTool, language, template) then: + verifier.hasDependency("io.opentelemetry.instrumentation", "opentelemetry-aws-sdk-2.2") + verifier.hasDependency("io.opentelemetry.contrib", "opentelemetry-aws-xray") + verifier.hasDependency("io.opentelemetry.contrib", "opentelemetry-aws-xray-propagator") + verifier.hasDependency("io.opentelemetry.contrib", "opentelemetry-aws-resources") template.contains('implementation platform("io.opentelemetry.instrumentation:opentelemetry-instrumentation-bom-alpha:1.14.0-alpha")') - template.contains('implementation("io.opentelemetry.instrumentation:opentelemetry-aws-sdk-2.2")') - template.contains('implementation("io.opentelemetry.contrib:opentelemetry-aws-xray")') - template.contains('implementation("io.opentelemetry:opentelemetry-extension-aws")') + !verifier.hasDependency('io.opentelemetry:opentelemetry-extension-aws') where: language << Language.values().toList() @@ -159,7 +165,7 @@ class OpenTelemetryXraySpec extends ApplicationContextSpec implements CommandOut compile """) - template.contains(""" + !template.contains(""" io.opentelemetry opentelemetry-extension-aws @@ -207,7 +213,7 @@ class OpenTelemetryXraySpec extends ApplicationContextSpec implements CommandOut compile """) - template.contains(""" + !template.contains(""" io.opentelemetry opentelemetry-extension-aws diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/oracecloud/OracleCloudVaultSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/oracecloud/OracleCloudVaultSpec.groovy index 4fd57242139..9bcd8647fee 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/oracecloud/OracleCloudVaultSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/oracecloud/OracleCloudVaultSpec.groovy @@ -14,8 +14,8 @@ class OracleCloudVaultSpec extends ApplicationContextSpec implements CommandOutp void 'test README.md with feature oracle-cloud-vault contains links to Micronaut docs'() { when: - def output = generate(['oracle-cloud-vault']) - def readme = output["README.md"] + Map output = generate(['oracle-cloud-vault']) + String readme = output["README.md"] then: readme diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/other/HttpSessionSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/other/HttpSessionSpec.groovy index 1ddf1dd9bc3..6e10c7a725a 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/other/HttpSessionSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/other/HttpSessionSpec.groovy @@ -21,8 +21,8 @@ class HttpSessionSpec extends ApplicationContextSpec implements CommandOutputFix void 'test readme.md with feature http-session contains links to micronaut docs'() { when: - def output = generate(['http-session']) - def readme = output["README.md"] + Map output = generate(['http-session']) + String readme = output["README.md"] then: readme diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/other/ManagementSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/other/ManagementSpec.groovy index dbdf326a34a..4513d80967a 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/other/ManagementSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/other/ManagementSpec.groovy @@ -9,8 +9,8 @@ class ManagementSpec extends BeanContextSpec implements CommandOutputFixture { @Unroll void 'test readme.md contains links to hazelcast and micronaut docs'() { when: - def output = generate(['management']) - def readme = output["README.md"] + Map output = generate(['management']) + String readme = output["README.md"] then: readme diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/other/OpenApiAdocSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/other/OpenApiAdocSpec.groovy index a8f86c8a11e..33fcbdad8e1 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/other/OpenApiAdocSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/other/OpenApiAdocSpec.groovy @@ -12,7 +12,7 @@ import io.micronaut.starter.options.Language import io.micronaut.starter.options.TestFramework import spock.lang.Unroll -class OpenApiAdocSpec extends ApplicationContextSpec implements CommandOutputFixture { +class OpenApiAdocSpec extends ApplicationContextSpec implements CommandOutputFixture { void "openapi-adoc feature includes openapi feature"() { when: diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/other/OpenApiExplorerSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/other/OpenApiExplorerSpec.groovy new file mode 100644 index 00000000000..903ec2c09bd --- /dev/null +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/other/OpenApiExplorerSpec.groovy @@ -0,0 +1,89 @@ +package io.micronaut.starter.feature.other + +import io.micronaut.starter.ApplicationContextSpec +import io.micronaut.starter.application.ApplicationType +import io.micronaut.starter.application.generator.GeneratorContext +import io.micronaut.starter.feature.Features +import io.micronaut.starter.fixture.CommandOutputFixture + +class OpenApiExplorerSpec extends ApplicationContextSpec implements CommandOutputFixture { + + void "test openapi-explorer features"() { + when: + Features features = getFeatures(['openapi-explorer']) + + then: + features.contains("openapi") + } + + void "test config without security feature"() { + when: + GeneratorContext ctx = buildGeneratorContext(['openapi-explorer']) + def output = generate(ApplicationType.DEFAULT, ctx) + + then: + ctx.configuration.get('micronaut.router.static-resources.swagger.paths') == "classpath:META-INF/swagger" + ctx.configuration.get('micronaut.router.static-resources.swagger.mapping') == "/swagger/**" + ctx.configuration.get('micronaut.router.static-resources.openapi-explorer.paths') == "classpath:META-INF/swagger/views/openapi-explorer" + ctx.configuration.get('micronaut.router.static-resources.openapi-explorer.mapping') == "/openapi-explorer/**" + + output["openapi.properties"].readLines()[0] == "swagger-ui.enabled=false" + output["openapi.properties"].readLines()[1] == "redoc.enabled=false" + output["openapi.properties"].readLines()[2] == "openapi-explorer.enabled=true" + output["openapi.properties"].readLines()[3] == "rapidoc.enabled=false" + output["openapi.properties"].readLines()[4] == "rapidoc.bg-color=#14191f" + output["openapi.properties"].readLines()[5] == "rapidoc.text-color=#aec2e0" + output["openapi.properties"].readLines()[6] == "rapidoc.sort-endpoints-by=method" + + output.containsKey("src/main/java/example/micronaut/FooController.java") + output.containsKey("src/test/java/example/micronaut/FooTest.java") + } + + void "test config with security feature"() { + when: + GeneratorContext ctx = buildGeneratorContext(['openapi-explorer', 'security']) + def output = generate(ApplicationType.DEFAULT, ctx) + + then: + ctx.configuration.get('micronaut.router.static-resources.swagger.paths') == "classpath:META-INF/swagger" + ctx.configuration.get('micronaut.router.static-resources.swagger.mapping') == "/swagger/**" + ctx.configuration.get('micronaut.router.static-resources.openapi-explorer.paths') == "classpath:META-INF/swagger/views/openapi-explorer" + ctx.configuration.get('micronaut.router.static-resources.openapi-explorer.mapping') == "/openapi-explorer/**" + + List> swaggerSec = ctx.configuration.get('micronaut.security.intercept-url-map') as List> + + swaggerSec.any { it.access == "isAnonymous()" && it.pattern == "/swagger/**" } + swaggerSec.any { it.access == "isAnonymous()" && it.pattern == "/openapi-explorer/**" } + + output["openapi.properties"].readLines()[0] == "swagger-ui.enabled=false" + output["openapi.properties"].readLines()[1] == "redoc.enabled=false" + output["openapi.properties"].readLines()[2] == "openapi-explorer.enabled=true" + output["openapi.properties"].readLines()[3] == "rapidoc.enabled=false" + output["openapi.properties"].readLines()[4] == "rapidoc.bg-color=#14191f" + output["openapi.properties"].readLines()[5] == "rapidoc.text-color=#aec2e0" + output["openapi.properties"].readLines()[6] == "rapidoc.sort-endpoints-by=method" + + output.containsKey("src/main/java/example/micronaut/FooController.java") + output.containsKey("src/test/java/example/micronaut/FooTest.java") + + } + + void "test openapi-explorer has third party docs"() { + when: + GeneratorContext ctx = buildGeneratorContext(['openapi-explorer']) + def output = generate(ApplicationType.DEFAULT, ctx) + + then: + output["README.md"].contains("https://github.com/Authress-Engineering/openapi-explorer") + } + + void "test openapi-explorer has Micronaut docs"() { + when: + GeneratorContext ctx = buildGeneratorContext(['openapi-explorer']) + def output = generate(ApplicationType.DEFAULT, ctx) + + then: + output["README.md"].contains("https://micronaut-projects.github.io/micronaut-openapi/latest/guide/#openapiExplorer") + } + +} diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/other/OpenApiSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/other/OpenApiSpec.groovy index 741e16a3b69..9f30fc24d47 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/other/OpenApiSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/other/OpenApiSpec.groovy @@ -16,8 +16,8 @@ class OpenApiSpec extends ApplicationContextSpec implements CommandOutputFixtur void 'test readme.md with feature openapi contains links to micronaut docs'() { when: - def output = generate(['openapi']) - def readme = output["README.md"] + Map output = generate(['openapi']) + String readme = output["README.md"] then: readme diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/other/OpenRewriteSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/other/OpenRewriteSpec.groovy index 6f58f079ab0..b3f738282b5 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/other/OpenRewriteSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/other/OpenRewriteSpec.groovy @@ -3,6 +3,8 @@ package io.micronaut.starter.feature.other import io.micronaut.core.version.SemanticVersion import io.micronaut.starter.ApplicationContextSpec import io.micronaut.starter.BuildBuilder +import io.micronaut.starter.build.BuildTestUtil +import io.micronaut.starter.build.BuildTestVerifier import io.micronaut.starter.fixture.CommandOutputFixture import io.micronaut.starter.options.BuildTool @@ -26,17 +28,17 @@ class OpenRewriteSpec extends ApplicationContextSpec implements CommandOutputFix String template = render(GRADLE) String pluginId = 'org.openrewrite.rewrite' + BuildTestVerifier verifier = BuildTestUtil.verifier(GRADLE,template) + then: - template.contains 'rewrite("org.openrewrite.recipe:rewrite-micronaut:' + verifier.hasDependency("org.openrewrite.recipe", "rewrite-micronaut", "rewrite") + verifier.hasBuildPlugin(pluginId) template.contains ''' rewrite { - activeRecipe("org.openrewrite.java.micronaut.Micronaut2to3Migration") + activeRecipe("org.openrewrite.java.micronaut.Micronaut3to4Migration") } ''' - - template.contains 'id("' + pluginId + '") version "' - when: Optional semver = parseCommunityGradlePluginVersion(pluginId, template).map(SemanticVersion::new) @@ -61,7 +63,7 @@ rewrite { ${openrewrite.maven.plugin.version} - org.openrewrite.java.micronaut.Micronaut2to3Migration + org.openrewrite.java.micronaut.Micronaut3to4Migration diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/other/ProjectLombokSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/other/ProjectLombokSpec.groovy index 2d45da27266..b760c2a18be 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/other/ProjectLombokSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/other/ProjectLombokSpec.groovy @@ -21,8 +21,8 @@ class ProjectLombokSpec extends ApplicationContextSpec implements CommandOutputF void 'test readme.md with feature projectLombok contains links to micronaut docs'() { when: - def output = generate(['lombok']) - def readme = output["README.md"] + Map output = generate(['lombok']) + String readme = output["README.md"] then: readme diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/other/RapiDocSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/other/RapiDocSpec.groovy index 6c472c87cf2..7a63939ec01 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/other/RapiDocSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/other/RapiDocSpec.groovy @@ -6,7 +6,7 @@ import io.micronaut.starter.application.generator.GeneratorContext import io.micronaut.starter.feature.Features import io.micronaut.starter.fixture.CommandOutputFixture -class RapiDocSpec extends ApplicationContextSpec implements CommandOutputFixture { +class RapiDocSpec extends ApplicationContextSpec implements CommandOutputFixture { void "test rapidoc features"() { when: @@ -29,10 +29,11 @@ class RapiDocSpec extends ApplicationContextSpec implements CommandOutputFixtur output["openapi.properties"].readLines()[0] == "swagger-ui.enabled=false" output["openapi.properties"].readLines()[1] == "redoc.enabled=false" - output["openapi.properties"].readLines()[2] == "rapidoc.enabled=true" - output["openapi.properties"].readLines()[3] == "rapidoc.bg-color=#14191f" - output["openapi.properties"].readLines()[4] == "rapidoc.text-color=#aec2e0" - output["openapi.properties"].readLines()[5] == "rapidoc.sort-endpoints-by=method" + output["openapi.properties"].readLines()[2] == "openapi-explorer.enabled=false" + output["openapi.properties"].readLines()[3] == "rapidoc.enabled=true" + output["openapi.properties"].readLines()[4] == "rapidoc.bg-color=#14191f" + output["openapi.properties"].readLines()[5] == "rapidoc.text-color=#aec2e0" + output["openapi.properties"].readLines()[6] == "rapidoc.sort-endpoints-by=method" output.containsKey("src/main/java/example/micronaut/FooController.java") output.containsKey("src/test/java/example/micronaut/FooTest.java") @@ -57,10 +58,11 @@ class RapiDocSpec extends ApplicationContextSpec implements CommandOutputFixtur output["openapi.properties"].readLines()[0] == "swagger-ui.enabled=false" output["openapi.properties"].readLines()[1] == "redoc.enabled=false" - output["openapi.properties"].readLines()[2] == "rapidoc.enabled=true" - output["openapi.properties"].readLines()[3] == "rapidoc.bg-color=#14191f" - output["openapi.properties"].readLines()[4] == "rapidoc.text-color=#aec2e0" - output["openapi.properties"].readLines()[5] == "rapidoc.sort-endpoints-by=method" + output["openapi.properties"].readLines()[2] == "openapi-explorer.enabled=false" + output["openapi.properties"].readLines()[3] == "rapidoc.enabled=true" + output["openapi.properties"].readLines()[4] == "rapidoc.bg-color=#14191f" + output["openapi.properties"].readLines()[5] == "rapidoc.text-color=#aec2e0" + output["openapi.properties"].readLines()[6] == "rapidoc.sort-endpoints-by=method" output.containsKey("src/main/java/example/micronaut/FooController.java") output.containsKey("src/test/java/example/micronaut/FooTest.java") diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/other/ReadMeSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/other/ReadMeSpec.groovy index 9e0849fd191..1dcbab31b1c 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/other/ReadMeSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/other/ReadMeSpec.groovy @@ -8,9 +8,9 @@ class ReadMeSpec extends BeanContextSpec implements CommandOutputFixture { void 'test readme.md contains links to micronaut user guides'() { when: - def output = generate([]) - def readme = output["README.md"] - def version = VersionInfo.isMicronautSnapshot() ? "snapshot" : VersionInfo.getMicronautVersion() + Map output = generate([]) + String readme = output["README.md"] + String version = VersionInfo.isMicronautSnapshot() ? "snapshot" : VersionInfo.getMicronautVersion() then: readme diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/other/RedocSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/other/RedocSpec.groovy index c77bb26cd00..6b2fc71bc4a 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/other/RedocSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/other/RedocSpec.groovy @@ -6,7 +6,7 @@ import io.micronaut.starter.application.generator.GeneratorContext import io.micronaut.starter.feature.Features import io.micronaut.starter.fixture.CommandOutputFixture -class RedocSpec extends ApplicationContextSpec implements CommandOutputFixture { +class RedocSpec extends ApplicationContextSpec implements CommandOutputFixture { void "test redoc features"() { when: @@ -29,10 +29,11 @@ class RedocSpec extends ApplicationContextSpec implements CommandOutputFixture output["openapi.properties"].readLines()[0] == "swagger-ui.enabled=false" output["openapi.properties"].readLines()[1] == "redoc.enabled=true" - output["openapi.properties"].readLines()[2] == "rapidoc.enabled=false" - output["openapi.properties"].readLines()[3] == "rapidoc.bg-color=#14191f" - output["openapi.properties"].readLines()[4] == "rapidoc.text-color=#aec2e0" - output["openapi.properties"].readLines()[5] == "rapidoc.sort-endpoints-by=method" + output["openapi.properties"].readLines()[2] == "openapi-explorer.enabled=false" + output["openapi.properties"].readLines()[3] == "rapidoc.enabled=false" + output["openapi.properties"].readLines()[4] == "rapidoc.bg-color=#14191f" + output["openapi.properties"].readLines()[5] == "rapidoc.text-color=#aec2e0" + output["openapi.properties"].readLines()[6] == "rapidoc.sort-endpoints-by=method" output.containsKey("src/main/java/example/micronaut/FooController.java") output.containsKey("src/test/java/example/micronaut/FooTest.java") @@ -56,10 +57,11 @@ class RedocSpec extends ApplicationContextSpec implements CommandOutputFixture output["openapi.properties"].readLines()[0] == "swagger-ui.enabled=false" output["openapi.properties"].readLines()[1] == "redoc.enabled=true" - output["openapi.properties"].readLines()[2] == "rapidoc.enabled=false" - output["openapi.properties"].readLines()[3] == "rapidoc.bg-color=#14191f" - output["openapi.properties"].readLines()[4] == "rapidoc.text-color=#aec2e0" - output["openapi.properties"].readLines()[5] == "rapidoc.sort-endpoints-by=method" + output["openapi.properties"].readLines()[2] == "openapi-explorer.enabled=false" + output["openapi.properties"].readLines()[3] == "rapidoc.enabled=false" + output["openapi.properties"].readLines()[4] == "rapidoc.bg-color=#14191f" + output["openapi.properties"].readLines()[5] == "rapidoc.text-color=#aec2e0" + output["openapi.properties"].readLines()[6] == "rapidoc.sort-endpoints-by=method" output.containsKey("src/main/java/example/micronaut/FooController.java") output.containsKey("src/test/java/example/micronaut/FooTest.java") diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/other/SwaggerUISpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/other/SwaggerUISpec.groovy index e5810143b74..887f5a0f656 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/other/SwaggerUISpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/other/SwaggerUISpec.groovy @@ -6,7 +6,7 @@ import io.micronaut.starter.application.generator.GeneratorContext import io.micronaut.starter.feature.Features import io.micronaut.starter.fixture.CommandOutputFixture -class SwaggerUISpec extends ApplicationContextSpec implements CommandOutputFixture { +class SwaggerUISpec extends ApplicationContextSpec implements CommandOutputFixture { void "test swagger-ui features"() { when: @@ -29,14 +29,14 @@ class SwaggerUISpec extends ApplicationContextSpec implements CommandOutputFixt output["openapi.properties"].readLines()[0] == "swagger-ui.enabled=true" output["openapi.properties"].readLines()[1] == "redoc.enabled=false" - output["openapi.properties"].readLines()[2] == "rapidoc.enabled=false" - output["openapi.properties"].readLines()[3] == "rapidoc.bg-color=#14191f" - output["openapi.properties"].readLines()[4] == "rapidoc.text-color=#aec2e0" - output["openapi.properties"].readLines()[5] == "rapidoc.sort-endpoints-by=method" + output["openapi.properties"].readLines()[2] == "openapi-explorer.enabled=false" + output["openapi.properties"].readLines()[3] == "rapidoc.enabled=false" + output["openapi.properties"].readLines()[4] == "rapidoc.bg-color=#14191f" + output["openapi.properties"].readLines()[5] == "rapidoc.text-color=#aec2e0" + output["openapi.properties"].readLines()[6] == "rapidoc.sort-endpoints-by=method" output.containsKey("src/main/java/example/micronaut/FooController.java") output.containsKey("src/test/java/example/micronaut/FooTest.java") - } void "test config with security feature"() { @@ -57,10 +57,11 @@ class SwaggerUISpec extends ApplicationContextSpec implements CommandOutputFixt output["openapi.properties"].readLines()[0] == "swagger-ui.enabled=true" output["openapi.properties"].readLines()[1] == "redoc.enabled=false" - output["openapi.properties"].readLines()[2] == "rapidoc.enabled=false" - output["openapi.properties"].readLines()[3] == "rapidoc.bg-color=#14191f" - output["openapi.properties"].readLines()[4] == "rapidoc.text-color=#aec2e0" - output["openapi.properties"].readLines()[5] == "rapidoc.sort-endpoints-by=method" + output["openapi.properties"].readLines()[2] == "openapi-explorer.enabled=false" + output["openapi.properties"].readLines()[3] == "rapidoc.enabled=false" + output["openapi.properties"].readLines()[4] == "rapidoc.bg-color=#14191f" + output["openapi.properties"].readLines()[5] == "rapidoc.text-color=#aec2e0" + output["openapi.properties"].readLines()[6] == "rapidoc.sort-endpoints-by=method" output.containsKey("src/main/java/example/micronaut/FooController.java") output.containsKey("src/test/java/example/micronaut/FooTest.java") diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/picocli/PicocliSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/picocli/PicocliSpec.groovy index 619cb42d927..ed46a313074 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/picocli/PicocliSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/picocli/PicocliSpec.groovy @@ -8,6 +8,7 @@ import io.micronaut.starter.build.BuildTestUtil import io.micronaut.starter.build.BuildTestVerifier import io.micronaut.starter.build.dependencies.Scope import io.micronaut.starter.feature.Features +import io.micronaut.starter.feature.build.Kapt import io.micronaut.starter.options.BuildTool import io.micronaut.starter.options.Language import io.micronaut.starter.options.Options @@ -18,17 +19,25 @@ class PicocliSpec extends ApplicationContextSpec { @Unroll void 'test cli app contains picocli-gen as annotation processor for buildTool=#buildTool language=#language'(Language language, BuildTool buildTool) { + given: + def features = language == Language.KOTLIN ? [Kapt.NAME] : [] + when: String template = new BuildBuilder(beanContext, buildTool) .language(language) + .features(features) .applicationType(ApplicationType.CLI) .render() BuildTestVerifier verifier = BuildTestUtil.verifier(buildTool, language, template) then: - verifier.hasAnnotationProcessor("info.picocli", "picocli-codegen") verifier.hasDependency("info.picocli", "picocli") verifier.hasDependency("io.micronaut.picocli", "micronaut-picocli") + if (language == Language.KOTLIN && buildTool.isGradle()) { + assert verifier.hasDependency("info.picocli", "picocli-codegen", "kapt") + } else { + assert verifier.hasAnnotationProcessor("info.picocli", "picocli-codegen") + } where: [language, buildTool] << [Language.values(), BuildTool.values()].combinations() @@ -89,6 +98,7 @@ class PicocliSpec extends ApplicationContextSpec { features.contains("picocli-junit") features.contains("junit") generatorContext.getTemplates().containsKey("picocliJunitTest") + !features.contains(Kapt.NAME) !features.contains("picocli-spock") !features.contains("picocli-kotlintest") !generatorContext.getTemplates().containsKey("testDir") @@ -109,11 +119,12 @@ class PicocliSpec extends ApplicationContextSpec { when: options = new Options(Language.KOTLIN, null, BuildTool.GRADLE) - features = getFeatures([], options, ApplicationType.CLI) - generatorContext = buildGeneratorContext([], options, ApplicationType.CLI) + features = getFeatures([Kapt.NAME], options, ApplicationType.CLI) + generatorContext = buildGeneratorContext([Kapt.NAME], options, ApplicationType.CLI) then: features.contains("picocli") + features.contains(Kapt.NAME) features.contains("picocli-junit") features.contains("junit") generatorContext.getTemplates().containsKey("picocliJunitTest") @@ -122,9 +133,10 @@ class PicocliSpec extends ApplicationContextSpec { !generatorContext.getTemplates().containsKey("testDir") when: + def kaptFeatures = language == Language.KOTLIN ? [Kapt.NAME] : [] options = new Options(language, TestFramework.JUNIT, BuildTool.GRADLE) - features = getFeatures([], options, ApplicationType.CLI) - generatorContext = buildGeneratorContext([], options, ApplicationType.CLI) + features = getFeatures(kaptFeatures, options, ApplicationType.CLI) + generatorContext = buildGeneratorContext(kaptFeatures, options, ApplicationType.CLI) then: features.contains("picocli") @@ -138,4 +150,29 @@ class PicocliSpec extends ApplicationContextSpec { where: language << Language.values() } + + void "test that picocli with kotlin language requires kapt with buildTool=#buildTool"() { + when: + new BuildBuilder(beanContext, buildTool) + .language(Language.KOTLIN) + .applicationType(ApplicationType.CLI) + .render() + + then: + def ex = thrown(IllegalArgumentException) + ex.getMessage() == 'Feature picocli-kotlin-application is incompatible with Kotlin KSP and requires Kapt instead.' + + when: + new BuildBuilder(beanContext, buildTool) + .language(Language.KOTLIN) + .features([Kapt.NAME]) + .applicationType(ApplicationType.CLI) + .render() + + then: + noExceptionThrown() + + where: "BuildTool.MAVEN always includes Kapt" + buildTool << BuildTool.valuesGradle() + } } diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/problemjson/ProblemJsonSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/problemjson/ProblemJsonSpec.groovy index dca056cfb6b..6384dbdd4ed 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/problemjson/ProblemJsonSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/problemjson/ProblemJsonSpec.groovy @@ -10,8 +10,8 @@ import spock.lang.Unroll class ProblemJsonSpec extends ApplicationContextSpec implements CommandOutputFixture { void 'test readme.md with feature problem-json contains links to micronaut docs'() { when: - def output = generate(['problem-json']) - def readme = output["README.md"] + Map output = generate(['problem-json']) + String readme = output["README.md"] then: readme diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/reactor/ReactorSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/reactor/ReactorSpec.groovy index 226a537ae9f..466ac5c3191 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/reactor/ReactorSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/reactor/ReactorSpec.groovy @@ -18,8 +18,8 @@ class ReactorSpec extends ApplicationContextSpec implements CommandOutputFixtur void 'test readme.md with feature reactor contains links to micronaut docs'() { when: - def output = generate(['reactor']) - def readme = output["README.md"] + Map output = generate(['reactor']) + String readme = output["README.md"] then: readme diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/retry/RetrySpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/retry/RetrySpec.groovy index 624981bcac3..17318c393f9 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/retry/RetrySpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/retry/RetrySpec.groovy @@ -20,8 +20,8 @@ class RetrySpec extends ApplicationContextSpec implements CommandOutputFixture { void 'test readme.md with feature retry contains links to micronaut docs'() { when: - def output = generate(['retry']) - def readme = output["README.md"] + Map output = generate(['retry']) + String readme = output["README.md"] then: readme diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/rss/RssItunesSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/rss/RssItunesSpec.groovy index 1384d4f7cf0..d9845ea1e11 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/rss/RssItunesSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/rss/RssItunesSpec.groovy @@ -11,8 +11,8 @@ class RssItunesSpec extends ApplicationContextSpec implements CommandOutputFixtu void 'test readme.md with feature rss-itunes-podcast contains links to micronaut docs'() { when: - def output = generate(['rss-itunes-podcast']) - def readme = output["README.md"] + Map output = generate(['rss-itunes-podcast']) + String readme = output["README.md"] then: readme diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/rss/RssSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/rss/RssSpec.groovy index f8f2571b6e8..eb938bf1233 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/rss/RssSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/rss/RssSpec.groovy @@ -11,8 +11,8 @@ class RssSpec extends ApplicationContextSpec implements CommandOutputFixture { void 'test readme.md with feature rss contains links to micronaut docs'() { when: - def output = generate(['rss']) - def readme = output["README.md"] + Map output = generate(['rss']) + String readme = output["README.md"] then: readme diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/rxjava/RxJava1Spec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/rxjava/RxJava1Spec.groovy index 9cafc67c08c..e8b4200d0d6 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/rxjava/RxJava1Spec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/rxjava/RxJava1Spec.groovy @@ -15,8 +15,8 @@ class RxJava1Spec extends ApplicationContextSpec implements CommandOutputFixtur void 'test readme.md with feature rxjava1 contains links to micronaut docs'() { when: - def output = generate(['rxjava1']) - def readme = output["README.md"] + Map output = generate(['rxjava1']) + String readme = output["README.md"] then: readme diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/rxjava/RxJava3Spec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/rxjava/RxJava3Spec.groovy index 2ed1e3f0aeb..eab22d6205a 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/rxjava/RxJava3Spec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/rxjava/RxJava3Spec.groovy @@ -18,8 +18,8 @@ class RxJava3Spec extends ApplicationContextSpec implements CommandOutputFixture void 'test readme.md with feature rxjava3 contains links to micronaut docs'() { when: - def output = generate(['rxjava3']) - def readme = output["README.md"] + Map output = generate(['rxjava3']) + String readme = output["README.md"] then: readme diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/secretsmanager/GoogleSecretManagerSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/secretsmanager/GoogleSecretManagerSpec.groovy index d6a473e2161..fcd64140f46 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/secretsmanager/GoogleSecretManagerSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/secretsmanager/GoogleSecretManagerSpec.groovy @@ -12,8 +12,8 @@ class GoogleSecretManagerSpec extends ApplicationContextSpec implements CommandO void 'test readme.md with feature gcp-secrets-manager contains links to micronaut docs'() { when: - def output = generate(['gcp-secrets-manager']) - def readme = output["README.md"] + Map output = generate(['gcp-secrets-manager']) + String readme = output["README.md"] then: readme diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/security/SecurityJWTSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/security/SecurityJWTSpec.groovy index 7e67cc8ed7f..21a28e8f6d6 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/security/SecurityJWTSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/security/SecurityJWTSpec.groovy @@ -15,8 +15,8 @@ class SecurityJWTSpec extends ApplicationContextSpec implements CommandOutputFi void 'test readme.md with feature security-jwt contains links to micronaut docs'() { when: - def output = generate(['security-jwt']) - def readme = output["README.md"] + Map output = generate(['security-jwt']) + String readme = output["README.md"] then: readme diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/security/SecurityLdapSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/security/SecurityLdapSpec.groovy index 2c3a6a6da7f..67b7209a3e3 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/security/SecurityLdapSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/security/SecurityLdapSpec.groovy @@ -14,8 +14,8 @@ class SecurityLdapSpec extends ApplicationContextSpec implements CommandOutputFi void 'test readme.md with feature security-ldap contains links to micronaut docs'() { when: - def output = generate(['security-ldap']) - def readme = output["README.md"] + Map output = generate(['security-ldap']) + String readme = output["README.md"] then: readme diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/security/SecurityOauth2Spec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/security/SecurityOauth2Spec.groovy index 20ab60fadaf..dbbf08f3da3 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/security/SecurityOauth2Spec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/security/SecurityOauth2Spec.groovy @@ -17,8 +17,8 @@ class SecurityOauth2Spec extends ApplicationContextSpec implements CommandOutput void 'test readme.md with feature security-oauth2 contains links to micronaut docs'() { when: - def output = generate(['security-oauth2']) - def readme = output["README.md"] + Map output = generate(['security-oauth2']) + String readme = output["README.md"] then: readme diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/security/SecuritySessionSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/security/SecuritySessionSpec.groovy index a95d54e28cd..7786c1324d6 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/security/SecuritySessionSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/security/SecuritySessionSpec.groovy @@ -15,8 +15,8 @@ class SecuritySessionSpec extends ApplicationContextSpec implements CommandOutpu void 'test readme.md with feature security-session contains links to micronaut docs'() { when: - def output = generate(['security-session']) - def readme = output["README.md"] + Map output = generate(['security-session']) + String readme = output["README.md"] then: readme diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/security/SecuritySpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/security/SecuritySpec.groovy index 80aafb24527..44d26c0be3c 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/security/SecuritySpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/security/SecuritySpec.groovy @@ -13,8 +13,8 @@ class SecuritySpec extends ApplicationContextSpec implements CommandOutputFixtur void 'test readme.md with feature security contains links to micronaut docs'() { when: - def output = generate(['security']) - def readme = output["README.md"] + Map output = generate(['security']) + String readme = output["README.md"] then: readme diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/server/JettyTestSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/server/JettyTestSpec.groovy index d77e00671f6..23cb88e82d0 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/server/JettyTestSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/server/JettyTestSpec.groovy @@ -7,8 +7,8 @@ class JettyTestSpec extends BeanContextSpec implements CommandOutputFixture { void 'test readme.md with feature jetty-server contains links to micronaut docs'() { when: - def output = generate(['jetty-server']) - def readme = output["README.md"] + Map output = generate(['jetty-server']) + String readme = output["README.md"] then: readme diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/server/TomcatSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/server/TomcatSpec.groovy index 493e0044469..d82a900a887 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/server/TomcatSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/server/TomcatSpec.groovy @@ -7,8 +7,8 @@ class TomcatSpec extends BeanContextSpec implements CommandOutputFixture { void 'test readme.md with feature tomcat-server contains links to micronaut docs'() { when: - def output = generate(['tomcat-server']) - def readme = output["README.md"] + Map output = generate(['tomcat-server']) + String readme = output["README.md"] then: readme diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/server/UndertowSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/server/UndertowSpec.groovy index 1e37f1e5841..d9f08af1de1 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/server/UndertowSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/server/UndertowSpec.groovy @@ -7,8 +7,8 @@ class UndertowSpec extends BeanContextSpec implements CommandOutputFixture { void 'test readme.md with feature undertow-server contains links to micronaut docs'() { when: - def output = generate(['undertow-server']) - def readme = output["README.md"] + Map output = generate(['undertow-server']) + String readme = output["README.md"] then: readme diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/sourcegen/SourcegenJavaSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/sourcegen/SourcegenJavaSpec.groovy new file mode 100644 index 00000000000..8b32ab415c4 --- /dev/null +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/sourcegen/SourcegenJavaSpec.groovy @@ -0,0 +1,75 @@ +package io.micronaut.starter.feature.sourcegen + +import io.micronaut.starter.ApplicationContextSpec +import io.micronaut.starter.BuildBuilder +import io.micronaut.starter.application.ApplicationType +import io.micronaut.starter.build.BuildTestUtil +import io.micronaut.starter.build.BuildTestVerifier +import io.micronaut.starter.build.dependencies.Scope +import io.micronaut.starter.feature.Category +import io.micronaut.starter.fixture.CommandOutputFixture +import io.micronaut.starter.options.BuildTool +import io.micronaut.starter.options.Language +import spock.lang.Shared + +class SourcegenJavaSpec extends ApplicationContextSpec implements CommandOutputFixture { + + @Shared + SourcegenJava sourcegenJava = beanContext.getBean(SourcegenJava) + + void 'test readme.md with feature sourcegen-generator contains links to micronaut docs'() { + when: + Map output = generate([SourcegenJava.NAME]) + String readme = output["README.md"] + + then: + readme + readme.contains("https://micronaut-projects.github.io/micronaut-sourcegen/latest/guide/") + } + + void "feature sourcegen-generator supports applicationType=#applicationType"(ApplicationType applicationType) { + expect: + sourcegenJava.supports(applicationType) + + where: + applicationType << ApplicationType.values() + } + + void "feature sourcegen-generator feature is API category"() { + expect: + sourcegenJava.category == Category.API + } + + void 'sourcegen-generator feature not supported for groovy'() { + when: + new BuildBuilder(beanContext, BuildTool.GRADLE) + .features([SourcegenJava.NAME]) + .language(Language.GROOVY) + .render() + + then: + IllegalArgumentException e = thrown() + e.message == 'sourcegen-generator is not supported in Groovy applications' + } + + + void "test dependencies are present for #buildTool and #language"(BuildTool buildTool, Language language) { + when: + String template = new BuildBuilder(beanContext, buildTool) + .features([SourcegenJava.NAME]) + .language(language) + .render() + BuildTestVerifier verifier = BuildTestUtil.verifier(buildTool, language, template) + + then: + verifier.hasDependency("io.micronaut.sourcegen", "micronaut-sourcegen-annotations", Scope.COMPILE) + if (language == Language.JAVA) { + assert verifier.hasAnnotationProcessor("io.micronaut.sourcegen", "micronaut-sourcegen-generator-java") + } else if (language == Language.KOTLIN) { + assert verifier.hasAnnotationProcessor("io.micronaut.sourcegen", "micronaut-sourcegen-generator-kotlin") + } + + where: + [buildTool, language] << [BuildTool.values(), [Language.JAVA, Language.KOTLIN]].combinations() + } +} diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/spring/SpringSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/spring/SpringSpec.groovy index 466947a7d20..91d828a1325 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/spring/SpringSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/spring/SpringSpec.groovy @@ -24,8 +24,8 @@ class SpringSpec extends ApplicationContextSpec implements CommandOutputFixture void 'test readme.md with feature spring contains links to micronaut docs'() { when: - def output = generate(['spring']) - def readme = output["README.md"] + Map output = generate(['spring']) + String readme = output["README.md"] then: readme diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/stackdriver/StackdriverSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/stackdriver/StackdriverSpec.groovy index 2935520e900..eef7dba18ec 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/stackdriver/StackdriverSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/stackdriver/StackdriverSpec.groovy @@ -7,8 +7,8 @@ class StackdriverSpec extends BeanContextSpec implements CommandOutputFixture { void 'test readme.md with feature gcp-cloud-trace contains links to micronaut docs'() { when: - def output = generate(['gcp-cloud-trace']) - def readme = output["README.md"] + Map output = generate(['gcp-cloud-trace']) + String readme = output["README.md"] then: readme diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/test/AssertJSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/test/AssertJSpec.groovy index 4971ed7ef3a..0694004e5a2 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/test/AssertJSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/test/AssertJSpec.groovy @@ -2,24 +2,31 @@ package io.micronaut.starter.feature.test import io.micronaut.starter.ApplicationContextSpec import io.micronaut.starter.BuildBuilder +import io.micronaut.starter.application.ApplicationType +import io.micronaut.starter.application.ContextFactory +import io.micronaut.starter.application.DefaultAvailableFeatures import io.micronaut.starter.feature.Category +import io.micronaut.starter.feature.FeatureContext import io.micronaut.starter.fixture.CommandOutputFixture +import io.micronaut.starter.io.ConsoleOutput import io.micronaut.starter.options.BuildTool +import io.micronaut.starter.options.JdkVersion import io.micronaut.starter.options.Language +import io.micronaut.starter.options.Options import io.micronaut.starter.options.TestFramework import spock.lang.Shared import spock.lang.Subject -import spock.lang.Unroll class AssertJSpec extends ApplicationContextSpec implements CommandOutputFixture { + @Shared @Subject AssertJ assertj = beanContext.getBean(AssertJ) void 'test readme.md with feature assertJ contains links to 3rd party docs'() { when: - def output = generate(['assertj']) - def readme = output["README.md"] + Map output = generate(['assertj']) + String readme = output["README.md"] then: readme @@ -31,7 +38,6 @@ class AssertJSpec extends ApplicationContextSpec implements CommandOutputFixture Category.DEV_TOOLS == assertj.category } - @Unroll void 'test gradle assertj feature for language=#language'() { when: String template = new BuildBuilder(beanContext, BuildTool.GRADLE) @@ -47,7 +53,31 @@ class AssertJSpec extends ApplicationContextSpec implements CommandOutputFixture language << Language.values().toList() } - @Unroll + void 'test gradle assertj succeeds for defaults as JUnit is automatically selected'() { + given: + ContextFactory contextFactory = beanContext.getBean(ContextFactory) + + when: + FeatureContext featureContext = contextFactory.createFeatureContext( + beanContext.getBean(DefaultAvailableFeatures), + ["assertj"], + ApplicationType.DEFAULT, + new Options(Language.JAVA, null, BuildTool.GRADLE_KOTLIN, JdkVersion.JDK_17), + null + ) + + then: + noExceptionThrown() + + when: + contextFactory.createGeneratorContext( + null, featureContext, ConsoleOutput.NOOP + ) + + then: + noExceptionThrown() + } + void 'test gradle assertj feature fails for language=#language when test framework is not Junit'() { when: new BuildBuilder(beanContext, BuildTool.GRADLE) @@ -70,7 +100,6 @@ class AssertJSpec extends ApplicationContextSpec implements CommandOutputFixture Language.GROOVY | TestFramework.KOTEST } - @Unroll void 'test maven assertj feature for language=#language'() { when: String template = new BuildBuilder(beanContext, BuildTool.MAVEN) diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/test/HamcrestSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/test/HamcrestSpec.groovy index 7c9064bc62e..9f6d39930ec 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/test/HamcrestSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/test/HamcrestSpec.groovy @@ -18,8 +18,8 @@ class HamcrestSpec extends ApplicationContextSpec implements CommandOutputFixtu void 'test readme.md with feature hamcrest contains links to 3rd party docs'() { when: - def output = generate(['hamcrest']) - def readme = output["README.md"] + Map output = generate(['hamcrest']) + String readme = output["README.md"] then: readme diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/test/LocalStackSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/test/LocalStackSpec.groovy index 266475c2df9..ff8c9d92aff 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/test/LocalStackSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/test/LocalStackSpec.groovy @@ -18,8 +18,8 @@ class LocalStackSpec extends ApplicationContextSpec implements CommandOutputFixt void 'test readme.md with feature localstack contains links to 3rd party docs'() { when: - def output = generate(['localstack']) - def readme = output["README.md"] + Map output = generate(['localstack']) + String readme = output["README.md"] then: readme diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/test/MicronautRestAssuredSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/test/MicronautRestAssuredSpec.groovy index 58a498221c4..681a00c4795 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/test/MicronautRestAssuredSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/test/MicronautRestAssuredSpec.groovy @@ -21,8 +21,8 @@ class MicronautRestAssuredSpec extends ApplicationContextSpec implements Command void 'test readme.md with feature micronaut-test-rest-assured contains links to docs'() { when: - def output = generate([FEATURE]) - def readme = output["README.md"] + Map output = generate([FEATURE]) + String readme = output["README.md"] then: readme diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/test/MockServerClientSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/test/MockServerClientSpec.groovy index 38d1b7d21b7..0cb0eea8f40 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/test/MockServerClientSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/test/MockServerClientSpec.groovy @@ -22,8 +22,8 @@ class MockServerClientSpec extends ApplicationContextSpec implements CommandOutp void 'test readme.md with feature MockServerClient contains links to 3rd party docs'() { when: - def output = generate([MockServerClient.NAME]) - def readme = output["README.md"] + Map output = generate([MockServerClient.NAME]) + String readme = output["README.md"] then: readme diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/test/MockitoSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/test/MockitoSpec.groovy index 2d8cc145237..d860b96fa05 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/test/MockitoSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/test/MockitoSpec.groovy @@ -18,8 +18,8 @@ class MockitoSpec extends ApplicationContextSpec implements CommandOutputFixture void 'test readme.md with feature mockito contains links to 3rd party docs'() { when: - def output = generate(['mockito']) - def readme = output["README.md"] + Map output = generate(['mockito']) + String readme = output["README.md"] then: readme diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/testresources/DbTypeSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/testresources/DbTypeSpec.groovy index 3f10ac0bdde..b69be1c6fea 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/testresources/DbTypeSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/testresources/DbTypeSpec.groovy @@ -14,6 +14,6 @@ class DbTypeSpec extends Specification { 'mysql' | DbType.MYSQL 'mariadb' | DbType.MARIADB 'mssql' | DbType.SQLSERVER - 'oracle' | DbType.ORACLEXE + 'oracle' | DbType.ORACLEFREE } } diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/validator/HibernateValidatorSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/validator/HibernateValidatorSpec.groovy index 8e9a3f02010..49d73586ee1 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/validator/HibernateValidatorSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/validator/HibernateValidatorSpec.groovy @@ -7,8 +7,8 @@ class HibernateValidatorSpec extends BeanContextSpec implements CommandOutputFi void 'test readme.md contains links to micronaut docs'() { when: - def output = generate(['hibernate-validator']) - def readme = output["README.md"] + Map output = generate(['hibernate-validator']) + String readme = output["README.md"] then: readme diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/view/FreemarkerSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/view/FreemarkerSpec.groovy index 94fc4f9848b..cf5bb753531 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/view/FreemarkerSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/view/FreemarkerSpec.groovy @@ -11,8 +11,8 @@ class FreemarkerSpec extends ApplicationContextSpec implements CommandOutputFixt void 'test readme.md with feature views-freemarker contains links to micronaut docs'() { when: - def output = generate(['views-freemarker']) - def readme = output["README.md"] + Map output = generate(['views-freemarker']) + String readme = output["README.md"] then: readme diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/view/HandlebarsSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/view/HandlebarsSpec.groovy index 59d8b3c0383..403cbc7cbb0 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/view/HandlebarsSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/view/HandlebarsSpec.groovy @@ -11,8 +11,8 @@ class HandlebarsSpec extends ApplicationContextSpec implements CommandOutputFix void 'test readme.md with feature views-handlebars contains links to micronaut docs'() { when: - def output = generate(['views-handlebars']) - def readme = output["README.md"] + Map output = generate(['views-handlebars']) + String readme = output["README.md"] then: readme diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/view/JTESpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/view/JTESpec.groovy index b02cde5c26a..8c5519224cf 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/view/JTESpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/view/JTESpec.groovy @@ -12,8 +12,8 @@ class JTESpec extends ApplicationContextSpec implements CommandOutputFixture { void 'test readme.md with feature views-jte contains links to micronaut docs'() { when: - def output = generate(['views-jte']) - def readme = output["README.md"] + Map output = generate(['views-jte']) + String readme = output["README.md"] then: readme diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/view/PebbleSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/view/PebbleSpec.groovy index 2c1b6b28cc3..04a3f9ff720 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/view/PebbleSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/view/PebbleSpec.groovy @@ -11,8 +11,8 @@ class PebbleSpec extends ApplicationContextSpec implements CommandOutputFixture void 'test readme.md with feature views-pebble contains links to micronaut docs'() { when: - def output = generate(['views-pebble']) - def readme = output["README.md"] + Map output = generate(['views-pebble']) + String readme = output["README.md"] then: readme diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/view/RockerSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/view/RockerSpec.groovy index 60076158820..e6321394dc1 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/view/RockerSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/view/RockerSpec.groovy @@ -3,6 +3,7 @@ package io.micronaut.starter.feature.view import io.micronaut.core.version.SemanticVersion import io.micronaut.starter.ApplicationContextSpec import io.micronaut.starter.BuildBuilder +import io.micronaut.starter.build.dependencies.StarterCoordinates import io.micronaut.starter.fixture.CommandOutputFixture import io.micronaut.starter.options.BuildTool import io.micronaut.starter.options.Language @@ -11,8 +12,8 @@ class RockerSpec extends ApplicationContextSpec implements CommandOutputFixture void 'test readme.md with feature views-rocker contains links to micronaut docs'() { when: - def output = generate(['views-rocker']) - def readme = output["README.md"] + Map output = generate(['views-rocker']) + String readme = output["README.md"] then: readme @@ -77,7 +78,7 @@ rocker { com.fizzed rocker-maven-plugin - 1.3.0 + ${StarterCoordinates.ROCKER_MAVEN_PLUGIN.version} generate-rocker-templates diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/view/SoySpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/view/SoySpec.groovy index eab32fc58ab..98fbbc7e103 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/view/SoySpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/view/SoySpec.groovy @@ -11,8 +11,8 @@ class SoySpec extends ApplicationContextSpec implements CommandOutputFixture { void 'test readme.md with feature views-soy contains links to micronaut docs'() { when: - def output = generate(['views-soy']) - def readme = output["README.md"] + Map output = generate(['views-soy']) + String readme = output["README.md"] then: readme diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/view/VelocitySpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/view/VelocitySpec.groovy index a6cd95deb9b..843e0dcb5e0 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/view/VelocitySpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/view/VelocitySpec.groovy @@ -14,8 +14,8 @@ class VelocitySpec extends ApplicationContextSpec implements CommandOutputFixtur void 'test readme.md with feature views-velocity contains links to micronaut docs'() { when: - def output = generate(['views-velocity']) - def readme = output["README.md"] + Map output = generate(['views-velocity']) + String readme = output["README.md"] then: readme diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/view/ViewsFieldsetTckSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/view/ViewsFieldsetTckSpec.groovy index 16e8aa88eef..8107f331a17 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/view/ViewsFieldsetTckSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/view/ViewsFieldsetTckSpec.groovy @@ -7,13 +7,10 @@ import io.micronaut.starter.build.BuildTestUtil import io.micronaut.starter.build.BuildTestVerifier import io.micronaut.starter.build.dependencies.Scope import io.micronaut.starter.feature.Category -import io.micronaut.starter.feature.function.awslambda.AwsLambda import io.micronaut.starter.fixture.CommandOutputFixture import io.micronaut.starter.options.BuildTool import io.micronaut.starter.options.Language -import io.micronaut.starter.options.Options import spock.lang.Subject -import spock.lang.Unroll class ViewsFieldsetTckSpec extends ApplicationContextSpec implements CommandOutputFixture { @@ -46,18 +43,21 @@ class ViewsFieldsetTckSpec extends ApplicationContextSpec implements CommandOutp applicationType << ApplicationType.values() - ApplicationType.DEFAULT } - @Unroll void 'test #buildTool views-fieldsets feature for language=#language'(Language language, BuildTool buildTool) { when: String template = new BuildBuilder(beanContext, buildTool) .language(language) - .features(['views-fieldset-tck']) + .features([ViewsFieldsetTck.NAME]) .render() BuildTestVerifier verifier = BuildTestUtil.verifier(buildTool, language, template) then: verifier.hasDependency("io.micronaut.views", "micronaut-views-fieldset-tck", Scope.TEST) - verifier.hasDependency("org.junit.platform", "junit-platform-suite-engine", Scope.TEST) + + and: + if (language != Language.GROOVY) { + assert verifier.hasDependency("org.junit.platform", "junit-platform-suite-engine", Scope.TEST) + } where: [language, buildTool] << [Language.values(), BuildTool.values()].combinations() @@ -65,7 +65,7 @@ class ViewsFieldsetTckSpec extends ApplicationContextSpec implements CommandOutp void 'ThymeleafSuite test is generated views-fieldset-tck'() { when: - Map output = generate(['views-fieldset-tck']) + Map output = generate([ViewsFieldsetTck.NAME]) then: output.containsKey("${Language.DEFAULT_OPTION.testSrcDir}/example/micronaut/ThymeleafSuite.$Language.DEFAULT_OPTION.extension".toString()) diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/websocket/WebsocketSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/websocket/WebsocketSpec.groovy index ed9874cad42..dcb33823488 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/websocket/WebsocketSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/websocket/WebsocketSpec.groovy @@ -20,8 +20,8 @@ class WebsocketSpec extends ApplicationContextSpec implements CommandOutputFixtu void 'test readme.md with feature websocket contains links to micronaut docs'() { when: - def output = generate([Websocket.NAME]) - def readme = output["README.md"] + Map output = generate([Websocket.NAME]) + String readme = output["README.md"] then: readme diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/xml/JacksonXmlSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/xml/JacksonXmlSpec.groovy index 56a3930e844..b634cefb61b 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/feature/xml/JacksonXmlSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/xml/JacksonXmlSpec.groovy @@ -11,8 +11,8 @@ class JacksonXmlSpec extends ApplicationContextSpec implements CommandOutputFix void 'test readme.md with feature jackson-xml contains links to micronaut docs'() { when: - def output = generate(['jackson-xml']) - def readme = output["README.md"] + Map output = generate(['jackson-xml']) + String readme = output["README.md"] then: readme diff --git a/starter-core/src/test/groovy/io/micronaut/starter/options/JdkVersionSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/options/JdkVersionSpec.groovy index 89b747d6a11..6fbe3c5e974 100644 --- a/starter-core/src/test/groovy/io/micronaut/starter/options/JdkVersionSpec.groovy +++ b/starter-core/src/test/groovy/io/micronaut/starter/options/JdkVersionSpec.groovy @@ -4,11 +4,16 @@ import spock.lang.Specification class JdkVersionSpec extends Specification { - void 'test valueOf with a supported JDK version'() { + void 'test valueOf(Integer) with a supported JDK version'() { expect: JdkVersion.JDK_17 == JdkVersion.valueOf(17) } + void 'test valueOf(String) with a supported JDK version'() { + expect: + JdkVersion.JDK_17 == JdkVersion.valueOf("JDK_17") + } + void 'test valueOf when the JDK version does not exist'() { when: JdkVersion.valueOf(3) diff --git a/starter-core/src/test/resources/expected-aot-jar.properties b/starter-core/src/test/resources/expected-aot-jar.properties index c8651fe266d..a8be2bd5b7b 100644 --- a/starter-core/src/test/resources/expected-aot-jar.properties +++ b/starter-core/src/test/resources/expected-aot-jar.properties @@ -8,6 +8,9 @@ cached.environment.enabled=true # Precomputes Micronaut configuration property keys from the current environment variables precompute.environment.properties.enabled=true +# Replaces logback.xml with a pure Java configuration +logback.xml.to.java.enabled=true + # Converts YAML configuration files to Java configuration yaml.to.java.config.enabled=true diff --git a/starter-core/src/test/resources/expected-aot-native-image.properties b/starter-core/src/test/resources/expected-aot-native-image.properties index 16ff726f563..71883d2ba68 100644 --- a/starter-core/src/test/resources/expected-aot-native-image.properties +++ b/starter-core/src/test/resources/expected-aot-native-image.properties @@ -8,6 +8,9 @@ cached.environment.enabled=true # Precomputes Micronaut configuration property keys from the current environment variables precompute.environment.properties.enabled=true +# Replaces logback.xml with a pure Java configuration +logback.xml.to.java.enabled=true + # Converts YAML configuration files to Java configuration yaml.to.java.config.enabled=false diff --git a/starter-gcp-function/build.gradle b/starter-gcp-function/build.gradle index 50988a59976..836e6bb8c6f 100644 --- a/starter-gcp-function/build.gradle +++ b/starter-gcp-function/build.gradle @@ -11,22 +11,29 @@ configurations { } dependencies { - implementation project(":starter-api") - implementation "io.micronaut:micronaut-inject" - implementation "io.micronaut.gcp:micronaut-gcp-function-http" + annotationProcessor("io.micronaut.serde:micronaut-serde-processor") + compileOnly("com.google.cloud.functions:functions-framework-api") + + implementation(project(":starter-api")) + implementation("io.micronaut:micronaut-inject") + implementation("io.micronaut.gcp:micronaut-gcp-function-http") + implementation("io.micronaut.serde:micronaut-serde-jackson") + developmentOnly(platform("io.micronaut.platform:micronaut-platform:$micronautVersion")) developmentOnly("com.google.cloud.functions:functions-framework-api") + runtimeOnly("ch.qos.logback:logback-classic") - testCompileOnly "io.micronaut:micronaut-inject-groovy" + + testCompileOnly("io.micronaut:micronaut-inject-groovy") + testImplementation("com.google.cloud.functions:functions-framework-api") - testImplementation "io.micronaut.test:micronaut-test-spock" + testImplementation("io.micronaut.test:micronaut-test-spock") + testRuntimeOnly("io.micronaut.serde:micronaut-serde-jackson") - invoker 'com.google.cloud.functions.invoker:java-function-invoker:1.3.1' - annotationProcessor("io.micronaut.serde:micronaut-serde-processor") - implementation("io.micronaut.serde:micronaut-serde-jackson") + invoker 'com.google.cloud.functions.invoker:java-function-invoker:1.3.1' } tasks.named("test", Test) { diff --git a/starter-web-netty/build.gradle b/starter-web-netty/build.gradle index ba4f361f888..62a24f3c1fc 100644 --- a/starter-web-netty/build.gradle +++ b/starter-web-netty/build.gradle @@ -12,17 +12,21 @@ micronaut { } dependencies { - implementation project(":starter-api") - implementation "io.micronaut.gcp:micronaut-gcp-http-client" - runtimeOnly "ch.qos.logback:logback-classic" - implementation "io.micronaut.crac:micronaut-crac" annotationProcessor("io.micronaut.serde:micronaut-serde-processor") + + implementation(project(":starter-api")) + implementation("io.micronaut.gcp:micronaut-gcp-http-client") + implementation("io.micronaut.crac:micronaut-crac") implementation("io.micronaut.serde:micronaut-serde-jackson") - testCompileOnly "io.micronaut:micronaut-inject-groovy" - testImplementation "io.micronaut.test:micronaut-test-spock" - testImplementation "io.micronaut:micronaut-http-client" + runtimeOnly("ch.qos.logback:logback-classic") + + testCompileOnly("io.micronaut:micronaut-inject-groovy") + + testImplementation("io.micronaut.test:micronaut-test-spock") + testImplementation("io.micronaut:micronaut-http-client") + testRuntimeOnly("io.micronaut.serde:micronaut-serde-jackson") } diff --git a/starter-web-netty/src/test/groovy/io/micronaut/starter/netty/JdkVersionSpec.groovy b/starter-web-netty/src/test/groovy/io/micronaut/starter/netty/JdkVersionSpec.groovy new file mode 100644 index 00000000000..0cb0d5e6929 --- /dev/null +++ b/starter-web-netty/src/test/groovy/io/micronaut/starter/netty/JdkVersionSpec.groovy @@ -0,0 +1,40 @@ +package io.micronaut.starter.netty + +import io.micronaut.json.JsonMapper +import io.micronaut.serde.annotation.Serdeable +import io.micronaut.starter.options.JdkVersion +import io.micronaut.starter.options.MicronautJdkVersionConfiguration +import io.micronaut.test.extensions.spock.annotation.MicronautTest +import jakarta.inject.Inject +import spock.lang.Specification + +@MicronautTest +class JdkVersionSpec extends Specification { + @Inject + JsonMapper jsonMapper + + void "Serialize and deserialize JdkVersion with jdk=#jdkVersion"(JdkVersion jdkVersion) { + given: + int jdk = jdkVersion.majorVersion() + + when: + String json = jsonMapper.writeValueAsString(new Foo(jdk: jdkVersion)) + + then: + json.contains("{\"jdk\":\"JDK_${jdk}\"}") + + when: + Foo foo = jsonMapper.readValue("{\"jdk\":\"JDK_${jdk}\"}", Foo.class) + + then: + jdkVersion == foo.jdk + + where: + jdkVersion << MicronautJdkVersionConfiguration.SUPPORTED_JDKS + } + + @Serdeable + static class Foo { + JdkVersion jdk + } +} diff --git a/starter-web-netty/src/test/groovy/io/micronaut/starter/netty/ReportAnalyticsNoApiKeySpec.groovy b/starter-web-netty/src/test/groovy/io/micronaut/starter/netty/ReportAnalyticsNoApiKeySpec.groovy index a9babd7fd2f..9871d1fc837 100644 --- a/starter-web-netty/src/test/groovy/io/micronaut/starter/netty/ReportAnalyticsNoApiKeySpec.groovy +++ b/starter-web-netty/src/test/groovy/io/micronaut/starter/netty/ReportAnalyticsNoApiKeySpec.groovy @@ -18,7 +18,7 @@ class ReportAnalyticsNoApiKeySpec extends Specification { void "test report analytics with no analytics api key configured"() { when: "no analytics api key is configured" - client.createApp("test", Collections.emptyList(), BuildTool.GRADLE, null, null) + client.createApp("test", Collections.emptyList(), BuildTool.GRADLE, null, null, null) then: "create endpoint completes successfully (analytics are not invoked)" noExceptionThrown() diff --git a/starter-web-netty/src/test/groovy/io/micronaut/starter/netty/ReportAnalyticsSpec.groovy b/starter-web-netty/src/test/groovy/io/micronaut/starter/netty/ReportAnalyticsSpec.groovy index 27d13a40560..b40f51980e4 100644 --- a/starter-web-netty/src/test/groovy/io/micronaut/starter/netty/ReportAnalyticsSpec.groovy +++ b/starter-web-netty/src/test/groovy/io/micronaut/starter/netty/ReportAnalyticsSpec.groovy @@ -57,7 +57,7 @@ class ReportAnalyticsSpec extends Specification { void "test report analytics"() { when: - client.createApp("test", Collections.emptyList(), BuildTool.MAVEN, null, null) + client.createApp("test", Collections.emptyList(), BuildTool.MAVEN, null, null, null) PollingConditions conditions = new PollingConditions() then: diff --git a/starter-web-netty/src/test/groovy/io/micronaut/starter/netty/ReportAnalyticsWrongApiKeySpec.groovy b/starter-web-netty/src/test/groovy/io/micronaut/starter/netty/ReportAnalyticsWrongApiKeySpec.groovy index 264fb10c4d3..9bdb6e041c4 100644 --- a/starter-web-netty/src/test/groovy/io/micronaut/starter/netty/ReportAnalyticsWrongApiKeySpec.groovy +++ b/starter-web-netty/src/test/groovy/io/micronaut/starter/netty/ReportAnalyticsWrongApiKeySpec.groovy @@ -30,7 +30,7 @@ class ReportAnalyticsWrongApiKeySpec extends Specification { when: "the wrong analytics api key is configured" UnauthorizedAnalyticsController controller = starterAnalytics.applicationContext.getBean(UnauthorizedAnalyticsController) - client.createApp("test", Collections.emptyList(), BuildTool.GRADLE_KOTLIN, null, null) + client.createApp("test", Collections.emptyList(), BuildTool.GRADLE_KOTLIN, null, null, null) PollingConditions conditions = new PollingConditions() then: "analytics endpoint is hit and comes back as UNAUTHORIZED" diff --git a/starter-web-netty/src/test/groovy/io/micronaut/starter/netty/ZipCreateControllerSpec.groovy b/starter-web-netty/src/test/groovy/io/micronaut/starter/netty/ZipCreateControllerSpec.groovy index 237e4d503f4..1697b71e74e 100644 --- a/starter-web-netty/src/test/groovy/io/micronaut/starter/netty/ZipCreateControllerSpec.groovy +++ b/starter-web-netty/src/test/groovy/io/micronaut/starter/netty/ZipCreateControllerSpec.groovy @@ -9,7 +9,9 @@ import io.micronaut.http.client.HttpClient import io.micronaut.http.client.annotation.Client import io.micronaut.http.client.exceptions.HttpClientResponseException import io.micronaut.starter.options.BuildTool +import io.micronaut.starter.options.JdkVersion import io.micronaut.starter.options.Language +import io.micronaut.starter.options.MicronautJdkVersionConfiguration import io.micronaut.starter.options.TestFramework import io.micronaut.starter.util.ZipUtil import io.micronaut.test.extensions.spock.annotation.MicronautTest @@ -74,7 +76,7 @@ class ZipCreateControllerSpec extends Specification { void "test default create app command"() { when: - def bytes = client.createApp("test", Collections.emptyList(), null, null, null) + def bytes = client.createApp("test", Collections.emptyList(), null, null, null, null) then: ZipUtil.isZip(bytes) @@ -83,7 +85,7 @@ class ZipCreateControllerSpec extends Specification { void "test default create app with feature"() { when: - def bytes = client.createApp("test", ['graalvm'], null, null, null) + def bytes = client.createApp("test", ['graalvm'], null, null, null, null) then: ZipUtil.containsFile(bytes, "build.gradle.kts") @@ -92,7 +94,7 @@ class ZipCreateControllerSpec extends Specification { void "test create app with kotlin"() { when: - def bytes = client.createApp("test", ['graalvm'], null, null, Language.KOTLIN) + def bytes = client.createApp("test", ['graalvm'], null, null, Language.KOTLIN, null) then: ZipUtil.containsFile(bytes, "Application.kt") @@ -100,7 +102,7 @@ class ZipCreateControllerSpec extends Specification { void "test create app with groovy"() { when: - def bytes = client.createApp("test", ['flyway'], null, null, Language.GROOVY) + def bytes = client.createApp("test", ['flyway'], null, null, Language.GROOVY, null) then: ZipUtil.containsFile(bytes, "Application.groovy") @@ -108,7 +110,7 @@ class ZipCreateControllerSpec extends Specification { void "test create app with maven"() { when: - def bytes = client.createApp("test", ['flyway'], BuildTool.MAVEN, null, Language.GROOVY) + def bytes = client.createApp("test", ['flyway'], BuildTool.MAVEN, null, Language.GROOVY, null) then: ZipUtil.containsFile(bytes, "pom.xml") @@ -116,21 +118,36 @@ class ZipCreateControllerSpec extends Specification { void "test create app with spock"() { when: - def bytes = client.createApp("test", ['flyway'], BuildTool.GRADLE, TestFramework.SPOCK, Language.GROOVY) + def bytes = client.createApp("test", ['flyway'], BuildTool.GRADLE, TestFramework.SPOCK, Language.GROOVY, null) then: ZipUtil.containsFileWithContents(bytes, "build.gradle", "spock") } + @Issue("https://github.com/micronaut-projects/micronaut-starter/issues/2321") + void "test create app with jdk=#jdkVersion"(JdkVersion jdkVersion) { + when: + def bytes = client.createApp("test", ['flyway'], BuildTool.GRADLE_KOTLIN, TestFramework.JUNIT, Language.JAVA, jdkVersion) + int jdk = jdkVersion.majorVersion + + then: + ZipUtil.containsFileWithContents(bytes, "build.gradle.kts", "sourceCompatibility = JavaVersion.toVersion(\"${jdk}\")") + ZipUtil.containsFileWithContents(bytes, "build.gradle.kts", "targetCompatibility = JavaVersion.toVersion(\"${jdk}\")") + + where: + jdkVersion << MicronautJdkVersionConfiguration.SUPPORTED_JDKS + } + @Client('/create') static interface CreateClient { - @Get(uri = "/default/{name}{?features,build,test,lang}", consumes = "application/zip") + @Get(uri = "/default/{name}{?features,build,test,lang,javaVersion}", consumes = "application/zip") byte[] createApp( String name, @Nullable List features, @Nullable BuildTool build, @Nullable TestFramework test, - @Nullable Language lang + @Nullable Language lang, + @Nullable JdkVersion javaVersion ); } } diff --git a/starter-web-servlet/README.md b/starter-web-servlet/README.md index e605a87d38a..fded4ba9d5f 100644 --- a/starter-web-servlet/README.md +++ b/starter-web-servlet/README.md @@ -16,6 +16,14 @@ Or with RapiDoc: http://localhost:8080/swagger/views/rapidoc +Or with ReDoc: + +http://localhost:8080/swagger/views/redoc + +Or with OpenAPI Explorer: + +http://localhost:8080/swagger/views/openapi-explorer + ## Deployment You can build the WAR file with: @@ -24,4 +32,4 @@ You can build the WAR file with: ./gradlew clean starter-web-servlet:assemble ``` -The WAR file will be located in `starter-web-servlet/build/libs` and can be deployed to any modern Servlet container (example Jetty 9 or Tomcat 9). \ No newline at end of file +The WAR file will be located in `starter-web-servlet/build/libs` and can be deployed to any modern Servlet container (example Jetty 9 or Tomcat 9). diff --git a/starter-web-servlet/build.gradle b/starter-web-servlet/build.gradle index 90d723594f0..5ea5e226140 100644 --- a/starter-web-servlet/build.gradle +++ b/starter-web-servlet/build.gradle @@ -11,19 +11,21 @@ configurations { } dependencies { - developmentOnly platform("io.micronaut.platform:micronaut-platform:$micronautVersion") - implementation project(":starter-api") - implementation "io.micronaut:micronaut-inject" + developmentOnly(platform("io.micronaut.platform:micronaut-platform:$micronautVersion")) + developmentOnly("io.micronaut.servlet:micronaut-http-server-jetty") + implementation(project(":starter-api")) + implementation("io.micronaut:micronaut-inject") implementation("io.micronaut.servlet:micronaut-servlet-engine") implementation("io.micronaut:micronaut-jackson-databind") - developmentOnly "io.micronaut.servlet:micronaut-http-server-jetty" - runtimeOnly "ch.qos.logback:logback-classic" - testImplementation "io.micronaut.servlet:micronaut-http-server-jetty" - testCompileOnly "io.micronaut:micronaut-inject-groovy" - testImplementation "io.micronaut.test:micronaut-test-spock" - testImplementation "io.micronaut:micronaut-http-client" + runtimeOnly("ch.qos.logback:logback-classic") + + testCompileOnly("io.micronaut:micronaut-inject-groovy") + + testImplementation("io.micronaut.servlet:micronaut-http-server-jetty") + testImplementation("io.micronaut.test:micronaut-test-spock") + testImplementation("io.micronaut:micronaut-http-client") } tasks.named("test", Test) { diff --git a/starter-web-servlet/src/main/resources/application.properties b/starter-web-servlet/src/main/resources/application.properties index a5b0eb60175..1ac6a99ae83 100644 --- a/starter-web-servlet/src/main/resources/application.properties +++ b/starter-web-servlet/src/main/resources/application.properties @@ -3,4 +3,8 @@ micronaut.router.static-resources.swagger.mapping=/swagger/** micronaut.router.static-resources.swagger-ui.paths=classpath:META-INF/swagger/views/swagger-ui micronaut.router.static-resources.swagger-ui.mapping=/swagger-ui/** micronaut.router.static-resources.rapidoc.paths=classpath:META-INF/swagger/views/rapidoc -micronaut.router.static-resources.rapidoc.mapping=/rapidoc/** \ No newline at end of file +micronaut.router.static-resources.rapidoc.mapping=/rapidoc/** +micronaut.router.static-resources.redoc.paths=classpath:META-INF/swagger/views/redoc +micronaut.router.static-resources.redoc.mapping=/redoc/** +micronaut.router.static-resources.openapi-explorer.paths=classpath:META-INF/swagger/views/openapi-explorer +micronaut.router.static-resources.openapi-explorer.mapping=/openapi-explorer/** diff --git a/starter-web-servlet/src/test/groovy/io/micronaut/starter/servlet/ZipCreateControllerSpec.groovy b/starter-web-servlet/src/test/groovy/io/micronaut/starter/servlet/ZipCreateControllerSpec.groovy index 2fd1bffa79c..a6e7d559ed5 100644 --- a/starter-web-servlet/src/test/groovy/io/micronaut/starter/servlet/ZipCreateControllerSpec.groovy +++ b/starter-web-servlet/src/test/groovy/io/micronaut/starter/servlet/ZipCreateControllerSpec.groovy @@ -4,10 +4,13 @@ import io.micronaut.core.annotation.Nullable import io.micronaut.http.annotation.Get import io.micronaut.http.client.annotation.Client import io.micronaut.starter.options.BuildTool +import io.micronaut.starter.options.JdkVersion import io.micronaut.starter.options.Language +import io.micronaut.starter.options.MicronautJdkVersionConfiguration import io.micronaut.starter.options.TestFramework import io.micronaut.starter.util.ZipUtil import io.micronaut.test.extensions.spock.annotation.MicronautTest +import spock.lang.Issue import spock.lang.Specification import jakarta.inject.Inject @@ -20,7 +23,7 @@ class ZipCreateControllerSpec extends Specification { void "test default create app command"() { when: - def bytes = client.createApp("test", Collections.emptyList(), null, null, null) + def bytes = client.createApp("test", Collections.emptyList(), null, null, null, null) then: ZipUtil.isZip(bytes) @@ -28,7 +31,7 @@ class ZipCreateControllerSpec extends Specification { void "test default create app with feature"() { when: - def bytes = client.createApp("test", ['graalvm'], null, null, null) + def bytes = client.createApp("test", ['graalvm'], null, null, null, null) then: ZipUtil.containsFile(bytes, "build.gradle.kts") @@ -37,7 +40,7 @@ class ZipCreateControllerSpec extends Specification { void "test create app with kotlin"() { when: - def bytes = client.createApp("test", ['graalvm'], null, null, Language.KOTLIN) + def bytes = client.createApp("test", ['graalvm'], null, null, Language.KOTLIN, null) then: ZipUtil.containsFile(bytes, "Application.kt") @@ -45,7 +48,7 @@ class ZipCreateControllerSpec extends Specification { void "test create app with groovy"() { when: - def bytes = client.createApp("test", ['flyway'], null, null, Language.GROOVY) + def bytes = client.createApp("test", ['flyway'], null, null, Language.GROOVY, null) then: ZipUtil.containsFile(bytes, "Application.groovy") @@ -53,7 +56,7 @@ class ZipCreateControllerSpec extends Specification { void "test create app with maven"() { when: - def bytes = client.createApp("test", ['flyway'], BuildTool.MAVEN, null, Language.GROOVY) + def bytes = client.createApp("test", ['flyway'], BuildTool.MAVEN, null, Language.GROOVY, null) then: ZipUtil.containsFile(bytes, "pom.xml") @@ -61,21 +64,36 @@ class ZipCreateControllerSpec extends Specification { void "test create app with spock"() { when: - def bytes = client.createApp("test", ['flyway'], BuildTool.GRADLE, TestFramework.SPOCK, Language.GROOVY) + def bytes = client.createApp("test", ['flyway'], BuildTool.GRADLE, TestFramework.SPOCK, Language.GROOVY, null) then: ZipUtil.containsFileWithContents(bytes, "build.gradle", "spock") } + @Issue("https://github.com/micronaut-projects/micronaut-starter/issues/2321") + void "test create app with jdk=#jdkVersion"(JdkVersion jdkVersion) { + when: + def bytes = client.createApp("test", ['flyway'], BuildTool.GRADLE_KOTLIN, TestFramework.JUNIT, Language.JAVA, jdkVersion) + int jdk = jdkVersion.majorVersion + + then: + ZipUtil.containsFileWithContents(bytes, "build.gradle.kts", "sourceCompatibility = JavaVersion.toVersion(\"${jdk}\")") + ZipUtil.containsFileWithContents(bytes, "build.gradle.kts", "targetCompatibility = JavaVersion.toVersion(\"${jdk}\")") + + where: + jdkVersion << MicronautJdkVersionConfiguration.SUPPORTED_JDKS + } + @Client('/create') static interface CreateClient { - @Get(uri = "/default/{name}{?features,build,test,lang}", consumes = "application/zip") + @Get(uri = "/default/{name}{?features,build,test,lang,javaVersion}", consumes = "application/zip") byte[] createApp( String name, @Nullable List features, @Nullable BuildTool build, @Nullable TestFramework test, - @Nullable Language lang + @Nullable Language lang, + @Nullable JdkVersion javaVersion ); } } diff --git a/test-aws/build.gradle b/test-aws/build.gradle index d04176d1ea3..5c15babfbef 100644 --- a/test-aws/build.gradle +++ b/test-aws/build.gradle @@ -3,7 +3,7 @@ plugins { } dependencies { - testImplementation project(":test-utils") - testImplementation project(":starter-core") + testImplementation(project(":test-utils")) + testImplementation(project(":starter-core")) testImplementation("ch.qos.logback:logback-classic") } diff --git a/test-buildtool/build.gradle b/test-buildtool/build.gradle index d04176d1ea3..5c15babfbef 100644 --- a/test-buildtool/build.gradle +++ b/test-buildtool/build.gradle @@ -3,7 +3,7 @@ plugins { } dependencies { - testImplementation project(":test-utils") - testImplementation project(":starter-core") + testImplementation(project(":test-utils")) + testImplementation(project(":starter-core")) testImplementation("ch.qos.logback:logback-classic") } diff --git a/test-cli/build.gradle b/test-cli/build.gradle index a7be44cdb34..236f9ac0749 100644 --- a/test-cli/build.gradle +++ b/test-cli/build.gradle @@ -3,7 +3,7 @@ plugins { } dependencies { - testImplementation project(":test-utils") - testImplementation project(":micronaut-cli") + testImplementation(project(":test-utils")) + testImplementation(project(":micronaut-cli")) testImplementation("ch.qos.logback:logback-classic") } diff --git a/test-cloud/build.gradle b/test-cloud/build.gradle index d04176d1ea3..5c15babfbef 100644 --- a/test-cloud/build.gradle +++ b/test-cloud/build.gradle @@ -3,7 +3,7 @@ plugins { } dependencies { - testImplementation project(":test-utils") - testImplementation project(":starter-core") + testImplementation(project(":test-utils")) + testImplementation(project(":starter-core")) testImplementation("ch.qos.logback:logback-classic") } diff --git a/test-cloud/src/test/groovy/io/micronaut/starter/core/test/cloud/aws/TracingOpentelemetryXrayIntegrationSpec.groovy b/test-cloud/src/test/groovy/io/micronaut/starter/core/test/cloud/aws/TracingOpentelemetryXrayIntegrationSpec.groovy new file mode 100644 index 00000000000..6c3ef97bb8c --- /dev/null +++ b/test-cloud/src/test/groovy/io/micronaut/starter/core/test/cloud/aws/TracingOpentelemetryXrayIntegrationSpec.groovy @@ -0,0 +1,33 @@ +package io.micronaut.starter.core.test.cloud.aws + +import io.micronaut.starter.application.ApplicationType +import io.micronaut.starter.feature.opentelemetry.OpenTelemetryXray +import io.micronaut.starter.options.BuildTool +import io.micronaut.starter.options.Language +import io.micronaut.starter.options.TestFramework +import io.micronaut.starter.test.CommandSpec + +class TracingOpentelemetryXrayIntegrationSpec extends CommandSpec { + + @Override + String getTempDirectoryPrefix() { + "tracing-opentelemetry-xray-function" + } + + void 'App with tracing-opentelemetry-xray features builds successfully'() { + given: + ApplicationType applicationType = ApplicationType.DEFAULT + Language lang = Language.JAVA + BuildTool build = BuildTool.GRADLE_KOTLIN + TestFramework testFramework = TestFramework.JUNIT + + List features = [OpenTelemetryXray.NAME] + generateProject(lang, build, features, applicationType, testFramework) + + when: + String output = executeBuild(build, "test") + + then: + output.contains("BUILD SUCCESS") + } +} diff --git a/test-cloud/src/test/groovy/io/micronaut/starter/core/test/cloud/oracecloud/CreateOracleFunctionSpec.groovy b/test-cloud/src/test/groovy/io/micronaut/starter/core/test/cloud/oracecloud/CreateOracleFunctionSpec.groovy index 41a19bdf71e..59dfad008da 100644 --- a/test-cloud/src/test/groovy/io/micronaut/starter/core/test/cloud/oracecloud/CreateOracleFunctionSpec.groovy +++ b/test-cloud/src/test/groovy/io/micronaut/starter/core/test/cloud/oracecloud/CreateOracleFunctionSpec.groovy @@ -1,12 +1,21 @@ package io.micronaut.starter.core.test.cloud.oracecloud import io.micronaut.starter.application.ApplicationType +import io.micronaut.starter.application.OperatingSystem +import io.micronaut.starter.application.generator.ProjectGenerator +import io.micronaut.starter.io.ConsoleOutput +import io.micronaut.starter.io.FileSystemOutputHandler import io.micronaut.starter.options.BuildTool +import io.micronaut.starter.options.JdkVersion import io.micronaut.starter.options.Language +import io.micronaut.starter.options.MicronautJdkVersionConfiguration +import io.micronaut.starter.options.Options import io.micronaut.starter.options.TestFramework import io.micronaut.starter.test.ApplicationTypeCombinations import io.micronaut.starter.test.BuildToolCombinations import io.micronaut.starter.test.CommandSpec +import io.micronaut.starter.util.NameUtils +import io.micronaut.starter.util.VersionInfo import spock.lang.Retry @Retry // can fail on CI due to port binding race condition, so retry @@ -34,6 +43,34 @@ class CreateOracleFunctionSpec extends CommandSpec{ [applicationType, lang, build, testFramework] << ApplicationTypeCombinations.combinations([ApplicationType.DEFAULT], Language.values() as List, BuildTool.valuesGradle()) } + void 'create-#applicationType with features oracle-function and "-" in the app name #lang and #build and test framework: #testFramework'(ApplicationType applicationType, Language lang, BuildTool build, + TestFramework testFramework) { + given: + List features = ['oracle-function'] + JdkVersion jdkVersion = VersionInfo.getJavaVersion() + if (jdkVersion.greaterThanEqual(MicronautJdkVersionConfiguration.DEFAULT_OPTION)) { + jdkVersion = MicronautJdkVersionConfiguration.DEFAULT_OPTION + } + beanContext.getBean(ProjectGenerator).generate(applicationType, + NameUtils.parse("example.micronaut.foo-test"), + new Options(lang, testFramework, build, jdkVersion), + OperatingSystem.LINUX, + features, + new FileSystemOutputHandler(dir, ConsoleOutput.NOOP), + ConsoleOutput.NOOP + ) + + when: + String output = executeBuild(build, "testClasses") + + then: + output.contains("BUILD SUCCESS") + + where: + [applicationType, lang, build, testFramework] << ApplicationTypeCombinations.combinations([ApplicationType.DEFAULT], Language.values() as List, BuildTool.valuesGradle()) + } + + void 'default application with features oracle-function, #serializationFeature, #lang and #build and test framework: #testFramework'( Language lang, String serializationFeature, diff --git a/test-core/build.gradle b/test-core/build.gradle index 4693757f160..9f24bf634b2 100644 --- a/test-core/build.gradle +++ b/test-core/build.gradle @@ -3,8 +3,8 @@ plugins { } dependencies { - testImplementation project(":test-utils") - testImplementation project(":starter-core") - testImplementation project(":micronaut-cli") + testImplementation(project(":test-utils")) + testImplementation(project(":starter-core")) + testImplementation(project(":micronaut-cli")) testImplementation("ch.qos.logback:logback-classic") } diff --git a/test-core/src/test/groovy/io/micronaut/starter/core/test/GradleDockerConfigSpec.groovy b/test-core/src/test/groovy/io/micronaut/starter/core/test/GradleDockerConfigSpec.groovy new file mode 100644 index 00000000000..bdc782dc353 --- /dev/null +++ b/test-core/src/test/groovy/io/micronaut/starter/core/test/GradleDockerConfigSpec.groovy @@ -0,0 +1,51 @@ +package io.micronaut.starter.core.test + +import io.micronaut.starter.options.BuildTool +import io.micronaut.starter.options.JdkVersion +import io.micronaut.starter.options.Language +import io.micronaut.starter.test.CommandSpec + +class GradleDockerConfigSpec extends CommandSpec { + + void "basic dockerfile creation as expected for #buildTool and Java #javaVersion"(BuildTool buildTool, Integer javaVersion) { + when: + generateProjectForVersion(Language.JAVA, JdkVersion.valueOf(javaVersion), buildTool) + + // dockerfileNative depends on compileJava so we need to exclude it (as if we're on Java 17, we can't compile a java 21 build) + def result = executeGradle("dockerfile", "dockerfileNative", "-x", "compileJava") + + then: + result.output.contains("BUILD SUCCESS") + new File(dir, "build/docker/main/Dockerfile").text.contains("FROM $dockerBaseImage") + new File(dir, "build/docker/native-main/DockerfileNative").text.contains("FROM ghcr.io/graalvm/native-image-community:$javaVersion-ol9 AS graalvm") + + where: + [buildTool, javaVersion] << [ + BuildTool.valuesGradle(), + [17, 21] + ].combinations() + dockerBaseImage = javaVersion == 17 ? "eclipse-temurin:17-jre" : "eclipse-temurin:21-jre" + } + + void "test #command works for #buildTool under java #javaVersion"(BuildTool buildTool, String command, Integer javaVersion) { + when: + generateProjectForVersion(Language.JAVA, JdkVersion.valueOf(javaVersion), buildTool) + + def result = executeGradle(command) + + then: + result.output.contains("BUILD SUCCESS") + + where: + [buildTool, command, javaVersion] << [ + BuildTool.valuesGradle(), + ['dockerBuild', 'dockerBuildNative'], + [17] + (Runtime.version().feature() >= 21 ? [21] : []) + ].combinations() + } + + @Override + String getTempDirectoryPrefix() { + return "gradleDockerConfigSpec" + } +} diff --git a/test-core/src/test/groovy/io/micronaut/starter/core/test/create/CreateCliSpec.groovy b/test-core/src/test/groovy/io/micronaut/starter/core/test/create/CreateCliSpec.groovy index 332c7743d14..0dbe7cf744c 100644 --- a/test-core/src/test/groovy/io/micronaut/starter/core/test/create/CreateCliSpec.groovy +++ b/test-core/src/test/groovy/io/micronaut/starter/core/test/create/CreateCliSpec.groovy @@ -2,6 +2,7 @@ package io.micronaut.starter.core.test.create import io.micronaut.starter.application.ApplicationType +import io.micronaut.starter.feature.build.Kapt import io.micronaut.starter.options.BuildTool import io.micronaut.starter.options.Language import io.micronaut.starter.test.CommandSpec @@ -21,7 +22,7 @@ class CreateCliSpec extends CommandSpec { void 'create-cli-app with #lang and #buildTool'(Language lang, BuildTool buildTool) { given: ApplicationType applicationType = ApplicationType.CLI - generateProject(lang, buildTool, [], applicationType) + generateProject(lang, buildTool, (lang == Language.KOTLIN) ? [Kapt.NAME] : [], applicationType) when: String output = null diff --git a/test-core/src/test/groovy/io/micronaut/starter/core/test/create/CreateGrpcSpec.groovy b/test-core/src/test/groovy/io/micronaut/starter/core/test/create/CreateGrpcSpec.groovy index 5ba03037ddd..54244348d88 100644 --- a/test-core/src/test/groovy/io/micronaut/starter/core/test/create/CreateGrpcSpec.groovy +++ b/test-core/src/test/groovy/io/micronaut/starter/core/test/create/CreateGrpcSpec.groovy @@ -1,5 +1,6 @@ package io.micronaut.starter.core.test.create +import io.micronaut.context.BeanContext import io.micronaut.starter.application.ApplicationType import io.micronaut.starter.cli.CodeGenConfig import io.micronaut.starter.cli.feature.grpc.CreateGrpcServiceCommand @@ -8,9 +9,10 @@ import io.micronaut.starter.io.ConsoleOutput import io.micronaut.starter.options.BuildTool import io.micronaut.starter.options.Language import io.micronaut.starter.test.CommandSpec -import io.micronaut.starter.test.LanguageBuildCombinations +import spock.lang.IgnoreIf import spock.lang.Unroll + class CreateGrpcSpec extends CommandSpec { @Override String getTempDirectoryPrefix() { @@ -18,33 +20,45 @@ class CreateGrpcSpec extends CommandSpec { } @Unroll - void 'grpc with #lang and #buildTool'(Language lang, BuildTool buildTool) { + void 'grpc with #lang and gradle'(Language lang) { given: + BuildTool buildTool = BuildTool.GRADLE + ConsoleOutput consoleOutput = Mock(ConsoleOutput) ApplicationType applicationType = ApplicationType.GRPC generateProject(lang, buildTool, [], applicationType) + CreateGrpcServiceCommand command = createGrpcServiceCommand(beanContext, consoleOutput) + command.setBeanContext(beanContext) + command.serviceName = "Greeting" - CodeGenConfig codeGenConfig = CodeGenConfig.load(beanContext, dir, ConsoleOutput.NOOP) - ConsoleOutput consoleOutput = Mock(ConsoleOutput) + expect: + command.applies() - CreateProtoServiceCommand protoServiceCommand = new CreateProtoServiceCommand( - codeGenConfig, - getOutputHandler(consoleOutput), - consoleOutput + when: + command.call() - ) - protoServiceCommand.setBeanContext(beanContext) + then: + 1 * consoleOutput.out({ it.contains("Rendered Proto service") }) + 1 * consoleOutput.out({ it.contains("Rendered gRPC service") }) - CreateGrpcServiceCommand command = new CreateGrpcServiceCommand( - codeGenConfig, - getOutputHandler(consoleOutput), - consoleOutput - ) { - @Override - protected CreateProtoServiceCommand getCreateProtoServiceCommand() { - return protoServiceCommand - } - } + when: + String output = executeBuild(buildTool, "test") + + then: + output.contains("BUILD SUCCESS") + + where: + lang << Language.values() + } + @IgnoreIf(value = { os.macOs }, reason = ": Error extracting protoc for version 3.11.4: Unsupported platform: protoc-3.11.4-osx-aarch_64.exe") + @Unroll + void 'grpc with #lang and maven'(Language lang) { + given: + BuildTool buildTool = BuildTool.MAVEN + ConsoleOutput consoleOutput = Mock(ConsoleOutput) + ApplicationType applicationType = ApplicationType.GRPC + generateProject(lang, buildTool, [], applicationType) + CreateGrpcServiceCommand command = createGrpcServiceCommand(beanContext, consoleOutput) command.setBeanContext(beanContext) command.serviceName = "Greeting" @@ -65,6 +79,31 @@ class CreateGrpcSpec extends CommandSpec { output.contains("BUILD SUCCESS") where: - [lang, buildTool] << LanguageBuildCombinations.combinations() + lang << Language.values() + } + + CreateGrpcServiceCommand createGrpcServiceCommand(BeanContext beanContext, + ConsoleOutput consoleOutput) { + CodeGenConfig codeGenConfig = CodeGenConfig.load(beanContext, dir, ConsoleOutput.NOOP) + + CreateProtoServiceCommand protoServiceCommand = new CreateProtoServiceCommand( + codeGenConfig, + getOutputHandler(consoleOutput), + consoleOutput + + ) + protoServiceCommand.setBeanContext(beanContext) + + CreateGrpcServiceCommand command = new CreateGrpcServiceCommand( + codeGenConfig, + getOutputHandler(consoleOutput), + consoleOutput + ) { + @Override + protected CreateProtoServiceCommand getCreateProtoServiceCommand() { + return protoServiceCommand + } + } + command } } diff --git a/test-core/src/test/groovy/io/micronaut/starter/core/test/create/CreateMessagingSpec.groovy b/test-core/src/test/groovy/io/micronaut/starter/core/test/create/CreateMessagingSpec.groovy index 3b155d7319d..bda098687d5 100644 --- a/test-core/src/test/groovy/io/micronaut/starter/core/test/create/CreateMessagingSpec.groovy +++ b/test-core/src/test/groovy/io/micronaut/starter/core/test/create/CreateMessagingSpec.groovy @@ -9,15 +9,11 @@ import io.micronaut.starter.options.BuildTool import io.micronaut.starter.options.Language import io.micronaut.starter.test.CommandSpec import io.micronaut.starter.test.LanguageBuildCombinations +import io.micronaut.starter.test.PredicateUtils import spock.lang.Unroll - import java.util.stream.Collectors class CreateMessagingSpec extends CommandSpec { - private static List EXCLUDED_FEATURES = [ - 'jms-aq', - ] - @Override String getTempDirectoryPrefix() { "test-messaging-createmessagingspec" @@ -40,8 +36,8 @@ class CreateMessagingSpec extends CommandSpec { where: [lang, buildTool, feature] << LanguageBuildCombinations.combinations( beanContext.streamOfType(MessagingFeature.class) - .filter( f -> !EXCLUDED_FEATURES.contains(f.name)) .map(Feature::getName) + .filter( f -> PredicateUtils.testFeatureIfMacOS(List.of( 'jms-oracle-aq')).test(f)) .filter( f -> !isCi() || (f != "jms-sqs" && isCi())) .collect(Collectors.toList())) } diff --git a/test-features/build.gradle b/test-features/build.gradle index ffdf93c078c..c5b1af73b53 100644 --- a/test-features/build.gradle +++ b/test-features/build.gradle @@ -4,13 +4,13 @@ plugins { } dependencies { - testImplementation project(":test-utils") - testImplementation project(":starter-core") - testImplementation 'com.azure:azure-identity:1.10.1' - testImplementation 'com.azure.resourcemanager:azure-resourcemanager-containerinstance:2.33.0' - testImplementation 'com.google.apis:google-api-services-run:v1-rev20201113-1.31.0' - testImplementation 'com.google.auth:google-auth-library-oauth2-http:1.20.0' - testImplementation "com.oracle.oci.sdk:oci-java-sdk-full:1.34.0" + testImplementation(project(":test-utils")) + testImplementation(project(":starter-core")) + testImplementation("com.azure:azure-identity:1.11.3") + testImplementation("com.azure.resourcemanager:azure-resourcemanager-containerinstance:2.37.0") + testImplementation("com.google.apis:google-api-services-run:v1-rev20201113-1.31.0") + testImplementation("com.google.auth:google-auth-library-oauth2-http:1.23.0") + testImplementation("com.oracle.oci.sdk:oci-java-sdk-full:1.34.0") testImplementation("ch.qos.logback:logback-classic") testImplementation("org.yaml:snakeyaml") testImplementation("org.apache.groovy:groovy-yaml") diff --git a/test-features/src/test/groovy/io/micronaut/starter/core/test/feature/chatbots/basecamp/BasecampAwsChatBotFunctionSpec.groovy b/test-features/src/test/groovy/io/micronaut/starter/core/test/feature/chatbots/basecamp/BasecampAwsChatBotFunctionSpec.groovy new file mode 100644 index 00000000000..b01b2591c31 --- /dev/null +++ b/test-features/src/test/groovy/io/micronaut/starter/core/test/feature/chatbots/basecamp/BasecampAwsChatBotFunctionSpec.groovy @@ -0,0 +1,49 @@ +package io.micronaut.starter.core.test.feature.chatbots.basecamp + +import io.micronaut.starter.application.ApplicationType +import io.micronaut.starter.feature.aws.Cdk +import io.micronaut.starter.feature.chatbots.basecamp.BasecampAwsChatBot +import io.micronaut.starter.options.BuildTool +import io.micronaut.starter.options.Language +import io.micronaut.starter.options.TestFramework +import io.micronaut.starter.test.CommandSpec + +class BasecampAwsChatBotFunctionSpec extends CommandSpec { + + @Override + String getTempDirectoryPrefix() { + return "basecampAwsChatBotFunctionSpec" + } + + void "#testFramework test #feature feature in #language with #buildTool"(BuildTool buildTool, Language language, TestFramework testFramework) { + when: + generateProject(language, buildTool, [feature], ApplicationType.FUNCTION, testFramework) + + then: + String result = executeBuild(buildTool, "test") + + then: + println result + result.contains("BUILD SUCCESS") + + where: + [buildTool, language, testFramework] << [BuildTool.values(), Language.values(), TestFramework.values()].combinations() + feature = BasecampAwsChatBot.NAME + } + + void "#testFramework test #feature feature with Cdk in #language with #buildTool"(BuildTool buildTool, Language language, TestFramework testFramework) { + when: + generateProject(language, buildTool, [feature, Cdk.NAME], ApplicationType.FUNCTION, testFramework) + + then: + String result = executeBuild(buildTool, "test") + + then: + println result + result.contains("BUILD SUCCESS") + + where: + [buildTool, language, testFramework] << [BuildTool.values(), Language.values(), TestFramework.values()].combinations() + feature = BasecampAwsChatBot.NAME + } +} diff --git a/test-features/src/test/groovy/io/micronaut/starter/core/test/feature/chatbots/basecamp/BasecampAzureChatBotFunctionSpec.groovy b/test-features/src/test/groovy/io/micronaut/starter/core/test/feature/chatbots/basecamp/BasecampAzureChatBotFunctionSpec.groovy new file mode 100644 index 00000000000..ef26931fabf --- /dev/null +++ b/test-features/src/test/groovy/io/micronaut/starter/core/test/feature/chatbots/basecamp/BasecampAzureChatBotFunctionSpec.groovy @@ -0,0 +1,32 @@ +package io.micronaut.starter.core.test.feature.chatbots.basecamp + +import io.micronaut.starter.application.ApplicationType +import io.micronaut.starter.feature.chatbots.basecamp.BasecampAzureChatBot +import io.micronaut.starter.options.BuildTool +import io.micronaut.starter.options.Language +import io.micronaut.starter.options.TestFramework +import io.micronaut.starter.test.CommandSpec + +class BasecampAzureChatBotFunctionSpec extends CommandSpec { + + @Override + String getTempDirectoryPrefix() { + return "basecampAzureChatBotFunctionSpec" + } + + void "#testFramework test #feature feature in #language with #buildTool"(BuildTool buildTool, Language language, TestFramework testFramework) { + when: + generateProject(language, buildTool, [feature], ApplicationType.FUNCTION, testFramework) + + then: + String result = executeBuild(buildTool, "test") + + then: + println result + result.contains("BUILD SUCCESS") + + where: + [buildTool, language, testFramework] << [BuildTool.values(), Language.values(), TestFramework.values()].combinations() + feature = BasecampAzureChatBot.NAME + } +} diff --git a/test-features/src/test/groovy/io/micronaut/starter/core/test/feature/chatbots/basecamp/BasecampControllerChatBotSpec.groovy b/test-features/src/test/groovy/io/micronaut/starter/core/test/feature/chatbots/basecamp/BasecampControllerChatBotSpec.groovy new file mode 100644 index 00000000000..b2d672bb436 --- /dev/null +++ b/test-features/src/test/groovy/io/micronaut/starter/core/test/feature/chatbots/basecamp/BasecampControllerChatBotSpec.groovy @@ -0,0 +1,32 @@ +package io.micronaut.starter.core.test.feature.chatbots.basecamp + +import io.micronaut.starter.application.ApplicationType +import io.micronaut.starter.feature.chatbots.basecamp.BasecampHttpChatBot +import io.micronaut.starter.options.BuildTool +import io.micronaut.starter.options.Language +import io.micronaut.starter.options.TestFramework +import io.micronaut.starter.test.CommandSpec + +class BasecampControllerChatBotSpec extends CommandSpec { + + @Override + String getTempDirectoryPrefix() { + return "basecampHttpChatBotSpec" + } + + void "#testFramework test #feature feature in #language with #buildTool"(BuildTool buildTool, Language language, TestFramework testFramework) { + when: + generateProject(language, buildTool, [feature], ApplicationType.DEFAULT, testFramework) + + then: + String result = executeBuild(buildTool, "test") + + then: + println result + result.contains("BUILD SUCCESS") + + where: + [buildTool, language, testFramework] << [BuildTool.values(), Language.values(), TestFramework.values()].combinations() + feature = BasecampHttpChatBot.NAME + } +} diff --git a/test-features/src/test/groovy/io/micronaut/starter/core/test/feature/chatbots/basecamp/BasecampGcpChatBotFunctionSpec.groovy b/test-features/src/test/groovy/io/micronaut/starter/core/test/feature/chatbots/basecamp/BasecampGcpChatBotFunctionSpec.groovy new file mode 100644 index 00000000000..5829f216fc1 --- /dev/null +++ b/test-features/src/test/groovy/io/micronaut/starter/core/test/feature/chatbots/basecamp/BasecampGcpChatBotFunctionSpec.groovy @@ -0,0 +1,31 @@ +package io.micronaut.starter.core.test.feature.chatbots.basecamp + +import io.micronaut.starter.application.ApplicationType +import io.micronaut.starter.feature.chatbots.basecamp.BasecampGcpChatBot +import io.micronaut.starter.options.BuildTool +import io.micronaut.starter.options.Language +import io.micronaut.starter.options.TestFramework +import io.micronaut.starter.test.CommandSpec + +class BasecampGcpChatBotFunctionSpec extends CommandSpec { + + @Override + String getTempDirectoryPrefix() { + return "basecampGcpChatBotFunctionSpec" + } + + void "#testFramework test #feature feature in #language with #buildTool"(BuildTool buildTool, Language language, TestFramework testFramework) { + when: + generateProject(language, buildTool, [feature], ApplicationType.FUNCTION, testFramework) + + then: + String result = executeBuild(buildTool, "test") + + then: + result.contains("BUILD SUCCESS") + + where: + [buildTool, language, testFramework] << [BuildTool.values(), Language.values(), TestFramework.values()].combinations() + feature = BasecampGcpChatBot.NAME + } +} diff --git a/test-features/src/test/groovy/io/micronaut/starter/core/test/feature/chatbots/TelegramAwsChatBotFunctionSpec.groovy b/test-features/src/test/groovy/io/micronaut/starter/core/test/feature/chatbots/telegram/TelegramAwsChatBotFunctionSpec.groovy similarity index 96% rename from test-features/src/test/groovy/io/micronaut/starter/core/test/feature/chatbots/TelegramAwsChatBotFunctionSpec.groovy rename to test-features/src/test/groovy/io/micronaut/starter/core/test/feature/chatbots/telegram/TelegramAwsChatBotFunctionSpec.groovy index 48ccdd35f64..0fd816f95ca 100644 --- a/test-features/src/test/groovy/io/micronaut/starter/core/test/feature/chatbots/TelegramAwsChatBotFunctionSpec.groovy +++ b/test-features/src/test/groovy/io/micronaut/starter/core/test/feature/chatbots/telegram/TelegramAwsChatBotFunctionSpec.groovy @@ -1,4 +1,4 @@ -package io.micronaut.starter.core.test.feature.chatbots +package io.micronaut.starter.core.test.feature.chatbots.telegram import io.micronaut.starter.application.ApplicationType import io.micronaut.starter.feature.aws.Cdk diff --git a/test-features/src/test/groovy/io/micronaut/starter/core/test/feature/chatbots/TelegramAzureChatBotFunctionSpec.groovy b/test-features/src/test/groovy/io/micronaut/starter/core/test/feature/chatbots/telegram/TelegramAzureChatBotFunctionSpec.groovy similarity index 94% rename from test-features/src/test/groovy/io/micronaut/starter/core/test/feature/chatbots/TelegramAzureChatBotFunctionSpec.groovy rename to test-features/src/test/groovy/io/micronaut/starter/core/test/feature/chatbots/telegram/TelegramAzureChatBotFunctionSpec.groovy index a201a606eaf..04732f8a8b0 100644 --- a/test-features/src/test/groovy/io/micronaut/starter/core/test/feature/chatbots/TelegramAzureChatBotFunctionSpec.groovy +++ b/test-features/src/test/groovy/io/micronaut/starter/core/test/feature/chatbots/telegram/TelegramAzureChatBotFunctionSpec.groovy @@ -1,4 +1,4 @@ -package io.micronaut.starter.core.test.feature.chatbots +package io.micronaut.starter.core.test.feature.chatbots.telegram import io.micronaut.starter.application.ApplicationType import io.micronaut.starter.feature.chatbots.telegram.TelegramAzureChatBot diff --git a/test-features/src/test/groovy/io/micronaut/starter/core/test/feature/chatbots/TelegramControllerChatBotSpec.groovy b/test-features/src/test/groovy/io/micronaut/starter/core/test/feature/chatbots/telegram/TelegramControllerChatBotSpec.groovy similarity index 94% rename from test-features/src/test/groovy/io/micronaut/starter/core/test/feature/chatbots/TelegramControllerChatBotSpec.groovy rename to test-features/src/test/groovy/io/micronaut/starter/core/test/feature/chatbots/telegram/TelegramControllerChatBotSpec.groovy index 6a70af4542a..c3f2eaa1992 100644 --- a/test-features/src/test/groovy/io/micronaut/starter/core/test/feature/chatbots/TelegramControllerChatBotSpec.groovy +++ b/test-features/src/test/groovy/io/micronaut/starter/core/test/feature/chatbots/telegram/TelegramControllerChatBotSpec.groovy @@ -1,4 +1,4 @@ -package io.micronaut.starter.core.test.feature.chatbots +package io.micronaut.starter.core.test.feature.chatbots.telegram import io.micronaut.starter.application.ApplicationType import io.micronaut.starter.feature.chatbots.telegram.TelegramGcpChatBot diff --git a/test-features/src/test/groovy/io/micronaut/starter/core/test/feature/chatbots/TelegramGcpChatBotFunctionSpec.groovy b/test-features/src/test/groovy/io/micronaut/starter/core/test/feature/chatbots/telegram/TelegramGcpChatBotFunctionSpec.groovy similarity index 94% rename from test-features/src/test/groovy/io/micronaut/starter/core/test/feature/chatbots/TelegramGcpChatBotFunctionSpec.groovy rename to test-features/src/test/groovy/io/micronaut/starter/core/test/feature/chatbots/telegram/TelegramGcpChatBotFunctionSpec.groovy index 7a2b27fda95..5ffe52a7423 100644 --- a/test-features/src/test/groovy/io/micronaut/starter/core/test/feature/chatbots/TelegramGcpChatBotFunctionSpec.groovy +++ b/test-features/src/test/groovy/io/micronaut/starter/core/test/feature/chatbots/telegram/TelegramGcpChatBotFunctionSpec.groovy @@ -1,4 +1,4 @@ -package io.micronaut.starter.core.test.feature.chatbots +package io.micronaut.starter.core.test.feature.chatbots.telegram import io.micronaut.starter.application.ApplicationType import io.micronaut.starter.feature.chatbots.telegram.TelegramGcpChatBot diff --git a/test-features/src/test/groovy/io/micronaut/starter/core/test/feature/database/DataHibernateReactiveSpec.groovy b/test-features/src/test/groovy/io/micronaut/starter/core/test/feature/database/DataHibernateReactiveSpec.groovy index ca4b376623e..d2971cf1808 100644 --- a/test-features/src/test/groovy/io/micronaut/starter/core/test/feature/database/DataHibernateReactiveSpec.groovy +++ b/test-features/src/test/groovy/io/micronaut/starter/core/test/feature/database/DataHibernateReactiveSpec.groovy @@ -7,6 +7,7 @@ import io.micronaut.starter.feature.database.MySQL import io.micronaut.starter.feature.database.Oracle import io.micronaut.starter.feature.database.PostgreSQL import io.micronaut.starter.feature.database.SQLServer +import io.micronaut.starter.feature.validator.MicronautValidationFeature import io.micronaut.starter.io.ConsoleOutput import io.micronaut.starter.io.FileSystemOutputHandler import io.micronaut.starter.options.BuildTool @@ -14,6 +15,7 @@ import io.micronaut.starter.options.Language import io.micronaut.starter.template.RockerWritable import io.micronaut.starter.test.BuildToolTest import io.micronaut.starter.test.CommandSpec +import io.micronaut.starter.test.PredicateUtils import org.gradle.testkit.runner.BuildResult import spock.lang.IgnoreIf @@ -27,7 +29,7 @@ class DataHibernateReactiveSpec extends CommandSpec { @IgnoreIf({ BuildToolTest.IGNORE_MAVEN }) void "test maven data-hibernate-reactive with java and #db"(String db) { when: - generateProject(Language.JAVA, BuildTool.MAVEN, [DataHibernateReactive.NAME, db]) + generateProject(Language.JAVA, BuildTool.MAVEN, [DataHibernateReactive.NAME, db, MicronautValidationFeature.NAME]) def fsoh = new FileSystemOutputHandler(dir, ConsoleOutput.NOOP) fsoh.write("src/main/java/example/micronaut/Book.java", new RockerWritable(book.template())) @@ -38,11 +40,14 @@ class DataHibernateReactiveSpec extends CommandSpec { where: db << featuresNames() + .stream() + .filter( f -> PredicateUtils.testFeatureIfMacOS(List.of(Oracle.NAME, SQLServer.NAME)).test(f)) + .toList() } void "test #buildTool data-hibernate-reactive with java and #db"(BuildTool buildTool, String db) { when: - generateProject(Language.JAVA, buildTool, [DataHibernateReactive.NAME, db]) + generateProject(Language.JAVA, buildTool, [DataHibernateReactive.NAME, db, MicronautValidationFeature.NAME]) def fsoh = new FileSystemOutputHandler(dir, ConsoleOutput.NOOP) fsoh.write("src/main/java/example/micronaut/Book.java", new RockerWritable(book.template())) @@ -52,7 +57,11 @@ class DataHibernateReactiveSpec extends CommandSpec { result?.output?.contains("BUILD SUCCESS") where: - [buildTool, db] << [BuildTool.valuesGradle(), featuresNames()].combinations() + [buildTool, db] << [BuildTool.valuesGradle(), featuresNames() + .stream() + .filter( f -> PredicateUtils.testFeatureIfMacOS(List.of(Oracle.NAME, SQLServer.NAME)).test(f)) + .toList() + ].combinations() } private static List featuresNames() { @@ -62,6 +71,8 @@ class DataHibernateReactiveSpec extends CommandSpec { PostgreSQL.NAME, Oracle.NAME, SQLServer.NAME - ] + ].stream() + .filter(n -> n != Oracle.NAME || Oracle.COMPATIBLE_WITH_HIBERNATE_REACTIVE) + .toList() } } diff --git a/test-features/src/test/groovy/io/micronaut/starter/core/test/feature/database/HibernateReactiveJpaSpec.groovy b/test-features/src/test/groovy/io/micronaut/starter/core/test/feature/database/HibernateReactiveJpaSpec.groovy index df3c5153671..632b7936fc7 100644 --- a/test-features/src/test/groovy/io/micronaut/starter/core/test/feature/database/HibernateReactiveJpaSpec.groovy +++ b/test-features/src/test/groovy/io/micronaut/starter/core/test/feature/database/HibernateReactiveJpaSpec.groovy @@ -7,6 +7,7 @@ import io.micronaut.starter.feature.database.MySQL import io.micronaut.starter.feature.database.Oracle import io.micronaut.starter.feature.database.PostgreSQL import io.micronaut.starter.feature.database.SQLServer +import io.micronaut.starter.feature.validator.MicronautValidationFeature import io.micronaut.starter.io.ConsoleOutput import io.micronaut.starter.io.FileSystemOutputHandler import io.micronaut.starter.options.BuildTool @@ -14,6 +15,7 @@ import io.micronaut.starter.options.Language import io.micronaut.starter.template.RockerWritable import io.micronaut.starter.test.BuildToolTest import io.micronaut.starter.test.CommandSpec +import io.micronaut.starter.test.PredicateUtils import org.gradle.testkit.runner.BuildResult import spock.lang.IgnoreIf @@ -26,7 +28,7 @@ class HibernateReactiveJpaSpec extends CommandSpec { @IgnoreIf({ BuildToolTest.IGNORE_MAVEN }) void "test maven hibernate-reactive-jpa with java and #db"(String db) { when: - generateProject(Language.JAVA, BuildTool.MAVEN, [HibernateReactiveJpa.NAME, db]) + generateProject(Language.JAVA, BuildTool.MAVEN, [HibernateReactiveJpa.NAME, db, MicronautValidationFeature.NAME]) def fsoh = new FileSystemOutputHandler(dir, ConsoleOutput.NOOP) fsoh.write("src/main/java/example/micronaut/Book.java", new RockerWritable(book.template())) @@ -36,12 +38,14 @@ class HibernateReactiveJpaSpec extends CommandSpec { output?.contains("BUILD SUCCESS") where: - db << featuresNames() + db << featuresNames().stream() + .filter( f -> PredicateUtils.testFeatureIfMacOS(List.of(Oracle.NAME, SQLServer.NAME)).test(f)) + .toList() } void "test #buildTool hibernate-reactive-jpa with java and #db"(BuildTool buildTool, String db) { when: - generateProject(Language.JAVA, buildTool, [HibernateReactiveJpa.NAME, db]) + generateProject(Language.JAVA, buildTool, [HibernateReactiveJpa.NAME, db, MicronautValidationFeature.NAME]) def fsoh = new FileSystemOutputHandler(dir, ConsoleOutput.NOOP) fsoh.write("src/main/java/example/micronaut/Book.java", new RockerWritable(book.template())) @@ -51,7 +55,10 @@ class HibernateReactiveJpaSpec extends CommandSpec { result?.output?.contains("BUILD SUCCESS") where: - [buildTool, db] << [BuildTool.valuesGradle(), featuresNames()].combinations() + [buildTool, db] << [BuildTool.valuesGradle(), featuresNames() + .stream() + .filter( f -> PredicateUtils.testFeatureIfMacOS(List.of(Oracle.NAME, SQLServer.NAME)).test(f)) + .toList()].combinations() } private static List featuresNames() { @@ -61,6 +68,8 @@ class HibernateReactiveJpaSpec extends CommandSpec { PostgreSQL.NAME, Oracle.NAME, SQLServer.NAME - ] + ].stream() + .filter(n -> n != Oracle.NAME || Oracle.COMPATIBLE_WITH_HIBERNATE_REACTIVE) + .toList() } } diff --git a/test-features/src/test/groovy/io/micronaut/starter/core/test/feature/opensearch/OpenSearchFunctionalSpec.groovy b/test-features/src/test/groovy/io/micronaut/starter/core/test/feature/opensearch/OpenSearchFunctionalSpec.groovy new file mode 100644 index 00000000000..4db2a4ecf68 --- /dev/null +++ b/test-features/src/test/groovy/io/micronaut/starter/core/test/feature/opensearch/OpenSearchFunctionalSpec.groovy @@ -0,0 +1,33 @@ +package io.micronaut.starter.core.test.feature.opensearch + +import io.micronaut.starter.feature.opensearch.OpenSearchFeature +import io.micronaut.starter.options.BuildTool +import io.micronaut.starter.options.Language +import io.micronaut.starter.test.CommandSpec + +class OpenSearchFunctionalSpec extends CommandSpec { + + void 'test #feature.name for #lang and #buildTool'(OpenSearchFeature feature, Language lang, BuildTool buildTool) { + given: + generateProject(lang, buildTool, [feature.name]) + + when: + String output = executeBuild(buildTool, "test") + + then: + output.contains("BUILD SUCCESS") + output.contains("Loaded 2 test resources resolvers: io.micronaut.testresources.opensearch.OpenSearchTestResourceProvider") + + where: + [feature, lang, buildTool] << [ + beanContext.getBeansOfType(OpenSearchFeature), + Language.values(), + BuildTool.values() + ].combinations() + } + + @Override + String getTempDirectoryPrefix() { + return "test-app-opensearch" + } +} diff --git a/test-features/src/test/groovy/io/micronaut/starter/core/test/feature/other/SwaggerUISpec.groovy b/test-features/src/test/groovy/io/micronaut/starter/core/test/feature/other/SwaggerUISpec.groovy index 0be8464b807..71243a671d1 100644 --- a/test-features/src/test/groovy/io/micronaut/starter/core/test/feature/other/SwaggerUISpec.groovy +++ b/test-features/src/test/groovy/io/micronaut/starter/core/test/feature/other/SwaggerUISpec.groovy @@ -150,6 +150,7 @@ class SwaggerUISpec extends CommandSpec { assert openAPIProperties.get("swagger-ui.enabled") == "true" assert openAPIProperties.get("redoc.enabled") == "false" + assert openAPIProperties.get("openapi-explorer.enabled") == "false" assert openAPIProperties.get("rapidoc.enabled") == "false" assert openAPIProperties.get("rapidoc.bg-color") == "#14191f" assert openAPIProperties.get("rapidoc.text-color") == "#aec2e0" diff --git a/test-features/src/test/groovy/io/micronaut/starter/core/test/feature/testcontainers/TestcontainersSpec.groovy b/test-features/src/test/groovy/io/micronaut/starter/core/test/feature/testcontainers/TestcontainersSpec.groovy index 8102c9cecb2..24330ee93ca 100644 --- a/test-features/src/test/groovy/io/micronaut/starter/core/test/feature/testcontainers/TestcontainersSpec.groovy +++ b/test-features/src/test/groovy/io/micronaut/starter/core/test/feature/testcontainers/TestcontainersSpec.groovy @@ -1,6 +1,8 @@ package io.micronaut.starter.core.test.feature.testcontainers import io.micronaut.starter.feature.database.DatabaseDriverFeature +import io.micronaut.starter.feature.database.Oracle +import io.micronaut.starter.feature.database.SQLServer import io.micronaut.starter.io.ConsoleOutput import io.micronaut.starter.io.FileSystemOutputHandler import io.micronaut.starter.options.BuildTool @@ -9,17 +11,14 @@ import io.micronaut.starter.options.Language import io.micronaut.starter.template.RockerWritable import io.micronaut.starter.test.BuildToolCombinations import io.micronaut.starter.test.CommandSpec +import io.micronaut.starter.test.PredicateUtils import io.micronaut.starter.util.VersionInfo -import spock.lang.Retry -import spock.lang.Unroll // Required so Groovy recognizes these as a class import io.micronaut.starter.core.test.feature.testcontainers.bookRepository import io.micronaut.starter.core.test.feature.testcontainers.book import io.micronaut.starter.core.test.feature.testcontainers.bookRepositoryTest -import java.util.stream.Collectors -@Retry // sometimes CI gets connection failure/reset resolving dependencies from Maven central class TestcontainersSpec extends CommandSpec { @Override @@ -27,7 +26,6 @@ class TestcontainersSpec extends CommandSpec { return "testcontainers" } - @Unroll void "test running tests with testcontainers with #buildTool and #driverFeature.getName()"(BuildTool buildTool, DatabaseDriverFeature driverFeature) { setup: boolean skip = driverFeature.name == "oracle-cloud-atp" && VersionInfo.getJavaVersion() == JdkVersion.JDK_8 @@ -58,9 +56,11 @@ class TestcontainersSpec extends CommandSpec { where: [buildTool, driverFeature] << [ BuildToolCombinations.buildTools, - beanContext.streamOfType(DatabaseDriverFeature) - .filter({ f -> !f.embedded() }) - .collect(Collectors.toList()) + beanContext.getBeansOfType(DatabaseDriverFeature) + .stream() + .filter( f -> PredicateUtils.testFeatureIfMacOS(List.of(Oracle.NAME, SQLServer.NAME)).test(f.name)) + .filter( f -> !f.embedded()) + .toList() ].combinations() } } diff --git a/test-lambda.sh b/test-lambda.sh index b376e2eb394..919422c4041 100755 --- a/test-lambda.sh +++ b/test-lambda.sh @@ -2,8 +2,8 @@ EXIT_STATUS=0 JAVA_VER=$(java -version 2>&1 | sed -n ';s/.* version "\(.*\)\.\(.*\)\..*".*/\1\2/p;') -if [[ "$JAVA_VER" != "170" ]]; then - echo test-lambda works only with Java 17 +if [[ "$JAVA_VER" != "210" ]]; then + echo test-lambda works only with Java 21 exit 1; fi @@ -14,7 +14,7 @@ rm -rf starter-cli/temp # | GRADLE | APP | JAVA | aws-lambda,aws-cdk,amazon-api-gateway-http ############ -./gradlew micronaut-cli:run --args="create-app --jdk 17 -b gradle -f \"aws-lambda,aws-cdk,amazon-api-gateway-http\" temp1" || EXIT_STATUS=$? +./gradlew micronaut-cli:run --args="create-app --jdk 21 -b gradle -f \"aws-lambda,aws-cdk,amazon-api-gateway-http\" temp1" || EXIT_STATUS=$? if [ $EXIT_STATUS -ne 0 ]; then exit $EXIT_STATUS @@ -39,7 +39,7 @@ rm -rf starter-cli/temp1 # | GRADLE | FUNCTION | JAVA | aws-lambda,aws-cdk,aws-lambda-function-url ############ -./gradlew micronaut-cli:run --args="create-function-app --jdk 17 -b gradle -f \"aws-lambda,aws-cdk,aws-lambda-function-url\" temp2" || EXIT_STATUS=$? +./gradlew micronaut-cli:run --args="create-function-app --jdk 21 -b gradle -f \"aws-lambda,aws-cdk,aws-lambda-function-url\" temp2" || EXIT_STATUS=$? if [ $EXIT_STATUS -ne 0 ]; then exit $EXIT_STATUS @@ -64,7 +64,7 @@ rm -rf starter-cli/temp2 # | GRADLE | APP | JAVA | aws-lambda,aws-cdk,amazon-api-gateway ############ -./gradlew micronaut-cli:run --args="create-app --jdk 17 -b gradle -f \"aws-lambda,aws-cdk,amazon-api-gateway\" temp3" || EXIT_STATUS=$? +./gradlew micronaut-cli:run --args="create-app --jdk 21 -b gradle -f \"aws-lambda,aws-cdk,amazon-api-gateway\" temp3" || EXIT_STATUS=$? if [ $EXIT_STATUS -ne 0 ]; then exit $EXIT_STATUS @@ -89,7 +89,7 @@ rm -rf starter-cli/temp3 # | GRADLE | FUNCTION | JAVA | aws-lambda,aws-cdk,amazon-api-gateway ############ -./gradlew micronaut-cli:run --args="create-function-app --jdk 17 -b gradle -f \"aws-lambda,aws-cdk,amazon-api-gateway\" temp4" || EXIT_STATUS=$? +./gradlew micronaut-cli:run --args="create-function-app --jdk 21 -b gradle -f \"aws-lambda,aws-cdk,amazon-api-gateway\" temp4" || EXIT_STATUS=$? if [ $EXIT_STATUS -ne 0 ]; then exit $EXIT_STATUS diff --git a/test-suite-graal/build.gradle b/test-suite-graal/build.gradle index 44071052738..30c2ccae124 100644 --- a/test-suite-graal/build.gradle +++ b/test-suite-graal/build.gradle @@ -10,8 +10,11 @@ repositories { dependencies { implementation(project(":starter-api")) + implementation(project(":micronaut-cli")) implementation(project(":starter-web-netty")) + testImplementation("io.micronaut.test:micronaut-test-junit5") + testImplementation("org.junit.jupiter:junit-jupiter-params") testImplementation("ch.qos.logback:logback-classic") } @@ -22,13 +25,6 @@ configurations.all { } } -configurations.all { - resolutionStrategy { - force "io.micronaut:micronaut-core-bom:$micronautCoreVersion" - force "io.micronaut:micronaut-inject-groovy:$micronautCoreVersion" - } -} - graalvmNative { binaries { all { diff --git a/test-suite-graal/src/test/java/example/GitHubApiClientMock.java b/test-suite-graal/src/test/java/example/GitHubApiClientMock.java deleted file mode 100644 index 579897c8b46..00000000000 --- a/test-suite-graal/src/test/java/example/GitHubApiClientMock.java +++ /dev/null @@ -1,107 +0,0 @@ -package example; - -import io.micronaut.context.annotation.Replaces; -import io.micronaut.starter.client.github.v3.GitHubApiClient; -import io.micronaut.starter.client.github.v3.GitHubRepository; -import io.micronaut.starter.client.github.v3.GitHubSecret; -import io.micronaut.starter.client.github.v3.GitHubSecretsPublicKey; -import io.micronaut.starter.client.github.v3.GitHubUser; -import io.micronaut.starter.client.github.v3.GitHubWorkflowRun; -import io.micronaut.starter.client.github.v3.GitHubWorkflowRuns; -import jakarta.annotation.PostConstruct; -import jakarta.annotation.PreDestroy; -import jakarta.inject.Singleton; -import org.eclipse.jgit.api.Git; -import org.eclipse.jgit.lib.Repository; -import org.eclipse.jgit.transport.URIish; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.File; -import java.net.URI; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.Comparator; - -@Replaces(GitHubApiClient.class) -@Singleton -public class GitHubApiClientMock implements GitHubApiClient { - - private static final Logger LOG = LoggerFactory.getLogger(GitHubApiClientMock.class); - - private Repository gitRepository; - - private String gitRepositoryUrl; - - @PostConstruct - public void initialize() throws Exception { - Path temp = Files.createTempDirectory("test-github-create"); - Git git = Git.init().setDirectory(temp.toFile()).setBare(true).call(); - gitRepository = git.getRepository(); - URIish uri = new URIish(gitRepository.getDirectory().toURI().toURL()); - gitRepositoryUrl = uri.toString(); - } - - @PreDestroy - public void close() { - if (gitRepository != null) { - try { - gitRepository.close(); - } catch (Exception e) { - LOG.warn("Failed to close git repository: {}", gitRepositoryUrl, e); - } - try { - Files.walk(Path.of(new URI(gitRepositoryUrl))) - .sorted(Comparator.reverseOrder()) - .map(Path::toFile) - .forEach(File::delete); - } catch (Exception e) { - LOG.warn("Failed to delete git repository: {}", gitRepositoryUrl, e); - } - } - } - - @Override - public GitHubRepository createRepository(String oauthToken, GitHubRepository gitHubRepository) { - try { - return new GitHubRepository(gitHubRepository.getName(), gitHubRepository.getDescription(), "url", "html_url", gitRepositoryUrl); - } catch (Exception e) { - throw new RuntimeException("Failed to create repository: " + gitHubRepository.getName(), e); - } - } - - @Override - public GitHubRepository getRepository(String oauthToken, String owner, String repo) { - return null; - } - - @Override - public void deleteRepository(String oauthToken, String owner, String repo) { - - } - - @Override - public GitHubUser getUser(String oauthToken) { - return new GitHubUser("testLogin", "testEmail", "testName"); - } - - @Override - public void createSecret(String oauthToken, String owner, String repo, String secretName, GitHubSecret secret) { - - } - - @Override - public GitHubSecretsPublicKey getSecretPublicKey(String oauthToken, String owner, String repo) { - return null; - } - - @Override - public GitHubWorkflowRuns listWorkflows(String oauthToken, String owner, String repo) { - return null; - } - - @Override - public GitHubWorkflowRun getWorkflowRun(String oauthToken, String owner, String repo, Long runId) { - return null; - } -} diff --git a/test-suite-graal/src/test/java/example/GitHubOAuthClientMock.java b/test-suite-graal/src/test/java/example/GitHubOAuthClientMock.java deleted file mode 100644 index cdb094bfb81..00000000000 --- a/test-suite-graal/src/test/java/example/GitHubOAuthClientMock.java +++ /dev/null @@ -1,16 +0,0 @@ -package example; - -import io.micronaut.context.annotation.Replaces; -import io.micronaut.starter.client.github.oauth.AccessToken; -import io.micronaut.starter.client.github.oauth.GitHubOAuthClient; -import jakarta.inject.Singleton; - -@Replaces(GitHubOAuthClient.class) -@Singleton -public class GitHubOAuthClientMock implements GitHubOAuthClient { - - @Override - public AccessToken accessToken(String clientId, String clientSecret, String code, String state) { - return new AccessToken("tokenTypeTest", "scopeTest", "accessTokenTest"); - } -} diff --git a/test-suite-graal/src/test/java/example/StarterWebNettyTest.java b/test-suite-graal/src/test/java/example/StarterWebNettyTest.java index f3c4ef91e65..1649eda1b50 100644 --- a/test-suite-graal/src/test/java/example/StarterWebNettyTest.java +++ b/test-suite-graal/src/test/java/example/StarterWebNettyTest.java @@ -5,7 +5,6 @@ import io.micronaut.http.client.HttpClient; import io.micronaut.http.client.annotation.Client; import io.micronaut.starter.api.StarterConfiguration; -import io.micronaut.starter.api.create.github.GitHubCreateDTO; import io.micronaut.starter.api.preview.PreviewDTO; import io.micronaut.starter.netty.Application; import io.micronaut.test.extensions.junit5.annotation.MicronautTest; @@ -18,7 +17,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue; @MicronautTest(application = Application.class) -public class StarterWebNettyTest { +class StarterWebNettyTest { private static final String BASE_URI = "/default/com.example.demo?lang=JAVA&build=GRADLE&test=JUNIT&javaVersion=JDK_17"; @@ -43,14 +42,6 @@ void testZipCreate() { assertTrue(response.getBody().isPresent()); } - @Test - void testGitHubCreate() { - starterConfiguration.setRedirectUri(null); - GitHubCreateDTO response = client.toBlocking().retrieve(HttpRequest.GET(GITHUB_CREATE_URI), GitHubCreateDTO.class); - assertNotNull(response); - assertNotNull(response.getCloneUrl()); - } - @Test void testPreview() { PreviewDTO response = client.toBlocking().retrieve(HttpRequest.GET(PREVIEW_URI), PreviewDTO.class); diff --git a/test-suite-graal/src/test/java/io/micronaut/starter/cli/command/CommandSupplier.java b/test-suite-graal/src/test/java/io/micronaut/starter/cli/command/CommandSupplier.java new file mode 100644 index 00000000000..2e8a6c01b63 --- /dev/null +++ b/test-suite-graal/src/test/java/io/micronaut/starter/cli/command/CommandSupplier.java @@ -0,0 +1,6 @@ +package io.micronaut.starter.cli.command; + +interface CommandSupplier { + + String nextCommand(); +} diff --git a/test-suite-graal/src/test/java/io/micronaut/starter/cli/command/CreateChatBotBuilderCommandTest.java b/test-suite-graal/src/test/java/io/micronaut/starter/cli/command/CreateChatBotBuilderCommandTest.java new file mode 100644 index 00000000000..9a8b0fc02ff --- /dev/null +++ b/test-suite-graal/src/test/java/io/micronaut/starter/cli/command/CreateChatBotBuilderCommandTest.java @@ -0,0 +1,98 @@ +package io.micronaut.starter.cli.command; + +import io.micronaut.context.ApplicationContext; +import io.micronaut.starter.application.OperatingSystem; +import io.micronaut.starter.application.generator.ProjectGenerator; +import io.micronaut.starter.feature.architecture.Arm; +import io.micronaut.starter.feature.architecture.X86; +import io.micronaut.starter.options.BuildTool; +import io.micronaut.starter.options.JdkVersion; +import io.micronaut.starter.options.Language; +import io.micronaut.starter.options.TestFramework; +import io.micronaut.starter.util.NameUtils; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +import java.util.HashSet; +import java.util.stream.Stream; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertEquals; + +class CreateChatBotBuilderCommandTest { + + static ApplicationContext applicationContext; + + @BeforeAll + static void setUp() { + applicationContext = ApplicationContext.run(); + } + + @AfterAll + static void tearDown() { + if (applicationContext != null) { + applicationContext.close(); + } + } + + static Stream provideCliOptions() { + return Stream.of(CreateChatBotBuilderCommand.ChatBotType.values()) + .flatMap(chatBotType -> Stream.of(CreateChatBotBuilderCommand.ChatBotDeployment.values()) + .flatMap(applicationType -> Stream.of(applicationContext.getBean(Arm.class), applicationContext.getBean(X86.class)) + .flatMap(cpuArchitecture -> Stream.of(false, true) + .flatMap(cdk -> Stream.of(Language.JAVA, Language.GROOVY, Language.KOTLIN) + .flatMap(language -> Stream.of(TestFramework.JUNIT, TestFramework.SPOCK, TestFramework.KOTEST) + .flatMap(testFramework -> Stream.of(BuildTool.GRADLE, BuildTool.GRADLE_KOTLIN, BuildTool.MAVEN) + .flatMap(buildTool -> + (applicationType == CreateChatBotBuilderCommand.ChatBotDeployment.AZURE ? Stream.of(JdkVersion.JDK_17) : Stream.of(JdkVersion.JDK_17, JdkVersion.JDK_21)) + .map(javaVersion -> + new CreateChatbotCommandCliOptions( + chatBotType, + applicationType, + cpuArchitecture, + cdk, + language, + testFramework, + buildTool, + javaVersion + ) + ) + ) + ) + ) + ) + ) + ) + ); + } + + @ParameterizedTest + @MethodSource("provideCliOptions") + void testCliOptions(CreateChatbotCommandCliOptions cliOptions) { + CreateChatBotBuilderCommand command = applicationContext.getBean(CreateChatBotBuilderCommand.class); + ProjectGenerator projectGenerator = applicationContext.getBean(ProjectGenerator.class); + + GenerateOptions options = command.createGenerateOptions(new StubbedLineReader(cliOptions)); + + assertEquals(cliOptions.getExpectedApplicationType(), options.getApplicationType()); + assertEquals(new HashSet<>(cliOptions.getFeatures()), options.getFeatures()); + assertEquals(cliOptions.language, options.getOptions().getLanguage()); + assertEquals(cliOptions.buildTool, options.getOptions().getBuildTool()); + assertEquals(cliOptions.testFramework, options.getOptions().getTestFramework()); + assertEquals(cliOptions.javaVersion, options.getOptions().getJavaVersion()); + + assertDoesNotThrow(() -> projectGenerator.generate( + options.getApplicationType(), + NameUtils.parse("foo"), + options.getOptions(), + OperatingSystem.LINUX, + cliOptions.getFeatures(), + new TemplateResolvingOutputHandler(), + new LoggingConsoleOutput() + ) + ); + } + +} diff --git a/test-suite-graal/src/test/java/io/micronaut/starter/cli/command/CreateChatbotCommandCliOptions.java b/test-suite-graal/src/test/java/io/micronaut/starter/cli/command/CreateChatbotCommandCliOptions.java new file mode 100644 index 00000000000..1d2972cb2ce --- /dev/null +++ b/test-suite-graal/src/test/java/io/micronaut/starter/cli/command/CreateChatbotCommandCliOptions.java @@ -0,0 +1,120 @@ +package io.micronaut.starter.cli.command; + +import io.micronaut.starter.application.ApplicationType; +import io.micronaut.starter.feature.architecture.Arm; +import io.micronaut.starter.feature.architecture.CpuArchitecture; +import io.micronaut.starter.feature.aws.LambdaFunctionUrl; +import io.micronaut.starter.feature.chatbots.basecamp.BasecampAwsChatBot; +import io.micronaut.starter.feature.chatbots.basecamp.BasecampAzureChatBot; +import io.micronaut.starter.feature.chatbots.basecamp.BasecampGcpChatBot; +import io.micronaut.starter.feature.chatbots.basecamp.BasecampHttpChatBot; +import io.micronaut.starter.feature.chatbots.telegram.TelegramAwsChatBot; +import io.micronaut.starter.feature.chatbots.telegram.TelegramAzureChatBot; +import io.micronaut.starter.feature.chatbots.telegram.TelegramGcpChatBot; +import io.micronaut.starter.feature.chatbots.telegram.TelegramHttpChatBot; +import io.micronaut.starter.options.BuildTool; +import io.micronaut.starter.options.JdkVersion; +import io.micronaut.starter.options.Language; +import io.micronaut.starter.options.TestFramework; + +import java.util.ArrayList; +import java.util.List; + +class CreateChatbotCommandCliOptions implements CommandSupplier { + + final CreateChatBotBuilderCommand.ChatBotType chatBotType; + final CreateChatBotBuilderCommand.ChatBotDeployment applicationType; + final CpuArchitecture cpuArchitecture; + final boolean cdk; + final Language language; + final TestFramework testFramework; + final BuildTool buildTool; + final JdkVersion javaVersion; + int index = 0; + + CreateChatbotCommandCliOptions( + CreateChatBotBuilderCommand.ChatBotType chatBotType, + CreateChatBotBuilderCommand.ChatBotDeployment applicationType, + CpuArchitecture cpuArchitecture, + boolean cdk, + Language language, + TestFramework testFramework, + BuildTool buildTool, + JdkVersion javaVersion + ) { + this.chatBotType = chatBotType; + this.applicationType = applicationType; + this.cpuArchitecture = cpuArchitecture; + this.cdk = cdk; + this.language = language; + this.testFramework = testFramework; + this.buildTool = buildTool; + this.javaVersion = javaVersion; + } + + List getFeatures() { + return switch (applicationType) { + case LAMBDA -> { + String type = chatBotType == CreateChatBotBuilderCommand.ChatBotType.BASECAMP ? BasecampAwsChatBot.NAME : TelegramAwsChatBot.NAME; + yield cdk ? List.of(type, cpuArchitecture.getName(), LambdaFunctionUrl.NAME) : List.of(type, cpuArchitecture.getName()); + } + case AZURE -> + List.of(chatBotType == CreateChatBotBuilderCommand.ChatBotType.BASECAMP ? BasecampAzureChatBot.NAME : TelegramAzureChatBot.NAME); + case GCP -> + List.of(chatBotType == CreateChatBotBuilderCommand.ChatBotType.BASECAMP ? BasecampGcpChatBot.NAME : TelegramGcpChatBot.NAME); + case HTTP -> + List.of(chatBotType == CreateChatBotBuilderCommand.ChatBotType.BASECAMP ? BasecampHttpChatBot.NAME : TelegramHttpChatBot.NAME); + }; + } + + ApplicationType getExpectedApplicationType() { + if (applicationType == CreateChatBotBuilderCommand.ChatBotDeployment.HTTP) { + return ApplicationType.DEFAULT; + } + return ApplicationType.FUNCTION; + } + + List getCliCommands() { + List ret = new ArrayList<>(); + ret.add("%d".formatted(chatBotType.ordinal() + 1)); + ret.add("%d".formatted(applicationType.ordinal() + 1)); + if (applicationType == CreateChatBotBuilderCommand.ChatBotDeployment.LAMBDA) { + ret.add(cpuArchitecture instanceof Arm ? "1" : "2"); + ret.add(cdk ? "1" : "2"); + } + ret.add("%d".formatted(language.ordinal() + 1)); + ret.add("%d".formatted(testFramework.ordinal() + 1)); + ret.add("%d".formatted(buildTool.ordinal() + 1)); + ret.add(javaVersion == JdkVersion.JDK_17 ? "1" : "2"); + return ret; + } + + @Override + public String toString() { + if (applicationType == CreateChatBotBuilderCommand.ChatBotDeployment.LAMBDA) { + return "%s %s %s %s %s %s %s %s".formatted( + chatBotType.name(), + applicationType.name(), + cpuArchitecture.getName(), + cdk, + language.name(), + testFramework.name(), + buildTool.name(), + javaVersion.name() + ); + } else { + return "%s %s %s %s %s %s".formatted( + chatBotType.name(), + applicationType.name(), + language.name(), + testFramework.name(), + buildTool.name(), + javaVersion.name() + ); + } + } + + public String nextCommand() { + return getCliCommands().get(index++); + } +} diff --git a/test-suite-graal/src/test/java/io/micronaut/starter/cli/command/CreateLambdaCommandCliOptions.java b/test-suite-graal/src/test/java/io/micronaut/starter/cli/command/CreateLambdaCommandCliOptions.java new file mode 100644 index 00000000000..f54f6cb3626 --- /dev/null +++ b/test-suite-graal/src/test/java/io/micronaut/starter/cli/command/CreateLambdaCommandCliOptions.java @@ -0,0 +1,122 @@ +package io.micronaut.starter.cli.command; + +import io.micronaut.core.annotation.Nullable; +import io.micronaut.starter.application.ApplicationType; +import io.micronaut.starter.feature.Feature; +import io.micronaut.starter.feature.architecture.Arm; +import io.micronaut.starter.feature.architecture.CpuArchitecture; +import io.micronaut.starter.feature.aws.Cdk; +import io.micronaut.starter.feature.function.awslambda.AwsLambda; +import io.micronaut.starter.feature.graalvm.GraalVM; +import io.micronaut.starter.options.BuildTool; +import io.micronaut.starter.options.JdkVersion; +import io.micronaut.starter.options.Language; +import io.micronaut.starter.options.TestFramework; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +class CreateLambdaCommandCliOptions implements CommandSupplier { + + final CodingStyle codingStyle; + final Feature apiFeature; + final LambdaDeployment lambdaDeployment; + final CpuArchitecture cpuArchitecture; + final boolean cdk; + final Language language; + final TestFramework testFramework; + final BuildTool buildTool; + final String javaVersion; + + final List allApiFeatures; + final List allLanguages; + final List allJdkVersions; + @Nullable final String expectedExceptionMessage; + + private int index = 0; + + CreateLambdaCommandCliOptions( + CodingStyle codingStyle, + Feature apiFeatures, + List allApiFeatures, + LambdaDeployment lambdaDeployment, + CpuArchitecture cpuArchitecture, + boolean cdk, + Language language, + Language[] allLanguages, + TestFramework testFramework, + BuildTool buildTool, + String javaVersion, + List allJdkVersions, + @Nullable String expectedExceptionMessage + ) { + this.codingStyle = codingStyle; + this.apiFeature = apiFeatures; + this.allApiFeatures = allApiFeatures; + this.lambdaDeployment = lambdaDeployment; + this.cpuArchitecture = cpuArchitecture; + this.cdk = cdk; + this.language = language; + this.allLanguages = Arrays.asList(allLanguages); + this.testFramework = testFramework; + this.buildTool = buildTool; + this.javaVersion = javaVersion; + this.allJdkVersions = allJdkVersions; + this.expectedExceptionMessage = expectedExceptionMessage; + } + + List getFeatures() { + List features = new ArrayList<>(); + features.add(AwsLambda.FEATURE_NAME_AWS_LAMBDA); + features.add(apiFeature.getName()); + if (lambdaDeployment == LambdaDeployment.NATIVE_EXECUTABLE) { + features.add(GraalVM.FEATURE_NAME_GRAALVM); + } + features.add(cpuArchitecture.getName()); + if (cdk) { + features.add(Cdk.NAME); + } + return features; + } + + ApplicationType getExpectedApplicationType() { + if (codingStyle != CodingStyle.HANDLER) { + return ApplicationType.DEFAULT; + } + return ApplicationType.FUNCTION; + } + + List getCliCommands() { + List commands = new ArrayList<>(); + commands.add("" + (codingStyle.ordinal() + 1)); + commands.add("" + (allApiFeatures.indexOf(apiFeature) + 1)); + commands.add("" + (lambdaDeployment.ordinal() + 1)); + commands.add(cpuArchitecture instanceof Arm ? "1" : "2"); + commands.add(cdk ? "1" : "2"); + commands.add("" + (allLanguages.indexOf(language) + 1)); + commands.add("" + (testFramework.ordinal() + 1)); + commands.add("" + (buildTool.ordinal() + 1)); + commands.add("" + (allJdkVersions.indexOf(javaVersion) + 1)); + return commands; + } + + @Override + public String toString() { + return "%s %s %s %s cdk:%s %s %s %s %s".formatted( + codingStyle, + apiFeature.getName(), + lambdaDeployment, + cpuArchitecture.getName(), + cdk, + language, + testFramework, + buildTool, + javaVersion + ); + } + + public String nextCommand() { + return getCliCommands().get(index++); + } +} diff --git a/test-suite-graal/src/test/java/io/micronaut/starter/cli/command/CreateLambdaCommandTest.java b/test-suite-graal/src/test/java/io/micronaut/starter/cli/command/CreateLambdaCommandTest.java new file mode 100644 index 00000000000..df182d87a83 --- /dev/null +++ b/test-suite-graal/src/test/java/io/micronaut/starter/cli/command/CreateLambdaCommandTest.java @@ -0,0 +1,132 @@ +package io.micronaut.starter.cli.command; + +import io.micronaut.context.ApplicationContext; +import io.micronaut.starter.application.ApplicationType; +import io.micronaut.starter.application.OperatingSystem; +import io.micronaut.starter.application.generator.ProjectGenerator; +import io.micronaut.starter.feature.Feature; +import io.micronaut.starter.feature.architecture.Arm; +import io.micronaut.starter.feature.architecture.X86; +import io.micronaut.starter.feature.aws.LambdaFunctionUrl; +import io.micronaut.starter.options.BuildTool; +import io.micronaut.starter.options.TestFramework; +import io.micronaut.starter.util.NameUtils; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +import java.util.HashSet; +import java.util.List; +import java.util.stream.Stream; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +class CreateLambdaCommandTest { + + static ApplicationContext applicationContext; + static CreateLambdaBuilderCommand command; + + @BeforeAll + static void setUp() { + applicationContext = ApplicationContext.run(); + command = applicationContext.getBean(CreateLambdaBuilderCommand.class); + } + + @AfterAll + static void tearDown() { + if (applicationContext != null) { + applicationContext.close(); + } + } + + static Stream provideCliOptions() { + return Stream.of(CodingStyle.values()) + .flatMap(codingStyle -> Stream.of(LambdaDeployment.values()) + .flatMap(lambdaDeployment -> Stream.of(applicationContext.getBean(Arm.class), applicationContext.getBean(X86.class)) + .flatMap(cpuArchitecture -> Stream.of(false, true) + .flatMap(cdk -> Stream.of(CreateLambdaBuilderCommand.languagesForDeployment(lambdaDeployment)) + .flatMap(language -> Stream.of(TestFramework.JUNIT, TestFramework.SPOCK, TestFramework.KOTEST) + .flatMap(testFramework -> Stream.of(BuildTool.GRADLE, BuildTool.GRADLE_KOTLIN, BuildTool.MAVEN) + .flatMap(buildTool -> getAllApiFeatures(codingStyle).stream() + .flatMap(feature -> command.getJdkVersionCandidates().stream() + .map(jdkVersion -> new CreateLambdaCommandCliOptions( + codingStyle, + feature, + getAllApiFeatures(codingStyle), + lambdaDeployment, + cpuArchitecture, + cdk, + language, + CreateLambdaBuilderCommand.languagesForDeployment(lambdaDeployment), + testFramework, + buildTool, + jdkVersion, + command.getJdkVersionCandidates(), + invalid(feature, cdk, buildTool, lambdaDeployment) + )) + ) + ) + ) + ) + ) + ) + ) + ); + } + + /** + * We don't support GraalVM with Maven and CDK, though the tool does allow this combination. + */ + private static String invalid(Feature feature, boolean cdk, BuildTool buildTool, LambdaDeployment lambdaDeployment) { + boolean hasCdk = feature instanceof LambdaFunctionUrl || cdk; + if (hasCdk && buildTool == BuildTool.MAVEN && lambdaDeployment == LambdaDeployment.NATIVE_EXECUTABLE) { + return "Maven, CDK and GraalVM are not yet supported"; + } + return null; + } + + private static List getAllApiFeatures(CodingStyle codingStyle) { + return codingStyle == CodingStyle.CONTROLLERS ? + CreateLambdaBuilderCommand.apiTriggerFeatures(ApplicationType.DEFAULT, applicationContext.getBeansOfType(Feature.class)) : + CreateLambdaBuilderCommand.triggerFeatures(applicationContext.getBeansOfType(Feature.class)); + } + + @ParameterizedTest + @MethodSource("provideCliOptions") + void testCliOptions(CreateLambdaCommandCliOptions cliOptions) { + CreateLambdaBuilderCommand command = applicationContext.getBean(CreateLambdaBuilderCommand.class); + ProjectGenerator projectGenerator = applicationContext.getBean(ProjectGenerator.class); + + GenerateOptions options = command.createGenerateOptions(new StubbedLineReader(cliOptions)); + + assertEquals(cliOptions.getExpectedApplicationType(), options.getApplicationType()); + assertEquals(new HashSet<>(cliOptions.getFeatures()), options.getFeatures()); + assertEquals(cliOptions.language, options.getOptions().getLanguage()); + assertEquals(cliOptions.buildTool, options.getOptions().getBuildTool()); + assertEquals(cliOptions.testFramework, options.getOptions().getTestFramework()); + assertEquals(cliOptions.javaVersion, options.getOptions().getJavaVersion().asString()); + + if (cliOptions.expectedExceptionMessage != null) { + IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> generate(projectGenerator, options)); + assertEquals(cliOptions.expectedExceptionMessage, ex.getMessage()); + } else { + assertDoesNotThrow(() -> generate(projectGenerator, options) + ); + } + } + + private static void generate(ProjectGenerator projectGenerator, GenerateOptions options) throws Exception { + projectGenerator.generate( + options.getApplicationType(), + NameUtils.parse("foo"), + options.getOptions(), + OperatingSystem.LINUX, + options.getFeatures().stream().toList(), + new TemplateResolvingOutputHandler(), + new LoggingConsoleOutput() + ); + } +} diff --git a/test-suite-graal/src/test/java/io/micronaut/starter/cli/command/LoggingConsoleOutput.java b/test-suite-graal/src/test/java/io/micronaut/starter/cli/command/LoggingConsoleOutput.java new file mode 100644 index 00000000000..d9dae39c524 --- /dev/null +++ b/test-suite-graal/src/test/java/io/micronaut/starter/cli/command/LoggingConsoleOutput.java @@ -0,0 +1,35 @@ +package io.micronaut.starter.cli.command; + +import io.micronaut.starter.io.ConsoleOutput; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +class LoggingConsoleOutput implements ConsoleOutput { + + private static final Logger LOG = LoggerFactory.getLogger(LoggingConsoleOutput.class); + + @Override + public void out(String message) { + LOG.info(message); + } + + @Override + public void err(String message) { + LOG.error(message); + } + + @Override + public void warning(String message) { + LOG.warn(message); + } + + @Override + public boolean showStacktrace() { + return false; + } + + @Override + public boolean verbose() { + return false; + } +} diff --git a/test-suite-graal/src/test/java/io/micronaut/starter/cli/command/NullOutputStream.java b/test-suite-graal/src/test/java/io/micronaut/starter/cli/command/NullOutputStream.java new file mode 100644 index 00000000000..6eafbe59019 --- /dev/null +++ b/test-suite-graal/src/test/java/io/micronaut/starter/cli/command/NullOutputStream.java @@ -0,0 +1,12 @@ +package io.micronaut.starter.cli.command; + +import java.io.IOException; +import java.io.OutputStream; + +class NullOutputStream extends OutputStream { + + @Override + public void write(int b) throws IOException { + // do nothing + } +} diff --git a/test-suite-graal/src/test/java/io/micronaut/starter/cli/command/StubbedLineReader.java b/test-suite-graal/src/test/java/io/micronaut/starter/cli/command/StubbedLineReader.java new file mode 100644 index 00000000000..409a0ff6175 --- /dev/null +++ b/test-suite-graal/src/test/java/io/micronaut/starter/cli/command/StubbedLineReader.java @@ -0,0 +1,261 @@ +package io.micronaut.starter.cli.command; + +import org.jline.keymap.KeyMap; +import org.jline.reader.Binding; +import org.jline.reader.Buffer; +import org.jline.reader.EndOfFileException; +import org.jline.reader.Expander; +import org.jline.reader.Highlighter; +import org.jline.reader.History; +import org.jline.reader.LineReader; +import org.jline.reader.MaskingCallback; +import org.jline.reader.ParsedLine; +import org.jline.reader.Parser; +import org.jline.reader.UserInterruptException; +import org.jline.reader.Widget; +import org.jline.terminal.MouseEvent; +import org.jline.terminal.Terminal; +import org.jline.utils.AttributedString; + +import java.io.File; +import java.util.Collection; +import java.util.Map; + +class StubbedLineReader implements LineReader { + + private final CommandSupplier commandSupplier; + + StubbedLineReader(CommandSupplier commandSupplier) { + this.commandSupplier = commandSupplier; + } + + @Override + public Map> defaultKeyMaps() { + return null; + } + + @Override + public String readLine() throws UserInterruptException, EndOfFileException { + return null; + } + + @Override + public String readLine(Character character) throws UserInterruptException, EndOfFileException { + return null; + } + + @Override + public String readLine(String s) throws UserInterruptException, EndOfFileException { + return commandSupplier.nextCommand(); + } + + @Override + public String readLine(String s, Character character) throws UserInterruptException, EndOfFileException { + return null; + } + + @Override + public String readLine(String s, Character character, String s1) throws UserInterruptException, EndOfFileException { + return null; + } + + @Override + public String readLine(String s, String s1, Character character, String s2) throws UserInterruptException, EndOfFileException { + return null; + } + + @Override + public String readLine(String s, String s1, MaskingCallback maskingCallback, String s2) throws UserInterruptException, EndOfFileException { + return null; + } + + @Override + public void printAbove(String s) { + + } + + @Override + public void printAbove(AttributedString attributedString) { + + } + + @Override + public boolean isReading() { + return false; + } + + @Override + public LineReader variable(String s, Object o) { + return null; + } + + @Override + public LineReader option(Option option, boolean b) { + return null; + } + + @Override + public void callWidget(String s) { + + } + + @Override + public Map getVariables() { + return null; + } + + @Override + public Object getVariable(String s) { + return null; + } + + @Override + public void setVariable(String s, Object o) { + + } + + @Override + public boolean isSet(Option option) { + return false; + } + + @Override + public void setOpt(Option option) { + + } + + @Override + public void unsetOpt(Option option) { + + } + + @Override + public Terminal getTerminal() { + return null; + } + + @Override + public Map getWidgets() { + return null; + } + + @Override + public Map getBuiltinWidgets() { + return null; + } + + @Override + public Buffer getBuffer() { + return null; + } + + @Override + public String getAppName() { + return null; + } + + @Override + public void runMacro(String s) { + + } + + @Override + public MouseEvent readMouseEvent() { + return null; + } + + @Override + public History getHistory() { + return null; + } + + @Override + public Parser getParser() { + return null; + } + + @Override + public Highlighter getHighlighter() { + return null; + } + + @Override + public Expander getExpander() { + return null; + } + + @Override + public Map> getKeyMaps() { + return null; + } + + @Override + public String getKeyMap() { + return null; + } + + @Override + public boolean setKeyMap(String s) { + return false; + } + + @Override + public KeyMap getKeys() { + return null; + } + + @Override + public ParsedLine getParsedLine() { + return null; + } + + @Override + public String getSearchTerm() { + return null; + } + + @Override + public RegionType getRegionActive() { + return null; + } + + @Override + public int getRegionMark() { + return 0; + } + + @Override + public void addCommandsInBuffer(Collection collection) { + + } + + @Override + public void editAndAddInBuffer(File file) throws Exception { + + } + + @Override + public String getLastBinding() { + return null; + } + + @Override + public String getTailTip() { + return null; + } + + @Override + public void setTailTip(String s) { + + } + + @Override + public void setAutosuggestion(SuggestionType suggestionType) { + + } + + @Override + public SuggestionType getAutosuggestion() { + return null; + } +} diff --git a/test-suite-graal/src/test/java/io/micronaut/starter/cli/command/TemplateResolvingOutputHandler.java b/test-suite-graal/src/test/java/io/micronaut/starter/cli/command/TemplateResolvingOutputHandler.java new file mode 100644 index 00000000000..e6be5ad5012 --- /dev/null +++ b/test-suite-graal/src/test/java/io/micronaut/starter/cli/command/TemplateResolvingOutputHandler.java @@ -0,0 +1,38 @@ +package io.micronaut.starter.cli.command; + +import io.micronaut.starter.io.OutputHandler; +import io.micronaut.starter.template.Template; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.io.OutputStream; + +class TemplateResolvingOutputHandler implements OutputHandler { + + private static final Logger LOG = LoggerFactory.getLogger(TemplateResolvingOutputHandler.class); + private final OutputStream outputStream = new NullOutputStream(); + + @Override + public boolean exists(String path) { + return false; + } + + @Override + public void write(String path, Template contents) throws IOException { + if (LOG.isTraceEnabled()) { + LOG.trace("Writing to path: {}", path); + } + // Force the contents to be rendered to shake out any rendering issues + contents.write(outputStream); + } + + @Override + public String getOutputLocation() { + return "something"; + } + + @Override + public void close() throws IOException { + } +} diff --git a/test-utils/build.gradle b/test-utils/build.gradle index 54077a4decc..ee624adfa8a 100644 --- a/test-utils/build.gradle +++ b/test-utils/build.gradle @@ -8,5 +8,5 @@ dependencies { implementation("org.spockframework:spock-core:$spockVersion") { exclude group: "org.apache.groovy", module: "groovy-all" } - implementation project(":starter-core") + implementation(project(":starter-core")) } diff --git a/test-utils/src/main/groovy/io/micronaut/starter/test/CommandSpec.groovy b/test-utils/src/main/groovy/io/micronaut/starter/test/CommandSpec.groovy index 85aa14d7431..32f08c28bb9 100644 --- a/test-utils/src/main/groovy/io/micronaut/starter/test/CommandSpec.groovy +++ b/test-utils/src/main/groovy/io/micronaut/starter/test/CommandSpec.groovy @@ -27,6 +27,7 @@ import io.micronaut.starter.io.OutputHandler import io.micronaut.starter.options.BuildTool import io.micronaut.starter.options.JdkVersion import io.micronaut.starter.options.Language +import io.micronaut.starter.options.MicronautJdkVersionConfiguration import io.micronaut.starter.options.Options import io.micronaut.starter.options.TestFramework import io.micronaut.starter.util.NameUtils @@ -126,11 +127,11 @@ abstract class CommandSpec extends Specification { ApplicationType applicationType = ApplicationType.DEFAULT, TestFramework testFramework = lang.getDefaults().test, boolean addMicronautGradleEnterpriseFeature = true, - JdkVersion maxJdkVersion = JdkVersion.JDK_17) { + JdkVersion maxJdkVersion = MicronautJdkVersionConfiguration.DEFAULT_OPTION) { if (addMicronautGradleEnterpriseFeature) { features += [MicronautGradleEnterprise.NAME] } - JdkVersion jdkVersion = VersionInfo.getJavaVersion(); + JdkVersion jdkVersion = VersionInfo.getJavaVersion() if (jdkVersion.greaterThanEqual(maxJdkVersion)) { jdkVersion = maxJdkVersion } @@ -144,6 +145,28 @@ abstract class CommandSpec extends Specification { ) } + void generateProjectForVersion( + Language lang, + JdkVersion jdkVersion, + BuildTool buildTool = BuildTool.DEFAULT_OPTION, + List features = [], + ApplicationType applicationType = ApplicationType.DEFAULT, + TestFramework testFramework = lang.getDefaults().test, + boolean addMicronautGradleEnterpriseFeature = true + ) { + if (addMicronautGradleEnterpriseFeature) { + features += [MicronautGradleEnterprise.NAME] + } + beanContext.getBean(ProjectGenerator).generate(applicationType, + NameUtils.parse("example.micronaut.foo"), + new Options(lang, testFramework, buildTool, jdkVersion), + io.micronaut.starter.application.OperatingSystem.LINUX, + features, + new FileSystemOutputHandler(dir, ConsoleOutput.NOOP), + ConsoleOutput.NOOP + ) + } + void generateProject(Project project, Language lang, BuildTool buildTool = BuildTool.DEFAULT_OPTION, diff --git a/test-utils/src/main/groovy/io/micronaut/starter/test/PredicateUtils.groovy b/test-utils/src/main/groovy/io/micronaut/starter/test/PredicateUtils.groovy new file mode 100644 index 00000000000..65e1616e7f5 --- /dev/null +++ b/test-utils/src/main/groovy/io/micronaut/starter/test/PredicateUtils.groovy @@ -0,0 +1,39 @@ +/* + * Copyright 2017-2024 original authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.micronaut.starter.test + +import groovy.transform.CompileStatic +import org.gradle.internal.os.OperatingSystem + +import java.util.function.Predicate + +@CompileStatic +final class PredicateUtils { + private PredicateUtils() { + } + + static Predicate testFeatureIfMacOS(List featuresNames) { + return new Predicate() { + @Override + boolean test(String s) { + if (featuresNames.contains(s)) { + return !OperatingSystem.current().isMacOsX() + } + true + } + } + } +}