Skip to content

构建与 CI 概览 ​

CoCache 使用 Gradle 9.8.1 的 Kotlin DSL,所有库模块均面向 JDK 17+。构建流水线集成了 Detekt 进行静态分析、Dokka 生成 API 文档、JaCoCo 进行代码覆盖率统计,以及 GitHub Actions 实现持续集成和部署。

Gradle 配置 ​

根 build.gradle.kts 通过 allprojects 和 configure 块将共享配置应用于所有子项目。Gradle 版本目录集中管理依赖版本。

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 工具链 ​

所有库模块通过根构建脚本中的 Kotlin JVM 工具链配置强制使用 JDK 17:

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))
    }
}

cocache-example 模块也显式声明了自己的 JDK 17 工具链。

Kotlin 编译器标志 ​

两个关键的 Kotlin 编译器标志应用于所有库模块:

标志用途来源
-Xjsr305=strict对 JSR-305 注解的 API(如 Spring、Guava)强制执行严格的空安全检查build.gradle.kts:95
-Xjvm-default=all-compatibility为接口生成默认方法实现,以实现 Java 互操作性build.gradle.kts:95
javaParameters = true在字节码中存储方法参数名称,供基于反射的工具使用build.gradle.kts:96

Java 编译也传递 -parameters 以保持一致的参数名保留:

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"))
}

依赖管理 ​

CoCache 使用两层依赖管理策略:

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
构件角色来源
cocache-dependencies聚合 Spring Boot、CoSid、fluent-assert 和库约束的平台 BOMcocache-dependencies/build.gradle.kts
cocache-bom发布的 BOM,将所有库模块作为依赖约束对外暴露cocache-bom/build.gradle.kts
gradle/libs.versions.toml版本目录,定义所有库和插件的版本gradle/libs.versions.toml

所有库模块通过以下方式导入平台:

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

关键依赖版本 ​

依赖版本来源
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

模块构建图 ​

下图展示了模块间的依赖关系:

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

根构建脚本将项目分为逻辑组进行配置:

分组项目用途来源
bomProjectscocache-bom、cocache-dependenciesJava Platform(BOM)模块build.gradle.kts:29-32
serverProjectscocache-example不发布的应用模块build.gradle.kts:34-36
libraryProjects除 BOM 和 server 之外的所有模块包含 Dokka、JaCoCo 和发布配置的已发布库模块build.gradle.kts:44-46

质量工具 ​

Detekt(静态分析) ​

Detekt 通过 allprojects 块应用于所有项目(包括 BOM 和 server 模块)。配置集中于 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
    }
}

关键 Detekt 配置覆盖:

规则设置来源
LongParameterList禁用detekt.yml:3
TooManyFunctions禁用detekt.yml:5
MaxLineLength300detekt.yml:10
ReturnCount禁用detekt.yml:12
MagicNumber禁用detekt.yml:18
UnusedPrivateMember禁用detekt.yml:15
WildcardImport允许 java.util.*detekt.yml:21-24

detekt-formatting 插件(来自 cocache-dependencies)也应用于所有项目,以强制执行统一的代码格式。

Dokka(API 文档) ​

Dokka 应用于所有库项目,用于生成 Kotlin/Java API 文档:

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

所有库模块还生成 javadocJar 和 sourcesJar 用于 Maven 发布:

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

JaCoCo(代码覆盖率) ​

JaCoCo 应用于所有库项目,用于各模块的覆盖率统计。code-coverage-report 模块使用 jacoco-report-aggregation 生成所有库模块的聚合覆盖率报告。

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)
    }
}

自定义 Logback 配置(config/logback.xml)被注入到所有测试任务中,以确保 JaCoCo 正确捕获所有日志输出:

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")

覆盖率有两道门禁:Gradle 任务 codeCoverageVerification(属于 check)在行覆盖率低于 90% 或分支覆盖率低于 80% 时使构建失败;codecov.yml 要求 PR 的整体覆盖率 ≥ 90%、增量覆盖率 ≥ 80%(容差 1%)。cocache-test 与 cocache-example 不计入。

构建命令 ​

命令用途备注
./gradlew build -x test跳过测试的完整构建快速编译检查
./gradlew check完整检查:测试 + Detekt + Dokka + 许可证头 + 覆盖率门禁需要 localhost:6379 的 Redis;CI 即运行此任务
./gradlew clean check清理后完整检查CI 中推荐使用以确保可重复性
./gradlew test运行所有测试通过 Jupiter 引擎运行 JUnit 5
./gradlew :cocache-core:test测试特定模块前缀 : 用于模块定向
./gradlew :cocache-core:test --tests "me.ahoo.cache.proxy.ProxyCacheTest"运行单个测试类完全限定类名
./gradlew detekt仅运行 Detekt 分析无构建的静态分析
./gradlew detektAutoFix运行 Detekt 并自动修正应用安全的格式化修正
./gradlew codeCoverageReport生成聚合 JaCoCo 报告由 CI 上传到 Codecov
./gradlew codeCoverageVerification覆盖率门禁行 ≥ 90%、分支 ≥ 80%
./gradlew checkLicenseHeader校验 Apache-2.0 许可证头属于 check
./gradlew publishToMavenLocal发布到本地 Maven 仓库用于本地集成测试

测试配置 ​

所有库模块配置 JUnit 5 (Jupiter) 作为测试平台,并启用完整的异常日志记录:

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")
}

注入到所有库模块的测试依赖:

依赖用途来源
junit-jupiter-apiJUnit 5 测试 APIbuild.gradle.kts:116
junit-jupiter-params参数化测试支持build.gradle.kts:117
fluent-assert-coreKotlin 流式断言 DSLbuild.gradle.kts:118
mockkKotlin 模拟框架build.gradle.kts:119
logback-classic测试日志实现build.gradle.kts:115
junit-platform-launcherJUnit 运行时启动器build.gradle.kts:122
junit-jupiter-engineJUnit 测试引擎build.gradle.kts:123

CI/CD 流水线 ​

所有工作流位于 .github/workflows/。每个工作流都声明最小权限 permissions,每个作业设置 timeout-minutes,并通过 actions/setup-java(cache: gradle)缓存 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
工作流触发内容
ci.ymlpush 到 main、Pull RequestStatic Analysis:actionlint、全模块 Detekt(合并后的 SARIF 上传到 GitHub code scanning)、checkLicenseHeader。Test & Coverage:在 redis:7-alpine 服务下运行 ./gradlew check(全部测试、Dokka、JMH 编译、JaCoCo 门禁:行 ≥ 90%、分支 ≥ 80%),并上传 Codecov。失败时上传测试报告。被新提交取代的 PR 运行会被取消。
labeler.ymlPull Request(pull_request_target,不检出代码)按模块、变更路径和分支前缀为 PR 打标签;标签决定发布说明分类(.github/release.yml)。
deploy-wiki.ymlwiki/** 变更PR 中构建 VitePress 站点;main 上构建并部署到 GitHub Pages。
package-deploy.ymlRelease published重新运行 clean check,然后把签名构件发布到 GitHub Packages 与 Maven Central。每个 tag 只运行一次,不会被取消。
renovate.yml每天自托管 Renovate 依赖更新。
gitee-sync.ymlpush 到 main、v* tag、每天镜像仓库到 Gitee。

来自 fork 的 PR 会跳过需要仓库 secrets 或写权限的两步(SARIF 上传、Codecov 上传),而不是失败。

其他配置 ​

Gradle Wrapper 固定为 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

settings.gradle.kts 使用 foojay-resolver-convention 插件(v1.0.0)来自动解析 JDK 工具链。

相关页面 ​

基于 Apache License 2.0 发布。