CI/CD 配置
合理的 CI/CD 配置可以自动化 KMP 项目的构建、测试和发布流程,提升团队效率。
GitHub Actions 配置
基础工作流
yaml
# .github/workflows/ci.yml
name: CI
on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main ]
jobs:
test:
runs-on: macos-latest # macOS 支持所有平台构建
steps:
- uses: actions/checkout@v4
- name: Setup JDK
uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: '17'
- name: Setup Gradle
uses: gradle/gradle-build-action@v3
- name: Run tests
run: ./gradlew allTests
- name: Upload test results
if: failure()
uses: actions/upload-artifact@v4
with:
name: test-results
path: '**/build/test-results/**/*.xml'多平台构建矩阵
yaml
# .github/workflows/build.yml
name: Build
on:
push:
tags:
- 'v*'
jobs:
build:
strategy:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
include:
- os: ubuntu-latest
task: assembleRelease
- os: macos-latest
task: linkReleaseFrameworkIosArm64
- os: windows-latest
task: jvmJar
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: '17'
- name: Build
run: ./gradlew ${{ matrix.task }}
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: build-${{ matrix.os }}
path: |
**/build/outputs/**/*.aar
**/build/libs/**/*.jar
**/build/bin/**/*.framework缓存优化
yaml
- name: Cache Gradle packages
uses: actions/cache@v4
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
~/.konan
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
restore-keys: |
${{ runner.os }}-gradle-GitLab CI 配置
yaml
# .gitlab-ci.yml
stages:
- test
- build
- deploy
variables:
GRADLE_USER_HOME: "$CI_PROJECT_DIR/.gradle"
cache:
paths:
- .gradle/wrapper
- .gradle/caches
test:
stage: test
image: openjdk:17-jdk
script:
- ./gradlew test
artifacts:
reports:
junit:
- '**/build/test-results/test/**/TEST-*.xml'
build-android:
stage: build
image: openjdk:17-jdk
script:
- ./gradlew assembleRelease
artifacts:
paths:
- app/build/outputs/apk/release/*.apk
only:
- tags
build-ios:
stage: build
tags:
- macos
script:
- ./gradlew linkReleaseFrameworkIosArm64
artifacts:
paths:
- shared/build/bin/iosArm64/releaseFramework/
only:
- tags自动化测试
单元测试
yaml
test:
runs-on: macos-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-java@v4
with:
java-version: '17'
- name: Run unit tests
run: |
./gradlew :shared:testDebugUnitTest
./gradlew :shared:iosX64Test
- name: Publish test report
uses: mikepenz/action-junit-report@v4
if: always()
with:
report_paths: '**/build/test-results/**/TEST-*.xml'UI 测试 (Android)
yaml
android-ui-test:
runs-on: macos-latest
steps:
- uses: actions/checkout@v4
- name: Run instrumented tests
uses: reactivecircus/android-emulator-runner@v2
with:
api-level: 29
script: ./gradlew connectedDebugAndroidTest版本发布自动化
语义化版本号
yaml
# .github/workflows/release.yml
name: Release
on:
push:
tags:
- 'v[0-9]+.[0-9]+.[0-9]+'
jobs:
release:
runs-on: macos-latest
steps:
- uses: actions/checkout@v4
- name: Extract version
id: version
run: echo "VERSION=${GITHUB_REF#refs/tags/v}" >> $GITHUB_OUTPUT
- name: Build artifacts
run: |
./gradlew assembleRelease
./gradlew linkReleaseFrameworkIosArm64
- name: Create GitHub Release
uses: softprops/action-gh-release@v1
with:
files: |
app/build/outputs/apk/release/*.apk
shared/build/bin/iosArm64/releaseFramework/**
body: |
## Version ${{ steps.version.outputs.VERSION }}
### Changes
- See [CHANGELOG.md](CHANGELOG.md)Maven 发布
yaml
publish:
runs-on: macos-latest
steps:
- uses: actions/checkout@v4
- name: Publish to Maven Central
run: ./gradlew publishAllPublicationsToMavenCentralRepository
env:
ORG_GRADLE_PROJECT_mavenCentralUsername: ${{ secrets.MAVEN_USERNAME }}
ORG_GRADLE_PROJECT_mavenCentralPassword: ${{ secrets.MAVEN_PASSWORD }}
ORG_GRADLE_PROJECT_signingInMemoryKey: ${{ secrets.SIGNING_KEY }}
ORG_GRADLE_PROJECT_signingInMemoryKeyPassword: ${{ secrets.SIGNING_PASSWORD }}代码质量检查
Detekt 静态分析
yaml
code-quality:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run Detekt
run: ./gradlew detekt
- name: Upload SARIF to GitHub
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: build/reports/detekt/detekt.sarif代码覆盖率
yaml
coverage:
runs-on: macos-latest
steps:
- uses: actions/checkout@v4
- name: Generate coverage report
run: ./gradlew koverXmlReport
- name: Upload to Codecov
uses: codecov/codecov-action@v4
with:
files: ./build/reports/kover/report.xml环境变量管理
使用 GitHub Secrets
yaml
steps:
- name: Build with secrets
run: ./gradlew assembleRelease
env:
API_KEY: ${{ secrets.API_KEY }}
RELEASE_KEYSTORE: ${{ secrets.RELEASE_KEYSTORE }}
KEYSTORE_PASSWORD: ${{ secrets.KEYSTORE_PASSWORD }}Gradle 属性注入
kotlin
// build.gradle.kts
android {
defaultConfig {
buildConfigField("String", "API_KEY", "\"${System.getenv("API_KEY")}\"")
}
}通知集成
Slack 通知
yaml
- name: Notify Slack on failure
if: failure()
uses: slackapi/slack-github-action@v1
with:
payload: |
{
"text": "Build failed for ${{ github.repository }}",
"blocks": [
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "Build <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|#${{ github.run_number }}> failed"
}
}
]
}
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}最佳实践
✅ 实践 1:分离构建和发布
yaml
# 构建在 PR 时触发
on: [pull_request]
# 发布仅在标签推送时触发
on:
push:
tags:
- 'v*'✅ 实践 2:使用依赖缓存
减少构建时间:
yaml
cache:
paths:
- ~/.gradle/caches
- ~/.gradle/wrapper
- ~/.konan✅ 实践 3:并行执行测试
yaml
test:
strategy:
matrix:
test-suite: [unit, integration, ui]
runs-on: macos-latest
steps:
- run: ./gradlew test${{ matrix.test-suite }}✅ 实践 4:失败快速反馈
yaml
jobs:
test:
strategy:
fail-fast: true # 任何任务失败立即停止通过自动化 CI/CD 流程,可以确保代码质量,加快交付速度,降低人工错误。