Skip to content

Commit 3b1bfe8

Browse files
authored
Add 0.15.0 migration guide (#242)
* Add a document describing how to migrate a project to BCV 0.15.0 * Update a migration guide with information about module exclusion * Add an old property to provide users with a more insightful error message
1 parent 3590611 commit 3b1bfe8

File tree

3 files changed

+121
-0
lines changed

3 files changed

+121
-0
lines changed

api/binary-compatibility-validator.api

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,9 @@ public abstract class kotlinx/validation/KotlinApiBuildTask : kotlinx/validation
6767
public abstract fun getInputClassesDirs ()Lorg/gradle/api/file/ConfigurableFileCollection;
6868
public abstract fun getInputDependencies ()Lorg/gradle/api/file/ConfigurableFileCollection;
6969
public abstract fun getInputJar ()Lorg/gradle/api/file/RegularFileProperty;
70+
public final fun getOutputApiDir ()Ljava/io/File;
7071
public abstract fun getOutputApiFile ()Lorg/gradle/api/file/RegularFileProperty;
72+
public final fun setOutputApiDir (Ljava/io/File;)V
7173
}
7274

7375
public class kotlinx/validation/KotlinApiCompareTask : org/gradle/api/DefaultTask {

docs/design/0.15.0-migration-guide.md

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
The major feature shipped with the release 0.15.0 of the Binary Compatibility Validator is Kotlin libraries (or KLibs)
2+
ABI validation support.
3+
4+
This support, however, comes with a few changes that break the plugin's compatibility or changes its behavior:
5+
- In multiplatform projects, empty modules are no longer ignored during ABI validation;
6+
- ABI file names (`api/<project name>.api`) are no longer treated in a case-insensitive way;
7+
- Gradle tasks provided by the plugin changed their API.
8+
9+
If you have a multiplatform project with modules having no sources, configure BCV Gradle tasks manually,
10+
or have an ABI file with a name in a case different from how the project was named in the settings,
11+
please check the following steps for smooth migration.
12+
13+
### In multiplatform projects, empty modules are no longer ignored during ABI validation
14+
15+
Previously, if there was an empty Gradle module/project (for example, test-only module), BCV ignored validation of
16+
such a module if the multiplatform platform plugin was applied there. However, BCV behaved differently for similar
17+
projects with the JVM-plugin applied.
18+
19+
Starting from `0.15.0` behavior was aligned and now BCV no longer ignores validation of empty modules/projects.
20+
If you have such a module, please either generate and commit (empty) ABI dump file for it by running
21+
`./gradlew apiDump`, or consider excluding the module from validation using `ignoredProjects` setting:
22+
```kotlin
23+
apiValidation {
24+
ignoredProjects += "empty-module"
25+
}
26+
```
27+
28+
### ABI file names are no longer treated in a case-insensitive way
29+
30+
Starting from the version `0.15.0`, name of an ABI dump file stored in the project's directory
31+
has to match project's name. Previously, a project named `gradle-project` might use an ABI file
32+
named `Gradle-Project.api`, but now it has to be `gradle-project.api`.
33+
34+
On case-insensitive filesystems (Windows and macOS filesystems are case-insensitive) the change won't manifest itself,
35+
but on case-sensitive filesystems (Linux filesystems) the validation will start failing due to a missing ABI dump file
36+
error.
37+
38+
You can either rename the existing file or delete it and run `apiDump` task.
39+
40+
If you're using git SCV, it's highly recommended to use `git mv` command to rename a file, or a pair of `git rm` and
41+
`git add` commands, if you're deleting the old file and then generating a new one. When done differently, git may
42+
not reflect changes in a repository index (it's specific to case-insensitive filesystems).
43+
44+
If you're using another SCV, please consult its documentation for details on how to deal with file renaming on
45+
case-insensitive filesystems.
46+
47+
### Gradle tasks provided by the plugin changed their API
48+
49+
All Gradle tasks that existed before are still presented and in use, but some of them changed
50+
their API to use Gradle Properties-based configuration. There are several advantages of using Gradle Property
51+
instead of regular Kotlin properties, but the main one is that it improves dependency tracking between tasks.
52+
You can [Gradle docs](https://docs.gradle.org/current/userguide/lazy_configuration.html) for more details
53+
on the subject.
54+
55+
The following task-classes changed their API:
56+
- KotlinApiBuildTask
57+
- `ignoredPackages`, `nonPublicMarkers`, `ignoredClasses`, `publicPackages`, `publicMarkers`, `publicClasses` are
58+
all `SetProperty<String>` instances now;
59+
- `outputApiDir` was renamed to `outputApiFile` and became `RegularFileProperty` instance; now it should point to
60+
the generated file instead of a directory holding it;
61+
- `inputClassesDirs` and `inputDependencies` are both `ConfigurableFileCollection` instances now.
62+
- KotlinApiCompareTask
63+
- `projectApiFile` and `generatedApiFile` are both `RegularFileProperty` instances now.
64+
65+
If you were configuring `KotlinApiBuildTask.outputApiDir`, `KotlinApiCompareTask.projectApiFile` or
66+
`KotlinApiCompareTask.generatedApiFile` by assigning a file instance to it, now these properties could only
67+
be configured by using [RegularFileProperty setters](https://docs.gradle.org/current/javadoc/org/gradle/api/file/RegularFileProperty.html).
68+
69+
Value assignments to `KotlinApiBuildTask.inputClassesDirs` and `KotlinApiBuildTask.inputDependencies` properties have
70+
to be replaced with [ConfigurableFileCollection setters](https://docs.gradle.org/current/javadoc/org/gradle/api/file/ConfigurableFileCollection.html).
71+
72+
All `KotlinApiBuildTask`'s filters could be configured by using [SetProperty setters](https://docs.gradle.org/current/javadoc/org/gradle/api/provider/SetProperty.html)
73+
now.
74+
75+
Below is an example of how task configuration needs to be updated:
76+
```kotlin
77+
// Old configuration
78+
val buildTask = tasks.register("buildApi", KotlinApiBuildTask::class.java) {
79+
val classes = compilation.output.classesDirs
80+
81+
it.inputClassesDirs = files(classes)
82+
it.inputDependencies = files(classes)
83+
it.outputApiDir = project.layout.buildDirectory.get().asFile
84+
it.ignoredPackages = setOf("org.example")
85+
}
86+
87+
val checkTask = tasks.register("checkApi", KotlinApiCompareTask::class.java) {
88+
it.projectApiFile = project.layout.projectDirectory.dir("api").file("gradle-project.api").asFile
89+
it.generatedApiFile = project.layout.buildDirectory.get().asFile.resolve("dump.api")
90+
91+
it.dependsOn(buildTask)
92+
}
93+
```
94+
95+
```kotlin
96+
// New configuration
97+
val buildTask = tasks.register("buildApi", KotlinApiBuildTask::class.java) {
98+
val classes = compilation.output.classesDirs
99+
100+
it.inputClassesDirs.from(classes)
101+
it.inputDependencies.from(classes)
102+
it.outputApiFile.set(project.layout.buildDirectory.map { it.file("gradle-project.api") })
103+
it.ignoredPackages.set(setOf("org.example"))
104+
}
105+
val checkTask = tasks.register("checkApi", KotlinApiCompareTask::class.java) {
106+
it.projectApiFile.set(project.layout.projectDirectory.dir("api").file("gradle-project.api"))
107+
it.generatedApiFile.set(buildTask.flatMap { it.outputApiFile })
108+
}
109+
```

src/main/kotlin/KotlinApiBuildTask.kt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,24 @@ import kotlinx.validation.api.*
99
import org.gradle.api.*
1010
import org.gradle.api.file.*
1111
import org.gradle.api.tasks.*
12+
import java.io.File
1213
import java.util.jar.JarFile
1314
import javax.inject.Inject
1415

16+
private const val MIGRATION_GUIDE_LINK = "https://github.com/Kotlin/binary-compatibility-validator/blob/master/docs/design/0.15.0-migration-guide.md"
17+
private const val OUTPUT_API_DIR_ERROR = "Property outputApiDir was replaced with outputApiFile. Please refer to the migration guide for migration details: $MIGRATION_GUIDE_LINK"
18+
1519
public abstract class KotlinApiBuildTask @Inject constructor(
1620
) : BuildTaskBase() {
1721
@get:OutputFile
1822
public abstract val outputApiFile: RegularFileProperty
1923

24+
@get:Internal
25+
@Deprecated(level = DeprecationLevel.ERROR, message = OUTPUT_API_DIR_ERROR)
26+
public var outputApiDir: File
27+
get() = throw UnsupportedOperationException(OUTPUT_API_DIR_ERROR)
28+
set(_) = throw UnsupportedOperationException(OUTPUT_API_DIR_ERROR)
29+
2030
@get:InputFiles
2131
@get:Optional
2232
@get:PathSensitive(PathSensitivity.RELATIVE)

0 commit comments

Comments
 (0)