Skip to content

Commit 901b0be

Browse files
committed
[Ruler-CLI] Split configuration into multiple parameters
1 parent c848cf4 commit 901b0be

File tree

6 files changed

+68
-41
lines changed

6 files changed

+68
-41
lines changed

ruler-cli/src/main/java/com/spotify/ruler/cli/RulerCli.kt

Lines changed: 42 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,16 @@
1818
package com.spotify.ruler.cli
1919

2020
import com.github.ajalt.clikt.core.CliktCommand
21+
import com.github.ajalt.clikt.parameters.options.default
22+
import com.github.ajalt.clikt.parameters.options.flag
2123
import com.github.ajalt.clikt.parameters.options.multiple
2224
import com.github.ajalt.clikt.parameters.options.option
2325
import com.github.ajalt.clikt.parameters.options.required
2426
import com.github.ajalt.clikt.parameters.types.file
2527
import com.spotify.ruler.common.BaseRulerTask
2628
import com.spotify.ruler.common.FEATURE_NAME
2729
import com.spotify.ruler.common.apk.ApkCreator
30+
import com.spotify.ruler.common.apk.ApkEntry
2831
import com.spotify.ruler.common.apk.InjectedToolApkCreator
2932
import com.spotify.ruler.common.apk.parseSplitApkDirectory
3033
import com.spotify.ruler.common.apk.unzipFile
@@ -49,7 +52,6 @@ import java.util.logging.Logger
4952
class RulerCli : CliktCommand(), BaseRulerTask {
5053
private val logger = Logger.getLogger("Ruler")
5154
private val dependencyMap by option().file().required()
52-
private val rulerConfigJson by option().file().required()
5355
private val apkFile by option().file()
5456
private val bundleFile by option().file()
5557
private val reportDir by option().file(canBeDir = true).required()
@@ -58,6 +60,15 @@ class RulerCli : CliktCommand(), BaseRulerTask {
5860
private val unstrippedNativeFiles: List<File> by option().file().multiple()
5961
private val aapt2Tool: File? by option().file()
6062
private val bloatyTool: File? by option().file()
63+
private val defaultOwner by option().default("unknown")
64+
private val staticComponentsFile by option().file()
65+
private val ownershipFile by option().file()
66+
private val omitFileBreakdown by option().flag()
67+
private val projectPath by option().required()
68+
private val deviceSpecFile by option().file()
69+
private val appInfoFile by option().file().required()
70+
private val additionalEntriesFile by option().file()
71+
private val ignoreFile by option().multiple()
6172

6273
override fun print(content: String) = echo(content)
6374

@@ -70,17 +81,26 @@ class RulerCli : CliktCommand(), BaseRulerTask {
7081
override fun provideBloatyPath() = bloatyTool?.path
7182

7283
private val config: RulerConfig by lazy {
73-
val json = Json.decodeFromStream<JsonRulerConfig>(rulerConfigJson.inputStream())
84+
val deviceSpec = deviceSpecFile?.let {
85+
Json.decodeFromStream<DeviceSpec>(it.inputStream())
86+
}
87+
val appInfo = Json.decodeFromStream<AppInfo>(appInfoFile.inputStream())
88+
89+
val additionalEntries =
90+
additionalEntriesFile?.let { Json.decodeFromStream<List<ApkEntry.Default>>(it.inputStream()) }
91+
logger.log(Level.INFO, "Got ${additionalEntries?.size} additional entries")
7492
RulerConfig(
75-
projectPath = json.projectPath,
76-
apkFilesMap = apkFiles(config = json),
93+
projectPath = projectPath,
94+
apkFilesMap = apkFiles(projectPath, deviceSpec),
7795
reportDir = reportDir,
78-
ownershipFile = json.ownershipFile?.let { File(it) },
79-
staticDependenciesFile = json.staticComponentsPath?.let { File(it) },
80-
appInfo = json.appInfo,
81-
deviceSpec = json.deviceSpec,
82-
defaultOwner = json.defaultOwner,
83-
omitFileBreakdown = json.omitFileBreakdown
96+
ownershipFile = ownershipFile,
97+
staticDependenciesFile = staticComponentsFile,
98+
appInfo = appInfo,
99+
deviceSpec = deviceSpec,
100+
defaultOwner = defaultOwner,
101+
omitFileBreakdown = omitFileBreakdown,
102+
additionalEntries = additionalEntries,
103+
ignoredFiles = ignoreFile
84104
)
85105
}
86106

@@ -110,7 +130,7 @@ class RulerCli : CliktCommand(), BaseRulerTask {
110130
dependencySanitizer.sanitize(entries)
111131
}
112132

113-
private fun apkFiles(config: JsonRulerConfig): Map<String, List<File>> {
133+
private fun apkFiles(projectPath: String, deviceSpec: DeviceSpec?): Map<String, List<File>> {
114134
return if (apkFile != null) {
115135
if (apkFile!!.extension == "apk") {
116136
logger.log(Level.INFO, "Using APK file ${apkFile?.path}")
@@ -122,20 +142,21 @@ class RulerCli : CliktCommand(), BaseRulerTask {
122142
parseSplitApkDirectory(directory.toFile())
123143
}
124144
} else if (bundleFile != null) {
125-
with(if (aapt2Tool != null) {
145+
with(
146+
if (aapt2Tool != null) {
126147
logger.log(
127148
Level.INFO,
128149
"Creating InjectedToolApkCreator with ${aapt2Tool?.path}"
129150
)
130151
InjectedToolApkCreator(aapt2Tool!!.toPath())
131152
} else {
132-
ApkCreator(File(config.projectPath))
153+
ApkCreator(File(projectPath))
133154
}
134155
) {
135156
createSplitApks(
136157
bundleFile!!,
137-
config.deviceSpec!!,
138-
File(config.projectPath).resolve(File("tmp")).apply {
158+
deviceSpec!!,
159+
File(projectPath).resolve(File("tmp")).apply {
139160
mkdir()
140161
}
141162
)
@@ -148,33 +169,25 @@ class RulerCli : CliktCommand(), BaseRulerTask {
148169
override fun provideDependencies(): Map<String, List<DependencyComponent>> = dependencies
149170

150171
override fun run() {
151-
logger.log(Level.INFO, """
172+
173+
logger.log(
174+
Level.INFO, """
152175
~~~~~ Starting Ruler ~~~~~
176+
153177
Using Dependency Map: ${dependencyMap.path}
154-
Using Ruler Config: ${rulerConfigJson.path}
155178
Using APK File: ${apkFile?.path}
156179
Using Bundle File: ${bundleFile?.path}
157180
Using Proguard Mapping File: ${mappingFile?.path}
158181
Using Resource Mapping File: ${resourceMappingFile?.path}
159182
Using AAPT2: ${aapt2Tool?.path}
160183
Using Bloaty: ${bloatyTool?.path}
161184
Writing reports to: ${reportDir.path}
162-
""".trimIndent())
185+
""".trimIndent()
186+
)
163187
super.run()
164188
}
165189
}
166190

167-
@Serializable
168-
data class JsonRulerConfig(
169-
val projectPath: String,
170-
val ownershipFile: String? = null,
171-
val staticComponentsPath: String? = null,
172-
val appInfo: AppInfo,
173-
val deviceSpec: DeviceSpec? = null,
174-
val defaultOwner: String,
175-
val omitFileBreakdown: Boolean
176-
)
177-
178191
@Serializable
179192
data class ModuleMap(
180193
val assets: List<Asset>,

ruler-common/src/main/java/com/spotify/ruler/common/BaseRulerTask.kt

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -91,10 +91,13 @@ interface BaseRulerTask {
9191
val classNameSanitizer = ClassNameSanitizer(provideMappingFile())
9292
val resourceNameSanitizer = ResourceNameSanitizer(provideResourceMappingFile())
9393
val apkSanitizer = ApkSanitizer(classNameSanitizer, resourceNameSanitizer)
94-
95-
return rulerConfig().apkFilesMap.mapValues { (_, apks) ->
96-
val entries = apks.flatMap(apkParser::parse)
97-
apkSanitizer.sanitize(entries)
94+
val config = rulerConfig()
95+
return config.apkFilesMap.mapValues { (name, apks) ->
96+
val entries = apks.flatMap(apkParser::parse).toMutableList()
97+
if (name == FEATURE_NAME && config.additionalEntries != null) {
98+
entries += config.additionalEntries
99+
}
100+
apkSanitizer.sanitize(entries, config.ignoredFiles)
98101
}
99102
}
100103

ruler-common/src/main/java/com/spotify/ruler/common/apk/ApkEntry.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,20 +16,25 @@
1616

1717
package com.spotify.ruler.common.apk
1818

19+
import kotlinx.serialization.Serializable
20+
1921
/** Single entry of an APK. */
22+
@Serializable
2023
sealed class ApkEntry {
2124
abstract val name: String
2225
abstract val downloadSize: Long
2326
abstract val installSize: Long
2427

2528
/** Default APK entry. If an entry has no special type, it is considered to be a default entry. */
29+
@Serializable
2630
data class Default(
2731
override val name: String,
2832
override val downloadSize: Long,
2933
override val installSize: Long,
3034
) : ApkEntry()
3135

3236
/** DEX file APK entry containing compiled classes. */
37+
@Serializable
3338
data class Dex(
3439
override val name: String,
3540
override val downloadSize: Long,
@@ -38,6 +43,7 @@ sealed class ApkEntry {
3843
) : ApkEntry()
3944

4045
/** Native Library entry containing files coming from native library. */
46+
@Serializable
4147
data class NativeLibrary(
4248
override val name: String,
4349
override val downloadSize: Long,

ruler-common/src/main/java/com/spotify/ruler/common/apk/ApkSanitizer.kt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,11 @@
1616

1717
package com.spotify.ruler.common.apk
1818

19+
import com.spotify.ruler.common.sanitizer.ClassNameSanitizer
20+
import com.spotify.ruler.common.sanitizer.ResourceNameSanitizer
1921
import com.spotify.ruler.models.AppFile
2022
import com.spotify.ruler.models.FileType
2123
import com.spotify.ruler.models.ResourceType
22-
import com.spotify.ruler.common.sanitizer.ClassNameSanitizer
23-
import com.spotify.ruler.common.sanitizer.ResourceNameSanitizer
2424

2525
/**
2626
* Responsible for sanitizing APK entries, so they can be attributed easier.
@@ -40,7 +40,7 @@ class ApkSanitizer(
4040
* @param entries List of raw entries parsed from an APK file
4141
* @return Sanitized list of entries
4242
*/
43-
fun sanitize(entries: List<ApkEntry>): List<AppFile> {
43+
fun sanitize(entries: List<ApkEntry>, ignoredFiles: List<String>): List<AppFile> {
4444
val buckets = listOf(
4545
NativeLibAssigningBucket(),
4646
DexFileBucket(),
@@ -52,7 +52,7 @@ class ApkSanitizer(
5252
)
5353

5454
// Separate entries into their different sanitization bucket
55-
entries.forEach { entry ->
55+
entries.filterNot { it.name in ignoredFiles }.forEach { entry ->
5656
val bucket = buckets.first { it.isApplicable(entry) }
5757
bucket.add(entry)
5858
}

ruler-common/src/main/java/com/spotify/ruler/common/models/RulerConfig.kt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
package com.spotify.ruler.common.models
1818

19+
import com.spotify.ruler.common.apk.ApkEntry
1920
import java.io.File
2021

2122
data class RulerConfig(
@@ -27,5 +28,7 @@ data class RulerConfig(
2728
val appInfo: AppInfo,
2829
val deviceSpec: DeviceSpec?,
2930
val defaultOwner: String,
30-
val omitFileBreakdown: Boolean
31+
val omitFileBreakdown: Boolean,
32+
val additionalEntries: List<ApkEntry.Default>?,
33+
val ignoredFiles: List<String>
3134
)

ruler-gradle-plugin/src/main/kotlin/com/spotify/ruler/plugin/RulerTask.kt

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,15 @@
1616

1717
package com.spotify.ruler.plugin
1818

19-
import com.spotify.ruler.common.apk.ApkCreator
20-
import com.spotify.ruler.plugin.dependency.EntryParser
2119
import com.spotify.ruler.common.BaseRulerTask
20+
import com.spotify.ruler.common.apk.ApkCreator
2221
import com.spotify.ruler.common.dependency.DependencyComponent
2322
import com.spotify.ruler.common.dependency.DependencySanitizer
2423
import com.spotify.ruler.common.models.AppInfo
2524
import com.spotify.ruler.common.models.DeviceSpec
2625
import com.spotify.ruler.common.models.RulerConfig
2726
import com.spotify.ruler.common.sanitizer.ClassNameSanitizer
27+
import com.spotify.ruler.plugin.dependency.EntryParser
2828
import org.gradle.api.DefaultTask
2929
import org.gradle.api.file.DirectoryProperty
3030
import org.gradle.api.file.RegularFile
@@ -97,7 +97,9 @@ abstract class RulerTask : DefaultTask(), BaseRulerTask {
9797
appInfo = appInfo.get(),
9898
deviceSpec = deviceSpec.get(),
9999
defaultOwner = defaultOwner.get(),
100-
omitFileBreakdown = omitFileBreakdown.get()
100+
omitFileBreakdown = omitFileBreakdown.get(),
101+
additionalEntries = emptyList(),
102+
ignoredFiles = emptyList()
101103
)
102104
}
103105

0 commit comments

Comments
 (0)