diff --git a/.github/workflows/1.pipeline.yml b/.github/workflows/1.pipeline.yml index 9756699..5837ac9 100644 --- a/.github/workflows/1.pipeline.yml +++ b/.github/workflows/1.pipeline.yml @@ -46,31 +46,6 @@ jobs: uses: ./.github/workflows/callable.integration-test.yml needs: build - gradle_release: - name: Create release - uses: ./.github/workflows/callable.gradle-release.yml - secrets: inherit - with: - type: ${{ inputs.type }} - needs: integration_test - if: | - github.event_name == 'workflow_dispatch' - && inputs.type != '...no release' - - publish_sonatype: - name: Publish artifact (Maven Central) - uses: ./.github/workflows/callable.publish-sonatype.yml - secrets: inherit - needs: integration_test - if: | - ( - github.event_name != 'workflow_dispatch' - || inputs.type == '...no release' - ) && ( - github.ref == 'refs/heads/main' - || github.ref_type == 'tag' - ) - publish_javadoc: name: Publish javadoc (GitHub Pages) permissions: diff --git a/.github/workflows/callable.gradle-release.yml b/.github/workflows/callable.gradle-release.yml deleted file mode 100644 index 2a684f0..0000000 --- a/.github/workflows/callable.gradle-release.yml +++ /dev/null @@ -1,76 +0,0 @@ -name: Gradle Release - -on: - workflow_call: - inputs: - type: - description: 'Release type' - required: true - type: string - -jobs: - release: - name: gradle release - runs-on: ubuntu-latest - steps: - - name: Validate 'Release Type' param - env: - TYPE: ${{ inputs.type }} - run: | - valid_types=(major minor patch) - if [[ ! ${valid_types[*]} =~ "$TYPE" ]]; then - echo "Unknown release type: $TYPE" - exit 1 - fi - - name: Checkout project sources ('main' branch) - uses: actions/checkout@v4 - with: - ref: main - token: ${{ secrets.CI_GITHUB_TOKEN }} - - uses: actions/setup-java@v4 - with: - distribution: 'corretto' - java-version: '21' - - uses: gradle/wrapper-validation-action@v1 - - name: Setup Gradle - uses: gradle/gradle-build-action@v2.11.1 - with: - cache-read-only: true - - - name: Get current version - run: | - source gradle.properties - echo "current_version=${version}" >> $GITHUB_ENV - - - name: Determine version type - env: - TYPE: ${{ inputs.type }} - VERSION: ${{ env.current_version }} - run: | - export major=$(echo "${VERSION}" | cut -d. -f1) - export minor=$(echo "${VERSION}" | cut -d. -f2) - export patch=$(echo "${VERSION}" | cut -d. -f3 | cut -d- -f1) - echo "resolved: ${major}.${minor}.${patch}" - - if [[ "$TYPE" == "major" ]]; then - echo "new_version=$((major+1)).0.0" >> $GITHUB_ENV - echo "new_snapshot_version=$((major+1)).0.1-SNAPSHOT" >> $GITHUB_ENV - elif [ "$TYPE" == "minor" ]; then - echo "new_version=${major}.$((minor+1)).0" >> $GITHUB_ENV - echo "new_snapshot_version=${major}.$((minor+1)).1-SNAPSHOT" >> $GITHUB_ENV - else - echo "new_version=${major}.${minor}.${patch}" >> $GITHUB_ENV - echo "new_snapshot_version=${major}.${minor}.$((patch+1))-SNAPSHOT" >> $GITHUB_ENV - fi - - name: Set git config 'user.name' and 'user.email' - run: | - git config --local user.email "action@github.com" - git config --local user.name "GitHub Action" - - name: Run 'gradle release' - run: | - echo "Type: ${{ inputs.type }}" - echo "Current version: ${{ env.current_version }}" - echo "New version: ${{ env.new_version }}" - echo "New snapshot version: ${{ env.new_snapshot_version }}" - echo "./gradlew release -Prelease.useAutomaticVersion=true -Prelease.releaseVersion=${{ env.new_version }} -Prelease.newVersion=${{ env.new_snapshot_version }}" - gradle release -Prelease.useAutomaticVersion=true -Prelease.releaseVersion=${{ env.new_version }} -Prelease.newVersion=${{ env.new_snapshot_version }} diff --git a/.github/workflows/callable.publish-sonatype.yml b/.github/workflows/callable.publish-sonatype.yml deleted file mode 100644 index 94f245f..0000000 --- a/.github/workflows/callable.publish-sonatype.yml +++ /dev/null @@ -1,39 +0,0 @@ -name: Publish to Sonatype (Maven Central) -on: - workflow_call: - -jobs: - publish: - name: gradle publish (Maven Central) - runs-on: ubuntu-latest - steps: - - name: Checkout project sources - uses: actions/checkout@v4 - - - uses: actions/setup-java@v4 - with: - distribution: 'corretto' - java-version: '21' - - uses: gradle/wrapper-validation-action@v1 - - name: Setup Gradle - uses: gradle/gradle-build-action@v2.11.1 - with: - cache-read-only: true - - # note the following two steps are identical but different names for better DX in GitHub Actions UI - - name: Publish SNAPSHOT to Sonatype (Maven Central) - if: github.ref == 'refs/heads/main' - run: ./gradlew publishToSonatype closeAndReleaseSonatypeStagingRepository - env: - GPG_SIGNING_KEY: ${{ secrets.GPG_SIGNING_KEY }} - GPG_SIGNING_PASSPHRASE: ${{ secrets.GPG_SIGNING_PASSPHRASE }} - OSSRH_PASSWORD: ${{ secrets.OSSRH_PASSWORD }} - OSSRH_USERNAME: ${{ secrets.OSSRH_USERNAME }} - - name: Publish RELEASE to Sonatype (Maven Central) - if: github.ref_type == 'tag' - run: ./gradlew publishToSonatype closeAndReleaseSonatypeStagingRepository - env: - GPG_SIGNING_KEY: ${{ secrets.GPG_SIGNING_KEY }} - GPG_SIGNING_PASSPHRASE: ${{ secrets.GPG_SIGNING_PASSPHRASE }} - OSSRH_PASSWORD: ${{ secrets.OSSRH_PASSWORD }} - OSSRH_USERNAME: ${{ secrets.OSSRH_USERNAME }} diff --git a/README.md b/README.md index ceabcf4..7161932 100644 --- a/README.md +++ b/README.md @@ -2,180 +2,17 @@ [![Use this template](https://img.shields.io/badge/from-java--library--template-brightgreen?logo=dropbox)](https://github.com/thriving-dev/java-library-template/generate) [![Java CI](https://github.com/thriving-dev/micronaut-gradle-renovate-example/actions/workflows/1.pipeline.yml/badge.svg)](https://github.com/thriving-dev/micronaut-gradle-renovate-example/actions/workflows/1.pipeline.yml) -[![Maven Central](https://img.shields.io/maven-central/v/dev.thriving.example/micronaut-gradle-renovate-example.svg)](https://central.sonatype.com/artifact/dev.thriving.example/micronaut-gradle-renovate-example) [![Contributor Covenant](https://img.shields.io/badge/Contributor%20Covenant-2.1-4baaaa.svg)](CODE_OF_CONDUCT.md) [![Javadoc](https://img.shields.io/badge/JavaDoc-Online-green)](https://thriving-dev.github.io/micronaut-gradle-renovate-example/javadoc/) -Automated migration completed, enjoy the template. +Micronaut gradle project with automated dependency updates by renovate that _actually_ updates the micronaut runtime used. -## Features -- đŸĨˇ One-click **automated initial project migration workflow** (GitHub Action) -- **Java 21** (corretto) 🤝 **Gradle Kotlin DSL**, version catalog -- **GitHub Actions CI/CD pipeline**, 👷 efficient build pipeline, caching, integration tests, test report & failed test annotations -- 🚀 **One-click release** process + **publish** to **Maven Central** -- **Security & đŸšĻ Vulnerability scan** with **[trivy](https://github.com/aquasecurity/trivy)** & GitHub CodeQL Analysis -- **Automated dependency updates** with **[Renovate](https://github.com/renovatebot/renovate)** 🤖 -- **Javadoc** deployed with **GitHub Pages** -- Open Source **Community ready** (Code of Conduct, Contribution guidelines, Issue & PR Templates) +TLDR: Projects created via [Micronaut Launch](https://micronaut.io/launch) define the micronaut version to be used in the `gradle.properties` file which is not discoverable by renovate. +Further, switching from the properties file to [version catalog](https://docs.gradle.org/current/userguide/platforms.html#sub:central-declaration-of-dependencies) the version also is not discoverable/resolvable by renovate. -## Quick Start -1. [Use this template](https://github.com/thriving-dev/java-library-template/generate) to create your own repository -2. Create & provide a PAT (Personal Access Token) for the CI/CD pipeline - - Three workflows commit and push changes to the repository and therefore require additional permissions. ('migrate-repo-template', 'publish-javadoc', 'gradle-release') - - The jobs expect a secret by the name `CI_GITHUB_TOKEN` that holds a PAT with _write_ permission for _Content_. - - To create a new access token, the following steps are required (ref [GitHub documentation](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens#creating-a-fine-grained-personal-access-token)): - 1. If the new repo owner is an organisation, **enrol** the organisation for '**Fine-grained personal access tokens**'. In the organisation ['Settings > Third-party Access > Personal access tokens'](https://github.com/organizations/thriving-dev/settings/personal-access-tokens). - 2. Head to the [Developer settings](https://github.com/settings/tokens?type=beta) and **enrol** your personal account for the new '**Fine-grained personal access tokens**'. (That's a one-off for your account and you might already have done this before) - 3. Next, click on the button '**Generate new token**' and create a token for the target _**Resource owner**_, with access to your project and the following '**Repository Permissions**' - * **Contents:** **Read** and **Write** access to code - * **Metadata:** **Read** access to metadata - - image - - 4. Provide your new PAT either as an Organisation secret or a Repository secret with the name `CI_GITHUB_TOKEN`. - - - -3. Trigger the '**!! INITIAL: Migrate Repo Template !!**' workflow - - ℹī¸ This workflow automatically 'migrates' all files in your new repository, updating the **gradle project group**, **module name**, **package names**, and **all references** to the repo `/`. - - - Head over to **Actions** (1) - - on the left-hand side select the topmost workflow '**!! INITIAL: Migrate Repo Template !!**' (2) - - click the **Run workflow** button (3) - - **fill out** the form & **start** the pipeline (4)(5) - - ![image](https://github.com/thriving-dev/java-library-template/assets/10864443/41a380d5-e521-4050-9296-9f5bee4088e6) - -4. Final one-off tasks - * Choose & update the LICENSE, [here](LICENSE) - * Update _Maven Publication_ details [here](micronaut-gradle-renovate-example/build.gradle.kts#L6-L13) - * [Configure GitHub Pages](#prerequisites-configure-github-pages) to deploy branch 'gh-pages' (Javadoc) - * Add secrets required for [publishing to Maven Central](#prerequisites-sonatype-credentials--gpg-signing-key) - * Install & configure renovate app ([instructions](#prerequisites-enable--configure-renovate)) - -## Project Structure -The project template consists of three top-level _folders_: -* `.github/`: Defines the GitHub Actions CI tasks and templates for new pull requests, issues, etc. -* `gradle/`: Contains Gradle Configuration files such as the Gradle [Version Catalog](https://docs.gradle.org/current/userguide/platforms.html) and the Gradle Wrapper. -* `micronaut-gradle-renovate-example/`: The library source code (Gradle sub-project). - -In addition, following _files_ are worth highlighting: -* `gradle/libs.versions.toml`: A [conventional file](https://docs.gradle.org/current/userguide/platforms.html#sub:conventional-dependencies-toml) to declare a version catalog. -* `settings.gradle.kts`: The multi-project Gradle settings file. Here are all the sub-projects defined. -* `gradle.properties`: Holds the library version, needed & maintained by the CI/CD pipeline [release process](#release-process). -* `**/build.gradle.kts`: Gradle build file - -## CI/CD Pipeline -The heart of this template is the ['Main GitHub Actions CI/CD Pipeline'](https://github.com/thriving-dev/micronaut-gradle-renovate-example/actions/workflows/1.pipeline.yml). - -![image](https://github.com/thriving-dev/java-library-template/assets/10864443/8e5436c3-f807-4617-9e77-6d21e9dfb7c2) - -The workflow encompasses multiple jobs, modelled and linked with dependencies and conditions. -Based on the context (trigger, ref, input arguments) it meets different use cases: -1. **Check**. Build, test, integration test; code quality & vulnerability scans. - Runs for active PRs - as well as part of all subsequent listed use cases. -2. **Latest**. 'Check', publish SNAPSHOT version to Maven Central and Javadoc (GitHub Pages). - Runs on pushes to the main branch. -3. **Release Process**. 'Check', executes (major|minor|patch) release process via the Gradle plugin. - Manually triggered workflow via GitHub UI/API. -3. **Library Release**. 'Check', publish RELEASE version to Maven Central and Javadoc (GitHub Pages). - Runs for pushed tags. - -## Publish to Maven Central -### Automated Process -The Maven publish process is fully automated and does not require manual action. -- The _main_ branch (per process definition) always is set to the next [SNAPSHOT version](gradle.properties) and is published to the Sonatype snapshot repository with each main CI/CD pipeline run. The pipeline runs e.g. when a PR is merged, but can also be triggered manually. -- Release deployment happens when a new tag is pushed to GitHub. (Part of the [release process](#release-process)) - -### Prerequisites: Sonatype Credentials & GPG Signing Key -The initial setup for your OSSRH repository requires some manual steps and human review (see why), after which your deployment process is typically modified to get components into OSSRH. These are all one time steps. -I recommend to follow the [official guide](https://central.sonatype.org/publish/publish-guide/). - -In order to deploy your components to OSSRH with Gradle, you have to meet the [requirements](https://central.sonatype.org/publish/requirements/) for your metadata in the pom.xml as well as supply the required, signed components. - -> ℹī¸ The publish process uses [io.github.gradle-nexus.publish-plugin](https://plugins.gradle.org/plugin/io.github.gradle-nexus.publish-plugin) under the hood. - -The gradle project as well as the CI/CD pipeline is already fully prepared for the publishing process. -The GH actions job [callable.publish-sonatype.yml](.github/workflows/callable.publish-sonatype.yml) requires the following Secrets: - -| Secret name | Value | -|--------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `OSSRH_USERNAME` | The username of your OSSRH account. | -| `OSSRH_PASSWORD` | The password of your OSSRH account. | -| `GPG_SIGNING_KEY` | The GPG private key to sign your artifacts (in ascii-armored format). You can obtain it with `gpg --armor --export-secret-keys ` or you can create one key online on [pgpkeygen.com](https://pgpkeygen.com). | -| `GPG_SIGNING_PASSPHRASE` | The passphrase for unlocking the secret key. (you picked it when creating the key). | - -Please define the secrets via your repository settings. ([Settings > Security > Secrets and variables > Actions](https://github.com/thriving-dev/micronaut-gradle-renovate-example/settings/secrets/actions)) -Preview of Javadoc published to GitHub Pages by the CI/CD pipeline - -## Release Process -### Creating a Release -To release a new version via the CI/CD Pipeline, please follow the instructions below. -- Navigate to Actions (1) -- \> Main Pipeline (2) -- Click 'Run workflow' button (3) -- Select a semver release type with the 'Release Library' dropdown (4) -- 'Run the workflow' (5) - ![image](https://github.com/thriving-dev/java-library-template/assets/10864443/8008fefd-efc3-466d-806f-5cc33eb74b7f) - -The release process includes -- Pipeline run (incl. build & tests) that executes the release plugin (6) -- The release plugin first sets & commits the new version (7a) -- Creates & pushes a new tag (7b) -- Sets the main branch to the next SNAPSHOT version (7c) - ![image](https://github.com/thriving-dev/java-library-template/assets/10864443/dd7694c7-36f2-497e-b768-f9a76516bacb) - -The new version is automatically published to Maven Central! 🚀 -![image](https://github.com/thriving-dev/java-library-template/assets/10864443/89db0a69-c4ea-4f45-a655-8349d448a4c6) - -### Prerequisites: PAT provided as `CI_GITHUB_TOKEN` -The CI/CD 'gradle-release' job expects a secret by the name `CI_GITHUB_TOKEN` that holds a PAT (Personal Access Token) with permission to push tags as part of the release process. - -If you have been following the Quick Start guide you should already have this configured. Please refer to ['Quick Start' step 2](#quick-start). - -## Javadoc -### Use -A Javadoc website of your library, generated by gradle, is 'published' to GitHub Pages by the CI/CD pipeline. In addition to each released version, the current snapshot version (_main_ branch) is published as `current`. --> visit the [live preview](https://thriving-dev.github.io/java-library-template/javadoc/). - -Preview of Javadoc published to GitHub Pages by the CI/CD pipeline - -### Prerequisites: Configure GitHub Pages -To host the generated Javadoc, configure GitHub Pages for your repository to deploy from branch `gh-pages`. You can also find all deployments under ['pages-build-deployment'](https://github.com/thriving-dev/micronaut-gradle-renovate-example/actions/workflows/pages/pages-build-deployment). - -> ℹī¸ The branch is created with the first CI/CD pipeline run. ('Publish javadoc' job) - -![image](https://github.com/thriving-dev/java-library-template/assets/10864443/208d68b8-f955-4089-b41a-48a2ef263186) - -## Security & CodeQL Analysis -### Common Vulnerabilities and Exposures (CVE) -The libraries gradle dependencies are scanned for known [CVE](https://www.cve.org/) with **[aquasecurity/trivy](https://github.com/aquasecurity/trivy)**. The scan results can be reviewed and managed under [Security > Vulnerability alerts > Code scanning](https://github.com/thriving-dev/micronaut-gradle-renovate-example/security/code-scanning). - -Scans are triggered -1. with each main CI/CD pipeline run -2. Scheduled (weekly) ([ref](.github/workflows/2.scheduled.code-analysis.yml)) - -Preview of a critical CVE listed in the GitHub Security 'Code scanning' overview page - -Please refer to [official GitHub documentation](https://docs.github.com/en/code-security/code-scanning/introduction-to-code-scanning/about-code-scanning) for more details. - -## Automated Dependency Updates with Renovate -### Dependency Dashboard - - - -### PRs created by renovate bot - - -### Prerequisites: Enable & Configure Renovate -This template ships with a prepared [renovate.json](renovate.json). - -The recommended way to enable renovate is to use the [Renovate GitHub App](https://github.com/apps/renovate). +## References +- [Micronaut Gradle Plugin](https://micronaut-projects.github.io/micronaut-gradle-plugin/latest/index.html) ## Credits - Created by https://github.com/thriving-dev/java-library-template diff --git a/build.gradle.kts b/build.gradle.kts index c48f88d..6cca0d8 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,29 +1,88 @@ +plugins { + alias(libs.plugins.johnrengelman.shadow) + alias(libs.plugins.micronaut.application) + alias(libs.plugins.micronaut.aot) +} + +version = "0.0.1" group = "dev.thriving.example" -plugins { - alias(libs.plugins.publish) - alias(libs.plugins.release) -} - -nexusPublishing { - repositories { - sonatype { - nexusUrl.set(uri("https://s01.oss.sonatype.org/service/local/")) - snapshotRepositoryUrl.set(uri("https://s01.oss.sonatype.org/content/repositories/snapshots/")) - val ossrhUsername = providers.environmentVariable("OSSRH_USERNAME") - val ossrhPassword = providers.environmentVariable("OSSRH_PASSWORD") - if (ossrhUsername.isPresent && ossrhPassword.isPresent) { - username.set(ossrhUsername.get()) - password.set(ossrhPassword.get()) - } - } +repositories { + mavenCentral() +} + +sourceSets { + create("intTest") { + compileClasspath += sourceSets.main.get().output + runtimeClasspath += sourceSets.main.get().output + } +} + +val intTestImplementation by configurations.getting { + extendsFrom(configurations.implementation.get()) +} + +configurations["intTestRuntimeOnly"].extendsFrom(configurations.runtimeOnly.get()) + +dependencies { + annotationProcessor("io.micronaut:micronaut-http-validation") + annotationProcessor("io.micronaut.serde:micronaut-serde-processor") + + implementation("io.micronaut.serde:micronaut-serde-jackson") + compileOnly("io.micronaut:micronaut-http-client") + runtimeOnly("ch.qos.logback:logback-classic") + + testImplementation("io.micronaut:micronaut-http-client") + testImplementation(libs.junit) + + intTestImplementation(libs.junit) + intTestImplementation(libs.bundles.testcontainers.junit) + intTestImplementation(libs.assertj) +} + + +application { + mainClass.set("dev.thriving.example.app.Application") +} +java { + sourceCompatibility = JavaVersion.toVersion("21") + targetCompatibility = JavaVersion.toVersion("21") +} + +val intTest = task("intTest") { + description = "Runs integration tests." + group = "verification" + + testClassesDirs = sourceSets["intTest"].output.classesDirs + classpath = sourceSets["intTest"].runtimeClasspath + shouldRunAfter("test") + + useJUnitPlatform() + + testLogging { + events("passed") } } -// do not generate extra load on Nexus with new staging repository if signing fails -val initializeSonatypeStagingRepository by tasks.existing -subprojects { - initializeSonatypeStagingRepository { - shouldRunAfter(tasks.withType()) +tasks.check { dependsOn(intTest) } + +graalvmNative.toolchainDetection.set(false) +micronaut { + runtime("netty") + testRuntime("junit5") + processing { + incremental(true) + annotations("dev.thriving.example.app.*") + } + aot { + // Please review carefully the optimizations enabled below + // Check https://micronaut-projects.github.io/micronaut-aot/latest/guide/ for more details + optimizeServiceLoading.set(false) + convertYamlToJava.set(false) + precomputeOperations.set(true) + cacheEnvironment.set(true) + optimizeClassLoading.set(true) + deduceEnvironment.set(true) + optimizeNetty.set(true) } } diff --git a/gradle.properties b/gradle.properties deleted file mode 100644 index 6b09920..0000000 --- a/gradle.properties +++ /dev/null @@ -1 +0,0 @@ -version=0.0.1-SNAPSHOT diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 5634dd2..2671d43 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -2,10 +2,14 @@ junit = "5.10.1" assertj = "3.25.1" testcontainers = "1.19.3" -publish_plugin = "1.3.0" -release_plugin = "3.0.2" +micronaut = "4.2.2" + +johnrengelman_shadow_plugin = "8.1.1" +micronaut_application_plugin = "4.2.0" +micronaut_aot_plugin = "4.2.0" [libraries] +micronaut = { module = "io.micronaut:micronaut-core", version.ref = "micronaut" } junit = { module = "org.junit.jupiter:junit-jupiter", version.ref = "junit" } assertj = { module = "org.assertj:assertj-core", version.ref = "assertj" } testcontainers = { module = "org.testcontainers:testcontainers", version.ref = "testcontainers" } @@ -15,5 +19,6 @@ testcontainers_junit5 = { module = "org.testcontainers:junit-jupiter", version.r testcontainers_junit = ["testcontainers", "testcontainers_junit5"] [plugins] -publish = { id = "io.github.gradle-nexus.publish-plugin", version.ref = "publish_plugin" } -release = { id = "net.researchgate.release", version.ref = "release_plugin" } +johnrengelman_shadow = { id = "com.github.johnrengelman.shadow", version.ref = "johnrengelman_shadow_plugin" } +micronaut_application = { id = "io.micronaut.application", version.ref = "micronaut_application_plugin" } +micronaut_aot = { id = "io.micronaut.aot", version.ref = "micronaut_aot_plugin" } diff --git a/micronaut-cli.yml b/micronaut-cli.yml new file mode 100644 index 0000000..9138c7a --- /dev/null +++ b/micronaut-cli.yml @@ -0,0 +1,6 @@ +applicationType: default +defaultPackage: dev.thriving.example +testFramework: junit +sourceLanguage: java +buildTool: gradle +features: [app-name, gradle, http-client-test, java, java-application, junit, logback, micronaut-aot, micronaut-build, micronaut-http-validation, netty-server, properties, readme, serialization-jackson, shade] diff --git a/micronaut-gradle-renovate-example/build.gradle.kts b/micronaut-gradle-renovate-example/build.gradle.kts deleted file mode 100644 index e7527a5..0000000 --- a/micronaut-gradle-renovate-example/build.gradle.kts +++ /dev/null @@ -1,144 +0,0 @@ -group = "dev.thriving.example" - -object Meta { - const val release = "https://s01.oss.sonatype.org/service/local/" - const val snapshot = "https://s01.oss.sonatype.org/content/repositories/snapshots/" - const val desc = "OSS GitHub Java Library Template Repository" - const val license = "Apache-2.0" - const val licenseUrl = "https://opensource.org/licenses/Apache-2.0" - const val githubRepo = "thriving-dev/micronaut-gradle-renovate-example" - const val developerId = "hartmut-co-uk" - const val developerName = "Your Name" - const val developerOrganization = "ACME Corporation" - const val developerOrganizationUrl = "https://yourdomain.com" -} - -java { - sourceCompatibility = JavaVersion.VERSION_21 -} - -plugins { - // Apply the java-library plugin for API and implementation separation. - `java-library` - `maven-publish` - signing -} - -repositories { - mavenCentral() -} - -sourceSets { - create("intTest") { - compileClasspath += sourceSets.main.get().output - runtimeClasspath += sourceSets.main.get().output - } -} - -val intTestImplementation by configurations.getting { - extendsFrom(configurations.implementation.get()) -} - -configurations["intTestRuntimeOnly"].extendsFrom(configurations.runtimeOnly.get()) - -dependencies { - testImplementation(libs.junit) - - intTestImplementation(libs.junit) - intTestImplementation(libs.bundles.testcontainers.junit) - intTestImplementation(libs.assertj) -} - -val intTest = task("intTest") { - description = "Runs integration tests." - group = "verification" - - testClassesDirs = sourceSets["intTest"].output.classesDirs - classpath = sourceSets["intTest"].runtimeClasspath - shouldRunAfter("test") - - useJUnitPlatform() - - testLogging { - events("passed") - } -} - -tasks.check { dependsOn(intTest) } - -tasks.named("test") { - // Use JUnit Platform for unit tests. - useJUnitPlatform() -} - -signing { - val signingKey = providers.environmentVariable("GPG_SIGNING_KEY") - val signingPassphrase = providers.environmentVariable("GPG_SIGNING_PASSPHRASE") - if (signingKey.isPresent && signingPassphrase.isPresent) { - useInMemoryPgpKeys(signingKey.get(), signingPassphrase.get()) - val extension = extensions.getByName("publishing") as PublishingExtension - sign(extension.publications) - } -} - -publishing { - publications { - create("maven") { - groupId = project.group.toString() - artifactId = project.name - version = project.version.toString() - from(components["java"]) - pom { - name.set(project.name) - description.set(Meta.desc) - url.set("https://github.com/${Meta.githubRepo}") - licenses { - license { - name.set(Meta.license) - url.set(Meta.licenseUrl) - } - } - developers { - developer { - id.set(Meta.developerId) - name.set(Meta.developerName) - organization.set(Meta.developerOrganization) - organizationUrl.set(Meta.developerOrganizationUrl) - } - } - scm { - url.set("https://github.com/${Meta.githubRepo}.git") - connection.set("scm:git:git://github.com/${Meta.githubRepo}.git") - developerConnection.set("scm:git:git://github.com/${Meta.githubRepo}.git") - } - issueManagement { - url.set("https://github.com/${Meta.githubRepo}/issues") - } - } - } - } -} - -tasks.jar { - manifest { - attributes( - mapOf( - "Implementation-Title" to project.name, - "Implementation-Version" to project.version, - ), - ) - } -} - -java { - withSourcesJar() - withJavadocJar() -} - -// gradle locking of dependency versions -// *required+used for trivy scan -dependencyLocking { - lockAllConfigurations() -} -// always run subproject task with parent -rootProject.tasks.dependencies { dependsOn(tasks.dependencies) } diff --git a/micronaut-gradle-renovate-example/src/intTest/java/dev/thriving/example/app/template/JavaLibraryTemplateIntegrationTest.java b/micronaut-gradle-renovate-example/src/intTest/java/dev/thriving/example/app/template/JavaLibraryTemplateIntegrationTest.java deleted file mode 100644 index 5c32e17..0000000 --- a/micronaut-gradle-renovate-example/src/intTest/java/dev/thriving/example/app/template/JavaLibraryTemplateIntegrationTest.java +++ /dev/null @@ -1,23 +0,0 @@ -package dev.thriving.example.app; - -import org.junit.jupiter.api.Test; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -/** - * Use e.g. testcontainers for integration tests... - */ -class JavaLibraryTemplateIntegrationTest { - - @Test - void toFunkyCase() { - // given - String input = "hello world!!!"; - - // when - String output = JavaLibraryTemplate.toFunkyCase(input); - - // then - assertEquals("hElLo wOrLd!!!", output); - } -} diff --git a/micronaut-gradle-renovate-example/src/main/java/dev/thriving/example/app/template/JavaLibraryTemplate.java b/micronaut-gradle-renovate-example/src/main/java/dev/thriving/example/app/template/JavaLibraryTemplate.java deleted file mode 100644 index 10e1230..0000000 --- a/micronaut-gradle-renovate-example/src/main/java/dev/thriving/example/app/template/JavaLibraryTemplate.java +++ /dev/null @@ -1,29 +0,0 @@ -package dev.thriving.example.app; - -/** - * Javadoc for {@link JavaLibraryTemplate} - */ -public class JavaLibraryTemplate { - - /** - * Converts input to fUnKyCaSe... - * - * @param str the input text - * @return the funky output of course - */ - public static String toFunkyCase(String str) { - final char[] chars = str.toCharArray(); - - char c; - for (int i = 0; i < chars.length; i++) { - c = chars[i]; - - chars[i] = i % 2 == 0 - ? Character.toLowerCase(c) - : Character.toUpperCase(c); - } - - return new String(chars); - } - -} diff --git a/micronaut-gradle-renovate-example/src/test/java/dev/thriving/example/app/template/JavaLibraryTemplateTest.java b/micronaut-gradle-renovate-example/src/test/java/dev/thriving/example/app/template/JavaLibraryTemplateTest.java deleted file mode 100644 index 88994ea..0000000 --- a/micronaut-gradle-renovate-example/src/test/java/dev/thriving/example/app/template/JavaLibraryTemplateTest.java +++ /dev/null @@ -1,34 +0,0 @@ -package dev.thriving.example.app; - -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; - -import static org.junit.jupiter.api.Assertions.*; - -class JavaLibraryTemplateTest { - - @Test - void toFunkyCase() { - // given - String input = "hello world!!!"; - - // when - String output = JavaLibraryTemplate.toFunkyCase(input); - - // then - assertEquals("hElLo wOrLd!!!", output); - } - - @Test - @Disabled // was introduced to verify the 'junit test report' output in CI/CD pipeline results - void toFunkyCaseDisabled() { - // given - String input = "hello world!!!"; - - // when - String output = JavaLibraryTemplate.toFunkyCase(input); - - // then - assertEquals("hElLo wOrLd!!!", output); - } -} diff --git a/settings.gradle.kts b/settings.gradle.kts index a4dbc63..c512b83 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,3 +1 @@ rootProject.name = "micronaut-gradle-renovate-example" - -include("micronaut-gradle-renovate-example") diff --git a/src/intTest/java/dev/thriving/example/app/ApplicationIntegrationTest.java b/src/intTest/java/dev/thriving/example/app/ApplicationIntegrationTest.java new file mode 100644 index 0000000..f0b8534 --- /dev/null +++ b/src/intTest/java/dev/thriving/example/app/ApplicationIntegrationTest.java @@ -0,0 +1,16 @@ +package dev.thriving.example.app; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.Assertions; + +/** + * Use e.g. testcontainers for integration tests... + */ +class ApplicationIntegrationTest { + + @Test + void testItWorks() { + Assertions.assertTrue(true); + } + +} diff --git a/src/main/java/dev/thriving/example/app/Application.java b/src/main/java/dev/thriving/example/app/Application.java new file mode 100644 index 0000000..d629069 --- /dev/null +++ b/src/main/java/dev/thriving/example/app/Application.java @@ -0,0 +1,10 @@ +package dev.thriving.example.app; + +import io.micronaut.runtime.Micronaut; + +public class Application { + + public static void main(String[] args) { + Micronaut.run(Application.class, args); + } +} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties new file mode 100644 index 0000000..c75c3e7 --- /dev/null +++ b/src/main/resources/application.properties @@ -0,0 +1,2 @@ +#Thu Jan 11 19:24:05 UTC 2024 +micronaut.application.name=micronaut-gradle-renovate-example diff --git a/src/main/resources/logback.xml b/src/main/resources/logback.xml new file mode 100644 index 0000000..2d77bda --- /dev/null +++ b/src/main/resources/logback.xml @@ -0,0 +1,14 @@ + + + + + + %cyan(%d{HH:mm:ss.SSS}) %gray([%thread]) %highlight(%-5level) %magenta(%logger{36}) - %msg%n + + + + + + + diff --git a/src/test/java/dev/thriving/example/app/ApplicationTest.java b/src/test/java/dev/thriving/example/app/ApplicationTest.java new file mode 100644 index 0000000..c6528dd --- /dev/null +++ b/src/test/java/dev/thriving/example/app/ApplicationTest.java @@ -0,0 +1,21 @@ +package dev.thriving.example.app; + +import io.micronaut.runtime.EmbeddedApplication; +import io.micronaut.test.extensions.junit5.annotation.MicronautTest; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.Assertions; + +import jakarta.inject.Inject; + +@MicronautTest +class ApplicationTest { + + @Inject + EmbeddedApplication application; + + @Test + void testItWorks() { + Assertions.assertTrue(application.isRunning()); + } + +}