diff --git a/CHANGELOG.md b/CHANGELOG.md index b67fb81..f6f3c84 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,11 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [Unreleased] + +### Fixed +- Library ownership: version-less `group:artifact` patterns now match any version of the artifact. Previously they matched nothing, silently leaving such libraries unattributed (`NA`), since real coordinates always carry a version + ## [0.2.0-alpha03] - 2026-07-29 ### Added diff --git a/app-sizer/src/main/kotlin/com/grab/sizer/analyzer/TeamMapping.kt b/app-sizer/src/main/kotlin/com/grab/sizer/analyzer/TeamMapping.kt index 60361e3..1aa3208 100644 --- a/app-sizer/src/main/kotlin/com/grab/sizer/analyzer/TeamMapping.kt +++ b/app-sizer/src/main/kotlin/com/grab/sizer/analyzer/TeamMapping.kt @@ -118,11 +118,17 @@ class YmlTeamMapping( private fun findBestPatternMatch(coordinate: String, teamMapping: Map>): String? { - // Priority: exact > artifact wildcard > group wildcard + // Within a team: exact > version-less coordinate > artifact wildcard > group wildcard. + // Teams are checked in file order; the first team with any matching pattern wins. for ((team, patterns) in teamMapping) { // Check exact match first if (coordinate in patterns) return team + // Check version-less coordinates (com.example:library): any version of exactly that artifact + patterns.filter { !it.contains("*") && it.count { c -> c == ':' } == 1 }.forEach { pattern -> + if (coordinate.startsWith("$pattern:")) return team + } + // Check artifact wildcards (com.example:library:*) patterns.filter { it.contains(":*") }.forEach { pattern -> val prefix = pattern.substringBeforeLast(":*") diff --git a/app-sizer/src/test/kotlin/com/grab/sizer/analyzer/YmlTeamMappingTest.kt b/app-sizer/src/test/kotlin/com/grab/sizer/analyzer/YmlTeamMappingTest.kt index 09d742c..bc9b807 100644 --- a/app-sizer/src/test/kotlin/com/grab/sizer/analyzer/YmlTeamMappingTest.kt +++ b/app-sizer/src/test/kotlin/com/grab/sizer/analyzer/YmlTeamMappingTest.kt @@ -141,6 +141,31 @@ class YmlTeamMappingTest { assertEquals(setOf("Team1", "Platform", "Networking"), teamMapping.getAllTeams()) } + @Test + fun testLibraryOwnershipVersionlessCoordinate() { + val moduleYml = tempFolder.newFile("modules.yml").apply { + writeText("Team1:\n - :module1") + } + val libraryYml = tempFolder.newFile("libraries.yml").apply { + writeText(""" + Media: + - com.example.media:player + Messaging: + - com.example.media:chat-ui + """.trimIndent()) + } + + val teamMapping = YmlTeamMapping(moduleYml, libraryYml) + + // A version-less group:artifact pattern matches any version of that artifact + assertEquals("Media", teamMapping.getLibraryOwner("com.example.media:player:1.2.3")) + assertEquals("Media", teamMapping.getLibraryOwner("com.example.media:player:2.0.0")) + assertEquals("Messaging", teamMapping.getLibraryOwner("com.example.media:chat-ui:0.9.0")) + // It must not match a different artifact sharing the name as a prefix, nor siblings + assertNull(teamMapping.getLibraryOwner("com.example.media:player-extras:1.0.0")) + assertNull(teamMapping.getLibraryOwner("com.example.media:contacts:1.0.0")) + } + @Test fun testLibraryOwnershipArtifactWildcard() { val moduleYml = tempFolder.newFile("modules.yml").apply { diff --git a/docs/cli.md b/docs/cli.md index 4af2f65..e490f62 100644 --- a/docs/cli.md +++ b/docs/cli.md @@ -75,8 +75,9 @@ Team2: Pattern matching is evaluated in this order; the first match wins: 1. **Exact coordinate** — e.g. `androidx.core:core-ktx:1.13.1` -2. **Group wildcard** using `:*` — e.g. `androidx.core:*` (matches any artifact under `androidx.core`) -3. **Group wildcard** using `.*` — e.g. `androidx.*` (matches any group beginning with `androidx.`) +2. **Version-less coordinate** — e.g. `androidx.core:core-ktx` (matches any version of that artifact) +3. **Group wildcard** using `:*` — e.g. `androidx.core:*` (matches any artifact under `androidx.core`) +4. **Group wildcard** using `.*` — e.g. `androidx.*` (matches any group beginning with `androidx.`) Libraries that do not match any pattern are reported as `NA` in team reports (see [Limitations](./limitation.md)). diff --git a/docs/plugin.md b/docs/plugin.md index ecb606a..bf0a842 100644 --- a/docs/plugin.md +++ b/docs/plugin.md @@ -143,8 +143,9 @@ Team2: Pattern matching is evaluated in this order; the first match wins: 1. **Exact coordinate** — e.g. `androidx.core:core-ktx:1.13.1` -2. **Group wildcard** using `:*` — e.g. `androidx.core:*` (matches any artifact under `androidx.core`) -3. **Group wildcard** using `.*` — e.g. `androidx.*` (matches any group beginning with `androidx.`) +2. **Version-less coordinate** — e.g. `androidx.core:core-ktx` (matches any version of that artifact) +3. **Group wildcard** using `:*` — e.g. `androidx.core:*` (matches any artifact under `androidx.core`) +4. **Group wildcard** using `.*` — e.g. `androidx.*` (matches any group beginning with `androidx.`) Libraries that do not match any pattern are reported as `NA` in team reports (see [Limitations](./limitation.md)).