diff --git a/README-jvm.md b/README-jvm.md index cd355ff..7229833 100644 --- a/README-jvm.md +++ b/README-jvm.md @@ -1,143 +1,16 @@ -![GitHub](https://img.shields.io/github/license/gmazzo/gradle-codeowners-plugin) -[![Maven Central](https://img.shields.io/maven-central/v/io.github.gmazzo.codeowners/core)](https://central.sonatype.com/artifact/io.github.gmazzo.codeowners/core) -[![Gradle Plugin Portal](https://img.shields.io/gradle-plugin-portal/v/io.github.gmazzo.codeowners.jvm)](https://plugins.gradle.org/plugin/io.github.gmazzo.codeowners.jvm) -[![Build Status](https://github.com/gmazzo/gradle-codeowners-plugin/actions/workflows/build.yaml/badge.svg)](https://github.com/gmazzo/gradle-codeowners-plugin/actions/workflows/build.yaml) -[![Coverage](https://codecov.io/gh/gmazzo/gradle-codeowners-plugin/branch/main/graph/badge.svg?token=ExYkP1Q9oE)](https://codecov.io/gh/gmazzo/gradle-codeowners-plugin) +# The `io.github.gmazzo.codeowners.jvm` plugin +Propagates CODEOWNERS to JVM classes, by generating a package-level `.codeowners` resource files. -# gradle-codeowners-plugin -A Gradle plugin to propagate CODEOWNERS to JVM classes - -# Usage -This plugin is designed to work as a whole build plugin, but you can selectively apply it to target the modules where you actually care about CODEOWNERS propagation. - -The simplest setup is to apply the plugin at the root project, and then to each submodule. At root `build.gradle.kts` add: -```kotlin -plugins { - id("io.github.gmazzo.codeowners.jvm") version "" -} - -subprojects { - apply(plugin = "io.github.gmazzo.codeowners.jvm") -} -``` - -Later, you can query a class's owner by: -```kotlin -val ownersOfFoo = codeOwnersOf() -``` -or in Java: -```java -Set ownersOfFoo = CodeOwners.getCodeOwners(Foo.class); -``` - -## Crash attribution -`Expection`s can also be attributed by inspecting its stacktrace (first match wins) -```kotlin -try { - // do some work - -} catch (ex: Throwable) { - val ownersOfErr = ex.codeOwners - // report to its owner -} -``` -or in Java: -```java -try { - // do some work - -} catch (Throwable ex) { - Set ownersOfErr = CodeOwners.getCodeOwners(ex); - // report to its owner -} -``` - -## Recommended setup on multi module projects -At root's `build.gradle.kts` add: -```kotlin -plugins { - id("io.github.gmazzo.codeowners.jvm") version "" -} - -subprojects { - apply(plugin = "io.github.gmazzo.codeowners.jvm") -} -``` -You must apply the plugin on every project that has source files. Those classes won't be attributed otherwise. -Applying it at the root project only, will only make sense on single module builds. - -## Disable it for specific `SourceSet`s (Java) -You can use the `sourceSet.codeOwners.enabled` property to configure it. -For instance, the following code will disable it `test`: -```kotlin -sourceSets.test { - codeOwners.enabled.set(false) -} -``` - -## Disable it for specific `Variant`s (Android) -You can use the `variant.codeOwners.enabled` property to configure it. -For instance, the following code will enable it only for `debug`: -```kotlin -androidComponents.onVariants { - it.codeOwners.enabled.set(it.buildType == "debug") -} -``` - -## Consuming the generated `mappedCodeOwnersFile` -Each `CodeOwnersResourcesTask` produces a .CODEOWNERS like file which translates build directories to Java packages (in folder format, not '.'). - -To explain this better, given a `.CODEOWNERS` file: -``` -src/main/java @java-devs -src/main/kotlin @koltin-devs -``` -And some source files: -``` -src/main/java/org/example/app/App.java -src/main/java/org/example/foo/Foo.java -src/main/kotlin/org/example/app/AppKt.kt -src/main/kotlin/org/example/bar/Bar.kt -``` -The generated `mappedCodeOwnersFile` will contain -``` -org/example/app @koltin-devs @java-devs -org/example/foo @java-devs -org/example/bar @koltin-devs -``` - -You could use these files up feed any observability service for instance, allowing to have owners attributions given a package name/path. - -In case you want to generate these but don't want to pollute/expose your production code with the ownership information, you use the `addCodeOwnershipAsResources` DSL to prevent the resources to be added (still generating the mapping files): -```kotlin -codeOwners.addCodeOwnershipAsResources.set(false) -``` - -To consume the `mappedCodeOwnersFile`, use the `.map`Property API, to ensure task dependencies are correctly computed, for instance: -```kotlin -tasks.register("collectMappingFiles") { - from(tasks.named("generateCodeOwnersResources").flatMap { it.mappedCodeOwnersFile }) - into(project.layout.buildDirectory.dir("mappings")) -} -``` - -## The CODEOWNERS file -The expected format is the same as [GitHub's](https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners#codeowners-syntax) and it can be located at any of the following paths: -- `$rootDir/CODEOWNERS` -- `$rootDir/.github/CODEOWNERS` -- `$rootDir/.gitlab/CODEOWNERS` -- `$rootDir/docs/CODEOWNERS` - -### Specifying CODEOWNERS file location -```kotlin -codeOwners.codeOwnersFile.set(layout.projectDirectory.file("somePath/.CODEOWNERS")) -``` +> [!NOTE] +> This plugin aggregates the `io.github.gmazzo.codeowners` plugin, so you don't need to apply it too. # How it works This plugin is mean to work at JVM level: compatible with `java`, `groovy` and `kotlin` and Android. The plugin binds by default on the compilation toolchain, inspecting the source folders and generating a set of java `.codeowners` resources that later the provided `xxx.codeowners` function will use to resolve the ownership information (or `getCodeOwners` on Java, see [Usage](#usage)) +You can later query its ownership information as described at [Usage](./README.md#usage). + ## Caveats on the approach The plugin will do its best to provide a reliable owners attribution on classes, even by inspecting dependencies looking for collision of packages. @@ -164,3 +37,21 @@ The final owners for classes located at the given package will be: Given the known limitations on the JVM resources approach, here is a list tips to have a 100% owners attributes accuracy: 1) Use a dedicated Java package per Gradle module 2) Prefer directory patterns over file extension ones + +## Disable it for specific `SourceSet`s (Java) +You can use the `codeOwners.enabled` property to configure it. +For instance, the following code will disable it for the `test` source set: +```kotlin +sourceSets.test { + codeOwners.enabled = false +} +``` + +## Disable it for specific `Variant`s (Android) +You can use the `codeOwners.enabled` property to configure it. +For instance, the following code will enable it only for variants of `debug` build type: +```kotlin +androidComponents.onVariants { variant -> + variant.codeOwners.enabled = false +} +``` diff --git a/README-kotlin.md b/README-kotlin.md index 3a7cb64..830fa45 100644 --- a/README-kotlin.md +++ b/README-kotlin.md @@ -1,166 +1,33 @@ -![GitHub](https://img.shields.io/github/license/gmazzo/gradle-codeowners-plugin) -[![Maven Central](https://img.shields.io/maven-central/v/io.github.gmazzo.codeowners/core)](https://central.sonatype.com/artifact/io.github.gmazzo.codeowners/core) -[![Gradle Plugin Portal](https://img.shields.io/gradle-plugin-portal/v/io.github.gmazzo.codeowners.jvm)](https://plugins.gradle.org/plugin/io.github.gmazzo.codeowners.jvm) -[![Build Status](https://github.com/gmazzo/gradle-codeowners-plugin/actions/workflows/build.yaml/badge.svg)](https://github.com/gmazzo/gradle-codeowners-plugin/actions/workflows/build.yaml) -[![Coverage](https://codecov.io/gh/gmazzo/gradle-codeowners-plugin/branch/main/graph/badge.svg?token=ExYkP1Q9oE)](https://codecov.io/gh/gmazzo/gradle-codeowners-plugin) +# The `io.github.gmazzo.codeowners.jvm` plugin +Propagates CODEOWNERS to Kotlin classes, by generating a `@CodeOwners` annotation on each Kotlin Class/File at compilation time. -# gradle-codeowners-plugin -A Gradle plugin to propagate CODEOWNERS to JVM classes +> [!NOTE] +> This plugin aggregates the `io.github.gmazzo.codeowners` plugin, so you don't need to apply it too. -# Usage -This plugin is designed to work as a whole build plugin, but you can selectively apply it to target the modules where you actually care about CODEOWNERS propagation. - -The simplest setup is to apply the plugin at the root project, and then to each submodule. At root `build.gradle.kts` add: -```kotlin -plugins { - id("io.github.gmazzo.codeowners.kotlin") version "" -} - -subprojects { - apply(plugin = "io.github.gmazzo.codeowners.kotlin") -} -``` - -Later, you can query a class's owner by: -```kotlin -val ownersOfFoo = codeOwnersOf() -``` -or in Java: -```java -Set ownersOfFoo = CodeOwners.getCodeOwners(Foo.class); -``` - -## Crash attribution -`Expection`s can also be attributed by inspecting its stacktrace (first match wins) -```kotlin -try { - // do some work - -} catch (ex: Throwable) { - val ownersOfErr = ex.codeOwners - // report to its owner -} -``` -or in Java: -```java -try { - // do some work +# How it works +When applies, it binds a Kotlin IR compiler plugin that hooks on the compilation process, and it will decorate all processed Kotlin classes/files with a `@CodeOwners` (or `@file:CodeOwners`) annotation. -} catch (Throwable ex) { - Set ownersOfErr = CodeOwners.getCodeOwners(ex); - // report to its owner -} -``` +You can later query its ownership information as described at [Usage](./README.md#usage). -## Recommended setup on multi module projects -At root's `build.gradle.kts` add: +## Disable it for specific `KotlinTarget`s +You can use the `codeOwners.enabled` property to configure it. +For instance, the following code will disable it for the `jvm` target: ```kotlin -plugins { - id("io.github.gmazzo.codeowners.kotlin") version "" -} - -subprojects { - apply(plugin = "io.github.gmazzo.codeowners.jvm") +kotlin.targets.named("jvm") { + codeOwners.enabled = false } ``` -You must apply the plugin on every project that has source files. Those classes won't be attributed otherwise. -Applying it at the root project only, will only make sense on single module builds. -## Disable it for specific `SourceSet`s (Java) -You can use the `sourceSet.codeOwners.enabled` property to configure it. -For instance, the following code will disable it `test`: +## Disable it for specific `KotlinCompilation`s +You can use the `codeOwners.enabled` property to configure it. +For instance, the following code will disable it for any non-`main` compilation of any `KotlinTarget` target: ```kotlin -sourceSets.test { - codeOwners.enabled.set(false) +kotlin.targets.configureEach { + compilations.configureEach { + codeOwners.enabled = name == "main" + } } ``` -## Disable it for specific `Variant`s (Android) -You can use the `variant.codeOwners.enabled` property to configure it. -For instance, the following code will enable it only for `debug`: -```kotlin -androidComponents.onVariants { - it.codeOwners.enabled.set(it.buildType == "debug") -} -``` - -## Consuming the generated `mappedCodeOwnersFile` -Each `CodeOwnersResourcesTask` produces a .CODEOWNERS like file which translates build directories to Java packages (in folder format, not '.'). - -To explain this better, given a `.CODEOWNERS` file: -``` -src/main/java @java-devs -src/main/kotlin @koltin-devs -``` -And some source files: -``` -src/main/java/org/example/app/App.java -src/main/java/org/example/foo/Foo.java -src/main/kotlin/org/example/app/AppKt.kt -src/main/kotlin/org/example/bar/Bar.kt -``` -The generated `mappedCodeOwnersFile` will contain -``` -org/example/app @koltin-devs @java-devs -org/example/foo @java-devs -org/example/bar @koltin-devs -``` - -You could use these files up feed any observability service for instance, allowing to have owners attributions given a package name/path. - -In case you want to generate these but don't want to pollute/expose your production code with the ownership information, you use the `addCodeOwnershipAsResources` DSL to prevent the resources to be added (still generating the mapping files): -```kotlin -codeOwners.addCodeOwnershipAsResources.set(false) -``` - -To consume the `mappedCodeOwnersFile`, use the `.map`Property API, to ensure task dependencies are correctly computed, for instance: -```kotlin -tasks.register("collectMappingFiles") { - from(tasks.named("generateCodeOwnersResources").flatMap { it.mappedCodeOwnersFile }) - into(project.layout.buildDirectory.dir("mappings")) -} -``` - -## The CODEOWNERS file -The expected format is the same as [GitHub's](https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners#codeowners-syntax) and it can be located at any of the following paths: -- `$rootDir/CODEOWNERS` -- `$rootDir/.github/CODEOWNERS` -- `$rootDir/.gitlab/CODEOWNERS` -- `$rootDir/docs/CODEOWNERS` - -### Specifying CODEOWNERS file location -```kotlin -codeOwners.codeOwnersFile.set(layout.projectDirectory.file("somePath/.CODEOWNERS")) -``` - -# How it works -This plugin is mean to work at JVM level: compatible with `java`, `groovy` and `kotlin` and Android. - -The plugin binds by default on the compilation toolchain, inspecting the source folders and generating a set of java `.codeowners` resources that later the provided `xxx.codeowners` function will use to resolve the ownership information (or `getCodeOwners` on Java, see [Usage](#usage)) - -## Caveats on the approach -The plugin will do its best to provide a reliable owners attribution on classes, even by inspecting dependencies looking for collision of packages. - -For instance, multiple source folders -- `src/main/java/com/test/myapp/aaa` -- `src/main/kotlin/com/test/myapp/bbb` - -may be contributing to the same `com.test.myapp` package. - -If you `.CODEOWNERS` file looks similar to this: -``` -aaaOwner src/*/java -bbbOwner src/*/kotlin -``` -The final owners for classes located at the given package will be: - -| pacakge | owners | -|----------------------|---------------------------| -| `com.test.myapp` | `aaaOwner` and `bbbOwner` | -| `com.test.myapp.aaa` | `aaaOwner` | -| `com.test.myapp.bbb` | `bbbOwner` | - -## General advices for structuring CODEOWNERS file for this plugin -Given the known limitations on the JVM resources approach, here is a list tips to have a 100% owners attributes accuracy: -1) Use a dedicated Java package per Gradle module -2) Prefer directory patterns over file extension ones +> [!NOTE] +> It supports any Kotlin subplugin: `jvm`, `android`, including `multiplatform` ones targeting `native` or `js` platforms. diff --git a/README-report.md b/README-report.md new file mode 100644 index 0000000..f9c6a52 --- /dev/null +++ b/README-report.md @@ -0,0 +1,15 @@ +# The `io.github.gmazzo.codeowners` plugin +Generates `codeOwnersReport` a task that produces a `.CODEOWNERS`-like file with class names: +```CODEOWNERS +# CodeOwners of module ':demo-project-jvm:app' + +org/test/jvm/app/AppClass app-devs +org/test/jvm/app/AppOwnersTest test-devs +org/test/jvm/app/BuildConfig app-devs +org/test/jvm/app/test/BuildConfig app-devs +org/test/jvm/utils/AppUtils app-devs +``` +This plugin integrates with Java, Android and Kotlin plugins, generating dedicated `codeOwnersXXXReport` tasks per source set/variant: +- For Java, creates a task per `SourceSet` +- For Android, creates a task per `Variant` (including their `UnitTest` and `AndroidTest`s) +- For Kotlin, creates a task per `KotlinSourceSet`. Supports any Kotlin subplugin: `jvm`, `android`, and `multiplatform` diff --git a/README.md b/README.md new file mode 100644 index 0000000..f181413 --- /dev/null +++ b/README.md @@ -0,0 +1,101 @@ +![GitHub](https://img.shields.io/github/license/gmazzo/gradle-codeowners-plugin) +[![Maven Central](https://img.shields.io/maven-central/v/io.github.gmazzo.codeowners/matcher)](https://central.sonatype.com/artifact/io.github.gmazzo.codeowners/matcher) +[![Gradle Plugin Portal](https://img.shields.io/gradle-plugin-portal/v/io.github.gmazzo.codeowners)](https://plugins.gradle.org/plugin/io.github.gmazzo.codeowners) +[![Build Status](https://github.com/gmazzo/gradle-codeowners-plugin/actions/workflows/build.yaml/badge.svg)](https://github.com/gmazzo/gradle-codeowners-plugin/actions/workflows/build.yaml) +[![Coverage](https://codecov.io/gh/gmazzo/gradle-codeowners-plugin/branch/main/graph/badge.svg?token=ExYkP1Q9oE)](https://codecov.io/gh/gmazzo/gradle-codeowners-plugin) + +# gradle-codeowners-plugin +A Gradle plugin to propagate CODEOWNERS information to classes + +It consists on 3 different plugins, each one providing a different set of features and targeting different use cases: +1) [The `io.github.gmazzo.codeowners` plugin](README-report.md) adds a Gradle report of classes' ownership +2) [The `io.github.gmazzo.codeowners.jvm` plugin](README-jvm.md) propagates the classes' ownership information to runtime. It supports any JVM build (`java`, `groovy`, etc) that produces `.class` files, but **JVM-only** +3) [The `io.github.gmazzo.codeowners.kotlin` Kotlin Compiler plugin](README-kotlin.md) propagates the classes' ownership information to runtime. It supports any Kotlin build (`jvm`, `android`, `multiplatform`, etc, but **Kotlin-only**) + +# Usage +This plugin is designed to work as a whole build plugin, but you can selectively apply it to target the modules where you actually care about CODEOWNERS propagation. + +The simplest setup is to apply the plugin at the root project, and then to each submodule. At root `build.gradle.kts` add: +```kotlin +plugins { + id("io.github.gmazzo.codeowners") version "" +} + +subprojects { + apply(plugin = "io.github.gmazzo.codeowners") +} +``` + +You should apply the right plugins according to your needs: +- `io.github.gmazzo.codeowners` (_Report_) is for the generating codeowners-like file by Java/Kotlin classes names +- `io.github.gmazzo.codeowners.jvm` (_JVM_) is for propagating codeowners info to JVM-only projects +- `io.github.gmazzo.codeowners.kotlin` (_Kotlin_) (recommended) is for propagating codeowners info to for **pure Kotlin** projects (including JVM and multiplatform) + +| Plugin / Feature | _Report_ | _JVM_ | _Kotlin_ | +|----------------------------------------------------------------------|----------|-------|----------| +| Generates class-like reports at build time | ✅ | ✅ * | ✅ * | +| Propagates codeowners info to runtime | ❌ | ✅ | ✅ | +| Works with JVM projects | ✅ | ✅ | ✅ | +| Works with Multiplatform projects | ❌ | ❌ | ✅ | +| Acurrancy:
Codeowners info matches alwats the original file ones | 🟢 | 🟡 ** | 🟢 | + +(*) inherited from `io.github.gmazzo.codeowners` (_Report_) plugin
+(**) because how the Java Resources API on JVM the ownership information may be inaccurate in some cases. See [Caveats on the approach](./README-jvm.md#caveats-on-the-approach) for more details. + +## Getting ownership information at runtime +Later, you can query a class's owner by: +```kotlin +val ownersOfFoo = codeOwnersOf() +``` +or in Java: +```java +Set ownersOfFoo = CodeOwners.getCodeOwners(Foo.class); +``` + +## Crash attribution +`Expection`s can also be attributed by inspecting its stacktrace (first match wins) +```kotlin +try { + // do some work + +} catch (ex: Throwable) { + val ownersOfErr = ex.codeOwners + // report to its owner +} +``` +or in Java: +```java +try { + // do some work + +} catch (Throwable ex) { + Set ownersOfErr = CodeOwners.getCodeOwners(ex); + // report to its owner +} +``` + +## Recommended setup on multi module projects +At root's `build.gradle.kts` add: +```kotlin +plugins { + id("io.github.gmazzo.codeowners") version "" +} + +subprojects { + apply(plugin = "io.github.gmazzo.codeowners") +} +``` +You must apply the plugin on **every project that has source files**. Those classes won't be computed otherwise. +Applying it at the root project only, will only make sense on single module builds. + +# The CODEOWNERS file +The expected format is the same as [GitHub's](https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners#codeowners-syntax) and it can be located at any of the following paths: +- `$rootDir/CODEOWNERS` +- `$rootDir/.github/CODEOWNERS` +- `$rootDir/.gitlab/CODEOWNERS` +- `$rootDir/docs/CODEOWNERS` + +### Specifying CODEOWNERS file location +```kotlin +codeOwners.codeOwnersFile.set(layout.projectDirectory.file("somePath/.CODEOWNERS")) +```