docs: add CLAUDE.md with project overview + Gitea→GitHub CI methodology
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,216 @@
|
|||||||
|
# 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).
|
||||||
Reference in New Issue
Block a user