Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
139 changes: 135 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,137 @@
# 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
```

---

### `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.

---

## 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-<version>` (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.
219 changes: 219 additions & 0 deletions scripts/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,134 @@ 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<String>,
moduleToVersionKey: Map<String, String>,
currentVersions: Map<String, String>,
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<String>()
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
}

/**
* 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<String> {
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<String>()
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.
* Skip with -PskipRelease=true.
*/
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<String, String> {
val tpaylib = "telepassLibVersion"
// Read Version on Gradle file
Expand Down Expand Up @@ -524,6 +652,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 skipRelease = project.properties["skipRelease"]?.toString()?.toBoolean() ?: false
if (!skipRelease) createGithubRelease(bomVersion, releaseNotes)

println("Upload BoM")
ByteArrayOutputStream().use { os ->
val result = exec {
Expand Down Expand Up @@ -551,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<String> = 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
*/
Expand Down