fix(pedido): el mismo articulo salia repetido, una fila por ficha de … #154
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Build & publish Android APK + OTA bundle | |
| # Cada push a main (que toque código de la app) publica el bundle web por OTA | |
| # (Capa 2, 31/07: @capgo/capacitor-updater) — las tablets se lo aplican solas, | |
| # sin instalar nada. La APK (Capa 1) queda RESERVADA para cambios nativos de | |
| # verdad (plugin nuevo, permisos, versión de Capacitor): solo se rebuildea y | |
| # sube cuando el push dispara el "gatillo nativo" (ver detect-native-trigger). | |
| # Sin ese gatillo, ni se toca Android/Gradle ni se reescribe version.json — la | |
| # Capa 1 no vuelve a ofrecer un sideload por un cambio que ya llegó por OTA. | |
| # | |
| # Política de forzado (mandatory), IGUAL en los dos canales: por defecto FALSE | |
| # → se ofrece/aplica en la próxima ventana segura, sin interrumpir el servicio | |
| # de cocina. Solo es OBLIGATORIA si el mensaje del commit lleva [force-update]. | |
| # | |
| # Gatillo nativo (build/sube APK + version.json), CUALQUIERA de: | |
| # · el commit lleva el marcador [apk] | |
| # · cambios bajo android/ | |
| # · cambios en capacitor.config.ts | |
| # · cambios en las deps @capacitor*/@capgo* de package.json | |
| # Ver src/native/appUpdate.ts + src/components/UpdateGate.tsx (Capa 1 + Capa 2) | |
| # y src/main.tsx (CapacitorUpdater.notifyAppReady(), INNEGOCIABLE). | |
| on: | |
| push: | |
| branches: [main] | |
| paths-ignore: | |
| - 'docs/**' | |
| - '**/*.md' | |
| - 'supabase/**' | |
| workflow_dispatch: | |
| jobs: | |
| build: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 2 # necesario para diffear HEAD~1..HEAD en el detector de gatillo nativo | |
| - name: Detect native trigger | |
| id: trigger | |
| run: | | |
| MSG="$(git log -1 --pretty=%B)" | |
| NATIVE=false | |
| if printf '%s' "$MSG" | grep -qF '[apk]'; then | |
| NATIVE=true | |
| echo "gatillo: marcador [apk] en el commit" | |
| fi | |
| # HEAD~1 puede no existir (primer commit del repo/historia superficial): | |
| # si falla, CHANGED queda vacío -> no fuerza nativo por error de git. | |
| CHANGED="$(git diff --name-only HEAD~1 HEAD 2>/dev/null || true)" | |
| if printf '%s\n' "$CHANGED" | grep -qE '^android/|^capacitor\.config\.ts$'; then | |
| NATIVE=true | |
| echo "gatillo: cambios en android/ o capacitor.config.ts" | |
| fi | |
| if printf '%s\n' "$CHANGED" | grep -qE '^package(-lock)?\.json$'; then | |
| # Solo cuenta si la línea que cambió es de una dep @capacitor*/@capgo* | |
| # de verdad (no cualquier otra dependencia tocada en el mismo commit). | |
| if git diff HEAD~1 HEAD -- package.json 2>/dev/null | grep -qE '^[+-].*"@(capacitor|capgo)/'; then | |
| NATIVE=true | |
| echo "gatillo: deps @capacitor*/@capgo* cambiadas en package.json" | |
| fi | |
| fi | |
| echo "native=${NATIVE}" >> "$GITHUB_OUTPUT" | |
| echo "Gatillo nativo: ${NATIVE} (commit: ${MSG%%$'\n'*})" | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: 22 | |
| cache: npm | |
| - uses: actions/setup-java@v4 | |
| if: steps.trigger.outputs.native == 'true' | |
| with: | |
| distribution: temurin | |
| java-version: '21' | |
| - name: Install deps | |
| run: npm ci | |
| - name: Build web bundle | |
| run: npm run build | |
| env: | |
| VITE_SUPABASE_URL: ${{ secrets.VITE_SUPABASE_URL }} | |
| VITE_SUPABASE_ANON_KEY: ${{ secrets.VITE_SUPABASE_ANON_KEY }} | |
| VITE_APP_URL: ${{ secrets.VITE_APP_URL }} | |
| VITE_MAPBOX_TOKEN: ${{ secrets.VITE_MAPBOX_TOKEN }} | |
| VITE_STRIPE_PUBLISHABLE_KEY: ${{ secrets.VITE_STRIPE_PUBLISHABLE_KEY }} | |
| # ── Canal OTA — SIEMPRE, toque o no código nativo ───────────────────── | |
| - name: Zip web bundle (OTA) | |
| run: (cd dist && zip -qr ../bundle.zip .) | |
| - name: Prepare bundle.json | |
| run: | | |
| VC="${{ github.run_number }}" | |
| MSG="$(git log -1 --pretty=%B)" | |
| if printf '%s' "$MSG" | grep -qF '[force-update]'; then | |
| MANDATORY=true | |
| else | |
| MANDATORY=false | |
| fi | |
| SHA="$(sha256sum bundle.zip | cut -d' ' -f1)" | |
| cat > bundle.json <<EOF | |
| { "bundleId": ${VC}, "versionName": "1.0.${VC}", "url": "${{ secrets.VITE_SUPABASE_URL }}/storage/v1/object/public/apps/bundle-${VC}.zip", "sha256": "${SHA}", "mandatory": ${MANDATORY} } | |
| EOF | |
| echo "mandatory=${MANDATORY} (commit: ${MSG%%$'\n'*})" | |
| echo "bundle.json:" && cat bundle.json | |
| - name: Upload bundle.zip + bundle.json to Supabase Storage (bucket apps, upsert) | |
| env: | |
| SB_URL: ${{ secrets.VITE_SUPABASE_URL }} | |
| SB_KEY: ${{ secrets.SUPABASE_SERVICE_KEY }} | |
| run: | | |
| VC="${{ github.run_number }}" | |
| echo "Subiendo bundle-${VC}.zip ($(du -h bundle.zip | cut -f1))…" | |
| curl -sSf -X POST "$SB_URL/storage/v1/object/apps/bundle-${VC}.zip" \ | |
| -H "Authorization: Bearer $SB_KEY" \ | |
| -H "x-upsert: true" \ | |
| -H "Content-Type: application/zip" \ | |
| --data-binary "@bundle.zip" | |
| echo "Subiendo bundle.json…" | |
| curl -sSf -X POST "$SB_URL/storage/v1/object/apps/bundle.json" \ | |
| -H "Authorization: Bearer $SB_KEY" \ | |
| -H "x-upsert: true" \ | |
| -H "Content-Type: application/json" \ | |
| --data-binary "@bundle.json" | |
| echo "OK · bundleId=${VC}" | |
| # ── Canal nativo (APK) — SOLO con gatillo nativo ────────────────────── | |
| - name: Capacitor sync (android) | |
| if: steps.trigger.outputs.native == 'true' | |
| run: npx cap sync android | |
| - name: Decode signing keystore | |
| if: steps.trigger.outputs.native == 'true' | |
| run: echo "${{ secrets.FOLVY_KEYSTORE_B64 }}" | base64 -d > android/app/folvy-release.jks | |
| - name: Build signed release APK | |
| if: steps.trigger.outputs.native == 'true' | |
| working-directory: android | |
| run: ./gradlew assembleRelease --no-daemon | |
| env: | |
| FOLVY_KEYSTORE_FILE: folvy-release.jks | |
| FOLVY_KEYSTORE_PWD: ${{ secrets.FOLVY_KEYSTORE_PWD }} | |
| FOLVY_KEY_ALIAS: ${{ secrets.FOLVY_KEY_ALIAS }} | |
| FOLVY_KEY_PWD: ${{ secrets.FOLVY_KEY_PWD }} | |
| FOLVY_VERSION_CODE: ${{ github.run_number }} | |
| - name: Prepare version.json | |
| if: steps.trigger.outputs.native == 'true' | |
| run: | | |
| VC="${{ github.run_number }}" | |
| MSG="$(git log -1 --pretty=%B)" | |
| if printf '%s' "$MSG" | grep -qF '[force-update]'; then | |
| MANDATORY=true | |
| else | |
| MANDATORY=false | |
| fi | |
| cat > version.json <<EOF | |
| { "versionCode": ${VC}, "versionName": "1.0.${VC}", "apkUrl": "${{ secrets.VITE_SUPABASE_URL }}/storage/v1/object/public/apps/folvy.apk", "mandatory": ${MANDATORY} } | |
| EOF | |
| echo "mandatory=${MANDATORY} (commit: ${MSG%%$'\n'*})" | |
| echo "version.json:" && cat version.json | |
| - name: Upload APK + version.json to Supabase Storage (bucket apps, upsert) | |
| if: steps.trigger.outputs.native == 'true' | |
| env: | |
| SB_URL: ${{ secrets.VITE_SUPABASE_URL }} | |
| SB_KEY: ${{ secrets.SUPABASE_SERVICE_KEY }} | |
| run: | | |
| APK="android/app/build/outputs/apk/release/app-release.apk" | |
| test -f "$APK" || { echo "APK no encontrado en $APK"; exit 1; } | |
| echo "Subiendo folvy.apk ($(du -h "$APK" | cut -f1))…" | |
| curl -sSf -X POST "$SB_URL/storage/v1/object/apps/folvy.apk" \ | |
| -H "Authorization: Bearer $SB_KEY" \ | |
| -H "x-upsert: true" \ | |
| -H "Content-Type: application/vnd.android.package-archive" \ | |
| --data-binary "@$APK" | |
| echo "Subiendo version.json…" | |
| curl -sSf -X POST "$SB_URL/storage/v1/object/apps/version.json" \ | |
| -H "Authorization: Bearer $SB_KEY" \ | |
| -H "x-upsert: true" \ | |
| -H "Content-Type: application/json" \ | |
| --data-binary "@version.json" | |
| echo "OK · versionCode=${{ github.run_number }}" |