Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
20c93a4
phase 1, compile pass
rahul-lohra Jul 29, 2026
a71478e
phase 2, pass robolectric tests
rahul-lohra Jul 29, 2026
e63cfad
fix(metrics): apply Compose BOM to metrics compose flavors
rahul-lohra Jul 29, 2026
ec9010f
fix(ui-compose): drop baselineProfileOutputDir="." for AGP 9
rahul-lohra Jul 29, 2026
90b9b6f
fix paparazzi tests
rahul-lohra Jul 29, 2026
b1779f4
use java 21 on github ci
rahul-lohra Jul 29, 2026
b8a1552
refer to use java 21 from stream-conventions repo
rahul-lohra Jul 29, 2026
ccd3e81
refer to use java 21 from stream-conventions repo
rahul-lohra Jul 30, 2026
91337e6
update robolectric to use sdk 24
rahul-lohra Jul 30, 2026
bc38a25
add a ci workflow to record paparazzi
rahul-lohra Jul 31, 2026
5ce1058
add a ci workflow to record paparazzi
rahul-lohra Jul 31, 2026
f811465
chore: record paparazzi goldens [record-paparazzi]
rahul-lohra Jul 31, 2026
b24316b
chore: reupload paparazzi goldens
rahul-lohra Jul 31, 2026
46cbfd3
fix(compose): bump BOM to 2025.08.01 (foundation 1.9.0) to fix FlowRo…
rahul-lohra Jul 31, 2026
167eed3
fix tests: add TrustManagerImpl for paparazzi/Robolectric
rahul-lohra Aug 5, 2026
52a98b9
update snapshot workflow
rahul-lohra Aug 12, 2026
db105f7
fix baselineProfileOutputDir for AGP 9+
rahul-lohra Aug 12, 2026
bd16530
Merge branch 'develop-v2' into v2/feature/rahullohra/build-on-sdk-37
rahul-lohra Aug 13, 2026
1ccc9aa
[record-paparazzi]
rahul-lohra Aug 13, 2026
64a2311
update paparazzi goldens
rahul-lohra Aug 14, 2026
8ddae0d
1. Remove snapshots stream dependency
rahul-lohra Aug 14, 2026
7291166
Replace branch name with commit-id on github ci
rahul-lohra Aug 14, 2026
19a8092
security: use commit id instead of release-tag
rahul-lohra Aug 14, 2026
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
2 changes: 1 addition & 1 deletion .github/workflows/android.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ jobs:
permissions:
contents: read
pull-requests: read
uses: GetStream/stream-build-conventions-android/.github/workflows/android-ci.yml@8c5fbade4ee9c06a0a979bcb0866e64669254f73
uses: GetStream/stream-build-conventions-android/.github/workflows/android-ci.yml@ed44d10e3ff86633a0897de216e9f7f3dc5a8339
secrets:
BUILD_CACHE_AWS_REGION: ${{ secrets.BUILD_CACHE_AWS_REGION }}
BUILD_CACHE_AWS_BUCKET: ${{ secrets.BUILD_CACHE_AWS_BUCKET }}
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/app-distribute.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ jobs:
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1
- uses: GetStream/android-ci-actions/actions/setup-java@cb46e4f44d105a68738bfd2a1cfd156bb768665b
with:
java-version: '21'
- name: Prepare environment
env:
ENV_PROPERTIES: ${{ secrets.ENV_PROPERTIES }}
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/e2e-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ jobs:
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1
- uses: GetStream/android-ci-actions/actions/setup-java@cb46e4f44d105a68738bfd2a1cfd156bb768665b
with:
java-version: '21'
- uses: GetStream/android-ci-actions/actions/enable-kvm@cb46e4f44d105a68738bfd2a1cfd156bb768665b
- uses: GetStream/android-ci-actions/actions/setup-ruby@cb46e4f44d105a68738bfd2a1cfd156bb768665b
- uses: GetStream/android-ci-actions/actions/gradle-cache@main
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/e2e-test-cron.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ jobs:
with:
name: apks
- uses: GetStream/android-ci-actions/actions/setup-java@cb46e4f44d105a68738bfd2a1cfd156bb768665b
with:
java-version: '21'
- uses: GetStream/android-ci-actions/actions/enable-kvm@cb46e4f44d105a68738bfd2a1cfd156bb768665b
- uses: GetStream/android-ci-actions/actions/setup-ruby@cb46e4f44d105a68738bfd2a1cfd156bb768665b
- uses: GetStream/android-ci-actions/actions/allure-launch@cb46e4f44d105a68738bfd2a1cfd156bb768665b
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/e2e-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ jobs:
with:
name: apks
- uses: GetStream/android-ci-actions/actions/setup-java@cb46e4f44d105a68738bfd2a1cfd156bb768665b
with:
java-version: '21'
- uses: GetStream/android-ci-actions/actions/enable-kvm@cb46e4f44d105a68738bfd2a1cfd156bb768665b
- uses: GetStream/android-ci-actions/actions/setup-ruby@cb46e4f44d105a68738bfd2a1cfd156bb768665b
- name: Run tests
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/internal-app-distribute.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ jobs:
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1
- uses: GetStream/android-ci-actions/actions/setup-java@cb46e4f44d105a68738bfd2a1cfd156bb768665b
with:
java-version: '21'
- name: Prepare environment
env:
ENV_PROPERTIES: ${{ secrets.ENV_PROPERTIES }}
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/publish-snapshot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
release:
permissions:
contents: write
uses: GetStream/stream-build-conventions-android/.github/workflows/release.yml@v0.13.1
uses: GetStream/stream-build-conventions-android/.github/workflows/release.yml@ed44d10e3ff86633a0897de216e9f7f3dc5a8339
with:
bump: patch
snapshot: true
Expand Down
55 changes: 55 additions & 0 deletions .github/workflows/record-paparazzi.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
name: Record Paparazzi Snapshots

# Manually-triggered job that regenerates Paparazzi golden images on the CI runner (Linux/amd64)
# and uploads them as an artifact. Paparazzi renders via native layoutlib, whose pixels depend on
# OS + architecture, so goldens must be produced in the same environment that verifies them —
# the CI runner.
# Download the artifact with scripts/paparazzi-pull-goldens.sh, then commit + push.
# Deliberately does NOT commit back: no write permissions needed, and you review the diff locally.
on:
# Manual trigger — only works once this file is on the default branch (kept for later).
workflow_dispatch:
# Branch trigger — works from a feature branch without default-branch access. The heavy job is
# gated by a commit-message marker (see the job's `if:`) so ordinary pushes don't run it.
# To trigger: git commit --allow-empty -m "record goldens [record-paparazzi]" && git push
push:
branches:
- "v2/feature/rahullohra/**"

concurrency:
group: record-paparazzi-${{ github.ref }}
cancel-in-progress: true

permissions:
contents: read

jobs:
record:
name: Record golden images (Linux/amd64)
runs-on: ubuntu-latest # Same runner as the verify job, so recorded pixels match verification.
# Run only on manual dispatch, or on a push whose commit message contains [record-paparazzi].
if: >-
github.event_name == 'workflow_dispatch' ||
contains(github.event.head_commit.message, '[record-paparazzi]')
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1
- name: Setup Java
uses: GetStream/android-ci-actions/actions/setup-java@cb46e4f44d105a68738bfd2a1cfd156bb768665b
with:
java-version: '21' # Paparazzi 2.0.0-alpha05 requires JDK 21.
distribution: temurin
- name: Setup Gradle
uses: gradle/actions/setup-gradle@748248ddd2a24f49513d8f472f81c3a07d4d50e1
- name: Record Paparazzi goldens
# cleanRecord so stale / differently-named goldens are removed and the artifact is the
# exact set the current tests produce under this Paparazzi/layoutlib version.
run: ./gradlew cleanRecordPaparazziDebug --stacktrace
- name: Upload recorded goldens
uses: actions/upload-artifact@v4
with:
name: paparazzi-goldens
# Paths are preserved relative to the workspace, i.e. <module>/src/test/snapshots/....,
# so the local pull script can overlay them straight onto the repo root.
path: '**/src/test/snapshots/**'
if-no-files-found: error
retention-days: 7
2 changes: 1 addition & 1 deletion .github/workflows/sdk-size-checks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ concurrency:

jobs:
compare-sdk-sizes:
uses: GetStream/stream-build-conventions-android/.github/workflows/sdk-size-checks.yml@v0.13.1
uses: GetStream/stream-build-conventions-android/.github/workflows/sdk-size-checks.yml.yml@ed44d10e3ff86633a0897de216e9f7f3dc5a8339
with:
modules: "stream-video-android-core stream-video-android-ui-xml stream-video-android-ui-compose"
metrics-project: "stream-video-android-metrics"
Expand Down
10 changes: 4 additions & 6 deletions benchmark/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,10 @@ android {

targetProjectPath = ":demo-app"

testOptions.managedDevices.devices {
maybeCreate<com.android.build.api.dsl.ManagedVirtualDevice>("pixel6api31").apply {
device = "Pixel 6"
apiLevel = 31
systemImageSource = "aosp"
}
testOptions.managedDevices.localDevices.maybeCreate("pixel6api31").apply {
device = "Pixel 6"
apiLevel = 31
systemImageSource = "aosp"
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import com.android.build.gradle.LibraryExtension
import io.getstream.video.configureAndroidCompose
import io.getstream.video.configureKotlinAndroid
import io.getstream.video.kotlinCompilerOptions
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.kotlin.dsl.configure
import org.gradle.kotlin.dsl.dependencies
import org.gradle.kotlin.dsl.withType
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

class AndroidLibraryComposeConventionPlugin : Plugin<Project> {
override fun apply(target: Project) {
with(target) {
pluginManager.apply("io.getstream.android.library")
pluginManager.apply("org.jetbrains.kotlin.plugin.compose")
pluginManager.apply("org.jetbrains.kotlin.android")
pluginManager.apply("binary-compatibility-validator")
pluginManager.apply("androidx.baselineprofile")
Expand All @@ -26,8 +26,10 @@ class AndroidLibraryComposeConventionPlugin : Plugin<Project> {
}
}

kotlinCompilerOptions {
freeCompilerArgs.add("-Xexplicit-api=strict")
tasks.withType<KotlinCompile>().configureEach {
compilerOptions {
freeCompilerArgs.addAll("-Xexplicit-api=strict")
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,35 +8,28 @@ import org.gradle.kotlin.dsl.configure
import org.gradle.kotlin.dsl.dependencies
import org.gradle.kotlin.dsl.getByType
import org.jetbrains.kotlin.compose.compiler.gradle.ComposeCompilerGradlePluginExtension
import org.jetbrains.kotlin.compose.compiler.gradle.ComposeFeatureFlag

/**
* Configure Compose-specific options
*/
internal fun Project.configureAndroidCompose(
commonExtension: CommonExtension<*, *, *, *, *, *>,
commonExtension: CommonExtension,
) {
pluginManager.apply("org.jetbrains.kotlin.plugin.compose")
val libs = extensions.getByType<VersionCatalogsExtension>().named("libs")
pluginManager.apply("org.jetbrains.kotlin.plugin.compose")
val libs = extensions.getByType<VersionCatalogsExtension>().named("libs")

commonExtension.apply {
buildFeatures {
compose = true
}
}
commonExtension.buildFeatures.compose = true

dependencies {
val bom = libs.findLibrary("androidx-compose-bom").get()
add("implementation", platform(bom))
add("androidTestImplementation", platform(bom))
}
dependencies {
val bom = libs.findLibrary("androidx-compose-bom").get()
add("implementation", platform(bom))
add("androidTestImplementation", platform(bom))
}

extensions.configure<ComposeCompilerGradlePluginExtension> {
featureFlags.addAll(ComposeFeatureFlag.StrongSkipping, ComposeFeatureFlag.IntrinsicRemember)
reportsDestination = layout.buildDirectory.dir("compose_compiler")
metricsDestination = layout.buildDirectory.dir("compose_compiler_metrics")
stabilityConfigurationFiles.add(
rootProject.layout.projectDirectory.file("compose_compiler_config.conf"),
)
}
extensions.configure<ComposeCompilerGradlePluginExtension> {
reportsDestination = layout.buildDirectory.dir("compose_compiler")
stabilityConfigurationFiles.add(
rootProject.layout.projectDirectory.file("compose_compiler_config.conf"),
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import com.android.build.api.dsl.ApplicationExtension
import com.android.build.api.dsl.ApplicationProductFlavor
import com.android.build.api.dsl.CommonExtension
import com.android.build.api.dsl.ProductFlavor
import org.gradle.api.NamedDomainObjectContainer

@Suppress("EnumEntryName")
enum class FlavorDimension {
Expand All @@ -21,28 +22,28 @@ enum class VideoDemoFlavor(val dimension: FlavorDimension, val applicationIdSuff
}

internal fun configureFlavors(
commonExtension: CommonExtension<*, *, *, *, *, *>,
commonExtension: CommonExtension,
) {
commonExtension.apply {
flavorDimensions += "environment"
productFlavors {
VideoDemoFlavor.values().forEach { flavor ->
create(flavor.name) {
dimension = "environment"
buildConfigField(
"String",
"APP_FLAVOR_SUFFIX",
"\"${flavor.applicationIdSuffix.orEmpty()}\"",
)
commonExtension.flavorDimensions += "environment"

if (this@apply is ApplicationExtension && this is ApplicationProductFlavor) {
if (flavor.applicationIdSuffix != null) {
applicationIdSuffix = flavor.applicationIdSuffix
}
}
proguardFiles("benchmark-rules.pro")
@Suppress("UNCHECKED_CAST")
val productFlavors =
commonExtension.productFlavors as NamedDomainObjectContainer<ProductFlavor>
VideoDemoFlavor.values().forEach { flavor ->
productFlavors.create(flavor.name) {
dimension = "environment"
buildConfigField(
"String",
"APP_FLAVOR_SUFFIX",
"\"${flavor.applicationIdSuffix.orEmpty()}\"",
)

if (commonExtension is ApplicationExtension && this is ApplicationProductFlavor) {
if (flavor.applicationIdSuffix != null) {
applicationIdSuffix = flavor.applicationIdSuffix
}
}
proguardFiles("benchmark-rules.pro")
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,22 @@ package io.getstream.video
import com.android.build.api.dsl.CommonExtension
import org.gradle.api.Project
import org.gradle.kotlin.dsl.withType
import org.jetbrains.kotlin.gradle.dsl.KotlinJvmCompilerOptions
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

/**
* Configure base Kotlin with Android options
*/
internal fun Project.configureKotlinAndroid(
commonExtension: CommonExtension<*, *, *, *, *, *>,
commonExtension: CommonExtension,
) {
commonExtension.apply {
lint {
abortOnError = false
}
}
commonExtension.lint.abortOnError = false

val warningsAsErrors = properties["warningsAsErrors"] as? Boolean ?: false

tasks.withType<KotlinCompile>().configureEach {
compilerOptions {
// Treat all Kotlin warnings as errors (disabled by default)
allWarningsAsErrors.set(warningsAsErrors)

freeCompilerArgs.addAll(
"-Xjvm-default=all",
"-opt-in=kotlin.RequiresOptIn",
Expand All @@ -32,9 +28,3 @@ internal fun Project.configureKotlinAndroid(
}
}
}

fun Project.kotlinCompilerOptions(block: KotlinJvmCompilerOptions.() -> Unit) {
tasks.withType<KotlinCompile>().configureEach {
compilerOptions(block)
}
}
16 changes: 7 additions & 9 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -109,14 +109,12 @@ subprojects {

afterEvaluate {
println("Running Add Pre Commit Git Hook Script on Build")
exec {
if (System.getProperty("os.name").toLowerCase().contains("win")) {
// Windows-specific command
commandLine("cmd", "/c", "copy", ".\\scripts\\git-hooks\\pre-push", ".\\.git\\hooks")
} else {
// Unix-based systems
commandLine("cp", "./scripts/git-hooks/pre-push", "./.git/hooks")
}
val prePushSource = file("scripts/git-hooks/pre-push")
val gitHooksDir = file(".git/hooks")
if (prePushSource.exists() && gitHooksDir.isDirectory) {
val prePushTarget = File(gitHooksDir, "pre-push")
prePushSource.copyTo(prePushTarget, overwrite = true)
prePushTarget.setExecutable(true)
println("Added pre-push Git Hook Script.")
}
println("Added pre-push Git Hook Script.")
}
13 changes: 12 additions & 1 deletion demo-app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ androidComponents {
.forEach {
val key: String = it.key.toString()
.replace(resConfigKeyPrefix, "")
.toLowerCase()
.lowercase()
applicationVariant.resValues?.put(
applicationVariant.makeResValueKey("string", key),
ResValue("${it.value}"),
Expand All @@ -208,6 +208,17 @@ androidComponents {
}
}

// stream-chat (6.10.0) transitively pulls the old stream-log file logger (1.3.1), whose namespace
// `io.getstream.log` collides with stream-log-android's. AGP 9 rejects duplicate namespaces (was a
// warning before). Bumping the catalog `streamLog` only moves the direct stream-log-android; this
// forces the transitive stream-log-file family up to 1.3.4, where it moved to `io.getstream.log.file`.
configurations.configureEach {
resolutionStrategy.eachDependency {
if (requested.group == "io.getstream" && requested.name.startsWith("stream-log")) {
useVersion("1.3.4")
}
}
}
dependencies {
// Stream Video SDK
implementation(project(":stream-video-android-ui-compose"))
Expand Down
12 changes: 11 additions & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,21 @@ android.defaults.buildfeatures.shaders=false
android.nonTransitiveRClass=true

# Disabled R8 full mode
android.suppressUnsupportedCompileSdk=34
android.suppressUnsupportedCompileSdk=37

# AGP 9 ships built-in Kotlin support (auto-registers the `kotlin` extension). This project
# still applies `org.jetbrains.kotlin.android` explicitly via convention plugins, so opt out of
# built-in Kotlin to avoid a duplicate `kotlin` extension. TODO: remove when migrating to
# built-in Kotlin (required before AGP 10). See https://developer.android.com/build/migrate-to-built-in-kotlin
android.builtInKotlin=false
android.newDsl=false

# Build Compose Compiler metrics
enableComposeCompilerMetrics=true
enableComposeCompilerReports=true

# Project version
version=1.30.0

# Enabled parallel sync for Gradle 9.4+
org.gradle.tooling.parallel=true
Loading
Loading