RIPDPI's own Compose conventions: ViewModel pattern, Route/Screen split, DataStore->StateFlow, RipDpiThemeTokens. Use for how this app does Compose, not generic Compose API questions (see compose).
日本語の概要は準備中です。原文の説明を表示しています。
Reference for RIPDPI release signing config and versioning. Use when touching signing config or version bumps. Keep rules: r8-jni-keep-rules. Tagging and publishing: ripdpi-release.
インストールする前に、エージェントに与えられる指示の中身を確認できます。
End-to-end release pipeline: signing config, R8/ProGuard, versioning, artifact naming.
Release flow: manually dispatch .github/workflows/release-candidate.yml for
an exact main SHA, then push the matching v* tag to trigger
.github/workflows/release.yml, which promotes the immutable candidate.
Four environment variables, read via Gradle providers in app/build.gradle.kts:
| Variable | Purpose |
|---|---|
RIPDPI_SIGNING_STORE_FILE | Path to decoded keystore file |
RIPDPI_SIGNING_STORE_PASSWORD | Keystore password |
RIPDPI_SIGNING_KEY_ALIAS | Key alias within the keystore |
RIPDPI_SIGNING_KEY_PASSWORD | Key password |
Lookup order: app/build.gradle.kts resolves each signing value through a localOrEnv(propKey, envKey) helper in the signingConfigs { } block: it reads local.properties first (keys signing.storeFile, signing.storePassword, signing.keyAlias, signing.keyPassword), falling back to the matching environment variable only when the property is absent. The release signing config is created only when the resolved store-file path is non-null -- a build with neither source configured skips signing.
CI flow: the keystore is stored as base64 in GitHub secret KEYSTORE_BASE64; release-candidate.yml decodes it to a temp file and exports RIPDPI_SIGNING_STORE_FILE (and the matching password/alias variables) so localOrEnv() resolves them from the environment. release.yml never touches the keystore -- it only promotes an already-signed candidate.
Never commit keystores to the repository.
Three layers of rules, evaluated together at build time:
| File | Purpose |
|---|---|
app/proguard-rules.pro | App-level rules (intentionally minimal -- relies on library consumer rules) |
core/data/consumer-rules.pro | Preserves protobuf lite classes: com.poyka.ripdpi.proto.** |
core/engine/consumer-rules.pro | Preserves each JNI binding class with -keepclasseswithmembernames, plus a couple of by-name-callback keep blocks; see the file for the current entries |
Enable with -Pripdpi.r8Diagnostics=true to generate analysis files:
./gradlew assembleGithubFullRelease -Pripdpi.r8Diagnostics=true
Output in app/build/outputs/mapping/githubFullRelease/ for that task:
usage.txt -- Classes/methods removed by R8seeds.txt -- Classes/methods kept by keep rulesconfiguration.txt -- Merged R8 configurationConfigured in ripdpi.android.application.gradle.kts.
When adding a new JNI binding class, add a keep rule to the module's consumer-rules.pro using the same shape as the existing entries:
-keepclasseswithmembernames class com.poyka.ripdpi.core.NewNativeBindings {
native <methods>;
}
A Kotlin callback invoked by name from native code (not a native method itself) needs a different keep shape; see the .agents/skills/r8-jni-keep-rules/SKILL.md decision tree for that case and for the general JNI keep-rule failure modes.
| Property | Location | Current |
|---|---|---|
versionCode | app/build.gradle.kts | read ripdpiVersionCode live |
versionName | app/build.gradle.kts | read ripdpiVersionName live |
Artifact naming pattern (from ripdpi.android.application.gradle.kts):
RIPDPI-{versionName}-{versionCode}-{buildType}-universal.aab
RIPDPI-{versionName}-{versionCode}-{buildType}-universal.apk
Version bumping checklist:
versionCode (must increment for every Play Store upload).versionName (semantic versioning).ripdpi-release skill, which enforces the release-window cut and the candidate-dispatch sequence before any tag exists.The release-candidate workflow builds and uploads:
| Artifact | Path |
|---|---|
| Play AAB | app/build/outputs/bundle/playFullRelease/*.aab |
| F-Droid APK | app/build/outputs/apk/fdroidFull/release/*.apk |
| GitHub APK | app/build/outputs/apk/githubFull/release/*.apk |
| R8 Mapping | app/build/outputs/mapping/*Release/mapping.txt |
| Compose Mapping | Compose stability report |
| Native Symbols | packaged release-native-symbols/manifest.json and release-native-symbols.zip |
The tag-triggered publication workflow downloads the candidate by its exact run
ID, reverifies its manifest and SHA, stages checksums and SBOMs, and uses the
pinned softprops/action-gh-release action without rebuilding app binaries.
The release-verification job in ci.yml builds all minified release variants
and, on the GitHub shard, assembles the GithubFullReleaseAndroidTest APK with
testBuildType=release. It uses prebuilt native inputs and no signing secrets, so
release-only Hilt, test ownership, and shrinker problems fail in ordinary CI
before the signed-candidate environment. This catches:
| Mistake | Fix |
|---|---|
| New JNI class without consumer-rules | R8 strips the class, native code crashes. Add keep rule to module's consumer-rules.pro. |
| Committing keystore to repo | Use environment variables + base64 encoding in CI secrets. |
Same versionCode as previous release | Play Store rejects. Always increment versionCode. |
| Skipping R8 diagnostics check | Run with -Pripdpi.r8Diagnostics=true before release to verify keep rules. |
Adding keep rules to app/proguard-rules.pro | Use module-level consumer-rules.pro so rules travel with the module. |
| Forgetting native symbol upload | Crash reports will lack native stack traces. Verify the packaged release-native-symbols.zip and manifest upload. |
.agents/skills/ripdpi-release/SKILL.md -- the gated tag/publish workflow this skill hands off to.agents/skills/r8-jni-keep-rules/SKILL.md -- general JNI/route/proto keep-rule decision tree.agents/skills/ci-workflow-authoring/SKILL.md -- CI pipeline guidancequality/release-gates/release-contract.json -- machine-readable release flow.github/workflows/release-candidate.yml -- signed candidate production.github/workflows/release.yml -- tag-bound candidate promotionまだレビューはありません。使ってみた感想をお寄せください。
概要と使いどころ
RIPDPI's own Compose conventions: ViewModel pattern, Route/Screen split, DataStore->StateFlow, RipDpiThemeTokens. Use for how this app does Compose, not generic Compose API questions (see compose).
日本語の概要は準備中です。原文の説明を表示しています。
ADB-based RIPDPI device/emulator debugging: build/install/launch, logcat filtering, fixture port-forwarding, instrumented tests, crash/ANR triage. Use when debugging on a real device or emulator.
日本語の概要は準備中です。原文の説明を表示しています。
RIPDPI Appium launch-contract reference: start routes and permission/service/data presets. Use when a test launches to the wrong screen or a new automation route is added. General flakiness: appium-test-debug.
日本語の概要は準備中です。原文の説明を表示しています。
RIPDPI Appium test authoring: page objects, resource-id locators, assertions, wait tiers. Use when writing a new Appium test or page object, or adding coverage for a new screen.
日本語の概要は準備中です。原文の説明を表示しています。
RIPDPI Appium failure triage: flaky tests, locator/session/wait issues, screenshot and element-tree debugging. Use when an Appium test fails or is flaky.
日本語の概要は準備中です。原文の説明を表示しています。
Add or modify a GitHub Actions job. Use when editing a file under .github/workflows/. Not for running a workflow locally (local-ci-act) or release signing (release-signing).
日本語の概要は準備中です。原文の説明を表示しています。