From 70764d2d3cbdb584da1d43da76a342343e4efccf Mon Sep 17 00:00:00 2001 From: Leo Gagliardi Date: Thu, 28 May 2026 18:11:50 +0200 Subject: [PATCH 1/4] feat(bom): auto-generate bom/CHANGELOG.md and optional GitHub Release on publish Co-Authored-By: Claude Sonnet 4.6 --- scripts/build.gradle.kts | 111 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 111 insertions(+) diff --git a/scripts/build.gradle.kts b/scripts/build.gradle.kts index 42f7ed8a4..7b352c66d 100644 --- a/scripts/build.gradle.kts +++ b/scripts/build.gradle.kts @@ -216,6 +216,108 @@ fun haveModuleTPay(key: String): Boolean { return list.contains(key) } +fun getBomVersionFromToml(): String { + val tomlFile = if (File("android-scripts/gradle/libs-urbi.versions.toml").exists()) + File("android-scripts/gradle/libs-urbi.versions.toml") + else + File("$rootDir/android-urbi-framework/android-scripts/gradle/libs-urbi.versions.toml") + return try { + tomlFile.readLines() + .firstOrNull { it.trimStart().startsWith("urbi-bom") } + ?.split("=")?.getOrNull(1) + ?.trim()?.removeSurrounding("\"") ?: "unknown" + } catch (e: Exception) { + println("Warning: cannot read BOM version from TOML: ${e.message}") + "unknown" + } +} + +/** + * Reads [Unreleased] entries from each changed module's changelog and writes a new entry + * to bom/CHANGELOG.md. Returns the generated entry text (used for GitHub Release notes). + */ +fun writeBomChangelog( + changedModules: Set, + moduleToVersionKey: Map, + currentVersions: Map, + dataNow: String, + bomVersion: String +): String { + val sb = StringBuilder() + sb.appendLine("## [$bomVersion] $dataNow") + sb.appendLine() + + changedModules.sorted().forEach { module -> + val versionKey = moduleToVersionKey[module] ?: return@forEach + val moduleVersion = currentVersions[versionKey] ?: "unknown" + val changelogFile = when { + File("$module/changelog.md").exists() -> File("$module/changelog.md") + File("$rootDir/android-urbi-framework/$module/changelog.md").exists() -> + File("$rootDir/android-urbi-framework/$module/changelog.md") + else -> null + } + + val entries = mutableListOf() + if (changelogFile != null) { + var inUnreleased = false + run breaking@{ + changelogFile.readLines().forEach { line -> + when { + line.startsWith("## [Unreleased]", ignoreCase = true) -> inUnreleased = true + inUnreleased && line.startsWith("##") -> return@breaking + inUnreleased && line.startsWith("-") -> entries.add(line) + } + } + } + } + + if (entries.isNotEmpty()) { + sb.appendLine("### $module — $moduleVersion") + entries.forEach { sb.appendLine(it) } + sb.appendLine() + } + } + + val newEntry = sb.toString().trimEnd() + val bomChangelogFile = if (File("bom").exists()) + File("bom/CHANGELOG.md") + else + File("$rootDir/android-urbi-framework/bom/CHANGELOG.md") + + val existing = if (bomChangelogFile.exists()) "\n\n${bomChangelogFile.readText()}" else "" + bomChangelogFile.writeText("$newEntry$existing") + println("BOM changelog updated: ${bomChangelogFile.path}") + return newEntry +} + +/** + * Creates a GitHub Release for the given BOM version using the gh CLI. + * Only runs when -PcreateRelease=true is passed. + */ +fun createGithubRelease(bomVersion: String, releaseNotes: String) { + val tempFile = File.createTempFile("bom-release-notes", ".md") + try { + tempFile.writeText(releaseNotes) + ByteArrayOutputStream().use { os -> + exec { + commandLine( + "gh", "release", "create", "bom-$bomVersion", + "--repo", "urbi-mobility/android-urbi-framework", + "--title", "BoM $bomVersion", + "--notes-file", tempFile.absolutePath + ) + standardOutput = os + } + println(os.toString()) + } + println("GitHub Release created: bom-$bomVersion") + } catch (e: Exception) { + println("Warning: GitHub Release creation failed: ${e.message}") + } finally { + tempFile.delete() + } +} + fun createMapVersion(): HashMap { val tpaylib = "telepassLibVersion" // Read Version on Gradle file @@ -524,6 +626,15 @@ tasks.register("upgrade-lib-version") { out.println(it) } } + + val format = SimpleDateFormat("yyyy-MM-dd") + val dataNow = format.format(Date()) + val bomVersion = getBomVersionFromToml() + val currentVersions = createMapVersion() + val releaseNotes = writeBomChangelog(keyToChangeVersion, mapVersionUrbi, currentVersions, dataNow, bomVersion) + val createRelease = project.properties["createRelease"]?.toString().toBoolean() + if (createRelease) createGithubRelease(bomVersion, releaseNotes) + println("Upload BoM") ByteArrayOutputStream().use { os -> val result = exec { From cdf2ac45479771faff6e6541ca9b3e7a6e9bcf5e Mon Sep 17 00:00:00 2001 From: Leo Gagliardi Date: Thu, 28 May 2026 18:19:10 +0200 Subject: [PATCH 2/4] docs(scripts): add README for publish tasks and bom changelog; make GitHub Release default Co-Authored-By: Claude Sonnet 4.6 --- README.md | 122 +++++++++++++++++++++++++++++++++++++-- scripts/build.gradle.kts | 4 +- 2 files changed, 120 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 02c6870e9..b59a7c993 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,120 @@ # android-scripts -This is an utility repo that contain scripts for use in our private repo sdk, -in particular is used as submodule for repos: -* [android-telepass-pay-framework](https://github.com/urbi-mobility/android-telepass-pay-framework) -* [android-urbi-unica-framework](https://github.com/wise-emotions/android-urbi-unica-framework) +Utility submodule used by `android-urbi-framework` (and other Urbi repos). +Contains Gradle scripts for version management, changelog automation, and library publishing. + +--- + +## Contents + +| Path | Purpose | +|---|---| +| `scripts/build.gradle.kts` | Publishing tasks: version bump, changelog update, BoM publish, GitHub Release | +| `gradle/depend.gradle` | Module version definitions (`//---Module Version---//` block) | +| `gradle/libs-urbi.versions.toml` | Version catalog, including the `urbi-bom` version (date-based) | + +--- + +## Gradle Tasks + +### `update-version-lib-changelog` +**Main entry point for a full publish cycle.** + +Reads `[Unreleased]` sections from all module changelogs, aggregates them into `urbisample/changelog.md`, updates the BoM version in the TOML to today's date, then delegates to `upgrade-lib-version`. + +```bash +# Default (patch bump) +./gradlew update-version-lib-changelog + +# Minor or major bump +./gradlew update-version-lib-changelog -Dargs=minor +./gradlew update-version-lib-changelog -Dargs=major +``` + +--- + +### `upgrade-lib-version` +Reads module changelogs for pending `[Unreleased]` entries, bumps the affected library versions in `depend.gradle`, then: + +1. Writes a new entry to `bom/CHANGELOG.md` (see [BoM Changelog](#bom-changelog)) +2. Creates a GitHub Release on `android-urbi-framework` (see [GitHub Release](#github-release)) +3. Publishes the BoM to GitHub Packages (`bom:publishAllBom`) +4. Uploads all changed libraries (`uploadlib`) + +```bash +./gradlew upgrade-lib-version # patch bump, publishes GitHub Release +./gradlew upgrade-lib-version -Dargs=minor +./gradlew upgrade-lib-version -PskipRelease=true # skip GitHub Release creation +``` + +--- + +### `uploadlib` +Publishes all libraries with pending changes to GitHub Packages. +For each module: replaces the `[Unreleased]` section with the new versioned entry in its `changelog.md`, then publishes the artifact. + +```bash +./gradlew uploadlib +./gradlew uploadlib -Pargs=skipService # skip copyServicesProvider +``` + +--- + +### `update-version-lib` +Lighter version of `upgrade-lib-version`: bumps versions and uploads libs, but does **not** update the BoM version, write the BoM changelog, or create a GitHub Release. + +--- + +## BoM Changelog + +`bom/CHANGELOG.md` (in `android-urbi-framework`) is auto-generated on every `upgrade-lib-version` run. + +**Format:** +```markdown +## [2026.05.28] 2026-05-28 + +### composeds — 3.4.1 +- #3027 | Fix orderId nella navigazione al dettaglio storico + +### utilitylib — 6.26.5 +- #3100 | Updated button style +``` + +Each entry lists only the modules that had `[Unreleased]` changes, with their new version and the individual changelog bullets. The BoM version matches the date in `libs-urbi.versions.toml` (`yyyy.MM.dd`). + +--- + +## GitHub Release + +A GitHub Release on `urbi-mobility/android-urbi-framework` is created automatically with tag `bom-` (e.g., `bom-2026.05.28`) and the same content written to `bom/CHANGELOG.md`. + +**Default behaviour:** Release is created on every `upgrade-lib-version` run. + +**To skip** (e.g., dry-run or CI test): +```bash +./gradlew upgrade-lib-version -PskipRelease=true +``` + +Requires the `gh` CLI to be authenticated in the environment (`gh auth login`). + +--- + +## Version Management + +Module versions live in `gradle/depend.gradle` between the `//---Module Version---//` and `//---End---//` markers: + +```groovy +//---Module Version---// + utilityVersion = '6.26.5' + modelVersion = '3.12.0' + // ... +//---End---// +``` + +The BoM version is separate, in `gradle/libs-urbi.versions.toml`: +```toml +[versions] +urbi-bom = "2026.05.28" +``` + +It is updated automatically by `update-version-lib-changelog` to today's date before each publish cycle. diff --git a/scripts/build.gradle.kts b/scripts/build.gradle.kts index 7b352c66d..a5999a24e 100644 --- a/scripts/build.gradle.kts +++ b/scripts/build.gradle.kts @@ -632,8 +632,8 @@ tasks.register("upgrade-lib-version") { val bomVersion = getBomVersionFromToml() val currentVersions = createMapVersion() val releaseNotes = writeBomChangelog(keyToChangeVersion, mapVersionUrbi, currentVersions, dataNow, bomVersion) - val createRelease = project.properties["createRelease"]?.toString().toBoolean() - if (createRelease) createGithubRelease(bomVersion, releaseNotes) + val skipRelease = project.properties["skipRelease"]?.toString().toBoolean() + if (!skipRelease) createGithubRelease(bomVersion, releaseNotes) println("Upload BoM") ByteArrayOutputStream().use { os -> From ea70d4a6662edb264309d203b9e0683ba14c26b3 Mon Sep 17 00:00:00 2001 From: gaglileo Date: Mon, 1 Jun 2026 11:31:58 +0200 Subject: [PATCH 3/4] feat(release-bom): add standalone BoM release task + fix skipRelease null-safety --- scripts/build.gradle.kts | 112 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 110 insertions(+), 2 deletions(-) diff --git a/scripts/build.gradle.kts b/scripts/build.gradle.kts index a5999a24e..c340972fc 100644 --- a/scripts/build.gradle.kts +++ b/scripts/build.gradle.kts @@ -290,9 +290,35 @@ fun writeBomChangelog( return newEntry } +/** + * Finds the versioned changelog section matching [versionTag] (e.g. "UTL_6.26.6") + * and returns its bullet-point entries. + */ +fun readModuleChangesForVersion(module: String, versionTag: String): List { + val pathFile = "$module/changelog.md" + val changelogFile = when { + File(pathFile).exists() -> File(pathFile) + File("$rootDir/android-urbi-framework/$pathFile").exists() -> + File("$rootDir/android-urbi-framework/$pathFile") + else -> return emptyList() + } + val entries = mutableListOf() + var inSection = false + run breaking@{ + changelogFile.readLines().forEach { line -> + when { + !inSection && line.startsWith("## [") && line.contains(versionTag) -> inSection = true + inSection && line.startsWith("##") -> return@breaking + inSection && line.startsWith("-") -> entries.add(line) + } + } + } + return entries +} + /** * Creates a GitHub Release for the given BOM version using the gh CLI. - * Only runs when -PcreateRelease=true is passed. + * Skip with -PskipRelease=true. */ fun createGithubRelease(bomVersion: String, releaseNotes: String) { val tempFile = File.createTempFile("bom-release-notes", ".md") @@ -632,7 +658,7 @@ tasks.register("upgrade-lib-version") { val bomVersion = getBomVersionFromToml() val currentVersions = createMapVersion() val releaseNotes = writeBomChangelog(keyToChangeVersion, mapVersionUrbi, currentVersions, dataNow, bomVersion) - val skipRelease = project.properties["skipRelease"]?.toString().toBoolean() + val skipRelease = project.properties["skipRelease"]?.toString()?.toBoolean() ?: false if (!skipRelease) createGithubRelease(bomVersion, releaseNotes) println("Upload BoM") @@ -662,6 +688,88 @@ tasks.register("upgrade-lib-version") { } } +/** + * Standalone BoM release — no lib upload required. + * + * For each module, reads the changelog section that matches the module's current version + * in depend.gradle (e.g. ## [UTL_6.26.6]). Writes bom/CHANGELOG.md, publishes the BoM to + * GitHub Packages, and creates a GitHub Release. + * + * Usage: + * ./gradlew release-bom # all modules with versioned entries + * ./gradlew release-bom -Pmodules=utilitylib,composeds # explicit subset + * ./gradlew release-bom -PskipRelease=true # skip GitHub Release creation + */ +tasks.register("release-bom") { + doLast { + val format = SimpleDateFormat("yyyy-MM-dd") + val dataNow = format.format(Date()) + val bomVersion = getBomVersionFromToml() + val changelogPrefixes = getChangelogMap() // module -> tag prefix, e.g. "UTL_" + val versionKeys = getVersionKeyFromModule() // module -> version key, e.g. "utilityVersion" + val currentVersions = createMapVersion() // version key -> version string + + val modulesParam = project.properties["modules"]?.toString() + val candidateModules: Set = if (!modulesParam.isNullOrBlank()) { + modulesParam.split(",").map { it.trim() }.filter { it.isNotEmpty() }.toSet() + } else { + changelogPrefixes.keys.toSet() + } + + val sb = StringBuilder() + sb.appendLine("## [$bomVersion] $dataNow") + sb.appendLine() + + var hasEntries = false + candidateModules.sorted().forEach { module -> + val prefix = changelogPrefixes[module] ?: return@forEach + val versionKey = versionKeys[module] ?: return@forEach + val version = currentVersions[versionKey] ?: return@forEach + val versionTag = "$prefix$version" + val entries = readModuleChangesForVersion(module, versionTag) + if (entries.isNotEmpty()) { + hasEntries = true + sb.appendLine("### $module — $version") + entries.forEach { sb.appendLine(it) } + sb.appendLine() + } + } + + if (!hasEntries) { + println("No versioned changelog entries found for current library versions. Nothing to release.") + return@doLast + } + + val releaseNotes = sb.toString().trimEnd() + + val bomChangelogFile = if (File("bom").exists()) + File("bom/CHANGELOG.md") + else + File("$rootDir/android-urbi-framework/bom/CHANGELOG.md") + val existing = if (bomChangelogFile.exists()) "\n\n${bomChangelogFile.readText()}" else "" + bomChangelogFile.writeText("$releaseNotes$existing") + println("BoM changelog updated: ${bomChangelogFile.path}") + + val publishThirdParty = project.properties["publishThirdParty"]?.toString()?.toBoolean() ?: false + println("Publishing BoM to GitHub Packages...") + ByteArrayOutputStream().use { os -> + val result = exec { + if (publishThirdParty) { + commandLine("./gradlew", "bom:publishAllBom") + } else { + commandLine("./gradlew", "bom:publishAllBomNoThirdParty") + } + standardOutput = os + } + println(os.toString()) + println("Publish BoM: $result") + } + + val skipRelease = project.properties["skipRelease"]?.toString()?.toBoolean() ?: false + if (!skipRelease) createGithubRelease(bomVersion, releaseNotes) + } +} + /** * This scripts read depend.gradle file where libs version are and upgrade patch versionif there is some change in their changelog, and then upload new libs */ From 3004596f13fd5600651923bd462cd62601965885 Mon Sep 17 00:00:00 2001 From: gaglileo Date: Mon, 1 Jun 2026 11:35:30 +0200 Subject: [PATCH 4/4] docs: document release-bom task in README --- README.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/README.md b/README.md index b59a7c993..641b88037 100644 --- a/README.md +++ b/README.md @@ -60,6 +60,23 @@ For each module: replaces the `[Unreleased]` section with the new versioned entr --- +### `release-bom` +**Standalone BoM release — no lib upload required.** + +For each module, looks up its current version in `depend.gradle` and reads the matching versioned section in its `changelog.md` (e.g. `## [UTL_6.26.6]`). Writes `bom/CHANGELOG.md`, publishes the BoM to GitHub Packages, and creates a GitHub Release. + +Use this when: +- You uploaded one or more libraries via `uploadlib` (or any other flow) and want to cut a new BoM release. +- You want to publish a new BoM snapshot from the current state of all library versions without running a full upload cycle. + +```bash +./gradlew release-bom # all modules with versioned entries +./gradlew release-bom -Pmodules=utilitylib,composeds # explicit subset +./gradlew release-bom -PskipRelease=true # skip GitHub Release creation +``` + +--- + ### `update-version-lib` Lighter version of `upgrade-lib-version`: bumps versions and uploads libs, but does **not** update the BoM version, write the BoM changelog, or create a GitHub Release.