<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** Resolves # # Checklist for submitter If some of the following don't apply, delete the relevant line. - [ ] Changes file added for user-visible changes in `changes/`, `orbit/changes/` or `ee/fleetd-chrome/changes`. See [Changes files](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/guides/committing-changes.md#changes-files) for more information. - [ ] Input data is properly validated, `SELECT *` is avoided, SQL injection is prevented (using placeholders for values in statements) - [ ] If paths of existing endpoints are modified without backwards compatibility, checked the frontend/CLI for any necessary changes ## Testing - [ ] Added/updated automated tests - [ ] Where appropriate, [automated tests simulate multiple hosts and test for host isolation](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/reference/patterns-backend.md#unit-testing) (updates to one hosts's records do not affect another) - [ ] QA'd all new/changed functionality manually For unreleased bug fixes in a release candidate, one of: - [ ] Confirmed that the fix is not expected to adversely impact load test results - [ ] Alerted the release DRI if additional load testing is needed ## Database migrations - [ ] Checked schema for all modified table for columns that will auto-update timestamps during migration. - [ ] Confirmed that updating the timestamps is acceptable, and will not cause unwanted side effects. - [ ] Ensured the correct collation is explicitly set for character columns (`COLLATE utf8mb4_unicode_ci`). ## New Fleet configuration settings - [ ] Setting(s) is/are explicitly excluded from GitOps If you didn't check the box above, follow this checklist for GitOps-enabled settings: - [ ] Verified that the setting is exported via `fleetctl generate-gitops` - [ ] Verified the setting is documented in a separate PR to [the GitOps documentation](https://github.com/fleetdm/fleet/blob/main/docs/Configuration/yaml-files.md#L485) - [ ] Verified that the setting is cleared on the server if it is not supplied in a YAML file (or that it is documented as being optional) - [ ] Verified that any relevant UI is disabled when GitOps mode is enabled ## fleetd/orbit/Fleet Desktop - [ ] Verified compatibility with the latest released version of Fleet (see [Must rule](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/workflows/fleetd-development-and-release-strategy.md)) - [ ] If the change applies to only one platform, confirmed that `runtime.GOOS` is used as needed to isolate changes - [ ] Verified that fleetd runs on macOS, Linux and Windows - [ ] Verified auto-update works from the released version of component to the new version (see [tools/tuf/test](../tools/tuf/test/README.md))
290 lines
9.3 KiB
Kotlin
290 lines
9.3 KiB
Kotlin
import org.gradle.testing.jacoco.plugins.JacocoTaskExtension
|
|
import java.io.FileInputStream
|
|
import java.util.Properties
|
|
|
|
// ==================== PLUGINS ====================
|
|
|
|
plugins {
|
|
alias(libs.plugins.android.application)
|
|
alias(libs.plugins.kotlin.android)
|
|
alias(libs.plugins.kotlin.compose)
|
|
alias(libs.plugins.kotlin.serialization)
|
|
alias(libs.plugins.spotless)
|
|
alias(libs.plugins.detekt)
|
|
id("jacoco")
|
|
}
|
|
|
|
// ==================== ANDROID CONFIG ====================
|
|
|
|
android {
|
|
namespace = "com.fleetdm.agent"
|
|
compileSdk = 36
|
|
|
|
defaultConfig {
|
|
applicationId = "com.fleetdm.agent"
|
|
minSdk = 33
|
|
targetSdk = 36
|
|
versionCode = 7
|
|
versionName = "1.2.0"
|
|
|
|
buildConfigField("String", "INFO_URL", "\"https://fleetdm.com/better\"")
|
|
|
|
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
|
|
|
// Pass integration test flag from project property to instrumentation runner
|
|
if (project.hasProperty("runIntegrationTests")) {
|
|
testInstrumentationRunnerArguments["runIntegrationTests"] = "true"
|
|
}
|
|
}
|
|
|
|
testOptions {
|
|
unitTests {
|
|
isIncludeAndroidResources = false
|
|
all {
|
|
it.apply {
|
|
// Validate integration test configuration
|
|
if (project.hasProperty("runIntegrationTests")) {
|
|
// Check for required SCEP configuration
|
|
if (!project.hasProperty("scep.url") || !project.hasProperty("scep.challenge")) {
|
|
throw GradleException(
|
|
"""
|
|
|
|
|
|ERROR: Integration tests require SCEP server configuration.
|
|
|
|
|
|Please provide both required properties:
|
|
| -Pscep.url=<SCEP_SERVER_URL>
|
|
| -Pscep.challenge=<SCEP_CHALLENGE>
|
|
|
|
|
|Example:
|
|
| ./gradlew test -PrunIntegrationTests=true \
|
|
| -Pscep.url=https://your-scep-server.com/scep \
|
|
| -Pscep.challenge=your-challenge-password
|
|
|
|
|
""".trimMargin(),
|
|
)
|
|
}
|
|
|
|
systemProperty("runIntegrationTests", "true")
|
|
systemProperty("scep.url", project.property("scep.url").toString())
|
|
systemProperty("scep.challenge", project.property("scep.challenge").toString())
|
|
}
|
|
|
|
// Enable jacoco coverage for Robolectric tests
|
|
extensions.configure<JacocoTaskExtension> {
|
|
isIncludeNoLocationClasses = true
|
|
excludes = listOf("jdk.internal.*")
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Load keystore properties for release signing
|
|
val keystorePropertiesFile = rootProject.file("keystore.properties")
|
|
val keystoreProperties = Properties()
|
|
if (keystorePropertiesFile.exists()) {
|
|
FileInputStream(keystorePropertiesFile).use { keystoreProperties.load(it) }
|
|
}
|
|
|
|
signingConfigs {
|
|
create("release") {
|
|
if (keystorePropertiesFile.exists()) {
|
|
storeFile = rootProject.file(keystoreProperties.getProperty("storeFile"))
|
|
storePassword = keystoreProperties.getProperty("storePassword")
|
|
keyAlias = keystoreProperties.getProperty("keyAlias")
|
|
keyPassword = keystoreProperties.getProperty("keyPassword")
|
|
}
|
|
}
|
|
}
|
|
|
|
buildTypes {
|
|
debug {
|
|
enableUnitTestCoverage = true
|
|
enableAndroidTestCoverage = true
|
|
}
|
|
release {
|
|
if (keystorePropertiesFile.exists()) {
|
|
signingConfig = signingConfigs.getByName("release")
|
|
}
|
|
isMinifyEnabled = false
|
|
proguardFiles(
|
|
getDefaultProguardFile("proguard-android-optimize.txt"),
|
|
"proguard-rules.pro",
|
|
)
|
|
}
|
|
}
|
|
compileOptions {
|
|
sourceCompatibility = JavaVersion.VERSION_11
|
|
targetCompatibility = JavaVersion.VERSION_11
|
|
}
|
|
buildFeatures {
|
|
compose = true
|
|
buildConfig = true
|
|
}
|
|
packaging {
|
|
resources {
|
|
excludes +=
|
|
setOf(
|
|
"META-INF/DEPENDENCIES",
|
|
"META-INF/DEPENDENCIES.txt",
|
|
"META-INF/LICENSE",
|
|
"META-INF/LICENSE.txt",
|
|
"META-INF/LICENSE.md",
|
|
"META-INF/LICENSE-notice.md",
|
|
"META-INF/NOTICE",
|
|
"META-INF/NOTICE.txt",
|
|
"META-INF/NOTICE.md",
|
|
"META-INF/notice.txt",
|
|
"META-INF/license.txt",
|
|
"META-INF/license.md",
|
|
"META-INF/dependencies.txt",
|
|
"META-INF/LGPL2.1",
|
|
"META-INF/AL2.0",
|
|
"META-INF/LGPL3.0",
|
|
"META-INF/*.kotlin_module",
|
|
)
|
|
}
|
|
}
|
|
}
|
|
|
|
// ==================== KOTLIN & JAVA TOOLCHAIN ====================
|
|
|
|
kotlin {
|
|
jvmToolchain(17)
|
|
compilerOptions {
|
|
jvmTarget.set(org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_11)
|
|
freeCompilerArgs.add("-opt-in=androidx.compose.material3.ExperimentalMaterial3Api")
|
|
}
|
|
}
|
|
|
|
java {
|
|
toolchain {
|
|
languageVersion.set(JavaLanguageVersion.of(17))
|
|
}
|
|
}
|
|
|
|
// ==================== CODE QUALITY ====================
|
|
|
|
detekt {
|
|
buildUponDefaultConfig = true
|
|
allRules = false
|
|
config.setFrom("$projectDir/detekt.yml")
|
|
}
|
|
|
|
// Don't run Detekt automatically in local builds, only in CI
|
|
tasks.named("check") {
|
|
setDependsOn(dependsOn.filterNot { it.toString().contains("detekt") })
|
|
}
|
|
|
|
// ==================== JACOCO COVERAGE ====================
|
|
|
|
jacoco {
|
|
toolVersion = "0.8.14"
|
|
}
|
|
|
|
tasks.register<JacocoReport>("jacocoTestReport") {
|
|
dependsOn("testDebugUnitTest")
|
|
|
|
reports {
|
|
xml.required.set(true)
|
|
html.required.set(true)
|
|
}
|
|
|
|
val fileFilter = listOf(
|
|
"**/R.class",
|
|
"**/R\$*.class",
|
|
"**/BuildConfig.*",
|
|
"**/Manifest*.*",
|
|
"**/*Test*.*",
|
|
"android/**/*.*",
|
|
"**/compose/**/*.*",
|
|
)
|
|
|
|
val debugTree = fileTree("${layout.buildDirectory.get()}/tmp/kotlin-classes/debug") {
|
|
exclude(fileFilter)
|
|
}
|
|
|
|
val mainSrc = listOf(
|
|
"${project.projectDir}/src/main/java",
|
|
"${project.projectDir}/src/main/kotlin",
|
|
)
|
|
|
|
sourceDirectories.setFrom(files(mainSrc))
|
|
classDirectories.setFrom(files(debugTree))
|
|
executionData.setFrom(
|
|
fileTree(layout.buildDirectory) {
|
|
include(
|
|
// Unit test coverage
|
|
"outputs/unit_test_code_coverage/debugUnitTest/testDebugUnitTest.exec",
|
|
// Instrumented test coverage
|
|
"outputs/code_coverage/debugAndroidTest/connected/**/*.ec",
|
|
)
|
|
},
|
|
)
|
|
}
|
|
|
|
// ==================== SPOTLESS FORMATTING ====================
|
|
|
|
spotless {
|
|
kotlin {
|
|
target("**/*.kt")
|
|
targetExclude("**/build/**/*.kt")
|
|
ktlint()
|
|
}
|
|
kotlinGradle {
|
|
target("*.gradle.kts")
|
|
ktlint()
|
|
}
|
|
}
|
|
|
|
// ==================== DEPENDENCIES ====================
|
|
|
|
dependencies {
|
|
// AndroidX and Compose
|
|
implementation(libs.androidx.core.ktx)
|
|
implementation(libs.androidx.lifecycle.runtime.ktx)
|
|
implementation(libs.androidx.activity.compose)
|
|
implementation(platform(libs.androidx.compose.bom))
|
|
implementation(libs.androidx.compose.ui)
|
|
implementation(libs.androidx.compose.ui.graphics)
|
|
implementation(libs.androidx.compose.ui.tooling.preview)
|
|
implementation(libs.androidx.compose.material3)
|
|
implementation(libs.androidx.compose.material.icons.extended)
|
|
implementation(libs.androidx.datastore.preferences)
|
|
implementation(libs.androidx.navigation.compose)
|
|
implementation(libs.androidx.work.runtime.ktx)
|
|
implementation(libs.amapi.sdk)
|
|
implementation(libs.kotlinx.serialization.json)
|
|
|
|
// SCEP (Simple Certificate Enrollment Protocol)
|
|
implementation(libs.jscep)
|
|
|
|
// Bouncy Castle - Cryptography provider
|
|
implementation(libs.bouncycastle.bcprov)
|
|
implementation(libs.bouncycastle.bcpkix)
|
|
|
|
// Apache Commons - Utilities used by jScep
|
|
implementation(libs.commons.codec)
|
|
|
|
// Logging - Required by jScep
|
|
implementation(libs.slf4j.api)
|
|
implementation(libs.slf4j.simple)
|
|
|
|
// Testing
|
|
testImplementation(libs.junit)
|
|
testImplementation(libs.androidx.work.testing)
|
|
testImplementation(libs.robolectric)
|
|
testImplementation(libs.kotlinx.coroutines.test)
|
|
testImplementation(libs.json) // For JSON parsing in unit tests
|
|
testImplementation(libs.okhttp.mockwebserver)
|
|
|
|
androidTestImplementation(libs.androidx.junit)
|
|
androidTestImplementation(libs.androidx.espresso.core)
|
|
androidTestImplementation(platform(libs.androidx.compose.bom))
|
|
androidTestImplementation(libs.androidx.compose.ui.test.junit4)
|
|
androidTestImplementation(libs.mockk.android)
|
|
|
|
debugImplementation(libs.androidx.compose.ui.tooling)
|
|
debugImplementation(libs.androidx.compose.ui.test.manifest)
|
|
}
|