diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index ed668f579e5ba0c6963d6a42b41995bfda385153..e2ffce6de3bf17c34bf3e1f83585d47d4272fc65 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,5 +1,5 @@ image: - name: wnwalker/android-gradle-build-image:34.0.0-jdk17-gradle8.7 + name: wnwalker/temerity-build-image@sha256:b1ea20cd261395671a541996f7e0cc2437ecf95a813b6fcc7581b41cde167fbf variables: ORG_GRADLE_PROJECT_signingKey: $SIGNING_KEY diff --git a/.sdkmanrc b/.sdkmanrc index 955c2580880005a57da000c2c867ea6a706864bd..dc041b2d9f45321aaea04f45e17d92088480ebb6 100644 --- a/.sdkmanrc +++ b/.sdkmanrc @@ -1,3 +1,3 @@ # Enable auto-env through the sdkman_auto_env config # Add key=value pairs of SDKs to use below -java=17.0.12-tem \ No newline at end of file +java=17.0.14-tem \ No newline at end of file diff --git a/build-image/temerity-build-image.dockerfile b/build-image/temerity-build-image.dockerfile index 4363c9d3691899d12946807ecec2f9c50045766a..37e7f9d3d47a5989eddd471b2fdbff00c2d03cd9 100644 --- a/build-image/temerity-build-image.dockerfile +++ b/build-image/temerity-build-image.dockerfile @@ -1,10 +1,13 @@ # Based on code available at https://github.com/MobileDevOps/android-sdk-image/blob/9cab35c5d0433ff08cc34f14b82f0f417464bc8e/Dockerfile +# To build and publish using experimental Docker buildx: +# docker buildx build --platform linux/amd64 --push -t <docker_hub_username>/<image_name>:<tag> . --file temerity-build-image.dockerfile + # To build: # docker build -t <docker_hub_username>/<image_name>:<tag> . --file temerity-build-image.dockerfile # To publish: # docker push <docker_hub_username>/<image_name>:<tag> -FROM --platform=linux/amd64 ubuntu:24.10 +FROM bitnami/minideb:bookworm AS base LABEL maintainer="wnwalker" @@ -12,8 +15,8 @@ LABEL maintainer="wnwalker" # https://developer.android.com/studio/index.html ENV ANDROID_SDK_TOOLS_VERSION=11076708 ENV ANDROID_SDK_TOOLS_CHECKSUM=2d2d50857e4eb553af5a6dc3ad507a17adf43d115264b1afc116f95c92e5e258 -ENV GRADLE_VERSION=8.7 -ENV JAVA_VERSION=17.0.12-tem +ENV GRADLE_VERSION=8.11 +ENV JAVA_VERSION=17.0.14-tem ENV ANDROID_HOME=/opt/android-sdk-linux ENV ANDROID_SDK_ROOT=$ANDROID_HOME ENV PATH=$PATH:$ANDROID_HOME/cmdline-tools:$ANDROID_HOME/cmdline-tools/bin:$ANDROID_HOME/platform-tools @@ -42,7 +45,7 @@ RUN apt-get -qq update \ git > /dev/null \ && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* -ENV HOME=/home/agbi +ENV HOME=/home/tbi WORKDIR $HOME/app # Install SDKMAN @@ -50,8 +53,10 @@ RUN curl -s "https://get.sdkman.io" | bash SHELL ["/bin/bash", "-c"] # Set the environment variable for sdkman to auto-answer during installation -RUN echo "sdkman_auto_answer=true" > "$HOME/.sdkman/etc/config" -RUN echo "sdkman_auto_env=true" > "$HOME/.sdkman/etc/config" +RUN mkdir -p "$HOME/.sdkman/etc/" +RUN touch "$HOME/.sdkman/etc/config" +RUN echo "sdkman_auto_answer=true" >> "$HOME/.sdkman/etc/config" +RUN echo "sdkman_auto_env=true" >> "$HOME/.sdkman/etc/config" # Install Gradle, Java RUN source "${HOME}/.sdkman/bin/sdkman-init.sh" \ diff --git a/build-logic/build.gradle.kts b/build-logic/build.gradle.kts index b7a239d6292ca1e41d8cb48a041e90f5403dacb1..97212ad8a534c567ec9dae79bd96a7eeffd55960 100644 --- a/build-logic/build.gradle.kts +++ b/build-logic/build.gradle.kts @@ -28,12 +28,8 @@ dependencies { } kotlin { - target { - compilations.configureEach { - kotlinOptions { - jvmToolchain(libs.versions.java.get().toInt()) - } - } + compilerOptions { + jvmToolchain(libs.versions.jvm.target.get().toInt()) } } diff --git a/build-logic/src/main/kotlin/edu/ucsc/its/temerity/buildlogic/convention/FormattingConventionPlugin.kt b/build-logic/src/main/kotlin/edu/ucsc/its/temerity/buildlogic/convention/FormattingConventionPlugin.kt index 4cb05356feddd63d524191e16d0538277869476a..418c6591deacedbd9aaa0a5b6107b72964de1c6a 100644 --- a/build-logic/src/main/kotlin/edu/ucsc/its/temerity/buildlogic/convention/FormattingConventionPlugin.kt +++ b/build-logic/src/main/kotlin/edu/ucsc/its/temerity/buildlogic/convention/FormattingConventionPlugin.kt @@ -11,7 +11,7 @@ class FormattingConventionPlugin : Plugin<Project> { kotlin { target("**/*.kt") targetExclude("${layout.buildDirectory}/**/*.kt") - ktlint().editorConfigOverride( + ktlint("1.5.0").editorConfigOverride( mapOf( "indent_size" to "2", "continuation_indent_size" to "2", diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 0070fa1bb5ece7cfb86312628307ca39e1160568..778814576534e00e449e40e3be69ba7685e4044e 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,47 +1,48 @@ [versions] -agp = "8.2.2" -java = "17" -kotlin = "2.1.0" -ksp = "2.1.0-1.0.29" - -kotlinx-serialization = "1.8.0-RC" -ktor = "3.0.3" -cache4k = "0.13.0" +agp = "8.7.3" +jvm-target = "17" +jvm-version = "17.0.14" +kotlin = "2.1.10" +ksp = "2.1.10-1.0.31" + +kotlinx-serialization = "1.8.0" +ktor = "3.1.1" +cache4k = "0.14.0" statelyConcurrentCollections = "2.1.0" -slf4j = "2.0.16" -kotlinx-io = "0.6.0" +slf4j = "2.0.17" +kotlinx-io = "0.7.0" -ktorfit = "2.2.0" +ktorfit = "2.4.0" coroutines = "1.10.1" -datetime = "0.6.1" -sandwich = "2.0.10" +datetime = "0.6.2" +sandwich = "2.1.0" arrow = "2.0.0" # Main Koin version - for core, android deps -koin = "4.0.1" -koinTest = "4.0.1" -gradleBuildConfigPlugin = "5.5.1" +koin = "4.0.2" +koinTest = "4.0.2" +gradleBuildConfigPlugin = "5.5.4" akkurate = "0.11.0" exposed = "0.56.0" dotenv-vault = "0.0.3" -kermit = "2.0.4" +kermit = "2.0.5" appdirs = "1.2.0" kstore = "0.9.1" -kmpIo = "0.1.5" +kmpIo = "0.1.6" kotlinSemver = "2.0.0" jansi = "2.4.1" temerity = "[0.1.0-dev0z+41180a5,0.1.0]" -kotlinx-dataframe = "0.14.2" +kotlinx-dataframe = "0.15.0" klaxon = "5.6" -kotest = "6.0.0.M1" +kotest = "6.0.0.M2" kotest-datatest = "5.9.1" dokka = "2.0.0" -spotless = "7.0.0.BETA4" -gitSemVer = "3.1.7" -conventionalCommits = "1.0.12" -konsist = "0.16.1" +spotless = "7.0.0" +gitSemVer = "4.0.2" +conventionalCommits = "1.0.15" +konsist = "0.17.3" minSdk = "24" targetSdk = "34" @@ -66,6 +67,7 @@ kotlinx-serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serializa kotlinx-coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "coroutines" } kotlinx-coroutines-debug = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-debug", version.ref = "coroutines" } kotlinx-coroutines-slf4j = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-slf4j", version.ref = "coroutines" } +kotlinx-coroutines-test = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-test", version.ref = "coroutines" } kotlinx-datetime = { module = "org.jetbrains.kotlinx:kotlinx-datetime", version.ref = "datetime" } kotlinx-io = { module = "org.jetbrains.kotlinx:kotlinx-io-core", version.ref = "kotlinx-io" } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index b82aa23a4f05d39d81870f8355ca43324f027298..94113f200e61179d552438ad36de4a645738eac2 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.7-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.11-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/settings.gradle.kts b/settings.gradle.kts index 51505d6d476a09b0dd62e478eee32bb068ec655b..241007b54e8ef1c5f9622944596e67f9f34d3ad3 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -23,6 +23,7 @@ dependencyResolutionManagement { maven("https://maven.pkg.jetbrains.space/kotlin/p/kotlin/dev") maven("https://plugins.gradle.org/m2") maven("https://git.ucsc.edu/api/v4/projects/12162/packages/maven") + maven("https://oss.sonatype.org/content/repositories/snapshots") } } diff --git a/temerity/build.gradle.kts b/temerity/build.gradle.kts index 10e38070333cc5d56439413bf07b39930599db52..0a4a0f62af75b1a686de1f479579e2cb8e7e0fe2 100644 --- a/temerity/build.gradle.kts +++ b/temerity/build.gradle.kts @@ -15,7 +15,6 @@ * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi import io.github.andreabrighi.gradle.gitsemver.conventionalcommit.ConventionalCommit import io.github.z4kn4fein.semver.Version import kotlinx.datetime.Clock @@ -68,6 +67,7 @@ buildConfig { } } }) + buildConfigField("JVM_VERSION", provider { libs.versions.jvm.version.get() }) } gitSemVer { @@ -79,11 +79,10 @@ dependencies { } kotlin { - jvmToolchain(libs.versions.java.get().toInt()) + jvmToolchain(libs.versions.jvm.target.get().toInt()) applyDefaultHierarchyTemplate() explicitApi() - @OptIn(ExperimentalKotlinGradlePluginApi::class) compilerOptions { freeCompilerArgs.add("-Xexpect-actual-classes") } @@ -111,6 +110,7 @@ kotlin { implementation(libs.statelyConcurrentCollections) implementation(libs.kmpIo) implementation(libs.kotlinx.io) + implementation(libs.kotlinSemver) } } val commonTest by getting { @@ -142,6 +142,7 @@ kotlin { implementation(libs.kotest.runner.junit5) implementation(libs.kotlinx.coroutines.slf4j) implementation(libs.kotlinx.coroutines.debug) + implementation(libs.kotlinx.coroutines.test) implementation(libs.kotlinx.dataframe) // Required for report exports // Used to convert dataframe rows to serializable objects @@ -149,8 +150,6 @@ kotlin { implementation(libs.koin.test) implementation(libs.koin.test.junit5) - - implementation(libs.kotlinSemver) } } } diff --git a/temerity/src/commonMain/kotlin/edu/ucsc/its/temerity/core/Temerity.kt b/temerity/src/commonMain/kotlin/edu/ucsc/its/temerity/core/Temerity.kt index 973acb0b0731e4ef8cd6439f356158e6584a24c2..97261a23863e7f1c0bd6739d798f72434e1062c8 100644 --- a/temerity/src/commonMain/kotlin/edu/ucsc/its/temerity/core/Temerity.kt +++ b/temerity/src/commonMain/kotlin/edu/ucsc/its/temerity/core/Temerity.kt @@ -111,6 +111,7 @@ public class Temerity internal constructor( * Constructor for Temerity * @param temApiToken The [String] API token to use for the Temerity client */ + @Suppress("Unused") internal constructor(temApiToken: String) : this(TemClientConfig.withToken(temApiToken)) /** @@ -299,80 +300,72 @@ public class Temerity internal constructor( } } - public override suspend fun getUsers(): List<User> = - withContext(libraryCoroutineDispatcher) { - val userRequest = platformApi.getUsers() - val response = userRequest.executeApiResponse<String>() - decodeResponseCatching(response) - } - - public override suspend fun getUser(userId: Long): User = - withContext(libraryCoroutineDispatcher) { - val returnedUsers = getUsers() - returnedUsers.first { it.userId == userId } - } + public override suspend fun getUsers(): List<User> = withContext(libraryCoroutineDispatcher) { + val userRequest = platformApi.getUsers() + val response = userRequest.executeApiResponse<String>() + decodeResponseCatching(response) + } - public override suspend fun createUser(primaryIdentifier: String, newUser: NewUser): HttpResponse = - withContext(libraryCoroutineDispatcher) { - val validationMessage = newUser.validate() - if (validationMessage != "Valid") { - error(validationMessage) - } else { - val serializedNewUser = createJobScope(jsonProcessingDispatcher).run { - json.encodeToString(newUser) - } - val request = platformApi.createUser(primaryIdentifier, serializedNewUser) - request.getOrThrow() - } - } + public override suspend fun getUser(userId: Long): User = withContext(libraryCoroutineDispatcher) { + val returnedUsers = getUsers() + returnedUsers.first { it.userId == userId } + } - public override suspend fun updateUser(userId: Long, userUpdate: UserUpdate): HttpResponse = - withContext(libraryCoroutineDispatcher) { - val serializedUpdatedUser = createJobScope(jsonProcessingDispatcher).run { - json.encodeToString(userUpdate) + public override suspend fun createUser(primaryIdentifier: String, newUser: NewUser): HttpResponse = withContext(libraryCoroutineDispatcher) { + val validationMessage = newUser.validate() + if (validationMessage != "Valid") { + error(validationMessage) + } else { + val serializedNewUser = createJobScope(jsonProcessingDispatcher).run { + json.encodeToString(newUser) } - val request = platformApi.setUser(userId, serializedUpdatedUser) + val request = platformApi.createUser(primaryIdentifier, serializedNewUser) request.getOrThrow() } + } - public override suspend fun deleteUser(userId: Long): HttpResponse = - withContext(libraryCoroutineDispatcher) { - val request = platformApi.deleteUser(userId) - request.getOrThrow() + public override suspend fun updateUser(userId: Long, userUpdate: UserUpdate): HttpResponse = withContext(libraryCoroutineDispatcher) { + val serializedUpdatedUser = createJobScope(jsonProcessingDispatcher).run { + json.encodeToString(userUpdate) } + val request = platformApi.setUser(userId, serializedUpdatedUser) + request.getOrThrow() + } - public override suspend fun refreshCachedUserRoles(): List<String> = - withContext(libraryCoroutineDispatcher) { - val usersRequest = platformApi.getUsers() - val returnedUsersResponse = usersRequest.executeApiResponse<String>().getOrThrow() - val returnedUserList = createJobScope(jsonProcessingDispatcher).run { - json.decodeFromString<List<User>>(returnedUsersResponse) - } - val roleTypes = returnedUserList.map { it.userType }.distinct() - cachedUserRoleList.clear() - roleTypes.forEach { - cachedUserRoleList[it.hashCode()] = it - } - roleTypes - } + public override suspend fun deleteUser(userId: Long): HttpResponse = withContext(libraryCoroutineDispatcher) { + val request = platformApi.deleteUser(userId) + request.getOrThrow() + } - public override suspend fun getCachedUserRoles(refresh: Boolean): List<String> = - withContext(libraryCoroutineDispatcher) { - if (refresh) { - refreshCachedUserRoles() - } - val returnedUserRoles = cachedUserRoleList.values.toList() - returnedUserRoles.ifEmpty { - refreshCachedUserRoles() - } + public override suspend fun refreshCachedUserRoles(): List<String> = withContext(libraryCoroutineDispatcher) { + val usersRequest = platformApi.getUsers() + val returnedUsersResponse = usersRequest.executeApiResponse<String>().getOrThrow() + val returnedUserList = createJobScope(jsonProcessingDispatcher).run { + json.decodeFromString<List<User>>(returnedUsersResponse) + } + val roleTypes = returnedUserList.map { it.userType }.distinct() + cachedUserRoleList.clear() + roleTypes.forEach { + cachedUserRoleList.put(it.hashCode(), it) } + roleTypes + } - public override suspend fun getUserGroups(userId: Long): List<UserGroup> = - withContext(libraryCoroutineDispatcher) { - val request = platformApi.getUserGroups(userId) - val response = request.executeApiResponse<String>() - decodeResponseCatching(response) + public override suspend fun getCachedUserRoles(refresh: Boolean): List<String> = withContext(libraryCoroutineDispatcher) { + if (refresh) { + refreshCachedUserRoles() } + val returnedUserRoles = cachedUserRoleList.values.toList() + returnedUserRoles.ifEmpty { + refreshCachedUserRoles() + } + } + + public override suspend fun getUserGroups(userId: Long): List<UserGroup> = withContext(libraryCoroutineDispatcher) { + val request = platformApi.getUserGroups(userId) + val response = request.executeApiResponse<String>() + decodeResponseCatching(response) + } public override suspend fun getUserGroupsOwned(userId: Long): List<UserGroup> = withContext(libraryCoroutineDispatcher) { val request = platformApi.getUserGroupsOwned(userId) diff --git a/temerity/src/commonMain/kotlin/edu/ucsc/its/temerity/extensions/datetime/DateTimeExt.kt b/temerity/src/commonMain/kotlin/edu/ucsc/its/temerity/extensions/datetime/DateTimeExt.kt index f10a839c34c9e7dffb0ccc0f5ba63bc6c1ff3ef4..6251f96c2fcf2df7952b86e1aac37be3fd86dcaf 100644 --- a/temerity/src/commonMain/kotlin/edu/ucsc/its/temerity/extensions/datetime/DateTimeExt.kt +++ b/temerity/src/commonMain/kotlin/edu/ucsc/its/temerity/extensions/datetime/DateTimeExt.kt @@ -15,6 +15,8 @@ * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +@file:Suppress("MemberVisibilityCanBePrivate") + package edu.ucsc.its.temerity.extensions.datetime import kotlinx.datetime.Clock diff --git a/temerity/src/commonMain/kotlin/edu/ucsc/its/temerity/extensions/log/FilesystemLogWriter.kt b/temerity/src/commonMain/kotlin/edu/ucsc/its/temerity/extensions/log/FilesystemLogWriter.kt index baf4c7d887f311954ef2b7cd7fe29e6472e57d47..6389ef182bcf2867d8aebb4521ff7cfca8ed1b5e 100644 --- a/temerity/src/commonMain/kotlin/edu/ucsc/its/temerity/extensions/log/FilesystemLogWriter.kt +++ b/temerity/src/commonMain/kotlin/edu/ucsc/its/temerity/extensions/log/FilesystemLogWriter.kt @@ -56,11 +56,10 @@ internal class FilesystemLogWriter internal constructor( } companion object { - operator fun invoke(block: Builder.() -> Unit) = - with(FilesystemLogWriterBuilder()) { - block(this) - build() - } + operator fun invoke(block: Builder.() -> Unit) = with(FilesystemLogWriterBuilder()) { + block(this) + build() + } } interface Builder { diff --git a/temerity/src/commonMain/kotlin/edu/ucsc/its/temerity/extensions/time/DateTimeExtensions.kt b/temerity/src/commonMain/kotlin/edu/ucsc/its/temerity/extensions/time/DateTimeExtensions.kt index 937184a81effcd30fa56e2e7c6035ca4ef089653..c007a54eb15a376260a7090304095527df34c294 100644 --- a/temerity/src/commonMain/kotlin/edu/ucsc/its/temerity/extensions/time/DateTimeExtensions.kt +++ b/temerity/src/commonMain/kotlin/edu/ucsc/its/temerity/extensions/time/DateTimeExtensions.kt @@ -26,12 +26,10 @@ import kotlinx.datetime.format * Formats a [LocalDate] object as a string in the format used by the YuJa API for audit log requests. * @return A string representation of the date in the format "dd/MM/yyyy". */ -internal fun LocalDate.applyAuditLogFormat(): String = - format(AUDIT_LOG_REQUEST_DATE_FORMAT) +internal fun LocalDate.applyAuditLogFormat(): String = format(AUDIT_LOG_REQUEST_DATE_FORMAT) /** * Formats a [LocalDate] object as a string in the format used by the YuJa API for sessions. * @return A string representation of the date in the format "dd-MM-yyyy". */ -internal fun LocalDate.applyScheduledSessionDateFormat(): String = - format(SCHEDULED_SESSION_DATE_FORMAT) +internal fun LocalDate.applyScheduledSessionDateFormat(): String = format(SCHEDULED_SESSION_DATE_FORMAT) diff --git a/temerity/src/jvmMain/kotlin/edu/ucsc/its/temerity/extensions/log/ColorFormatter.kt b/temerity/src/jvmMain/kotlin/edu/ucsc/its/temerity/extensions/log/ColorFormatter.kt index d11bb8f44f4a9c7949808ddded9343f09f56e290..1b15cc11b595bf9a03b2f503136c03539f55395e 100644 --- a/temerity/src/jvmMain/kotlin/edu/ucsc/its/temerity/extensions/log/ColorFormatter.kt +++ b/temerity/src/jvmMain/kotlin/edu/ucsc/its/temerity/extensions/log/ColorFormatter.kt @@ -33,18 +33,15 @@ private fun withBrightColor(messageStringFormatter: MessageStringFormatter = Def internal class ColorFormatter( messageStringFormatter: MessageStringFormatter = DefaultFormatter, ) : WrappingFormatter(messageStringFormatter) { - override fun prefix(severity: Severity?, tag: Tag?, message: Message) = - severity?.toAnsiColor() ?: "" + override fun prefix(severity: Severity?, tag: Tag?, message: Message) = severity?.toAnsiColor() ?: "" - override fun suffix(severity: Severity?, tag: Tag?, message: Message) = - resetColor() + override fun suffix(severity: Severity?, tag: Tag?, message: Message) = resetColor() } internal class BrightColorFormatter( messageStringFormatter: MessageStringFormatter = DefaultFormatter, ) : WrappingFormatter(messageStringFormatter) { - override fun prefix(severity: Severity?, tag: Tag?, message: Message) = - severity?.toBrightAnsiColor() ?: "" + override fun prefix(severity: Severity?, tag: Tag?, message: Message) = severity?.toBrightAnsiColor() ?: "" override fun suffix(severity: Severity?, tag: Tag?, message: Message) = resetColor() } diff --git a/temerity/src/jvmTest/kotlin/edu/ucsc/its/temerity/test/DevDeviceApiTests.kt b/temerity/src/jvmTest/kotlin/edu/ucsc/its/temerity/test/DevDeviceApiTests.kt index efec7524c820719f11fafb4a3f51598cb40545d1..4c6b0b83626df5ed163ccccab912786e1a3196ba 100644 --- a/temerity/src/jvmTest/kotlin/edu/ucsc/its/temerity/test/DevDeviceApiTests.kt +++ b/temerity/src/jvmTest/kotlin/edu/ucsc/its/temerity/test/DevDeviceApiTests.kt @@ -17,17 +17,10 @@ */ package edu.ucsc.its.temerity.test -import edu.ucsc.its.temerity.core.Temerity import kotlinx.coroutines.runBlocking -private class DevDeviceApiTests : TemerityFunSpec() { +private class DevDeviceApiTests : TemDevFunSpec() { init { - beforeTest { - testTemerity = Temerity { - configureDevEnvironment(dotenv) - } - } - test("4.2.1 - PlatformClient can fetch a list of devices") { runBlocking { val returnedDevices = testTemerity.getDevices() diff --git a/temerity/src/jvmTest/kotlin/edu/ucsc/its/temerity/test/DevGroupApiTests.kt b/temerity/src/jvmTest/kotlin/edu/ucsc/its/temerity/test/DevGroupApiTests.kt index 521acc2a60bb99349dfffc7102a1e740e8bb94f8..41be5fea20aa996d8fef57a874c3e3b210090276 100644 --- a/temerity/src/jvmTest/kotlin/edu/ucsc/its/temerity/test/DevGroupApiTests.kt +++ b/temerity/src/jvmTest/kotlin/edu/ucsc/its/temerity/test/DevGroupApiTests.kt @@ -17,17 +17,10 @@ */ package edu.ucsc.its.temerity.test -import edu.ucsc.its.temerity.core.Temerity import kotlinx.coroutines.runBlocking -private class DevGroupApiTests : TemerityFunSpec() { +private class DevGroupApiTests : TemDevFunSpec() { init { - beforeTest { - testTemerity = Temerity { - configureDevEnvironment(dotenv) - } - } - test("2.2.1 - PlatformClient can fetch a list of groups") { runBlocking { val returnedGroups = testTemerity.getGroups() diff --git a/temerity/src/jvmTest/kotlin/edu/ucsc/its/temerity/test/DevUserApiTests.kt b/temerity/src/jvmTest/kotlin/edu/ucsc/its/temerity/test/DevUserApiTests.kt index 43885a0c174e9dabb24a2fffc3bb777ff28d2e0e..07c2e7e8027e19d3444265dc92a94a14b61bc3fc 100644 --- a/temerity/src/jvmTest/kotlin/edu/ucsc/its/temerity/test/DevUserApiTests.kt +++ b/temerity/src/jvmTest/kotlin/edu/ucsc/its/temerity/test/DevUserApiTests.kt @@ -20,7 +20,6 @@ package edu.ucsc.its.temerity.test import co.touchlab.kermit.Logger import com.skydoves.sandwich.StatusCode import com.skydoves.sandwich.ktor.getStatusCode -import edu.ucsc.its.temerity.core.Temerity import edu.ucsc.its.temerity.model.NewUser import edu.ucsc.its.temerity.model.UserUpdate import io.kotest.common.ExperimentalKotest @@ -28,17 +27,11 @@ import io.kotest.matchers.shouldBe import io.ktor.http.HttpStatusCode import kotlinx.coroutines.runBlocking -private class DevUserApiTests : TemerityFunSpec() { +private class DevUserApiTests : TemDevFunSpec() { init { @OptIn(ExperimentalKotest::class) blockingTest = true - beforeTest { - testTemerity = Temerity { - configureDevEnvironment(dotenv) - } - } - test("1.2.1 - PlatformClient can fetch a list of users") { runBlocking { val returnedUsers = testTemerity.getUsers() diff --git a/temerity/src/jvmTest/kotlin/edu/ucsc/its/temerity/test/DevUtilityTests.kt b/temerity/src/jvmTest/kotlin/edu/ucsc/its/temerity/test/DevUtilityTests.kt index aa3e10bdf99fe3a9071122dffa4839d8bd57ed9b..64b5cbc5ff3176921774331c3982695df4e03c86 100644 --- a/temerity/src/jvmTest/kotlin/edu/ucsc/its/temerity/test/DevUtilityTests.kt +++ b/temerity/src/jvmTest/kotlin/edu/ucsc/its/temerity/test/DevUtilityTests.kt @@ -15,25 +15,21 @@ * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +@file:OptIn(KotestInternal::class) + package edu.ucsc.its.temerity.test -import edu.ucsc.its.temerity.core.Temerity import io.kotest.common.ExperimentalKotest +import io.kotest.common.KotestInternal import io.kotest.engine.runBlocking import kotlin.time.Duration.Companion.hours import kotlin.time.Duration.Companion.minutes -private class DevUtilityTests : TemerityFunSpec() { - +private class DevUtilityTests : TemDevFunSpec() { init { @OptIn(ExperimentalKotest::class) blockingTest = true - beforeTest { - testTemerity = Temerity { - configureDevEnvironment(dotenv) - } - } timeout = 5.minutes.inWholeMilliseconds test("Delete all Canvas Test Student Users").config(blockingTest = true, timeout = 12.hours) { diff --git a/temerity/src/jvmTest/kotlin/edu/ucsc/its/temerity/test/ModelTests.kt b/temerity/src/jvmTest/kotlin/edu/ucsc/its/temerity/test/ModelTests.kt index cec8e213c84032918802ac2e63629c41aa607c97..7ef1162569b947f7fe90f38ae471a216b2e198bb 100644 --- a/temerity/src/jvmTest/kotlin/edu/ucsc/its/temerity/test/ModelTests.kt +++ b/temerity/src/jvmTest/kotlin/edu/ucsc/its/temerity/test/ModelTests.kt @@ -21,7 +21,6 @@ import edu.ucsc.its.temerity.model.EventType import io.kotest.common.ExperimentalKotest private class ModelTests : TemerityFunSpec() { - init { @OptIn(ExperimentalKotest::class) blockingTest = true diff --git a/temerity/src/jvmTest/kotlin/edu/ucsc/its/temerity/test/ProdReportTests.kt b/temerity/src/jvmTest/kotlin/edu/ucsc/its/temerity/test/ProdReportTests.kt index ec0e28666aa40da5528082abbda2e9fc1d2789a4..87a59821f0318ea4551199a3d0f5a614608a5df0 100644 --- a/temerity/src/jvmTest/kotlin/edu/ucsc/its/temerity/test/ProdReportTests.kt +++ b/temerity/src/jvmTest/kotlin/edu/ucsc/its/temerity/test/ProdReportTests.kt @@ -17,7 +17,6 @@ */ package edu.ucsc.its.temerity.test -import edu.ucsc.its.temerity.core.Temerity import edu.ucsc.its.temerity.model.AuditLogSortOrder.NEW_FIRST import edu.ucsc.its.temerity.model.EventType.AUTOMATED_SESSION_FAILED_TO_START import edu.ucsc.its.temerity.model.EventType.AUTOMATED_SESSION_MONITOR @@ -47,7 +46,7 @@ import kotlin.uuid.ExperimentalUuidApi import kotlin.uuid.Uuid @OptIn(ExperimentalUuidApi::class) -private class ProdReportTests : TemerityFunSpec() { +private class ProdReportTests : TemProdFunSpec() { init { @OptIn(ExperimentalKotest::class) @@ -55,12 +54,6 @@ private class ProdReportTests : TemerityFunSpec() { val today = currentDate() - beforeTest { - testTemerity = Temerity { - configureProdEnvironment(dotenv) - } - } - timeout = 5.minutes.inWholeMilliseconds test("PlatformClient can fetch a list of devices") { diff --git a/temerity/src/jvmTest/kotlin/edu/ucsc/its/temerity/test/ProdUtilityTests.kt b/temerity/src/jvmTest/kotlin/edu/ucsc/its/temerity/test/ProdUtilityTests.kt index 632ec391b6437708d66aeb8e13061be3e9c6426d..4dfbc5f4ee81950826933234163307c86fa64412 100644 --- a/temerity/src/jvmTest/kotlin/edu/ucsc/its/temerity/test/ProdUtilityTests.kt +++ b/temerity/src/jvmTest/kotlin/edu/ucsc/its/temerity/test/ProdUtilityTests.kt @@ -15,26 +15,22 @@ * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +@file:OptIn(KotestInternal::class) + package edu.ucsc.its.temerity.test -import edu.ucsc.its.temerity.core.Temerity import io.kotest.common.ExperimentalKotest +import io.kotest.common.KotestInternal import io.kotest.engine.runBlocking import kotlin.time.Duration.Companion.hours import kotlin.time.Duration.Companion.minutes -private class ProdUtilityTests : TemerityFunSpec() { +private class ProdUtilityTests : TemProdFunSpec() { init { @OptIn(ExperimentalKotest::class) blockingTest = true - beforeTest { - testTemerity = Temerity { - configureProdEnvironment(dotenv) - } - } - timeout = 5.minutes.inWholeMilliseconds test("Delete all Canvas Test Student Users").config(blockingTest = true, timeout = 12.hours) { diff --git a/temerity/src/jvmTest/kotlin/edu/ucsc/its/temerity/test/TemerityDevTest.kt b/temerity/src/jvmTest/kotlin/edu/ucsc/its/temerity/test/TemerityDevTest.kt index 8ae6e130ed5eb1bc61d3312c4c2820c213f8d063..c3c4f8cc5c9e9878129c86fe1ec9c7bd5c771d77 100644 --- a/temerity/src/jvmTest/kotlin/edu/ucsc/its/temerity/test/TemerityDevTest.kt +++ b/temerity/src/jvmTest/kotlin/edu/ucsc/its/temerity/test/TemerityDevTest.kt @@ -42,17 +42,11 @@ import kotlin.uuid.ExperimentalUuidApi import kotlin.uuid.Uuid @OptIn(ExperimentalUuidApi::class) -private class TemerityDevTest : TemerityFunSpec() { +private class TemerityDevTest : TemDevFunSpec() { init { @OptIn(ExperimentalKotest::class) blockingTest = true - beforeTest { - testTemerity = Temerity { - configureDevEnvironment(dotenv) - } - } - test("Temerity client returns a correctly-formatted version String") { val returnedVersion = testTemerity.version.toVersion() kermit.d { "Returned client version: $returnedVersion" } diff --git a/temerity/src/jvmTest/kotlin/edu/ucsc/its/temerity/test/Util.kt b/temerity/src/jvmTest/kotlin/edu/ucsc/its/temerity/test/Util.kt index d343b206640489762e84e2164050d4ee1e883571..f2c8893b9ef6c7c056651f846f405426c55c93d9 100644 --- a/temerity/src/jvmTest/kotlin/edu/ucsc/its/temerity/test/Util.kt +++ b/temerity/src/jvmTest/kotlin/edu/ucsc/its/temerity/test/Util.kt @@ -15,6 +15,8 @@ * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +@file:OptIn(KotestInternal::class) + package edu.ucsc.its.temerity.test import edu.ucsc.its.temerity.core.TemClientConfig @@ -23,7 +25,9 @@ import edu.ucsc.its.temerity.core.Temerity.Companion.createLogger import io.github.cdimascio.dotenv.Configuration import io.github.cdimascio.dotenv.Dotenv import io.github.cdimascio.dotenv.dotenv +import io.kotest.common.KotestInternal import io.kotest.core.extensions.TestCaseExtension +import io.kotest.core.spec.Spec import io.kotest.core.spec.style.FunSpec import io.kotest.core.test.TestCase import io.kotest.core.test.TestResult @@ -68,11 +72,10 @@ private class KoinExtensionImpl( execute(testCase) } - private fun TestCase.isApplicable() = - mode == KoinLifecycleMode.Root && - isRootTest() || - mode == KoinLifecycleMode.Test && - type == TestType.Test + private fun TestCase.isApplicable() = mode == KoinLifecycleMode.Root && + isRootTest() || + mode == KoinLifecycleMode.Test && + type == TestType.Test } enum class KoinLifecycleMode { @@ -104,3 +107,21 @@ internal abstract class TemerityFunSpec : FunSpec() { internal val kermit: KermitLogger = createLogger() internal lateinit var testTemerity: Temerity } + +internal abstract class TemDevFunSpec : TemerityFunSpec() { + override suspend fun beforeSpec(spec: Spec) { + testTemerity = Temerity { + configureDevEnvironment(dotenv) + } + super.beforeSpec(spec) + } +} + +internal abstract class TemProdFunSpec : TemerityFunSpec() { + override suspend fun beforeSpec(spec: Spec) { + testTemerity = Temerity { + configureProdEnvironment(dotenv) + } + super.beforeSpec(spec) + } +} diff --git a/temerity/src/jvmTest/kotlin/edu/ucsc/its/temerity/test/konsist/TestKonsistTest.kt b/temerity/src/jvmTest/kotlin/edu/ucsc/its/temerity/test/konsist/TestKonsistTest.kt index b8920bc3153e0ab7b066652e0464589d0b6060c1..e988c97a74fe019b386df1321ab401a7d2c87427 100644 --- a/temerity/src/jvmTest/kotlin/edu/ucsc/its/temerity/test/konsist/TestKonsistTest.kt +++ b/temerity/src/jvmTest/kotlin/edu/ucsc/its/temerity/test/konsist/TestKonsistTest.kt @@ -27,7 +27,7 @@ class TestKonsistTest : FunSpec() { init { - beforeTest { + beforeSpec { konsist = Konsist.scopeFromProject() }