Skip to content

Build & CI Overview ​

CoCache uses Gradle 9.8.1 with the Kotlin DSL, targeting JDK 17+ across all library modules. The build pipeline integrates Detekt for static analysis, Dokka for API documentation, JaCoCo for code coverage, and GitHub Actions for continuous integration and deployment.

Gradle Setup ​

The root build.gradle.kts applies shared configuration to all subprojects through allprojects and configure blocks. The Gradle Version Catalog centralizes dependency versions.

mermaid
graph LR
    subgraph Root Build["Root build.gradle.kts"]
        direction TB
        A["allprojects"] --> B["Detekt Plugin"]
        A --> C["Repository Config"]
        D["configure(libraryProjects)"] --> E["Dokka"]
        D --> F["JaCoCo"]
        D --> G["Java Library"]
        D --> H["Kotlin JVM"]
        D --> I["KotlinCompile Options"]
        D --> J["Test Config"]
    end
    style Root Build fill:#161b22,stroke:#6d5dfc,color:#e6edf3
    style A fill:#2d333b,stroke:#6d5dfc,color:#e6edf3
    style B fill:#2d333b,stroke:#6d5dfc,color:#e6edf3
    style C fill:#2d333b,stroke:#6d5dfc,color:#e6edf3
    style D fill:#2d333b,stroke:#6d5dfc,color:#e6edf3
    style E fill:#2d333b,stroke:#6d5dfc,color:#e6edf3
    style F fill:#2d333b,stroke:#6d5dfc,color:#e6edf3
    style G fill:#2d333b,stroke:#6d5dfc,color:#e6edf3
    style H fill:#2d333b,stroke:#6d5dfc,color:#e6edf3
    style I fill:#2d333b,stroke:#6d5dfc,color:#e6edf3
    style J fill:#2d333b,stroke:#6d5dfc,color:#e6edf3

JDK 17 Toolchain ​

All library modules enforce JDK 17 via the Kotlin JVM toolchain configuration in the root build script:

kotlin
// [build.gradle.kts:88-91](https://github.com/Ahoo-Wang/CoCache/blob/main/build.gradle.kts#L88-L91)
configure<KotlinJvmProjectExtension> {
    jvmToolchain {
        languageVersion.set(JavaLanguageVersion.of(17))
    }
}

The cocache-example module also declares its own JDK 17 toolchain explicitly.

Kotlin Compiler Flags ​

Two critical Kotlin compiler flags are applied to all library modules:

FlagPurposeSource
-Xjsr305=strictEnforces strict null-safety for JSR-305 annotated APIs (e.g., Spring, Guava)build.gradle.kts:95
-Xjvm-default=all-compatibilityGenerates default method implementations in interfaces for Java interoperabilitybuild.gradle.kts:95
javaParameters = trueStores method parameter names in bytecode for reflection-based toolsbuild.gradle.kts:96

Java compilation also passes -parameters for consistent parameter name retention:

kotlin
// [build.gradle.kts:99-101](https://github.com/Ahoo-Wang/CoCache/blob/main/build.gradle.kts#L99-L101)
tasks.withType<JavaCompile> {
    options.compilerArgs.addAll(listOf("-parameters"))
}

Dependency Management ​

CoCache uses a two-tier dependency management strategy:

mermaid
graph TD
    subgraph Dependency Strategy["Dependency Management"]
        direction TB
        BOM["cocache-dependencies<br>(BOM / Platform)"] --> API["cocache-api"]
        BOM --> CORE["cocache-core"]
        BOM --> SPRING["cocache-spring"]
        BOM --> SPRING_REDIS["cocache-spring-redis"]
        BOM --> SPRING_CACHE["cocache-spring-cache"]
        BOM --> SPRING_BOOT["cocache-spring-boot-starter"]
        BOM --> TEST["cocache-test"]
        CATALOG["gradle/libs.versions.toml<br>(Version Catalog)"] --> BOM
    end
    style Dependency Strategy fill:#161b22,stroke:#6d5dfc,color:#e6edf3
    style BOM fill:#2d333b,stroke:#6d5dfc,color:#e6edf3
    style CATALOG fill:#2d333b,stroke:#6d5dfc,color:#e6edf3
    style API fill:#2d333b,stroke:#6d5dfc,color:#e6edf3
    style CORE fill:#2d333b,stroke:#6d5dfc,color:#e6edf3
    style SPRING fill:#2d333b,stroke:#6d5dfc,color:#e6edf3
    style SPRING_REDIS fill:#2d333b,stroke:#6d5dfc,color:#e6edf3
    style SPRING_CACHE fill:#2d333b,stroke:#6d5dfc,color:#e6edf3
    style SPRING_BOOT fill:#2d333b,stroke:#6d5dfc,color:#e6edf3
    style TEST fill:#2d333b,stroke:#6d5dfc,color:#e6edf3
ArtifactRoleSource
cocache-dependenciesPlatform BOM aggregating Spring Boot, CoSid, fluent-assert, and library constraintscocache-dependencies/build.gradle.kts
cocache-bomPublished BOM exposing all library modules as dependency constraintscocache-bom/build.gradle.kts
gradle/libs.versions.tomlVersion catalog defining all library and plugin versionsgradle/libs.versions.toml

All library modules import the platform via:

kotlin
// [build.gradle.kts:111](https://github.com/Ahoo-Wang/CoCache/blob/main/build.gradle.kts#L111)
api(platform(dependenciesProject))

Key Dependency Versions ​

DependencyVersionSource
Kotlin2.4.0libs.versions.toml:15
Spring Boot4.1.0libs.versions.toml:3
CoSid3.2.0libs.versions.toml:4
Detekt1.23.8libs.versions.toml:13
Dokka2.2.0libs.versions.toml:14
JUnit6.1.1libs.versions.toml:9
fluent-assert1.0.0libs.versions.toml:10
mockk1.14.11libs.versions.toml:11

Module Build Graph ​

The following diagram shows the inter-module dependency relationships:

mermaid
graph TD
    subgraph Modules["Module Dependency Graph"]
        direction TB
        API["cocache-api"]
        CORE["cocache-core"]
        SPRING["cocache-spring"]
        SPRING_CACHE["cocache-spring-cache"]
        SPRING_REDIS["cocache-spring-redis"]
        SPRING_BOOT["cocache-spring-boot-starter"]
        TEST["cocache-test"]
        BOM["cocache-bom"]
        DEPS["cocache-dependencies"]
        EXAMPLE["cocache-example"]
        COVERAGE["code-coverage-report"]

        CORE --> API
        SPRING --> CORE
        SPRING_CACHE --> CORE
        SPRING_REDIS --> CORE
        SPRING_REDIS --> SPRING
        SPRING_BOOT --> SPRING
        SPRING_BOOT --> SPRING_CACHE
        SPRING_BOOT --> SPRING_REDIS
        TEST --> CORE
        EXAMPLE --> SPRING_BOOT
        COVERAGE -.->|jacocoAggregation| CORE
        COVERAGE -.->|jacocoAggregation| SPRING
        COVERAGE -.->|jacocoAggregation| SPRING_REDIS
        COVERAGE -.->|jacocoAggregation| SPRING_BOOT
    end
    style Modules fill:#161b22,stroke:#6d5dfc,color:#e6edf3
    style API fill:#2d333b,stroke:#6d5dfc,color:#e6edf3
    style CORE fill:#2d333b,stroke:#6d5dfc,color:#e6edf3
    style SPRING fill:#2d333b,stroke:#6d5dfc,color:#e6edf3
    style SPRING_CACHE fill:#2d333b,stroke:#6d5dfc,color:#e6edf3
    style SPRING_REDIS fill:#2d333b,stroke:#6d5dfc,color:#e6edf3
    style SPRING_BOOT fill:#2d333b,stroke:#6d5dfc,color:#e6edf3
    style TEST fill:#2d333b,stroke:#6d5dfc,color:#e6edf3
    style BOM fill:#2d333b,stroke:#6d5dfc,color:#e6edf3
    style DEPS fill:#2d333b,stroke:#6d5dfc,color:#e6edf3
    style EXAMPLE fill:#2d333b,stroke:#6d5dfc,color:#e6edf3
    style COVERAGE fill:#2d333b,stroke:#6d5dfc,color:#e6edf3

The root build script classifies projects into logical groups for configuration:

GroupProjectsPurposeSource
bomProjectscocache-bom, cocache-dependenciesJava Platform (BOM) modulesbuild.gradle.kts:29-32
serverProjectscocache-exampleNon-published application modulesbuild.gradle.kts:34-36
libraryProjectsAll others minus BOMs and serverPublished library modules with Dokka, JaCoCo, and publishingbuild.gradle.kts:44-46

Quality Tooling ​

Detekt (Static Analysis) ​

Detekt is applied to all projects (including BOM and server modules) via the allprojects block. Configuration is centralized at config/detekt/detekt.yml.

kotlin
// [build.gradle.kts:54-59](https://github.com/Ahoo-Wang/CoCache/blob/main/build.gradle.kts#L54-L59)
allprojects {
    apply<DetektPlugin>()
    configure<DetektExtension> {
        config.setFrom(files("${rootProject.rootDir}/config/detekt/detekt.yml"))
        buildUponDefaultConfig = true
        autoCorrect = true
    }
}

Key Detekt configuration overrides:

RuleSettingSource
LongParameterListdisableddetekt.yml:3
TooManyFunctionsdisableddetekt.yml:5
MaxLineLength300detekt.yml:10
ReturnCountdisableddetekt.yml:12
MagicNumberdisableddetekt.yml:18
UnusedPrivateMemberdisableddetekt.yml:15
WildcardImportallows java.util.*detekt.yml:21-24

The detekt-formatting plugin (from cocache-dependencies) is also applied to all projects, enforcing consistent code formatting.

Dokka (API Documentation) ​

Dokka is applied to all library projects to generate Kotlin/Java API documentation:

kotlin
// [build.gradle.kts:80](https://github.com/Ahoo-Wang/CoCache/blob/main/build.gradle.kts#L80)
apply<DokkaPlugin>()

All library modules also generate javadocJar and sourcesJar for Maven publication:

kotlin
// [build.gradle.kts:83-86](https://github.com/Ahoo-Wang/CoCache/blob/main/build.gradle.kts#L83-L86)
configure<JavaPluginExtension> {
    withJavadocJar()
    withSourcesJar()
}

JaCoCo (Code Coverage) ​

JaCoCo is applied to all library projects for per-module coverage. The code-coverage-report module uses jacoco-report-aggregation to produce an aggregated coverage report across all library modules.

kotlin
// [code-coverage-report/build.gradle.kts:20-26](https://github.com/Ahoo-Wang/CoCache/blob/main/code-coverage-report/build.gradle.kts#L20-L26)
val libraryProjects = rootProject.ext.get("libraryProjects") as Iterable<Project>
dependencies {
    libraryProjects.forEach {
        jacocoAggregation(it)
    }
}

A custom Logback configuration (config/logback.xml) is injected into all test tasks to ensure JaCoCo captures all logging output correctly:

kotlin
// [build.gradle.kts:108](https://github.com/Ahoo-Wang/CoCache/blob/main/build.gradle.kts#L108)
jvmArgs = listOf("-Dlogback.configurationFile=${rootProject.rootDir}/config/logback.xml")

Coverage is enforced twice: the Gradle task codeCoverageVerification (part of check) fails the build below 90% line or 80% branch coverage, and codecov.yml requires 90% project and 80% patch coverage on pull requests (1% threshold). cocache-test and cocache-example are excluded.

Build Commands ​

CommandPurposeNotes
./gradlew build -x testFull build without testsFast compilation check
./gradlew checkFull check: tests + Detekt + Dokka + license headers + coverage gateNeeds Redis at localhost:6379; what CI runs
./gradlew clean checkClean full checkRecommended for CI to ensure reproducibility
./gradlew testRun all testsJUnit 5 via Jupiter engine
./gradlew :cocache-core:testTest a specific modulePrefix with : for module targeting
./gradlew :cocache-core:test --tests "me.ahoo.cache.proxy.ProxyCacheTest"Run a single test classFull qualified class name
./gradlew detektRun Detekt analysis onlyStatic analysis without build
./gradlew detektAutoFixRun Detekt with auto-fixApplies safe formatting corrections
./gradlew codeCoverageReportGenerate aggregated JaCoCo reportUploaded to Codecov by CI
./gradlew codeCoverageVerificationEnforce coverage thresholds≥ 90% lines, ≥ 80% branches
./gradlew checkLicenseHeaderVerify Apache-2.0 headersPart of check
./gradlew publishToMavenLocalPublish to local Maven repoFor local integration testing

Test Configuration ​

All library modules configure JUnit 5 (Jupiter) as the test platform with full exception logging:

kotlin
// [build.gradle.kts:102-109](https://github.com/Ahoo-Wang/CoCache/blob/main/build.gradle.kts#L102-L109)
tasks.withType<Test> {
    useJUnitPlatform()
    testLogging {
        exceptionFormat = TestExceptionFormat.FULL
    }
    jvmArgs = listOf("-Dlogback.configurationFile=${rootProject.rootDir}/config/logback.xml")
}

Test dependencies injected to all library modules:

DependencyPurposeSource
junit-jupiter-apiJUnit 5 test APIbuild.gradle.kts:116
junit-jupiter-paramsParameterized test supportbuild.gradle.kts:117
fluent-assert-coreFluent assertion DSL for Kotlinbuild.gradle.kts:118
mockkKotlin mocking frameworkbuild.gradle.kts:119
logback-classicLogging implementation for testsbuild.gradle.kts:115
junit-platform-launcherJUnit runtime launcherbuild.gradle.kts:122
junit-jupiter-engineJUnit test enginebuild.gradle.kts:123

CI/CD Pipelines ​

All workflows live in .github/workflows/. Every workflow declares least-privilege permissions and a timeout-minutes per job, and caches Gradle through actions/setup-java (cache: gradle).

mermaid
graph LR
    PR["Pull request / push to main"] --> CI["ci.yml"]
    CI --> SA["Static Analysis<br>actionlint · Detekt → code scanning · license headers"]
    CI --> TC["Test & Coverage<br>check with Redis · coverage gate · Codecov"]
    PR --> LB["labeler.yml<br>module / type labels"]
    PR -->|wiki/** changed| WK["deploy-wiki.yml<br>build (PR) · deploy (main)"]
    REL["Release published"] --> DEP["package-deploy.yml<br>verify → GitHub Packages + Maven Central"]

    style PR fill:#2d333b,stroke:#6d5dfc,color:#e6edf3
    style CI fill:#2d333b,stroke:#6d5dfc,color:#e6edf3
    style SA fill:#2d333b,stroke:#6d5dfc,color:#e6edf3
    style TC fill:#2d333b,stroke:#6d5dfc,color:#e6edf3
    style LB fill:#2d333b,stroke:#6d5dfc,color:#e6edf3
    style WK fill:#2d333b,stroke:#6d5dfc,color:#e6edf3
    style REL fill:#2d333b,stroke:#6d5dfc,color:#e6edf3
    style DEP fill:#2d333b,stroke:#6d5dfc,color:#e6edf3
WorkflowTriggerWhat it does
ci.ymlPush to main, pull requestStatic Analysis: actionlint, Detekt on every module (merged SARIF uploaded to GitHub code scanning), checkLicenseHeader. Test & Coverage: ./gradlew check against a redis:7-alpine service (all tests, Dokka, JMH compile, JaCoCo gate ≥ 90% lines / ≥ 80% branches), then Codecov upload. Test reports are uploaded as an artifact on failure. Superseded PR runs are cancelled.
labeler.ymlPull request (pull_request_target, no checkout)Labels PRs by module, changed paths and branch prefix; labels drive release-note categories (.github/release.yml).
deploy-wiki.ymlwiki/** changesBuilds the VitePress site on PRs; builds and deploys to GitHub Pages on main.
package-deploy.ymlRelease publishedRe-runs clean check, then publishes signed artifacts to GitHub Packages and Maven Central. One run per tag, never cancelled.
renovate.ymlDailySelf-hosted Renovate dependency updates.
gitee-sync.ymlPush to main, v* tags, dailyMirrors the repository to Gitee.

Fork pull requests skip the two steps that need repository secrets or write access (SARIF upload, Codecov upload) instead of failing.

Other Configuration ​

The Gradle wrapper is pinned to Gradle 9.8.1:

properties
# [gradle-wrapper.properties:3](https://github.com/Ahoo-Wang/CoCache/blob/main/gradle/wrapper/gradle-wrapper.properties#L3)
distributionUrl=https\://services.gradle.org/distributions/gradle-9.8.1-bin.zip

The settings.gradle.kts uses the foojay-resolver-convention plugin (v1.0.0) for automatic JDK toolchain resolution.

Released under the Apache License 2.0.