Zum Inhalt springen

updraft-android plugin integration

Type Skill
Plugin awl-android · v0.0.19
Invoke /awl-android:updraft-plugin-integration
Source plugins/awl-android/skills/updraft-plugin-integration/SKILL.md

Complete integration guide for the Updraft Android Gradle plugin. Use when adding Updraft to an Android project for automated APK/AAB uploads to the Updraft distribution platform.

updraft (com.appswithlove.updraft:updraft) is an Android Gradle plugin that uploads APK and AAB files to Updraft — a mobile app distribution platform. It registers Gradle tasks per build variant and automatically attaches Git metadata (branch, commit, tags, URL) to each upload.

Version compatibility:

  • AGP ≥ 9.0 → plugin version 3.0.0
  • AGP < 9.0 → plugin version 2.3.0

Ask the user these questions using askUserQuestionTool before touching any files:

  1. Upload scope — “Which build variants should be configured for Updraft uploads?”

    • Release variants only (e.g., release, stagingRelease, prodRelease)
    • All variants including debug
    • Only specific variants (follow up with a free-text question to get exact names)
  2. Release notes — “How should release notes be sourced for each upload?”

    • Last git commit message (default — no config needed)
    • Static text in the updraft {} DSL block
    • Text file (src/main/updraft/release-notes.txt)
    • Gradle CLI property passed at runtime (-PreleaseNotes="...")

Also ask the user (free text) for the Updraft upload URL(s) — one per variant/app, copied from the Updraft dashboard (App Settings → copy the upload URL from the curl command). Do not proceed without the URLs. Ask whether the URLs may be committed or should stay out of the repo (the AWL templates read them from UPDRAFT_URL_DEV / UPDRAFT_URL_PROD, see section 3.2).

Do not proceed until you have answers to all questions.


Before adding the plugin, read the project’s AGP version to determine which plugin version to use.

Check these files in order until you find the version:

gradle/libs.versions.toml:

[versions]
agp = "X.Y.Z"

Root build.gradle.kts:

id("com.android.application") version "X.Y.Z"
// or
classpath("com.android.tools.build:gradle:X.Y.Z")

Root build.gradle (Groovy):

classpath 'com.android.tools.build:gradle:X.Y.Z'

Decision:

AGP version Plugin version to use
≥ 9.0.0 3.0.0
< 9.0.0 2.3.0

Use the resolved version as <plugin-version> throughout all steps below.


Version catalog rule: If gradle/libs.versions.toml exists in the project, all plugin and dependency declarations must go through the version catalog. Never hardcode versions inline when the catalog is present.

2.1 Add to version catalog (if gradle/libs.versions.toml exists)

Abschnitt betitelt „2.1 Add to version catalog (if gradle/libs.versions.toml exists)“
[versions]
updraft = "<plugin-version>"
[plugins]
updraft = { id = "com.appswithlove.updraft", version.ref = "updraft" }

Apply the plugin to every app module that will upload builds.

Version catalog — Kotlin DSL (app/build.gradle.kts)

Abschnitt betitelt „Version catalog — Kotlin DSL (app/build.gradle.kts)“
plugins {
alias(libs.plugins.updraft)
}

No version catalog — Kotlin DSL (app/build.gradle.kts)

Abschnitt betitelt „No version catalog — Kotlin DSL (app/build.gradle.kts)“
plugins {
id("com.appswithlove.updraft") version "<plugin-version>"
}
plugins {
id 'com.appswithlove.updraft' version '<plugin-version>'
}

If the project uses buildscript {} in the root build file instead of the plugins {} DSL:

Root build.gradle.kts:

buildscript {
repositories { mavenCentral() }
dependencies {
classpath("com.appswithlove.updraft:updraft:<plugin-version>")
}
}

Root build.gradle (Groovy):

buildscript {
repositories { mavenCentral() }
dependencies {
classpath 'com.appswithlove.updraft:updraft:<plugin-version>'
}
}

Then apply in app/build.gradle.kts:

apply(plugin = "com.appswithlove.updraft")

Or app/build.gradle (Groovy):

apply plugin: 'com.appswithlove.updraft'

After adding the plugin, sync Gradle and confirm it completes without errors before continuing.


Add the updraft {} block to the app module’s build file. It maps capitalized variant names to lists of upload URLs.

Variant name Config key
release "Release"
debug "Debug"
stagingRelease "StagingRelease"
prodRelease "ProdRelease"

A single variant can upload to multiple Updraft apps by listing multiple URLs.

Preferred shape (AWL KMP template, androidApp/build.gradle.kts): the URLs stay out of the repo and come from the environment (CI variables UPDRAFT_URL_DEV / UPDRAFT_URL_PROD) or from the gitignored keystore.properties, through the same secret() helper the release signing config uses. A variant whose URL is unset gets no entry, so its upload task is a no-op:

val keystoreProps = Properties().also { props ->
val f = rootProject.file("keystore.properties")
if (f.exists()) f.inputStream().use { props.load(it) }
}
fun secret(name: String): String? = System.getenv(name) ?: keystoreProps.getProperty(name)
updraft {
urls = listOfNotNull(
secret("UPDRAFT_URL_DEV")?.let { "DevDebug" to listOf(it) },
secret("UPDRAFT_URL_PROD")?.let { "ProdRelease" to listOf(it) },
).toMap()
// release notes default to last git commit message
}

Reuse an existing secret() helper if the module already has one. Committed URLs (only when the user allows it):

updraft {
urls = mapOf(
"Release" to listOf("https://app.getupdraft.com/api/app_upload/<your-token>/")
)
}

Multi-variant / multi-destination example:

updraft {
urls = mapOf(
"StagingRelease" to listOf("https://app.getupdraft.com/api/app_upload/<staging-token>/"),
"ProdRelease" to listOf(
"https://app.getupdraft.com/api/app_upload/<prod-token-1>/",
"https://app.getupdraft.com/api/app_upload/<prod-token-2>/"
)
)
}
updraft {
urls = [
"Release": ["https://app.getupdraft.com/api/app_upload/<your-token>/"]
]
}

Only configure the variants the user requested in section 0. Variants not listed in urls have their tasks registered but will not upload anything.


Configure based on the user’s answer from section 0.

Priority (highest to lowest): CLI property → DSL releaseNotes → text file → last commit message.

No configuration needed. The plugin uses the last commit message automatically when none of the other options are set.

Kotlin DSL:

updraft {
urls = mapOf(/* ... */)
releaseNotes = "Build for QA review"
}

Groovy:

updraft {
urls = [/* ... */]
releaseNotes = "Build for QA review"
}

Create one of:

  • app/src/main/updraft/release-notes.txt — applies to all variants
  • app/src/<flavorName>/updraft/release-notes.txt — applies to a specific flavor only

No DSL property needed; the plugin picks up the file automatically.

Option D — Gradle CLI property (runtime, no DSL change needed)

Abschnitt betitelt „Option D — Gradle CLI property (runtime, no DSL change needed)“

Pass the notes at invocation time:

Terminal-Fenster
./gradlew updraftRelease -PreleaseNotes="Sprint 42 build"

The plugin registers one task per variant per artifact type after syncing:

Task pattern Artifact Example
updraft<Variant> APK updraftRelease, updraftStagingRelease
updraftBundle<Variant> AAB updraftBundleRelease, updraftBundleProdRelease

These tasks depend on assemble<Variant> / bundle<Variant> respectively — the build runs automatically before the upload. The AWL android CI component runs :<module>:updraftBundle<Variant> in its updraftDev / updraftProd jobs once enable_updraft_dev / enable_updraft_prod are set (see the android cicd pipeline setup skill); an unsigned release variant makes that task fail on a filename mismatch, so pair it with signing_from_ci: true.

Run locally:

Terminal-Fenster
# Upload APK
./gradlew updraftRelease
# Upload AAB
./gradlew updraftBundleRelease

  1. Sync Gradle — confirm no errors after adding the plugin and configuration.
  2. List tasks — run ./gradlew tasks | grep -i updraft to confirm tasks are registered for the configured variants.
  3. Run a task./gradlew updraftRelease (replace with the relevant variant).
  4. Check output — a successful upload prints a public link to the uploaded build.
  5. If a task is missing — the variant key in urls is likely wrong. Recheck capitalization (e.g., "StagingRelease" not "stagingRelease").

Constraint Detail
AGP version Plugin 3.0.0 requires AGP ≥ 9.0. Use 2.3.0 for older AGP.
curl required Plugin uses system curl for uploads. Must be in PATH on the machine running the task.
URL source Upload URLs come from the Updraft dashboard — the plugin cannot generate them. Keep them in CI variables / keystore.properties rather than in the build file (section 3.2).
Variant key capitalization Keys in urls must use capitalized variant names ("Release" not "release").
No separate API key Auth is embedded in the upload URL — no extra credentials config needed.
Multiple URLs per variant A single variant can target multiple Updraft apps by listing multiple URLs.
Git metadata Branch, commit, tags, and remote URL are collected automatically from the local Git repo.
Maven Central Plugin is on Maven Central — no extra repository block needed in most modern projects.

Symbol Kind Purpose
com.appswithlove.updraft Plugin ID Applied in plugins {} block
updraft {} Extension block Configure upload URLs and release notes
urls Map<String, List<String>> Maps capitalized variant names to lists of upload URLs
releaseNotes String? Optional static release notes text (default: last git commit message)
updraft<Variant> Gradle task Builds and uploads the APK for the named variant
updraftBundle<Variant> Gradle task Builds and uploads the AAB for the named variant