name: Build macOS release # Compila la app de escritorio para macOS y arma el paquete que consume el # auto-updater (soma_pro_updater). Corre en un runner macOS de GitHub: un build # de Mac NO se puede compilar desde Linux ni Windows (necesita Xcode), así que # esto reemplaza a tener una Mac propia. # # Se dispara a mano desde la pestaña Actions ("Run workflow") y elegís a qué # Supabase apunta el build (prod o dev). # # Qué deja: # - Un .dmg para la PRIMERA instalación (contiene la carpeta SOMA PRO con el # updater y la app como hermanos + version.json). Sale como artifact. # - El paquete de actualización (zip del SOMA PRO.app) + manifest.json. # También como artifact, y si el build es de prod se publica solo al feed # de GitHub Pages (repo peblo423/soma-pro-releases, carpeta macos/), que es # de donde el updater baja las nuevas versiones. # # Por qué updater + app como hermanos y no una subcarpeta app/ (como Windows): # en macOS cada .app es un bundle autocontenido, así que el updater y la app # real conviven en la misma carpeta sin pisarse. Lo espera así updater_service.dart. # # Firma / Gatekeeper. El .app sale con firma ad-hoc (sin cuenta de Apple # Developer, USD 99/año), así que la PRIMERA vez macOS lo bloquea por venir "sin # verificar". Se destraba una única vez, tras arrastrar la carpeta a Aplicaciones: # xattr -dr com.apple.quarantine "/Applications/SOMA PRO" # De ahí en más las actualizaciones son automáticas: el updater las baja por HTTP # (no quedan en cuarentena) y las aplica con ditto, que preserva permisos y # symlinks del bundle. La única forma de borrar hasta ese paso inicial es pagar # Apple Developer y notarizar. on: workflow_dispatch: inputs: environment: description: "Entorno / Supabase al que apunta la app" type: choice options: - prod - dev default: dev jobs: build: runs-on: macos-latest steps: - name: Checkout del repo uses: actions/checkout@v4 # Barrera contra publicar código de desarrollo en producción: solo master # puede generar un build de prod. El dropdown sigue permitiendo elegir # "prod" desde otra rama (útil para compilar y probar el artifact), pero # el paso "Publicar al feed" ya tiene su propio if, y este step corta # antes de gastar tiempo compilando si la intención no tiene sentido. - name: Verificar rama para builds de prod if: ${{ inputs.environment == 'prod' && github.ref != 'refs/heads/master' }} run: | echo "::error::Los builds de prod solo se publican desde master, no desde ${GITHUB_REF#refs/heads/}." echo "Si querés compilar desde esta rama para probar, elegí 'dev' en el dropdown." exit 1 # Misma versión que usa Pablo localmente, para que el build sea reproducible. - name: Instalar Flutter 3.41.6 uses: subosito/flutter-action@v2 with: flutter-version: 3.41.6 channel: stable cache: true - name: Habilitar macOS desktop run: flutter config --enable-macos-desktop # --- App principal --- - name: Dependencias app (pub get) working-directory: flutter_soma_app run: flutter pub get - name: Compilar app release (${{ inputs.environment }}) working-directory: flutter_soma_app run: flutter build macos --release --dart-define-from-file=config/${{ inputs.environment }}.json # --- Updater --- - name: Dependencias updater (pub get) working-directory: soma_pro_updater run: flutter pub get - name: Compilar updater release working-directory: soma_pro_updater run: flutter build macos --release # --- Empaquetado --- - name: Armar layout, paquete de update y manifest id: package run: | set -euo pipefail APP="flutter_soma_app/build/macos/Build/Products/Release/SOMA PRO.app" UPDATER="soma_pro_updater/build/macos/Build/Products/Release/soma_pro_updater.app" test -d "$APP" || { echo "No se encontró la app en $APP"; exit 1; } test -d "$UPDATER" || { echo "No se encontró el updater en $UPDATER"; exit 1; } VERSION=$(grep -m1 '^version:' flutter_soma_app/pubspec.yaml \ | sed 's/version:[[:space:]]*//' | cut -d'+' -f1 | tr -d '[:space:]') echo "version=$VERSION" >> "$GITHUB_OUTPUT" echo "Empaquetando SOMA PRO v$VERSION (${{ inputs.environment }})" # Carpeta de instalación: updater y app como hermanos + version.json. # ditto (no cp) para preservar permisos y symlinks de cada bundle. STAGE="release/macos/SOMA PRO" rm -rf release/macos && mkdir -p "$STAGE" ditto "$UPDATER" "$STAGE/soma_pro_updater.app" ditto "$APP" "$STAGE/SOMA PRO.app" echo "{\"version\": \"$VERSION\"}" > "$STAGE/version.json" # Paquete de actualización: SOLO el bundle de la app, que es lo que el # updater baja y extrae sobre la carpeta de instalación. `ditto -c -k` # preserva permisos y symlinks (un zip común los rompe); --keepParent # deja el .app como carpeta raíz del zip, tal como el updater lo espera. mkdir -p out ZIP="out/soma_pro-macos-$VERSION.zip" ditto -c -k --keepParent "$APP" "$ZIP" SHA=$(shasum -a 256 "$ZIP" | cut -d' ' -f1) # Manifest que consume el updater desde GitHub Pages. cat > out/manifest.json <