Skip to content

Commit 193df6e

Browse files
committed
feat(build): 支持区分默认版与Foss版的构建与发布流程
- 更新`.github/workflows/release.yml`,通过增加分支与标签条件区分默认版与Foss版的构建逻辑 - 在CI流程中新增`Determine Build Variant`阶段,根据环境决定构建目标(默认版或Foss版) - 调整默认版与Foss版构建条件,确保发布流程符合预期 - 重构模块依赖,通过条件编译支持`default`与`foss`环境 - 更新`gradle/androidx.versions.toml`,回退Android Gradle插件版本以解决兼容性问题 - 新增`SortKoinModulesTask`,自动排序Koin KSP生成文件以增强代码一致性
1 parent bfcfec2 commit 193df6e

File tree

15 files changed

+239
-4
lines changed

15 files changed

+239
-4
lines changed

.github/workflows/release.yml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@ on:
33
push:
44
branches:
55
- master
6+
- master-fdroid # Foss 构建
67
tags:
78
- 'v*'
9+
- 'v*-fdroid' # Foss 发版
810
workflow_dispatch:
911
inputs:
1012
name:
@@ -49,8 +51,22 @@ jobs:
4951

5052
run: |
5153
echo $GOOGLE_SERVICE_JSON > app/google-services.json
54+
# 根据分支决定构建类型
55+
- name: Determine Build Variant
56+
id: variant
57+
run: |
58+
if [[ "${{ github.ref }}" == refs/heads/master-fdroid ]] || [[ "${{ github.ref }}" == refs/tags/v*-fdroid ]]; then
59+
echo "build_foss=true" >> $GITHUB_OUTPUT
60+
echo "build_default=false" >> $GITHUB_OUTPUT
61+
echo "Building Foss variant only (master-fdroid branch)"
62+
else
63+
echo "build_foss=false" >> $GITHUB_OUTPUT
64+
echo "build_default=true" >> $GITHUB_OUTPUT
65+
echo "Building Default variant only (master branch)"
66+
fi
5267
5368
- name: Build Foss Release apk
69+
if: steps.variant.outputs.build_foss == 'true'
5470
env:
5571
RELEASE_KEYSTORE_PASSWORD: ${{ secrets.RELEASE_KEYSTORE_PASSWORD }}
5672
RELEASE_KEYSTORE_ALIAS: ${{ secrets.RELEASE_KEYSTORE_ALIAS }}
@@ -59,6 +75,7 @@ jobs:
5975
GH_PACKAGE_TOKEN: ${{ secrets.GH_PACKAGE_TOKEN }}
6076
run: ./gradlew assembleFossRelease -PapplyFirebasePlugins=false --stacktrace
6177
- name: Build Default Release apk
78+
if: steps.variant.outputs.build_default == 'true'
6279
env:
6380
RELEASE_KEYSTORE_PASSWORD: ${{ secrets.RELEASE_KEYSTORE_PASSWORD }}
6481
RELEASE_KEYSTORE_ALIAS: ${{ secrets.RELEASE_KEYSTORE_ALIAS }}

app/build.gradle.kts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,5 +98,7 @@ dependencies {
9898
implementation(project(":lib_feature"))
9999

100100
baselineProfile(project(":baselineprofile"))
101-
ksp(libs.koin.ksp.compiler)
101+
if (project.findProperty("applyFirebasePlugins") == "true") {
102+
ksp(libs.koin.ksp.compiler)
103+
}
102104
}
File renamed without changes.
File renamed without changes.
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package com.mrl.pixiv
2+
3+
import org.koin.core.module.dsl.viewModel
4+
import org.koin.dsl.bind
5+
import org.koin.dsl.module
6+
7+
object AppModule {
8+
val module = module {
9+
viewModel { _ -> com.mrl.pixiv.splash.SplashViewModel() } bind (com.mrl.pixiv.common.viewmodel.BaseMviViewModel::class)
10+
}
11+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package com.mrl.pixiv.di
2+
3+
import com.mrl.pixiv.AppModule
4+
import com.mrl.pixiv.FeatureModule
5+
import com.mrl.pixiv.common.CommonModule
6+
7+
val allModule = listOf(
8+
AppModule.module,
9+
CommonModule.module,
10+
FeatureModule.module,
11+
)

build-logic/src/main/kotlin/com/mrl/pixiv/buildsrc/KotlinAndroid.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ internal fun Project.configureKotlinAndroid(
5454
}
5555

5656
configureKotlin()
57+
configureSortKoinKspGeneration()
5758

5859
val libs = extensions.getByType<VersionCatalogsExtension>().named("libs")
5960

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
package com.mrl.pixiv.buildsrc
2+
3+
import com.android.build.gradle.LibraryExtension
4+
import com.android.build.gradle.internal.dsl.BaseAppModuleExtension
5+
import org.gradle.api.DefaultTask
6+
import org.gradle.api.Project
7+
import org.gradle.api.file.DirectoryProperty
8+
import org.gradle.api.tasks.InputDirectory
9+
import org.gradle.api.tasks.TaskAction
10+
import org.gradle.kotlin.dsl.configure
11+
import org.gradle.kotlin.dsl.register
12+
import org.gradle.kotlin.dsl.support.uppercaseFirstChar
13+
import java.io.File
14+
15+
abstract class SortKoinModulesTask : DefaultTask() {
16+
// 📥 输入目录(带 @InputDirectory 标注)
17+
@get:InputDirectory
18+
abstract val kspOutputDir: DirectoryProperty
19+
20+
@TaskAction
21+
fun sortModules() {
22+
val outputDir = kspOutputDir.get().asFile
23+
logger.quiet(" 📂 处理目录: ${outputDir.absolutePath}")
24+
25+
if (!outputDir.exists()) {
26+
logger.warn(" ⚠️ 目录不存在,跳过排序")
27+
return
28+
}
29+
30+
// 直接在 @TaskAction 中执行逻辑(不捕获 Project)
31+
val moduleFiles = outputDir.listFiles { file ->
32+
file.isFile && file.name.endsWith(".kt")
33+
} ?: return
34+
35+
logger.quiet(" 📋 发现 ${moduleFiles.size} 个文件: ${moduleFiles.joinToString(", ") { it.name }}")
36+
37+
var sortedCount = 0
38+
moduleFiles.forEach { moduleFile ->
39+
val originalContent = moduleFile.readText(Charsets.UTF_8)
40+
val sortedContent = sortKoinModuleContent(originalContent)
41+
42+
if (originalContent != sortedContent) {
43+
moduleFile.writeText(sortedContent, Charsets.UTF_8)
44+
logger.quiet(" ✅ Sorted: ${moduleFile.name}")
45+
sortedCount++
46+
} else {
47+
logger.quiet(" ⏭️ Already sorted: ${moduleFile.name}")
48+
}
49+
}
50+
logger.lifecycle(" 📊 共排序 $sortedCount 个文件")
51+
}
52+
}
53+
54+
fun Project.configureSortKoinKspGeneration() {
55+
val taskBlock: (variant: String) -> Unit = { variant ->
56+
tasks.register<SortKoinModulesTask>("sort${variant.uppercaseFirstChar()}KoinModules") {
57+
group = "koin"
58+
description = "Sort Koin KSP generated modules for variant: $variant"
59+
60+
// 2️⃣ 通过 Property 注入路径(支持配置缓存)
61+
val outputDir =
62+
layout.buildDirectory.dir("generated/ksp/$variant/kotlin/org/koin/ksp/generated")
63+
kspOutputDir.set(outputDir)
64+
onlyIf {
65+
outputDir.get().asFile.exists()
66+
}
67+
}
68+
tasks.whenTaskAdded {
69+
if (name == "ksp${variant.uppercaseFirstChar()}Kotlin") {
70+
finalizedBy("sort${variant.uppercaseFirstChar()}KoinModules")
71+
logger.quiet("✅ 已链接: $name -> sort${variant.uppercaseFirstChar()}KoinModules")
72+
} else if (name == "compile${variant.uppercaseFirstChar()}Kotlin") {
73+
dependsOn("sort${variant.uppercaseFirstChar()}KoinModules")
74+
}
75+
}
76+
}
77+
if (plugins.hasPlugin("com.android.application")) {
78+
extensions.configure<BaseAppModuleExtension> {
79+
applicationVariants.all {
80+
val variant = name
81+
taskBlock(variant)
82+
}
83+
}
84+
} else {
85+
extensions.configure<LibraryExtension> {
86+
libraryVariants.all {
87+
val variant = name
88+
taskBlock(variant)
89+
}
90+
}
91+
}
92+
}
93+
94+
/**
95+
* ⭐ 排序逻辑(可复用)
96+
*/
97+
fun sortKoinModuleContent(content: String): String {
98+
val moduleRegex = Regex(
99+
pattern = """module\s*\{([\s\S]*?)\n\s*\}""",
100+
options = setOf(RegexOption.MULTILINE)
101+
)
102+
103+
return moduleRegex.replace(content) { matchResult ->
104+
val blockContent = matchResult.groupValues[1]
105+
106+
val lines = blockContent.split("\n").filter { it.isNotBlank() }.sorted()
107+
108+
val rebuiltContent = lines.joinToString("\n")
109+
"""module {
110+
$rebuiltContent
111+
}"""
112+
}
113+
}
114+
115+
/**
116+
* ⭐ 处理单个 KSP 输出目录
117+
*/
118+
fun Project.processKspDirectory(dir: File) {
119+
val moduleFiles = dir.listFiles { file ->
120+
file.isFile && file.name.endsWith(".kt")
121+
} ?: return
122+
logger.quiet(moduleFiles.joinToString(", ") { it.name })
123+
124+
moduleFiles.forEach { moduleFile ->
125+
val originalContent = moduleFile.readText(Charsets.UTF_8)
126+
val sortedContent = sortKoinModuleContent(originalContent)
127+
128+
if (originalContent != sortedContent) {
129+
moduleFile.writeText(sortedContent, Charsets.UTF_8)
130+
println(" ✅ Sorted: ${moduleFile.name}")
131+
}
132+
}
133+
}

gradle/androidx.versions.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[versions]
2-
agp = "8.13.0"
2+
agp = "8.11.2"
33
lifecycle = "2.9.4"
44
appcompat = "1.7.1"
55
baselineprofile = "1.4.1"

lib_common/build.gradle.kts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,9 @@ dependencies {
4545
api(androidx.navigation.compose)
4646
// Koin
4747
api(libs.bundles.koin)
48-
ksp(libs.koin.ksp.compiler)
48+
if (project.findProperty("applyFirebasePlugins") == "true") {
49+
ksp(libs.koin.ksp.compiler)
50+
}
4951
// Ktor
5052
api(kotlinx.bundles.ktor)
5153
// Coroutines

0 commit comments

Comments
 (0)