diff --git a/.gitignore b/.gitignore index 616b217..35b7181 100644 --- a/.gitignore +++ b/.gitignore @@ -52,3 +52,6 @@ Thumbs.db build .flutter-plugins .flutter-plugins-dependencies + +# Cles API de build (dart-define) — jamais dans git. +tool/build_keys.env diff --git a/tool/build_apk.sh b/tool/build_apk.sh new file mode 100644 index 0000000..ad66c22 --- /dev/null +++ b/tool/build_apk.sh @@ -0,0 +1,83 @@ +#!/usr/bin/env bash +# +# Build d'un APK release avec les dart-define du flavor. +# +# tool/build_apk.sh dev [--install] +# +# Pourquoi ce script plutôt que la ligne de commande du README : +# +# 1. Un build sans --dart-define=API_KEY produit une app qui s'affiche mais ne +# télécharge rien : 401 sur l'instance comme sur l'export, et un message +# « vérifiez votre connexion » qui envoie chercher au mauvais endroit. +# 2. Les clés ne doivent plus vivre dans .vscode/launch.json — il est suivi par +# git, et les clés qui y étaient sont mortes (401) après rotation. +# 3. Un build incrémental réutilise le kernel Dart en cache et ignore un +# changement de --dart-define : d'où le `clean`, et la vérification finale +# que le GIT_SHA demandé est bien dans le binaire livré. + +set -euo pipefail + +flavor="${1:-}" +if [[ -z "$flavor" ]]; then + echo "usage: tool/build_apk.sh [--install]" >&2 + exit 1 +fi + +cd "$(dirname "$0")/.." + +if [[ ! -f tool/build_keys.env ]]; then + echo "tool/build_keys.env manquant — copier tool/build_keys.env.example et le remplir." >&2 + exit 1 +fi +# shellcheck disable=SC1091 +source tool/build_keys.env + +upper=$(echo "$flavor" | tr '[:lower:]' '[:upper:]') +instance_var="${upper}_INSTANCE_ID" +base_var="${upper}_API_BASE_URL" +key_var="${upper}_API_KEY" +instance="${!instance_var:-}" +base="${!base_var:-}" +key="${!key_var:-}" + +if [[ -z "$instance" || -z "$base" || -z "$key" ]]; then + echo "flavor '$flavor' : ${instance_var}, ${base_var} ou ${key_var} vide dans tool/build_keys.env" >&2 + exit 1 +fi + +# La clé est vérifiée AVANT les dix minutes de build : 200 = bonne instance, +# 403 = clé d'une autre instance, 401 = clé morte. +code=$(curl -s -o /dev/null -w "%{http_code}" -H "X-Api-Key: $key" "$base/api/instance/$instance" --max-time 25 || echo "000") +if [[ "$code" != "200" ]]; then + echo "clé $flavor refusée par $base (HTTP $code) — voir tool/build_keys.env.example" >&2 + exit 1 +fi + +sha=$(git rev-parse --short HEAD) +echo "build $flavor · instance $instance · $base · sha $sha" + +flutter clean >/dev/null +flutter pub get >/dev/null +flutter build apk --release --flavor "$flavor" -t lib/main.dart \ + --dart-define=FLAVOR="$flavor" \ + --dart-define=INSTANCE_ID="$instance" \ + --dart-define=API_BASE_URL="$base" \ + --dart-define=API_KEY="$key" \ + --dart-define=GIT_SHA="$sha" + +apk="build/app/outputs/flutter-apk/app-${flavor}-release.apk" + +# « Built » ne prouve rien : c'est le binaire qu'on interroge. +tmp=$(mktemp) +unzip -p "$apk" lib/arm64-v8a/libapp.so > "$tmp" +if ! grep -q -a "$sha" "$tmp"; then + rm -f "$tmp" + echo "APK construit mais $sha absent de libapp.so — build périmé, relancer." >&2 + exit 1 +fi +rm -f "$tmp" +echo "OK · $apk · sha $sha vérifié dans le binaire" + +if [[ "${2:-}" == "--install" ]]; then + adb install -r "$apk" +fi diff --git a/tool/build_keys.env.example b/tool/build_keys.env.example new file mode 100644 index 0000000..ea735f9 --- /dev/null +++ b/tool/build_keys.env.example @@ -0,0 +1,28 @@ +# Modèle de tool/build_keys.env — copier, remplir, ne jamais committer le résultat. +# +# Les clés API sont embarquées dans le binaire au build (--dart-define=API_KEY). +# Sans clé valide, l'app ne peut ni lire l'instance ni télécharger une visite : +# `instanceGetDetail` et `configuration/{id}/export` répondent 401, et le +# dialogue de téléchargement affiche « vérifiez votre connexion » — un message +# trompeur qui a déjà coûté une demi-journée. +# +# Obtenir une clé pour une instance : +# curl "https://api.mymuseum.be/api/instance/app-key?pinCode=&appType=Mobile" +# (route publique, le pinCode se lit dans le Manager). Ou Manager → clés API. +# +# Vérifier qu'une clé est bien vivante ET rattachée à la bonne instance : +# curl -o /dev/null -w "%{http_code}\n" -H "X-Api-Key: " \ +# https://api.mymuseum.be/api/instance/ +# 200 = bonne clé · 403 = clé d'une autre instance · 401 = clé morte + +DEV_INSTANCE_ID=63514fd67ed8c735aaa4b8f2 +DEV_API_BASE_URL=https://api.mymuseum.be +DEV_API_KEY= + +MDLF_INSTANCE_ID=65ccc67265373befd15be511 +MDLF_API_BASE_URL=https://api.mymuseum.be +MDLF_API_KEY= + +FORTSAINTHERIBERT_INSTANCE_ID=633ee379d9405f32f166f047 +FORTSAINTHERIBERT_API_BASE_URL=https://api.mymuseum.be +FORTSAINTHERIBERT_API_KEY=