feat(kotlin-compose): design system + 33 components + gallery_kt + e2e android emulator + scaffolder fixes
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,117 @@
|
||||
---
|
||||
name: init_kotlin_app
|
||||
kind: pipeline
|
||||
lang: bash
|
||||
domain: pipelines
|
||||
version: "1.0.0"
|
||||
purity: impure
|
||||
signature: "init_kotlin_app(name: string, [--project <p>] [--desc <s>] [--tags <csv>] [--package <id>]) -> void"
|
||||
description: "Scaffolder canonico de app Android Kotlin Compose con FnTheme + Roborazzi tests + e2e_checks declarados. Mirror exacto del patron init_cpp_app para el stack Kotlin."
|
||||
tags: [android, kotlin, compose, scaffolder, launcher]
|
||||
uses_functions:
|
||||
- ensure_repo_synced_bash_infra
|
||||
- gradle_run_bash_infra
|
||||
- gradle_assemble_debug_bash_infra
|
||||
- gradle_unit_test_bash_infra
|
||||
- gradle_screenshot_test_bash_infra
|
||||
- fn_theme_kt_ui
|
||||
- fn_tokens_kt_ui
|
||||
uses_types: []
|
||||
returns: []
|
||||
returns_optional: false
|
||||
error_type: "error_go_core"
|
||||
imports: []
|
||||
params:
|
||||
- name: name
|
||||
desc: "nombre de la app en snake_case. Sera el id en registry.db y el repo dataforge/<name>"
|
||||
- name: "--project"
|
||||
desc: "proyecto bajo projects/ donde crear la app (opcional). Si se omite va a apps/<name>/. El project.md debe existir"
|
||||
- name: "--desc"
|
||||
desc: "descripcion breve para el frontmatter app.md (default: 'App Android Kotlin Compose')"
|
||||
- name: "--tags"
|
||||
desc: "tags CSV adicionales para el frontmatter (siempre se anaden kotlin, compose, android)"
|
||||
- name: "--package"
|
||||
desc: "application id Android (default: com.fnregistry.<name>). Ej: com.aurgi.scanner"
|
||||
output: "Stdout con pasos y archivos creados. Exit 0 = scaffold completo y ready para build. Exit !=0 si falla validacion (nombre invalido, destino existe, proyecto inexistente) o git init."
|
||||
tested: false
|
||||
tests: []
|
||||
test_file_path: ""
|
||||
file_path: "bash/functions/pipelines/init_kotlin_app.sh"
|
||||
---
|
||||
|
||||
## Ejemplo
|
||||
|
||||
```bash
|
||||
# App suelta en apps/<name>/
|
||||
fn run init_kotlin_app my_scanner --desc "Escaner de documentos" --package "com.aurgi.scanner"
|
||||
|
||||
# App dentro de un proyecto
|
||||
fn run init_kotlin_app expense_tracker --project budget --desc "Tracker de gastos" --tags "finance,mobile"
|
||||
|
||||
# Con package id personalizado
|
||||
fn run init_kotlin_app pos_terminal --package "com.aurgi.pos" --desc "Terminal de punto de venta"
|
||||
```
|
||||
|
||||
## Que genera
|
||||
|
||||
```
|
||||
apps/<name>/ (o projects/<p>/apps/<name>/)
|
||||
├── settings.gradle.kts # rootProject + include(:app) + composite build ui
|
||||
├── build.gradle.kts # top-level (apply false)
|
||||
├── app/build.gradle.kts # Compose + Material3 + Roborazzi + tests
|
||||
├── gradle.properties
|
||||
├── gradlew # stub ejecutable
|
||||
├── gradle/wrapper/gradle-wrapper.properties # Gradle 8.6
|
||||
├── app/
|
||||
│ └── src/
|
||||
│ ├── main/
|
||||
│ │ ├── AndroidManifest.xml # activity con LAUNCHER intent
|
||||
│ │ ├── kotlin/<pkg_path>/
|
||||
│ │ │ └── MainActivity.kt # FnTheme + Surface + Text("<name> ready")
|
||||
│ │ └── res/values/strings.xml
|
||||
│ ├── test/kotlin/<pkg_path>/
|
||||
│ │ └── ExampleScreenshotTest.kt # Roborazzi: captura FnTheme + Surface
|
||||
│ └── androidTest/kotlin/<pkg_path>/
|
||||
│ └── MainActivityTest.kt # Compose ui-test: assertIsDisplayed("<name> ready")
|
||||
├── app.md # frontmatter registry (lang:kt, framework:compose)
|
||||
├── .gitignore
|
||||
└── README.md
|
||||
```
|
||||
|
||||
## Composite build
|
||||
|
||||
La app apunta via `includeBuild` a `kotlin/functions/ui` del registry (FnTheme + FnTokens).
|
||||
El path relativo se calcula automaticamente:
|
||||
|
||||
| Ubicacion | Path al composite |
|
||||
|---|---|
|
||||
| `apps/<name>/` | `../../kotlin/functions/ui` |
|
||||
| `projects/<p>/apps/<name>/` | `../../../../kotlin/functions/ui` |
|
||||
|
||||
La dependencia se declara como `implementation("fn.compose:ui")` en `app/build.gradle.kts`.
|
||||
|
||||
## e2e_checks generados
|
||||
|
||||
| id | cmd | timeout |
|
||||
|---|---|---|
|
||||
| `unit` | `fn run gradle_unit_test_bash_infra <dir>` | 240s |
|
||||
| `screenshot` | `fn run gradle_screenshot_test_bash_infra <dir>` | 240s |
|
||||
| `build` | `fn run gradle_assemble_debug_bash_infra <dir>` | 360s |
|
||||
| `emu_start` | `fn run android_emulator_start_bash_infra Medium_Phone_API_35` | 240s |
|
||||
| `instrumented` | `fn run gradle_instrumented_test_bash_infra <dir>` | 600s |
|
||||
| `emu_stop` | `fn run android_emulator_stop_bash_infra` | 30s (warning) |
|
||||
|
||||
## Despues de crear
|
||||
|
||||
1. Completar `uses_functions` en `app.md` cuando la app consuma funciones adicionales del registry.
|
||||
2. Para tests Roborazzi: los snapshots se generan en `app/src/test/snapshots/images/` (gitignored).
|
||||
Para actualizar golden images: `./gradlew recordRoborazziDebug`.
|
||||
3. Para tests instrumentados se necesita un AVD creado con `avdmanager create avd -n Medium_Phone_API_35 ...`.
|
||||
|
||||
## Notas
|
||||
|
||||
- `fn_theme_kt_ui` y `fn_tokens_kt_ui` se referencian en `uses_functions` del `app.md` generado
|
||||
aunque todavia no esten indexados en registry.db — son los modulos del composite build.
|
||||
- `ensure_repo_synced_bash_infra` requiere `GITEA_URL` y `GITEA_TOKEN`. Sin ellos se hace
|
||||
`git init + git commit` local y se avisa al usuario.
|
||||
- Si `--project <p>` se especifica, se ejecuta `fn index` al final para registrar la nueva app.
|
||||
Reference in New Issue
Block a user