MK
摩柯社区 - 一个极简的技术知识社区
AI 面试

Kotlin持续集成流水线配置指南

2023-03-176.6k 阅读

一、持续集成简介

持续集成(Continuous Integration,简称 CI)是一种软件开发实践,团队开发成员频繁地(通常每天多次)将他们的代码更改合并到共享的主分支中。每次合并后,会自动运行一系列测试,以确保新代码没有破坏现有功能,尽早发现集成错误,提高软件质量。

在 Kotlin 项目中,配置持续集成流水线至关重要。它可以帮助开发者快速发现代码中的问题,比如编译错误、单元测试失败、代码风格不规范等。常见的持续集成工具包括 Jenkins、GitLab CI/CD、Travis CI、CircleCI 等。接下来,我们以 GitLab CI/CD 为例,详细介绍如何为 Kotlin 项目配置持续集成流水线。

二、准备 Kotlin 项目

  1. 项目结构 假设我们有一个简单的 Kotlin 项目,其目录结构如下:
my - kotlin - project
├── src
│   ├── main
│   │   └── kotlin
│   │       └── com
│   │           └── example
│   │               └── myproject
│   │                   └── Main.kt
│   └── test
│       └── kotlin
│           └── com
│               └── example
│                   └── myproject
│                       └── MainTest.kt
├── build.gradle.kts
└── settings.gradle.kts

Main.kt 中,我们有如下简单代码:

package com.example.myproject

class Main {
    fun greet(): String {
        return "Hello, Kotlin CI!"
    }
}

MainTest.kt 中,使用 JUnit 5 编写单元测试:

package com.example.myproject

import org.junit.jupiter.api.Test
import kotlin.test.assertEquals

class MainTest {
    @Test
    fun testGreet() {
        val main = Main()
        assertEquals("Hello, Kotlin CI!", main.greet())
    }
}
  1. Gradle 配置 build.gradle.kts 文件配置如下,用于构建 Kotlin 项目并运行测试:
plugins {
    kotlin("jvm") version "1.6.21"
    application
    id("org.jetbrains.kotlin.plugin.serialization") version "1.6.21"
    id("jacoco") version "0.8.8"
}

group = "com.example"
version = "1.0.0"

repositories {
    mavenCentral()
}

dependencies {
    implementation(kotlin("stdlib"))
    testImplementation("org.junit.jupiter:junit - jupiter:5.8.2")
    testImplementation(kotlin("test - junit5"))
}

tasks.test {
    useJUnitPlatform()
}

application {
    mainClass.set("com.example.myproject.MainKt")
}

settings.gradle.kts 文件内容:

rootProject.name = "my - kotlin - project"

三、GitLab CI/CD 配置

  1. 创建 .gitlab-ci.yml 文件 在 Kotlin 项目根目录下创建 .gitlab-ci.yml 文件,这是 GitLab CI/CD 的配置文件。以下是一个基础的配置示例:
image: gradle:7.5.1 - jdk11

stages:
    - test

test:
    stage: test
    script:
        - gradle test

在这个配置中:

  • image 定义了运行流水线的 Docker 镜像,这里使用了官方的 Gradle 7.5.1 与 JDK11 镜像。
  • stages 定义了流水线的阶段,这里只有一个 test 阶段。
  • test 部分定义了 test 阶段的具体操作,script 中使用 gradle test 命令来运行 Kotlin 项目的测试。
  1. 更详细的配置 我们可以添加更多的功能,比如代码覆盖率报告、构建产物打包等。
image: gradle:7.5.1 - jdk11

stages:
    - test
    - coverage
    - build

test:
    stage: test
    script:
        - gradle test

coverage:
    stage: coverage
    script:
        - gradle jacocoTestReport
    artifacts:
        when: always
        paths:
            - build/reports/jacoco/test/html

build:
    stage: build
    script:
        - gradle build
    artifacts:
        when: on_success
        paths:
            - build/libs
  • coverage 阶段:使用 Gradle 的 Jacoco 插件生成代码覆盖率报告。script 中的 gradle jacocoTestReport 命令会生成覆盖率报告。artifacts 部分配置在流水线运行结束后,将 build/reports/jacoco/test/html 目录下的报告文件保留,方便开发者查看。
  • build 阶段:使用 gradle build 命令构建项目,生成可执行的 JAR 文件。artifacts 配置在构建成功时,保留 build/libs 目录下的构建产物,例如 JAR 文件。

四、其他持续集成工具配置

  1. Jenkins 配置
    • 安装插件:登录 Jenkins 管理界面,在 “插件管理” 中安装 Kotlin 相关插件(如 Kotlin 代码分析插件等)、Gradle 插件。
    • 创建新任务:点击 “新建 Item”,输入任务名称并选择 “Freestyle project”。
    • 源码管理:如果项目在 Git 仓库,配置 Git 仓库地址、认证信息等。
    • 构建环境:选择已安装的 JDK 和 Gradle 工具。
    • 构建步骤:在 “Execute shell”(如果是 Linux 代理)或 “Execute Windows batch command”(如果是 Windows 代理)中输入 gradle test 来运行测试,若要进行构建和其他操作,类似地添加相应的 Gradle 命令。
    • 构建后操作:可以配置发送邮件通知、归档测试报告等。例如,使用 “Publish JUnit test result report” 插件来展示测试结果,使用 “Publish HTML reports” 插件展示代码覆盖率报告(前提是生成了相应报告)。
  2. Travis CI 配置 在 Kotlin 项目根目录创建 .travis.yml 文件。示例配置如下:
language: kotlin

jdk:
    - openjdk11

install:
    - chmod +x gradlew
    -./gradlew build -x test

script:
    -./gradlew test
  • language 设置为 kotlin,表明这是一个 Kotlin 项目。
  • jdk 选择 OpenJDK 11。
  • install 步骤中,给 Gradle Wrapper 添加可执行权限,并运行 gradlew build -x test 进行依赖安装,但跳过测试。
  • script 步骤运行测试。

五、常见问题及解决方法

  1. 依赖下载失败 在持续集成流水线中,依赖下载失败是常见问题。这可能是由于网络问题、仓库配置错误等原因导致。
  • 网络问题:如果使用的是公司内部网络,可能存在代理设置。在 .gitlab-ci.yml 中,可以通过环境变量设置代理。例如,对于 HTTP 代理:
image: gradle:7.5.1 - jdk11

variables:
    HTTP_PROXY: http://proxy.example.com:8080
    HTTPS_PROXY: http://proxy.example.com:8080

stages:
    - test

test:
    stage: test
    script:
        - gradle test
  • 仓库配置错误:检查 build.gradle.kts 中的仓库配置,确保使用的是正确的 Maven 仓库地址。例如,确保 mavenCentral() 配置正确,若使用了自定义仓库,检查其 URL 和认证信息。
  1. 测试失败 测试失败可能是由于代码问题、测试环境差异等原因。
  • 代码问题:仔细查看测试失败的日志,定位到具体的测试用例和失败原因。例如,如果是断言失败,检查断言的逻辑和预期结果。在 Kotlin 中,assertEquals 等断言方法的参数需要准确匹配。
  • 测试环境差异:在本地测试通过,但在持续集成环境中失败,可能是环境差异导致。例如,数据库连接配置、文件路径等。确保在持续集成环境中设置了正确的环境变量,并且测试代码不依赖于本地特定的环境配置。在 Kotlin 中,可以使用 System.getenv() 来获取环境变量,使代码更加灵活。
  1. 构建产物问题 如果构建产物(如 JAR 文件)生成不正确,可能是 Gradle 配置问题。
  • 检查 Gradle 插件配置:确保 kotlin("jvm")application 等插件配置正确。例如,application 插件的 mainClass 设置要准确,否则生成的可执行 JAR 文件可能无法运行。
  • 构建任务顺序:某些情况下,构建任务的顺序很重要。例如,如果先运行了打包任务,而依赖还未完全下载或编译,可能导致打包的 JAR 文件缺少依赖。在 .gitlab-ci.yml 中,合理安排 testbuild 等阶段的顺序。

六、优化持续集成流水线

  1. 缓存依赖 在持续集成流水线中,每次都重新下载依赖会浪费大量时间。以 GitLab CI/CD 为例,可以使用缓存来加速依赖下载。
image: gradle:7.5.1 - jdk11

cache:
    paths:
        - ~/.gradle/caches/
        - ~/.gradle/wrapper/

stages:
    - test

test:
    stage: test
    script:
        - gradle test

cache 部分配置了 Gradle 缓存目录和 Wrapper 目录。这样,在后续的流水线运行中,如果依赖没有变化,Gradle 会直接使用缓存中的文件,大大提高下载速度。 2. 并行测试 对于大型项目,测试用例较多,并行运行测试可以显著缩短测试时间。在 Gradle 中,可以通过配置 maxParallelForks 来实现并行测试。在 build.gradle.kts 文件中:

tasks.test {
    useJUnitPlatform()
    maxParallelForks = Runtime.getRuntime().availableProcessors()
}

这里将 maxParallelForks 设置为当前运行机器的可用处理器数量,使测试能够并行执行。 3. 定时运行流水线 有些情况下,我们希望定期运行持续集成流水线,以检查代码是否有潜在问题,即使没有新的代码提交。在 GitLab CI/CD 中,可以通过设置 cron 表达式来实现定时运行。

image: gradle:7.5.1 - jdk11

stages:
    - test

test:
    stage: test
    script:
        - gradle test
    rules:
        - if: '$CI_PIPELINE_SOURCE == "push" || $CI_PIPELINE_SOURCE == "merge_request_event"'
          when: manual
        - if: '$CI_PIPELINE_SOURCE == "schedule"'
          when: manual
          allow_failure: true

rules 部分,第一个规则表示当流水线是由代码推送或合并请求触发时,手动运行。第二个规则表示当流水线是由定时调度触发时,手动运行,并且允许失败(例如,如果测试环境临时不可用等情况)。在 GitLab 项目的 “Settings” -> “CI/CD” -> “Schedules” 中,可以设置 cron 表达式,如 0 0 * * * 表示每天凌晨 0 点运行。

七、与代码质量管理工具集成

  1. 与 SonarQube 集成 SonarQube 是一款流行的代码质量管理工具,可以检测代码中的漏洞、代码异味等。
  • 在 SonarQube 中创建项目:登录 SonarQube 管理界面,创建一个新的 Kotlin 项目,并获取项目的令牌。
  • 配置 Gradle:在 build.gradle.kts 文件中添加 SonarQube 插件和配置:
plugins {
    id("org.sonarqube") version "3.3"
}

sonarqube {
    properties {
        property("sonar.projectKey", "my - kotlin - project")
        property("sonar.organization", "my - org")
        property("sonar.host.url", "http://sonarqube.example.com")
        property("sonar.login", "your - token")
    }
}
  • 配置 CI 流水线:在 .gitlab-ci.yml 中添加 SonarQube 扫描步骤:
image: gradle:7.5.1 - jdk11

stages:
    - test
    - sonar

test:
    stage: test
    script:
        - gradle test

sonar:
    stage: sonar
    script:
        - gradle sonarqube

运行流水线后,SonarQube 会对 Kotlin 项目进行扫描,并展示详细的代码质量报告。 2. 与 Checkstyle 集成 Checkstyle 是一个用于检查 Java 和 Kotlin 代码是否符合编码规范的工具。

  • 安装 Checkstyle 插件:在 build.gradle.kts 中添加 Checkstyle 插件:
plugins {
    id("org.jlleitschuh.gradle.ktlint") version "10.3.0"
}

ktlint {
    version.set("0.44.0")
    android.set(false)
}

tasks.named("ktlintCheck") {
    dependsOn("classes")
}

tasks.named("ktlintFormat") {
    dependsOn("classes")
}
  • 配置 CI 流水线:在 .gitlab-ci.yml 中添加 Checkstyle 检查步骤:
image: gradle:7.5.1 - jdk11

stages:
    - test
    - checkstyle

test:
    stage: test
    script:
        - gradle test

checkstyle:
    stage: checkstyle
    script:
        - gradle ktlintCheck

运行流水线后,Checkstyle 会检查 Kotlin 代码是否符合设定的编码规范,并报告不符合的地方。

八、安全相关配置

  1. 保护敏感信息 在持续集成流水线中,可能会涉及到一些敏感信息,如数据库密码、API 密钥等。以 GitLab CI/CD 为例,可以使用 CI/CD 变量来保护敏感信息。
  • 设置变量:在 GitLab 项目的 “Settings” -> “CI/CD” -> “Variables” 中设置变量,如 DB_PASSWORD。变量类型可以选择 “Variable” 或 “File”,如果是密码等敏感信息,建议选择 “Masked variable”,这样在流水线日志中不会明文显示。
  • 在流水线中使用变量:在 .gitlab-ci.yml 中:
image: gradle:7.5.1 - jdk11

stages:
    - test

test:
    stage: test
    script:
        - gradle - PdbPassword=$DB_PASSWORD test

gradle 命令中,通过 -P 参数传递变量值,确保敏感信息不会暴露在代码或配置文件中。 2. 容器安全 由于持续集成流水线常使用 Docker 容器,容器安全至关重要。

  • 使用官方和安全的镜像:在 .gitlab-ci.yml 中选择官方的、经过安全审核的 Docker 镜像,如 gradle:7.5.1 - jdk11。定期更新镜像版本,以获取最新的安全补丁。
  • 扫描容器漏洞:可以使用工具如 Trivy 对运行流水线的容器进行漏洞扫描。在 GitLab CI/CD 中,可以添加如下步骤:
image: gradle:7.5.1 - jdk11

stages:
    - test
    - scan

test:
    stage: test
    script:
        - gradle test

scan:
    stage: scan
    image: aquasec/trivy
    script:
        - trivy image gradle:7.5.1 - jdk11

运行流水线后,Trivy 会扫描 gradle:7.5.1 - jdk11 镜像中的漏洞,并报告结果。如果发现高危漏洞,应及时更换镜像版本或采取其他安全措施。

通过以上详细的配置指南,开发者可以为 Kotlin 项目搭建一个高效、稳定且安全的持续集成流水线,提高项目的开发效率和代码质量。在实际应用中,可根据项目的具体需求和规模,灵活调整配置和优化策略。