# CLAUDE.md — Postiz Android ## Projet Application Android (React Native / Expo SDK 52) pour piloter une instance [Postiz](https://postiz.com) auto-hébergée. Pas de compte expo.dev ni EAS cloud — le build APK est 100 % local ou via GitHub Actions. --- ## Structure du dépôt ``` Postiz-android/ ├── artifacts/postiz-mobile/ ← app React Native (source de vérité) │ ├── app/(tabs)/ ← écrans : compose, calendar, posts, settings, notifications │ ├── components/ ← ChannelChip, MediaLibraryModal, … │ ├── context/PostizContext.tsx ← état global : workspaces, clients, API │ ├── hooks/ ← useColors, usePostizQuery, … │ ├── build-apk.sh ← build signé local (sans EAS) │ └── install-android-sdk.sh ← setup Android SDK first-time ├── lib/ ← packages partagés (api-spec, api-zod, db, …) ├── .github/workflows/release.yml ← CI GitHub Actions (build APK + GitHub Release) └── CLAUDE.md ← ce fichier ``` --- ## Screens & fonctionnalités | Écran | Description | |-------|-------------| | **Compose** | Éditeur de post, sélection de channels par workspace (tap header = tout sélectionner), images, scheduling | | **Calendar** | Vue mensuelle avec dots colorés par état (indigo=schedulé, vert=publié, rouge=erreur) | | **Posts** | Liste filtrée (All/Queue/Published/Draft/Error), swipe gauche=supprimer, swipe droite=reprogrammer | | **Settings** | Gestion multi-workspace : nom, Base URL, API key, test de connexion | | **Notifications** | Polling toutes les 15 min, alerte locale sur PUBLISHED/ERROR | --- ## Modèle de données clé `PostizWorkspace` (dans `PostizContext.tsx`) : ```ts { id, name, baseUrl, apiKey } ``` Stockage : `AsyncStorage` clé `postiz_workspaces_v2`. Migration auto depuis l'ancien format mono-workspace. Channels groupés par workspace dans la vue Compose. Tap sur le header workspace = sélection/désélection collective. Sélection individuelle par chip toujours possible. --- ## Commandes utiles ```bash # Dev (Expo Go sur l'appareil) pnpm --filter @workspace/postiz-mobile run dev # Build APK signé local cd artifacts/postiz-mobile ./install-android-sdk.sh # première fois seulement cp ~/.config/postiz-mobile/signing.env.example ~/.config/postiz-mobile/signing.env # remplir les credentials keystore dans signing.env ./build-apk.sh # → dist/postiz-mobile-YYYYMMDD-HHMM.apk # Déclencher un build + release GitHub git tag v1.x.y git push origin v1.x.y # le push mirror Gitea→GitHub déclenche Actions ``` --- ## Secrets GitHub Actions requis | Secret | Contenu | |--------|---------| | `KEYSTORE_B64` | Keystore `.jks` encodé en base64 | | `KEYSTORE_ALIAS` | Alias de la clé dans le keystore | | `KEYSTORE_STORE_PASSWORD` | Mot de passe du keystore | | `KEYSTORE_KEY_PASSWORD` | Mot de passe de la clé | --- ## Postiz API (endpoints utilisés) | Méthode | Endpoint | Usage | |---------|----------|-------| | `GET` | `/integrations` | Liste des channels connectés | | `GET` | `/posts?startDate=&endDate=` | Posts sur une plage de dates | | `POST` | `/posts` | Créer / programmer un post | | `DELETE` | `/posts/:id` | Supprimer un post | | `POST` | `/upload` | Upload image (multipart) | --- --- ## Méthodologie CI : Gitea sans runner → push mirror → GitHub Actions > Template réutilisable pour tout projet hébergé sur une instance Gitea privée > sans runner CI, avec build automatisé via GitHub Actions. ### Principe ``` Développement local ↓ git push Gitea (privé) ← dépôt principal, pas de runner ↓ push mirror automatique (configuré dans Gitea) GitHub (public ou privé) ← miroir en lecture ↓ tag v*.*.* GitHub Actions ← CI/CD, build, release ``` Gitea joue le rôle de source de vérité et de dépôt privé. GitHub est un miroir passif qui fournit les runners CI gratuitement. Aucun runner n'est installé côté Gitea. ### Configuration du push mirror dans Gitea Dans Gitea → Settings → Repository → **Push Mirrors** : - Mirror URL : `https://github.com/USER/REPO.git` - Credentials : token GitHub avec scope `repo` - Synchronisation : à chaque push (immédiat) Tous les commits, branches et tags poussés sur Gitea sont automatiquement répliqués sur GitHub dans les secondes qui suivent. ### Workflow GitHub Actions type `.github/workflows/release.yml` : ```yaml name: Release on: push: tags: - 'v*.*.*' jobs: build: # Guard clause : n'exécuter que sur GitHub, pas sur Gitea # (au cas où Gitea serait un jour équipé d'un runner) if: github.server_url == 'https://github.com' runs-on: ubuntu-latest permissions: contents: write # nécessaire pour créer une GitHub Release steps: - uses: actions/checkout@v4 # … étapes de build … - name: Create GitHub Release uses: softprops/action-gh-release@v2 with: files: dist/*.apk ``` **Points clés du workflow :** - Déclencheur : `push.tags: ['v*.*.*']` — seul un tag au format semver déclenche le build. - Guard `if: github.server_url == 'https://github.com'` — protection si Gitea obtient un runner à l'avenir. - `permissions: contents: write` — obligatoire pour `action-gh-release`. - Les secrets sensibles (keystores, tokens) sont stockés dans GitHub → Settings → Secrets, jamais dans le dépôt. ### Génération du changelog automatique Le workflow extrait les commits `feat:` et `fix:` entre le tag précédent et HEAD : ```bash PREV_TAG=$(git tag --sort=-version:refname | grep -v "^${{ github.ref_name }}$" | head -1) FEATS=$(git log "${PREV_TAG}..HEAD" --pretty=format:"%s" --no-merges \ | grep -E "^feat(\([^)]+\))?: " \ | sed -E 's/^feat(\([^)]+\))?: //' \ | sed 's/^/- /') FIXES=$(git log "${PREV_TAG}..HEAD" --pretty=format:"%s" --no-merges \ | grep -E "^fix(\([^)]+\))?: " \ | sed -E 's/^fix(\([^)]+\))?: //' \ | sed 's/^/- /') ``` Nécessite des messages de commit au format [Conventional Commits](https://www.conventionalcommits.org/). ### Workflow de release ```bash # 1. Développer et commiter normalement git add -p git commit -m "feat(scope): description" git push # → répliqué sur GitHub automatiquement # 2. Quand prêt pour une release git tag v1.x.y git push origin v1.x.y # → tag répliqué sur GitHub → Actions déclenché # 3. Suivre le build # GitHub → Actions → workflow en cours # L'APK (ou autre artefact) est attaché à la GitHub Release créée automatiquement ``` ### Avantages de cette approche | Aspect | Bénéfice | |--------|---------| | Pas de runner Gitea | Aucune infrastructure à maintenir côté self-hosted | | GitHub gratuit | Runners Ubuntu illimités sur repos publics | | Gitea comme source de vérité | Dépôt principal privé, contrôle total | | Tag comme déclencheur | Build intentionnel, pas à chaque commit | | Guard clause | Workflow safe si l'architecture évolue | ### Limites et points de vigilance - Le push mirror est unidirectionnel : Gitea → GitHub. Ne jamais pousser directement sur GitHub. - Les secrets GitHub ne sont pas répliqués — à configurer manuellement sur GitHub. - Si le mirror est en retard (rare), attendre quelques secondes avant de vérifier que le tag est bien arrivé sur GitHub. - Les GitHub Actions sur repos privés consomment des minutes (quota mensuel).