Ajoute le README et le modele de configuration
This commit is contained in:
@@ -0,0 +1,122 @@
|
||||
# Migration Gogs → Gitea (figureslibres.io)
|
||||
|
||||
Scripts utilisés pour migrer les dépôts d'une instance Gogs vers une instance Gitea
|
||||
sur le même serveur (YunoHost), en conservant les propriétaires d'origine.
|
||||
|
||||
**Portée volontairement limitée à :**
|
||||
- les dépôts git (branches, tags, historique complet) ;
|
||||
- les collaborateurs (contributeurs) de chaque dépôt ;
|
||||
- les webhooks ;
|
||||
- les dates de création/mise à jour affichées.
|
||||
|
||||
**Explicitement hors scope** : issues, wiki, labels, milestones, releases, pull
|
||||
requests. Les webhooks pointant vers des services internes avec secret non exposé
|
||||
par l'API (ex: Kanboard) sont exclus par défaut.
|
||||
|
||||
## Contexte
|
||||
|
||||
Gogs et Gitea tournent tous les deux en local sur le même serveur (loopback,
|
||||
`127.0.0.1`), ce qui permet de scripter la migration sans jamais passer par les
|
||||
domaines publics ni par le SSO. Le script part du principe que les comptes
|
||||
utilisateurs (individus) sont déjà identiques des deux côtés (ex: synchronisés via
|
||||
un LDAP commun) — il ne crée jamais de compte utilisateur automatiquement. Les
|
||||
organisations, en revanche, peuvent être créées automatiquement si absentes.
|
||||
|
||||
### Pièges rencontrés (et déjà gérés par le script)
|
||||
|
||||
- **L'authentification HTTP Basic Auth de l'API Gogs est cassée sur cette
|
||||
instance** (401 identique avec de bons ou de mauvais identifiants) → l'API Gogs
|
||||
s'utilise donc avec un **token**, jamais avec login/mot de passe.
|
||||
- **`GET /api/v1/repos/search` de Gogs ne fait pas une vraie recherche
|
||||
site-wide**, même avec un compte admin : il ne renvoie que les dépôts publics +
|
||||
ceux du compte du token. La découverte se fait donc propriétaire par
|
||||
propriétaire (`/users|orgs/{login}/repos`), en partant de la liste des comptes
|
||||
connus côté Gitea.
|
||||
- **Les dépôts privés d'un propriétaire n'apparaissent dans cette liste que si le
|
||||
compte utilisé par le script a explicitement accès au dépôt** (ajouté comme
|
||||
collaborateur) — l'admin ne "voit" pas tout par magie via cet endpoint.
|
||||
- **`GET /api/v1/orgs/{login}` de Gogs ne vérifie pas le type** : il renvoie `200`
|
||||
pour n'importe quel login existant, user ou org. La détection des vraies
|
||||
organisations se fait donc en scrapant `/explore/organizations`, pas via cet
|
||||
endpoint.
|
||||
- **Le service `"gogs"` de l'API `/repos/migrate` de Gitea interroge d'abord
|
||||
l'API Gogs et récupère son `clone_url` public**, qui repasse par le mur SSO et
|
||||
fait échouer le clonage. Le script utilise le service générique `"git"` à la
|
||||
place, qui clone brutalement l'adresse fournie (le loopback), sans ce détour.
|
||||
- **`ALLOW_LOCALNETWORKS` doit être activé côté Gitea** (`app.ini`, section
|
||||
`[migrations]`) pour autoriser une migration dont la source est une adresse
|
||||
locale/loopback (protection anti-SSRF activée par défaut).
|
||||
- **Un compte de service synchronisé LDAP se fait périodiquement réécraser son
|
||||
statut admin** par la resynchronisation. Utiliser un compte **local** (pas
|
||||
LDAP) pour le compte de service du script, des deux côtés (Gogs et Gitea).
|
||||
- **L'API Gitea n'expose aucun moyen d'éditer `created_at`/`updated_at`** d'un
|
||||
dépôt existant. `fix_creation_dates.py` compare les dates via les deux API
|
||||
(lecture seule) et génère un script SQL à exécuter soi-même après vérification
|
||||
du schéma et sauvegarde de la base.
|
||||
|
||||
## Prérequis
|
||||
|
||||
- Python 3 + `pip install requests`
|
||||
- `git` installé
|
||||
- Un **token API Gogs** admin (Gogs → Settings → Applications → Generate New Token)
|
||||
- Un **compte Gitea admin local** (pas LDAP) avec mot de passe
|
||||
|
||||
## Configuration
|
||||
|
||||
```bash
|
||||
cp config.env.example config.env
|
||||
# éditer config.env et renseigner les valeurs -- ce fichier ne doit JAMAIS être commité
|
||||
```
|
||||
|
||||
## Utilisation
|
||||
|
||||
### `migrate_gogs_to_gitea.py` — dépôts, collaborateurs, webhooks
|
||||
|
||||
Toujours en **dry-run par défaut** (rien n'est écrit) :
|
||||
|
||||
```bash
|
||||
python3 migrate_gogs_to_gitea.py # dry-run, tous les dépôts
|
||||
python3 migrate_gogs_to_gitea.py --only owner/repo # dry-run, un seul dépôt
|
||||
python3 migrate_gogs_to_gitea.py --limit 3 # dry-run, 3 premiers dépôts
|
||||
python3 migrate_gogs_to_gitea.py --apply --only owner/repo # exécution réelle, ciblée
|
||||
python3 migrate_gogs_to_gitea.py --apply # exécution réelle, tout
|
||||
```
|
||||
|
||||
Un dépôt déjà présent côté Gitea n'est **jamais recréé ni écrasé** — seuls les
|
||||
collaborateurs, webhooks et le topic `migrated-from-gogs` peuvent être complétés.
|
||||
|
||||
### Vérifier l'historique git des dépôts déjà migrés à la main
|
||||
|
||||
Compare les branches/tags Gogs vs Gitea des dépôts déjà présents (lecture seule) :
|
||||
|
||||
```bash
|
||||
python3 migrate_gogs_to_gitea.py --verify-existing
|
||||
```
|
||||
|
||||
Ajoute les refs **totalement absentes** côté Gitea (jamais les branches
|
||||
divergentes, jamais de `--force`) :
|
||||
|
||||
```bash
|
||||
python3 migrate_gogs_to_gitea.py --verify-existing --apply
|
||||
```
|
||||
|
||||
### `fix_creation_dates.py` — dates de création/mise à jour
|
||||
|
||||
Ne se connecte jamais à la base de données. Compare via les deux API (lecture
|
||||
seule) et génère un script SQL à vérifier puis exécuter soi-même :
|
||||
|
||||
```bash
|
||||
python3 fix_creation_dates.py # tous les dépôts communs
|
||||
python3 fix_creation_dates.py --only owner/repo # un seul dépôt (test)
|
||||
```
|
||||
|
||||
Avant d'exécuter le `fix_dates.sql` généré :
|
||||
1. Vérifier le nom des colonnes (`DESCRIBE repository;`) — `created_unix` /
|
||||
`updated_unix` sont les noms standards des versions récentes de Gitea, mais à
|
||||
confirmer sur la version en place.
|
||||
2. Faire une sauvegarde de la table `repository` (ou de la base entière).
|
||||
3. Exécuter avec le nom de la base en argument :
|
||||
```bash
|
||||
mysql -u USER -pMOTDEPASSE NOM_BASE < fix_dates.sql
|
||||
```
|
||||
(le script valide lui-même avec un `COMMIT;` en fin de fichier)
|
||||
@@ -0,0 +1,33 @@
|
||||
# Copier ce fichier en config.env puis renseigner les valeurs.
|
||||
# config.env ne doit JAMAIS être partagé ni collé dans un chat/ticket.
|
||||
|
||||
# URL locales (loopback) des deux instances -- valeurs déjà vérifiées sur ce serveur.
|
||||
GOGS_URL=http://127.0.0.1:17750
|
||||
GITEA_URL=http://127.0.0.1:6002
|
||||
|
||||
# Token API Gogs (Gogs -> Settings -> Applications -> Generate New Token).
|
||||
# Requis : sur cette instance, l'authentification HTTP Basic Auth de l'API Gogs est
|
||||
# rejetée systématiquement (401 identique avec de bons ou de mauvais identifiants).
|
||||
GOGS_TOKEN=
|
||||
|
||||
# Compte admin Gogs -- utilisé UNIQUEMENT pour le clonage git (auth_username/password
|
||||
# transmis à Gitea lors de /repos/migrate), pas pour les appels à l'API Gogs.
|
||||
GOGS_ADMIN_USERNAME=
|
||||
GOGS_ADMIN_PASSWORD=
|
||||
|
||||
# Compte admin Gitea (authentification HTTP Basic, pas de token requis).
|
||||
# Ce compte doit être admin du site : création d'orgs, ajout de collaborateurs sur
|
||||
# n'importe quel dépôt, création de webhooks, etc.
|
||||
GITEA_ADMIN_USERNAME=
|
||||
GITEA_ADMIN_PASSWORD=
|
||||
|
||||
# Topic Gitea posé sur chaque dépôt migré/complété, pour les retrouver facilement.
|
||||
MIGRATION_TOPIC=migrated-from-gogs
|
||||
|
||||
# Créer automatiquement les organisations Gogs absentes côté Gitea (true/false).
|
||||
# Les comptes UTILISATEURS ne sont jamais créés automatiquement, quel que soit ce réglage.
|
||||
AUTO_CREATE_ORGS=true
|
||||
|
||||
# Webhooks dont l'URL contient cette sous-chaîne : jamais migrés (ex: kanboard interne,
|
||||
# dont les secrets ne sont de toute façon pas exposés par l'API Gogs).
|
||||
WEBHOOK_EXCLUDE_SUBSTR=figureslibres.io/kanboard
|
||||
Reference in New Issue
Block a user