RussellSpitzer commented on code in PR #18: URL: https://github.com/apache/polaris-tools/pull/18#discussion_r2152685970
########## apprunner/README.md: ########## @@ -0,0 +1,365 @@ +<!-- + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you 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 + + http://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. +--> + +# Polaris Apprunner Gradle and Maven Plugins + +Gradle and Maven plugins to run a Polaris process and "properly" terminate it for integration testing. + +## Java integration tests + +Tests that run via a Gradle `Test` type task, "decorated" with the Polaris Apprunner plugin, have access to +four system properties. Integration tests using the Maven plugin have access to the same system properties. +The names of the system properties can be changed, if needed. See the [Gradle Kotlin DSL](#kotlin-dsl--all-in-one) +and [Maven](#maven) sections below for a summary of the available options. + +* `quarkus.http.test-port` the port on which the Quarkus server listens for application HTTP requests +* `quarkus.management.test-port` the URL on which the Quarkus server listens for management HTTP requests, this + URL is the one emitted by Quarkus during startup and will contain `0.0.0.0` as the host. +* `quarkus.http.test-url` the port on which the Quarkus server listens for application HTTP requests +* `quarkus.management.test-url` the URL on which the Quarkus server listens for management HTTP requests, this + URL is the one emitted by Quarkus during startup and will contain `0.0.0.0` as the host. + +The preferred way to get the URI/URL for application HTTP requests is to get the `quarkus.http.test-port` system +property and construct the URI against `127.0.0.1` (or `::1` if you prefer). + +```java +public class ITWorksWithPolaris { + static final URI POLARIS_SERVER_URI = + URI.create( + String.format( + "http://127.0.0.1:%s/", + requireNonNull( + System.getProperty("quarkus.http.test-port"), + "Required system property quarkus.http.test-port is not set"))); + + @Test + public void pingNessie() { + // Use the POLARIS_SERVER_URI in your tests ... + } +} +``` + +## Gradle + +The Polaris Apprunner Gradle ensures that the Polaris Quarkus Server is up and running if and when the configured +test tasks run. It also ensures, as long as you do not forcibly kill Gradle processes, that the Polaris Quarkus Server +is shutdown after the configured test task has finished. Each configured test task gets its "own" Polaris Quarkus +Server started up. + +It is possible to configure multiple tasks/test-suites within a Gradle project to run with a Polaris Quarkus Server. +Since tasks of the same Gradle project do not run concurrently (as of today), there are should be no conflicts, except +potentially the working directory. + +### Using the plugin in projects in the polaris-tools repository + +1. include the apprunner build in your project by adding the following snippet at the beginning of your + `settings.gradle.kts` file: + ```kotlin + includeBuild("../apprunner") { name = "polaris-apprunner" } + ``` + +### Kotlin DSL / step by step + +`build.gradle.kts` + +1. add the plugin + ```kotlin + plugins { + // Replace the version with a release version of the Polaris Apprunner Plugin. + // Omit the version when using the apprunner plugin as a Gradle include build. + id("org.apache.polaris.apprunner") version "0.0.0" + } + ``` +2. Add the Polaris Quarkus Server as a dependency + ```kotlin + // Gradle configuration to reference the tarball + val polarisTarball by + configurations.creating { description = "Used to reference the distribution tarball" } + + dependencies { + polarisTarball("org.apache.polaris:polaris-quarkus-server:1.0.0-incubating-SNAPSHOT:@tgz") + } + + // Directory where the Polaris tarball is extracted to + val unpackedTarball = project.layout.buildDirectory.dir("polaris-tarball") + + // Extracts the Polaris tarball, truncating the path + val polarisUnpackedTarball by + tasks.registering(Sync::class) { + inputs.files(polarisTarball) + destinationDir = unpackedTarball.get().asFile + from(provider { tarTree(polarisTarball.singleFile) }) + eachFile { + // truncates the path (removes the first path element) + relativePath = RelativePath(true, *relativePath.segments.drop(1).toTypedArray()) + } + includeEmptyDirs = false + } + ``` +3. If necessary, add a separate test suite + ```kotlin + testing { + suites { + val polarisServerTest by registering(JvmTestSuite::class) { + // more test-suite related configurations + } + } + } + + tasks.named<Test>("polarisServerTest") { + // Dependency to have the extracted tarball + dependsOn(polarisUnpackedTarball) + } + ``` +4. Tell the Apprunner plugin which test tasks need the Polaris server + ```kotlin + polarisQuarkusApp { + // Add the name of the test task - usually the same as the name of your test source + includeTask(tasks.named("polarisServerTest")) + // Reference the quarkus-run.jar in the tarball, apprunner plugin will then run that jar + executableJar = provider { unpackedTarball.get().file("quarkus-run.jar") } + } + ``` + +Note: the above also works within the `:polaris-quarkus-server` project, but the test suite must be neither +`test` nor `intTest` nor `integrationTest`. + +### Kotlin DSL / all configuration options + +```kotlin +polarisQuarkusApp { + // Ensure that the `test` task has a Polaris Server available. + includeTask(tasks.named<Test>("polarisServerIntegrationTest")) + // Note: prefer setting up separate `polarisServerIntegrationTest` test suite (the name is up to you!), + // see https://docs.gradle.org/current/userguide/jvm_test_suite_plugin.html + + // Override the default Java version (21) to run the Polaris server / Quarkus. + // Must be at least 21! + javaVersion.set(21) + // Additional environment variables for the Polaris server / Quarkus + // (Added to the Gradle inputs used to determine Gradle's UP-TO-DATE status) + environment.put("MY_ENV_VAR", "value") + // Additional environment variables for the Polaris server / Quarkus + // (NOT a Gradle inputs used to determine Gradle's UP-TO-DATE status) + // Put system specific variables (e.g. local paths) here + environmentNonInput.put("MY_ENV_VAR", "value") + // System properties for the Polaris server / Quarkus + // (Added to the Gradle inputs used to determine Gradle's UP-TO-DATE status) + systemProperties.put("my.sys.prop", "value") + // System properties for the Polaris server / Quarkus + // (NOT a Gradle inputs used to determine Gradle's UP-TO-DATE status) + // Put system specific variables (e.g. local paths) here + systemPropertiesNonInput.put("my.sys.prop", "value") + // JVM arguments for the Polaris server JVM (list of strings) + // (Added to the Gradle inputs used to determine Gradle's UP-TO-DATE status) + jvmArguments.add("some-arg") + // JVM arguments for the Polaris server JVM (list of strings) + // (NOT a Gradle inputs used to determine Gradle's UP-TO-DATE status) + // Put system specific variables (e.g. local paths) here + jvmArgumentsNonInput.add("some-arg") + // Use this (full) path to the executable jar of the Polaris server. + // Note: This option should generally be avoided in build scripts, prefer the 'polarisQuarkusServer' + // configuration mentioned above. + executableJar = file("/my/custom/polars-quarkus-server.jar") + // Override the working directory for the Polaris Quarkus server, defaults to `polaris-quarkus-server/` + // in the Gradle project's `build/` directory. + workingDirectory = file("/i/want/it/to/run/here") + // override the default timeout of 30 seconds to wait for the Polaris Quarkus Server to emit the + // listen URLs. + timeToListenUrlMillis = 30000 + // Override the default timeout of 15 seconds to wait for the Polaris Quarkus Server to stop before + // it is forcefully killed + timeToStopMillis = 15000 + // Arguments for the Polaris server (list of strings) + // (Added to the Gradle inputs used to determine Gradle's UP-TO-DATE status) + arguments.add("some-arg") + // Arguments for the Polaris server (list of strings) + // (NOT a Gradle inputs used to determine Gradle's UP-TO-DATE status) + // Put system specific variables here + argumentsNonInput.add("some-arg") + // The following options can be used to use different property names than described above + // in this README + httpListenPortProperty = "quarkus.http.test-port" + httpListenUrlProperty = "quarkus.http.test-url" + managementListenPortProperty = "quarkus.management.test-port" + managementListenUrlProperty = "quarkus.management.test-url" +} +``` + +### Groovy DSL + +`build.gradle` - note: the version number needs to be replaced with a (not yet existing) binary release of +Apache Polaris. + +```groovy +plugins { + id 'java-library' + id 'org.apache.polaris.apprunner' version "0.0.0" +} + +dependencies { + // specify the GAV of the Polaris Quarkus server runnable (uber-jar) + polarisQuarkusServer "org.apache.polaris:polaris-quarkus-server:0.0.0:runner" +} + +polarisQuarkusApp { + // Ensure that the `test` task has a Polaris Server available when the tests run. + includeTask(tasks.named("test")) + // Note: prefer setting up separate `polarisServerIntegrationTest` test suite (the name is up to you!), + // see https://docs.gradle.org/current/userguide/jvm_test_suite_plugin.html + + // See the Kotlin DSL description above for information about the options +} +``` + +## Maven + +The `org.apache.polaris.apprunner:polaris-apprunner-maven-plugin` Maven plugin should be used together with the +standard `maven-failsafe-plugin` + +`pom.xml` - note: the version number needs to be replaced with a (not yet existing) binary release of +Apache Polaris. + +```xml +<project> + <build> + <plugins> + <plugin> + <!-- The Polaris Apprunner Maven plugin should be used for integration tests --> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-failsafe-plugin</artifactId> + </plugin> + + <plugin> + <groupId>org.apache.polaris.apprunner</groupId> + <artifactId>polaris-apprunner-maven-plugin</artifactId> + <!-- TODO replace the version -->> + <version>0.0.0</version> + <configuration> + <!-- Preferred way, specify the GAV of the Polaris Quarkus server (uber-jar) --> + <!-- TODO replace the version -->> + <appArtifactId>org.apache.polaris:polaris-quarkus-server:jar:runner:0.0.0</appArtifactId> + <!-- The system properties passed to the Polaris server --> + <systemProperties> + <foo>bar</foo> + </systemProperties> + <!-- The environment variables passed to the Polaris server --> + <environment> + <HELLO>world</HELLO> + </environment> + <!-- + More options: + <executableJar> (string) Use this (full) path to the executable jar of the Polaris server. + Note: This option should generally be avoided in build scripts, + prefer the 'appArtifactId' option mentioned above. + <javaVersion> (int) Override the default Java version (21) + <jvmArguments> (list<string>) Additional JVM arguments for the Polaris server JVM + <arguments> (list<string>) Additional application arguments for the Polaris server + <workingDirectory> (string) Path of the working directory of the Polaris server, + defaults to "${build.directory}/polaris-quarkus". + <httpListenPortProperty> Override the default 'quarkus.http.test-port' property name + <httpListenUrlProperty> Override the default 'quarkus.http.test-url' property name + <managementListenPortProperty> Override the default 'quarkus.http.management-port' property name + <managementListenUrlProperty> Override the default 'quarkus.http.management-url' property name + --> + </configuration> + <executions> + <execution> + <!-- Start the Polaris Server before the integration tests start --> + <id>start</id> + <phase>pre-integration-test</phase> + <goals> + <goal>start</goal> + </goals> + </execution> + <execution> + <!-- Stop the Polaris Server after the integration tests finished --> + <id>stop</id> + <phase>post-integration-test</phase> + <goals> + <goal>stop</goal> + </goals> + </execution> + </executions> + </plugin> + </plugins> + </build> +</project> +``` + +## Implicit Quarkus options + +The plugins always pass the following configuration options as system properties to Quarkus: + +``` +quarkus.http.port=0 +quarkus.management.port=0 +quarkus.log.level=INFO +quarkus.log.console.level=INFO +``` + +Those are meant to let Quarkus bind to a random-ish port, so that the started instances do not conflict with anything +else running on the system and that the necessary log line containing the listen-URLs gets emitted. + +You can explicitly override those via the `systemProperties` options of the Gradle and Maven plugins. + +## Developing the plugins + +The Polaris Apprunner plugins are built via a Gradle "included build" (composite build). As generally with composite +builds, task selection via `gradlew` does _not_ get propagated to included builds. This is especially true for +tasks like `spotlessApply`. + +In other words, running `./gradlew spotlessApply` against the "main" Polaris build will run `spotlessApply` +_only_ in the projects in the "main" Polaris build, but _not_ in the apprunner build. This is also true for other +tasks like `check`. + +This means, the easiest way is to just change the current working directory to `tools/apprunner` and work from there. +Publishing the plugins also has to be done from the `tools/apprunner` directory. This is why `gradlew` & co are +present in `tools/apprunner`. + +## FAQ + +### Does it have to be a Polaris Quarkus server? Review Comment: I would probably leave this question/answer out unless we want to support this code for other projects. -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
