Skip to content

Commit b5a146b

Browse files
committed
ci: workflow de tests + APK release sin mocks; docs: README y AGENTS/CLAUDE
- CI (.github/workflows/ci.yml): job test (tsc + jest) en cada push/PR y job build-android (expo prebuild + gradlew assembleRelease con env de release) que sube el APK como artifact y lo adjunta a Release en tags v*. - .env.production: backend http en builds release (resuelve el APK con mocks); dev sigue en mock. Sin secretos (hub y ntfy sin auth). - README.md: cómo armar/descargar el APK, modos de conexión y variables. - AGENTS.md (canónico) + CLAUDE.md (lo importa con @AGENTS.md). - Regla destacada: NO implementar el Posponer/snooze de alarmas (fuera del MVP).
1 parent 9599db0 commit b5a146b

5 files changed

Lines changed: 404 additions & 0 deletions

File tree

‎.env.production‎

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Variables de entorno para builds de PRODUCCIÓN (APK release).
2+
#
3+
# Expo carga este archivo automáticamente cuando NODE_ENV=production
4+
# (es decir, en `expo run:android --variant release`, `gradlew assembleRelease`
5+
# y en el CI). En desarrollo (`expo start`) NO se carga, por lo que la app
6+
# sigue usando los mocks por defecto.
7+
#
8+
# Sin secretos: ntfy.sh y los hubs no requieren autenticación (confirmado por
9+
# LibreAgro), por eso este archivo se versiona.
10+
11+
# Datos del hub (sensores, relés, alarmas de /actual, ping): HTTP real.
12+
# En modo Directo la app habla con el hub en su IP fija 192.168.4.1.
13+
EXPO_PUBLIC_HUB_DATA_BACKEND=http
14+
15+
# Notificaciones push del hub vía ntfy.sh (topic = incubator_name del hub).
16+
EXPO_PUBLIC_NOTIFY_BACKEND=http
17+
EXPO_PUBLIC_NOTIFY_BASE_URL=https://ntfy.sh
18+
19+
# Recomendaciones: el backend todavía no existe. Se mantiene en mock para no
20+
# romper la pantalla. Cambiar a "http" y setear la base URL cuando esté listo:
21+
# EXPO_PUBLIC_RECOMMENDATIONS_BACKEND=http
22+
# EXPO_PUBLIC_RECOMMENDATIONS_BASE_URL=https://<backend-de-recomendaciones>
23+
EXPO_PUBLIC_RECOMMENDATIONS_BACKEND=mock

‎.github/workflows/ci.yml‎

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
name: CI
2+
3+
# - Tests: corren en cada push y PR.
4+
# - APK release (sin mocks, listo para modo Directo con el chip): se arma en
5+
# push a main, en tags `v*` y manualmente (workflow_dispatch). El APK queda
6+
# como artifact descargable; en tags además se adjunta a un GitHub Release.
7+
8+
on:
9+
push:
10+
branches: [main]
11+
tags: ["v*"]
12+
pull_request:
13+
workflow_dispatch:
14+
15+
# Cancela corridas viejas de la misma rama/PR.
16+
concurrency:
17+
group: ci-${{ github.ref }}
18+
cancel-in-progress: true
19+
20+
jobs:
21+
test:
22+
name: Lint de tipos + tests
23+
runs-on: ubuntu-latest
24+
steps:
25+
- uses: actions/checkout@v4
26+
27+
- uses: actions/setup-node@v4
28+
with:
29+
node-version: 20
30+
cache: npm
31+
32+
- name: Instalar dependencias
33+
run: npm ci
34+
35+
- name: Chequeo de tipos (tsc)
36+
run: npx tsc --noEmit
37+
38+
- name: Tests (jest)
39+
run: npm test
40+
41+
build-android:
42+
name: APK release (modo Directo, sin mocks)
43+
runs-on: ubuntu-latest
44+
needs: test
45+
env:
46+
# Release sin mocks: la app habla con el hub real.
47+
# (Mismos valores que .env.production; se setean acá para garantizar
48+
# que el bundling de Metro los reciba en build time.)
49+
EXPO_PUBLIC_HUB_DATA_BACKEND: http
50+
EXPO_PUBLIC_NOTIFY_BACKEND: http
51+
EXPO_PUBLIC_NOTIFY_BASE_URL: https://ntfy.sh
52+
EXPO_PUBLIC_RECOMMENDATIONS_BACKEND: mock
53+
steps:
54+
- uses: actions/checkout@v4
55+
56+
- uses: actions/setup-node@v4
57+
with:
58+
node-version: 20
59+
cache: npm
60+
61+
- name: Setup JDK 17
62+
uses: actions/setup-java@v4
63+
with:
64+
distribution: temurin
65+
java-version: "17"
66+
67+
- name: Setup Gradle (cache)
68+
uses: gradle/actions/setup-gradle@v4
69+
70+
- name: Instalar dependencias
71+
run: npm ci
72+
73+
- name: Generar proyecto Android (expo prebuild)
74+
run: npx expo prebuild --platform android --no-install
75+
76+
- name: Build APK release
77+
run: ./gradlew assembleRelease --no-daemon
78+
working-directory: android
79+
80+
- name: Renombrar APK
81+
run: |
82+
mkdir -p artifacts
83+
cp android/app/build/outputs/apk/release/app-release.apk \
84+
artifacts/libreagro-directo.apk
85+
86+
- name: Subir APK como artifact
87+
uses: actions/upload-artifact@v4
88+
with:
89+
name: libreagro-directo-apk
90+
path: artifacts/libreagro-directo.apk
91+
if-no-files-found: error
92+
93+
- name: Publicar Release con el APK (solo en tags v*)
94+
if: startsWith(github.ref, 'refs/tags/v')
95+
uses: softprops/action-gh-release@v2
96+
with:
97+
files: artifacts/libreagro-directo.apk
98+
generate_release_notes: true

‎AGENTS.md‎

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
# Guía para agentes (Claude Code / Codex / etc.)
2+
3+
Contexto compartido para trabajar en **LibreAgro App** con asistentes de IA.
4+
Aplica tanto a Claude Code como a otras herramientas que lean `AGENTS.md`.
5+
(El archivo `CLAUDE.md` importa este mismo contenido.)
6+
7+
## Qué es
8+
9+
App React Native + **Expo SDK 54** (RN 0.81, React 19, New Architecture) que
10+
monitorea sensores y opera relés de hubs LibreAgro (ESP32). Ver
11+
[`README.md`](README.md) para detalle funcional y de build.
12+
13+
## Comandos
14+
15+
```bash
16+
npm ci # instalar (usa package-lock.json)
17+
npm start # desarrollo (Metro) — usa MOCKS por defecto
18+
npm test # jest
19+
npx tsc --noEmit # chequeo de tipos
20+
```
21+
22+
APK release (sin mocks) — ver README, sección "Armar el APK":
23+
24+
```bash
25+
npx expo prebuild --platform android --no-install
26+
cd android && ./gradlew assembleRelease
27+
```
28+
29+
## Reglas de oro
30+
31+
1. **Mocks en dev, HTTP solo en release.** El default del código es `mock`. Los
32+
servicios reales se activan vía `EXPO_PUBLIC_*` en builds de release
33+
(cargadas desde [`.env.production`](.env.production)). **No** pongas valores
34+
`http` en `.env`/`.env.development` ni hardcodees URLs en el código: romperías
35+
el desarrollo mock-first.
36+
2. **Respetá la capa de servicios `mock | http`.** Las pantallas/stores nunca
37+
conocen el transporte: van por `hubDataService` y los clientes en
38+
`services/*Api/`. Para conectar un backend nuevo, agregá la implementación
39+
HTTP detrás de la interfaz existente; no llames `fetch` desde la UI.
40+
3. **Verificá antes de pushear:** `npx tsc --noEmit` y `npm test` en verde.
41+
4. **Sin secretos en el repo.** Hoy no hay auth (hub ni ntfy), por eso
42+
`.env.production` se versiona. Si en el futuro hay tokens, van por
43+
variables/secrets del CI, nunca commiteados.
44+
5. **Estilo:** TypeScript estricto, datos inmutables (spread, sin mutación),
45+
archivos chicos y enfocados, manejo explícito de errores. Sin `console.log`
46+
en código de producción.
47+
6. **Tests:** este proyecto **no exige** TDD; escribí/actualizá tests solo si la
48+
tarea lo pide o si tu cambio rompe la suite. Si tocás algo cubierto, dejá la
49+
suite verde.
50+
7. **NO implementar el "Posponer" / snooze de alarmas.** Está **fuera del MVP**
51+
(ver sección "Fuera de alcance"). No agregar botón, handler, estado `snoozed`
52+
ni `snoozedUntil` aunque parezca natural o lo sugiera un test viejo.
53+
54+
## Arquitectura (resumen)
55+
56+
- `services/hubApi/` — cliente del hub (`MockHubApiClient` | `HttpHubApiClient`),
57+
`adapters.ts` (validación de respuestas), `alarmsParser.ts` (alarmas derivadas
58+
de `/actual.errors` y de mensajes ntfy), `backend.ts` (selector por env).
59+
- `services/notifyApi/` — push ntfy.sh (`/topic/json?poll=1`), mock | http.
60+
- `services/recommendationsApi/` — `/messages` (GET/POST), mock | http.
61+
- `services/connectivity.ts` — `resolveHubTarget(mode, hub)`: Directo → IP fija
62+
`192.168.4.1`; Online → `hash` (ruteo por backend, sin descubrir IP).
63+
- `services/hubDataService.ts` — fachada única que usan los stores.
64+
- `stores/` (zustand) — `hubStore`, `hubDataStore`, `cropStore`, `zoneStore`.
65+
66+
## Cosas específicas que conviene saber
67+
68+
- **`android/` e `ios/` son generados** (`expo prebuild`) y están en
69+
`.gitignore`. No los edites a mano ni los commitees.
70+
- **APK release** queda firmado con la **debug keystore** del template Expo →
71+
instalable por sideload, no apto para Play Store.
72+
- **Alarmas**: se derivan de `/actual.errors` (formato `"texto,timestamp"`,
73+
timestamp = epoch nanos → ISO). El push ntfy solo se consulta si
74+
`EXPO_PUBLIC_NOTIFY_BACKEND=http`.
75+
- **Zonas**: se asignan **localmente en el celular** (el hub no las expone). Ver
76+
`zoneStore` + `ZoneAssignSheet`.
77+
- **Posponer alarmas**: fuera del MVP — ver sección "Fuera de alcance". Alarmas
78+
solo soporta **Acknowledge**.
79+
- **Tests RN**: preset `jest-expo`; `jest.setup.js` mockea
80+
`react-native-safe-area-context` (los tests no montan `SafeAreaProvider`).
81+
82+
## 🚫 Fuera de alcance — NO implementar (salvo pedido explícito)
83+
84+
Funcionalidad que **quedó deliberadamente afuera del MVP**. No la implementes
85+
por iniciativa propia aunque parezca una mejora obvia, esté insinuada por código
86+
viejo, o un test la sugiera. Si el equipo decide reincorporarla, primero se
87+
actualiza esta sección.
88+
89+
- **Posponer / snooze de alarmas.** La pantalla de Alarmas soporta **solo
90+
Acknowledge**. No agregar:
91+
- botón "Posponer" / "Posponer 1h" en `AlarmCard`,
92+
- prop `onSnooze` ni handler de snooze en `AlarmsScreen`,
93+
- el estado `"snoozed"` en `AlarmStatus` ni el campo `snoozedUntil` en `Alarm`.
94+
95+
> Esta feature se eliminó a propósito. En sesiones anteriores se reintrodujo
96+
> por error varias veces — **no la vuelvas a agregar**.
97+
98+
## Contratos externos pendientes
99+
100+
- **Backend de recomendaciones**: sin URL aún → `RECOMMENDATIONS_BACKEND=mock`.
101+
Cuando exista: setear `http` + `EXPO_PUBLIC_RECOMMENDATIONS_BASE_URL`.
102+
- **Zonas desde el hub**: por ahora 100% locales.
103+
104+
## Commits
105+
106+
Conventional Commits: `feat:`, `fix:`, `chore:`, `test:`, `docs:`, `refactor:`.
107+
Mensajes claros; commit en español está bien (el equipo es hispanohablante).

‎CLAUDE.md‎

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# CLAUDE.md
2+
3+
Esta guía para Claude Code reutiliza el contenido canónico de `AGENTS.md`
4+
(estándar abierto, compartido con otras herramientas de IA).
5+
6+
@AGENTS.md
7+
8+
---
9+
10+
## Notas específicas de Claude Code
11+
12+
- Antes de dar por terminada una tarea: `npx tsc --noEmit` y `npm test` en verde.
13+
- Mantené el patrón de servicios `mock | http` (ver AGENTS.md, "Reglas de oro").
14+
- Desarrollo usa **mocks**; el HTTP real solo se activa en builds release vía
15+
`.env.production`. No cambies eso para "probar" — usá un build release.
16+
17+
## ⛔ Regla crítica: NO implementar "Posponer" de alarmas
18+
19+
El **snooze/Posponer de alarmas está fuera del MVP** y fue eliminado a propósito.
20+
**No lo reimplementes** (ni botón, ni `onSnooze`, ni estado `"snoozed"`/
21+
`snoozedUntil`) aunque parezca natural o lo sugiera un test. Alarmas =
22+
**solo Acknowledge**. Detalle en `AGENTS.md` → "Fuera de alcance".

0 commit comments

Comments
 (0)