# Mergin Maps Mobile - Two-Stage Docker Build Guide

## Vue d'ensemble

Ce projet utilise maintenant une approche de build en deux étapes distinctes pour construire l'application Mergin Maps Mobile. Cette approche optimise la taille des layers, améliore la réutilisabilité des images et accélère les builds en séparant l'installation des dépendances de la compilation de l'application.

## Architecture du Build

### Structure en Deux Images

Le système de build est maintenant organisé en deux images distinctes :

#### 1. Image de Base (`mergin-maps-base`)
- **Fichier** : `Dockerfile.base`
- **Contenu** : Environnement Linux de base avec **TOUTES** les dépendances et SDKs
- **Rôle** : Fournir un environnement complet avec toutes les dépendances pré-installées
- **Taille** : ~4-5 GB (dépendances système, Qt, Android SDK, NDK, SDKs Mergin Maps, Gradle)
- **Volume partagé** : Toutes les dépendances sont disponibles via volume partagé

#### 2. Image de Build (`mergin-maps-build`)
- **Fichier** : `Dockerfile.build`
- **Contenu** : **UNIQUEMENT** la compilation de l'application
- **Rôle** : Construire l'APK finale en utilisant les dépendances de l'image de base
- **Taille** : ~1-2 GB (code source, APK finale)
- **Dépendances** : Réutilise le volume partagé de l'image de base

### Avantages de l'Approche

1. **Optimisation des Layers** : Les dépendances de base sont cachées et réutilisées
2. **Volume Partagé** : Toutes les dépendances sont disponibles via volume partagé
3. **Builds Plus Rapides** : Seule l'image de build est reconstruite lors des changements de code
4. **Séparation des Responsabilités** : 
   - Image de base = Téléchargement et installation des dépendances
   - Image de build = Compilation uniquement
5. **Maintenance Simplifiée** : Mise à jour des dépendances indépendante du code
6. **Réutilisabilité** : L'image de base peut servir pour d'autres projets
7. **Efficacité** : Pas de re-téléchargement des dépendances à chaque build

## Processus de Build

### Étape 1: Construction de l'Image de Base

```bash
# Construction de l'image de base
podman build -f Dockerfile.base -t mergin-maps-base:latest .
```

**Contenu de l'image de base :**
- Ubuntu 24.04
- Dépendances système (CMake, Ninja, OpenJDK 17, etc.)
- Qt 6.6.3 fourni via une archive ZIP (Artifactory) passée par `ZIP_URL`
- **Android SDK et NDK** (téléchargés et installés)
- **SDKs Mergin Maps** (ARM et ARM64) (téléchargés et extraits)
- **SDKMAN et Gradle** (installés)
- Outils de build et bibliothèques
- **Volume partagé** avec toutes les dépendances

### Étape 2: Construction de l'Image de Build

```bash
# Construction de l'image de build
podman build -f Dockerfile.build -t mergin-maps-build:latest .
```

**Contenu de l'image de build :**
- **UNIQUEMENT** le code source de l'application
- **UNIQUEMENT** la compilation et génération de l'APK
- **Réutilisation** du volume partagé de l'image de base
- APK finale compilée

### Étape 3: Extraction de l'APK

```bash
# Extraction de l'APK
podman run --rm -v $(pwd)/output:/output:Z mergin-maps-build:latest \
  cp /var/www/mergin-maps/build/app/android-build/build/outputs/apk/release/android-build-release.apk /output/
```

## Utilisation du Script de Build

### Script Automatisé

Un script de build automatisé est fourni pour simplifier le processus :

```bash
# Rendre le script exécutable
chmod +x build-two-stage.sh

# Build avec tag latest
./build-two-stage.sh latest

# Build avec tag de version
VERSION=1.0.0 ./build-two-stage.sh version

# Build avec tag basé sur la date
./build-two-stage.sh date

# Build avec tag basé sur Git
./build-two-stage.sh git

# Build avec tag combiné
VERSION=1.0.0 ./build-two-stage.sh combined
```

### Options Disponibles

#### 1. Tag `latest` (Recommandé pour le développement)
```bash
./build-two-stage.sh latest
```

#### 2. Tag basé sur la version (Recommandé pour les releases)
```bash
VERSION=1.0.0 ./build-two-stage.sh version
```

#### 3. Tag basé sur la date (Format: YYYYMMDD-HHMM)
```bash
./build-two-stage.sh date
```

#### 4. Tag basé sur le commit Git
```bash
./build-two-stage.sh git
```

#### 5. Tag combiné (Version + Date)
```bash
VERSION=1.0.0 ./build-two-stage.sh combined
```

## Pipeline CI/CD

### Architecture du Pipeline

Le pipeline CI/CD a été adapté pour utiliser l'approche en deux étapes :

#### Stages du Pipeline

1. **`cleanup`** - Nettoyage des ressources Podman
2. **`base_build`** - Construction de l'image de base
3. **`build_image`** - Construction de l'image de build
4. **`apk_export`** - Extraction et sauvegarde de l'APK

#### Déclenchement Automatique

Le pipeline se déclenche automatiquement sur :
- **Push** vers la branche `feat/build-ratp`
- **Merge Request** vers la branche `feat/build-ratp`
- **Schedule** (pipelines programmés)
- **Web** (déclenchement manuel via l'interface GitLab)
- **API** (déclenchement via API)

### Stratégie de Tagging

#### Tags Automatiques Générés

Le pipeline génère automatiquement plusieurs tags selon la branche :

##### 1. Tags de l'Image de Base
- **`feat/build-ratp`** → `base-YYYYMMDD-HHMM`
- **Version** (v1.0.0, 2.1.3) → `base-1.0.0`, `base-2.1.3`
- **Autres branches** → `base-commit-SHORTSHA`

##### 2. Tags de l'Image de Build
- **`feat/build-ratp`** → `build-YYYYMMDD-HHMM`
- **Version** (v1.0.0, 2.1.3) → `build-1.0.0`, `build-2.1.3`
- **Autres branches** → `build-commit-SHORTSHA`

### Exemples de Tags

```bash
# Branche feat/build-ratp
mergin-maps-base:base-20241220-1430
mergin-maps-build:build-20241220-1430

# Branche de version
mergin-maps-base:base-1.0.0
mergin-maps-build:build-1.0.0

# Branche de feature
mergin-maps-base:base-commit-a1b2c3d
mergin-maps-build:build-commit-a1b2c3d
```

## Configuration des Variables

### Variables Globales

```yaml
variables:
  # Podman configuration
  PODMAN_HOST: "unix:///run/user/$(id -u)/podman/podman.sock"
  CONTAINER_RUNTIME: "podman"
  
  # Image configuration
  BASE_IMAGE_NAME: "mergin-maps-base"
  BUILD_IMAGE_NAME: "mergin-maps-build"
  
  # Artifactory URLs for external dependencies
  ARTIFACTORY_URL: "https://artifactory.company.com"
  ANDROID_SDK_URL: "${ARTIFACTORY_URL}/android-sdk"
  MERGIN_SDK_ARM_URL: "${ARTIFACTORY_URL}/mergin-sdk/arm-android-20240517-224/mergin-maps-input-sdk-qt-6.6.3-arm-android-20240517-224.tar.gz"
  MERGIN_SDK_ARM64_URL: "${ARTIFACTORY_URL}/mergin-sdk/arm64-android-20240517-224/mergin-maps-input-sdk-qt-6.6.3-arm64-android-20240517-224.tar.gz"
  SDKMAN_URL: "${ARTIFACTORY_URL}/sdkman/get.sdkman.io"
  SDKMAN_API_URL: "${ARTIFACTORY_URL}/sdkman/api/2"
  
  # APK configuration
  APK_SOURCE_PATH: "/var/www/mergin-maps/build/app/android-build/build/outputs/apk/release/android-build-release.apk"
  APK_ARTIFACT_NAME: "mergin-maps-mobile.apk"
```

## Détail des Jobs

### 1. `cleanup_podman`

**Objectif** : Nettoyer les ressources Podman pour optimiser l'espace disque

**Configuration** :
- **Stage** : `cleanup`
- **Image** : `quay.io/podman/stable:latest`
- **Tags** : `build-mergin-maps`
- **Règles** : Déclenché sur push vers `feat/build-ratp`
- **Allow failure** : `true` (ne bloque pas le pipeline)

### 2. `build_base_image`

**Objectif** : Construire l'image de base avec toutes les dépendances

**Configuration** :
- **Stage** : `base_build`
- **Image** : `quay.io/podman/stable:latest`
- **Tags** : `build-mergin-maps`
- **Cache** : Cache optimisé pour l'image de base

**Actions** :
1. Génération du tag de base selon la branche
2. Construction de l'image de base avec `Dockerfile.base`
3. Application de multiples tags
4. Sauvegarde des informations d'image pour les stages suivants

### 3. `build_application_image`

**Objectif** : Construire l'image de build en utilisant l'image de base

**Configuration** :
- **Stage** : `build_image`
- **Image** : `quay.io/podman/stable:latest`
- **Tags** : `build-mergin-maps`
- **Dependencies** : `build_base_image`
- **Cache** : Cache optimisé pour l'image de build

**Actions** :
1. Génération du tag de build selon la branche
2. Mise à jour du Dockerfile.build pour utiliser la bonne image de base
3. Construction de l'image de build avec `Dockerfile.build`
4. Application de multiples tags
5. Sauvegarde des informations d'image pour les stages suivants

### 4. `extract_apk`

**Objectif** : Extraire l'APK finale et la sauvegarder comme artefact

**Configuration** :
- **Stage** : `apk_export`
- **Image** : `quay.io/podman/stable:latest`
- **Tags** : `build-mergin-maps`
- **Dependencies** : `build_application_image`

**Actions** :
1. Extraction de l'APK depuis le conteneur de build
2. Vérification de l'existence et de la validité de l'APK
3. Génération de métadonnées JSON
4. Sauvegarde comme artefact téléchargeable

## Gestion des Artefacts

### APK Artefact

**Nom** : `mergin-maps-apk-$CI_COMMIT_SHORT_SHA`
**Durée de vie** : 30 jours
**Contenu** :
- `mergin-maps-mobile.apk` - APK finale
- `apk_metadata.json` - Métadonnées du build

### Métadonnées APK

Le fichier `apk_metadata.json` contient :
```json
{
  "project": "mergin-maps-mobile",
  "branch": "feat/build-ratp",
  "commit": "a1b2c3d4e5f6...",
  "short_commit": "a1b2c3d",
  "pipeline_id": "12345",
  "build_date": "2024-12-20T14:30:00Z",
  "base_image_tag": "mergin-maps-base:base-20241220-1430",
  "build_image_tag": "mergin-maps-build:build-20241220-1430",
  "apk_name": "mergin-maps-mobile.apk",
  "apk_size": "52428800",
  "container_runtime": "podman",
  "build_strategy": "two-stage"
}
```

## Optimisations

### Cache Podman

Le pipeline utilise un cache Podman optimisé :
```yaml
cache:
  key: "mergin-maps-cache-$CI_COMMIT_REF_SLUG"
  paths:
    - .podman-cache/
  policy: pull-push
```

### Build Args

"Documentation (with examples) in English"

Build arguments passed to Dockerfiles:
- `BUILD_DATE` - ISO 8601 build date
- `VCS_REF` - Git commit hash
- `VERSION` - Version tag
- `ZIP_URL` - HTTPS URL to `qt-dependencies.zip` in Artifactory
- `QT_VERSION` - Qt version layout inside the ZIP (default `6.6.3`)

Examples:

```bash
# Base image (Qt via ZIP)
podman build -f Dockerfile.base \
  --build-arg ZIP_URL="https://artifactory.example.com/qt/qt-dependencies.zip" \
  --build-arg QT_VERSION=6.6.3 \
  -t mergin-maps-base:zip .

# Build image
podman build -f Dockerfile.build -t mergin-maps-build:latest .
```

Expected ZIP layout:

```text
deps/
  qt/
    ${QT_VERSION}/
      gcc_64/bin/qmake
      gcc_64/lib/cmake/Qt6/
      android_arm64_v8a/lib/cmake/Qt6/qt.toolchain.cmake
```

## Migration depuis l'Ancien Système

### Ancien processus (Multi-stage)
```bash
# Build complet en une seule commande
podman build --network=host -t mergin-maps:latest .
```

### Nouveau processus (Deux étapes)
```bash
# Étape 1: Build de l'image de base
podman build -f Dockerfile.base -t mergin-maps-base:latest .

# Étape 2: Build de l'application
podman build -f Dockerfile.build -t mergin-maps-build:latest .

# Ou utiliser le script automatisé
./build-two-stage.sh latest
```

## Avantages de la Migration

### 1. Performance
- **Builds plus rapides** : L'image de base est cachée et réutilisée
- **Cache optimisé** : Seules les parties modifiées sont reconstruites
- **Parallélisation** : Possibilité de construire les images en parallèle

### 2. Maintenance
- **Séparation des responsabilités** : Dépendances vs code source
- **Mise à jour simplifiée** : Mise à jour des dépendances indépendante
- **Debugging facilité** : Isolation des problèmes par image

### 3. Réutilisabilité
- **Image de base commune** : Peut servir pour d'autres projets
- **Tags standardisés** : Gestion cohérente des versions
- **Documentation claire** : Chaque image a un rôle défini

## Dépannage

### Problèmes de Build

#### Image de Base Non Trouvée
```bash
# Vérifier que l'image de base existe
podman images | grep mergin-maps-base

# Reconstruire l'image de base si nécessaire
podman build -f Dockerfile.base -t mergin-maps-base:latest .
```

#### Échec de Construction de l'Image de Build
```bash
# Vérifier les logs de build
podman build -f Dockerfile.build -t mergin-maps-build:latest . --no-cache

# Vérifier que l'image de base est correcte
podman inspect mergin-maps-base:latest
```

### Problèmes de Pipeline

#### Échec du Job de Base
- Vérifier les logs du job `build_base_image`
- S'assurer que les dépendances système sont disponibles
- Vérifier la connectivité réseau

#### Échec du Job de Build
- Vérifier que l'image de base a été construite avec succès
- S'assurer que les variables d'environnement sont correctes
- Vérifier les logs du job `build_application_image`

## Support

Pour toute question ou problème :
1. Vérifiez les logs du pipeline dans GitLab
2. Consultez la documentation Podman
3. Vérifiez la configuration du runner
4. Contactez l'équipe DevOps

---

**Note** : Ce système de build en deux étapes remplace complètement l'ancien Dockerfile multi-stage. Les anciens fichiers peuvent être supprimés après validation du nouveau système.
