Aller au contenu

Alimenter un projet depuis un dépôt GitHub

Pointez un agent vers un dépôt GitHub et vous récupérez un tableau opérationnel : chaque issue devient une story, dans l’état que son historique impose, avec les checklists, les libellés et les jalons repris au passage. Ensuite, ce même agent prend une story, se l’attribue, la fait avancer dans la machine à états et y rattache la pull request qu’il a ouverte.

Cette page décrit cette boucle de bout en bout. L’étape d’alimentation a deux voies : GitHub-to-EAT, l’importateur open source d’East Agile, fait le travail en une seule commande (étape 3) ; l’API d’import fait la même chose appel par appel (étapes 4 et 5), ce qu’un agent pilote quand il veut le handle du job. Tout ce qui suit passe par l’API, parce que l’idée est justement qu’un agent puisse faire le reste sans surveillance.

Ce n’est pas un « import IA » distinct. L’étape d’alimentation utilise le même importateur GitHub que vous lancez à la main depuis Paramètres du projet → Import / Export, décrit dans Mode d’emploi → Importer depuis d’autres outils de suivi. L’agent appelle le même endpoint que vous. Ce que cette page ajoute, c’est tout ce qui l’entoure : qui détient la clé, comment vérifier l’import avant qu’il n’écrive, et ce que l’agent fait du tableau une fois qu’il existe.

La source GitHub de l'onglet Import / Export : propriétaire et dépôt renseignés, jeton laissé vide, pull requests et jalons cochés

  • Un projet — et une session ou une clé ea_user_… pour le créer.
  • Une clé d’agent — une clé ea_agent_… limitée à ce projet. Le rôle dont elle a besoin dépend de la part de la boucle que vous voulez confier à l’agent ; voir l’étape 2. Voir aussi Guide de l’API → Deux types de clés.
  • Un jeton d’accès personnel GitHub — avec un accès en lecture aux issues du dépôt. Chaque import s’authentifie, parce que la récupération passe par l’API GraphQL de GitHub et que GraphQL refuse toute requête sans jeton. Vous ne pouvez l’omettre que si le Tracker récupère pour votre compte : un dépôt public, sur un déploiement qui dispose d’un jeton partagé de repli (le service hébergé eastagiletracker.com en a un ; une installation auto-hébergée n’en a aucun tant que son opérateur n’a pas défini GITHUB_IMPORT_PAT), et pas avec --engine direct de GitHub-to-EAT. Voir Jetons et limites de débit.
  • Node.js 22+ — uniquement pour la voie GitHub-to-EAT de l’étape 3. La voie API n’a besoin que de curl.

Le projet doit exister avant la clé d’agent, et il doit être créé par une personne : les clés d’agent sont liées à un seul projet au moment de leur émission et ne peuvent pas amorcer un projet. Créez-le dans l’interface, ou avec votre propre clé ea_user_… :

Fenêtre de terminal
curl -X POST https://eastagiletracker.com/api/v1/projects \
-H "X-TrackerToken: $TRACKER_USER_TOKEN" \
-H "Content-Type: application/json" \
-d '{"name": "hello-world", "iteration_length_weeks": 1}'

La réponse porte le project_id dont tous les appels ci-dessous ont besoin.

Un propriétaire de projet crée les clés d’agent dans Paramètres du projet → Agents. Le rôle que vous choisissez décide de la part de cette page que l’agent peut faire seul, et il y a deux réponses raisonnables :

  • owner — une seule clé fait toute la boucle, import compris. L’import est réservé au propriétaire, parce qu’un import réécrit la forme du projet en bloc. Émettre un agent au rôle owner exige que vous soyez vous-même propriétaire du projet : le rôle d’un agent ne peut jamais dépasser celui de son créateur.
  • member — moindre privilège. L’agent prend des stories, les déplace, commente et rattache des pull requests, mais ne peut pas importer. Vous lancez l’import vous-même (étape 5) avec votre propre clé, puis vous confiez le tableau à l’agent.

Dans les deux cas, ne laissez pas la valeur par défaut. Une nouvelle clé d’agent est viewer tant que vous ne dites rien d’autre, et un viewer peut lire le tableau mais ne peut ni prendre ni déplacer une story — ce qui est l’essentiel de cette boucle.

Les clés d’agent comptent ici pour une raison qui dépasse l’accès. Une clé d’agent agit comme un participant nommé dans un seul projet : chaque story qu’elle crée, chaque changement d’état qu’elle opère et chaque commentaire qu’elle écrit est attribué à cet agent dans l’historique — distinct de votre propre travail plutôt que fondu dedans.

Fenêtre de terminal
export TRACKER_TOKEN="ea_agent_xxxxx"

Faites lire /meta à l’agent avant toute chose :

Fenêtre de terminal
curl https://eastagiletracker.com/api/v1/meta \
-H "X-TrackerToken: $TRACKER_TOKEN"

Cela répond aux deux questions que l’agent devrait sinon deviner : à quel projet la clé est liée (auth.project_id), et quels changements d’état sont légaux pour chaque type de story (transitions). Une feature suit unstarted → started → finished → delivered → accepted ; une chore n’est que unstarted → started → accepted. Lire la carte vaut mieux que la coder en dur.

GitHub-to-EAT est l’importateur open source d’East Agile : un outil en ligne de commande sous licence MIT qui fait toute l’étape d’alimentation — les étapes 4 et 5 ci-dessous — en une seule commande. Choisissez-le quand une personne est devant un terminal. Choisissez l’API en dessous quand un agent travaille sans surveillance et veut le handle du job pour l’interroger.

Il demande Node.js 22+ et n’a aucune dépendance d’exécution. Il n’est pas encore publié sur npm, installez-le donc depuis le dépôt :

Fenêtre de terminal
git clone git@github.com:EastAgile/GitHub-to-EAT.git
cd GitHub-to-EAT
npm install --global .

Pointez-le ensuite vers la clé émise à l’étape 2 et le projet créé à l’étape 1 :

Fenêtre de terminal
export EAT_AGENT_KEY="ea_agent_xxxxx"
github-to-eat --project $PROJECT_ID --repo octocat/hello-world

Il affiche d’abord une légende de correspondance — exactement comment chaque type sélectionné va atterrir — et vous demande confirmation avant d’écrire quoi que ce soit. Hors d’un terminal, dans un tube, en CI ou dans un agent, il n’y a nulle part où afficher cette invite : une exécution qui écrirait doit donc passer --yes ; sans cela l’outil sort en 2 et n’écrit rien plutôt que de deviner votre réponse. Relancer est sans risque : tout ce qui est déjà importé est ignoré, jamais dupliqué.

IndicateurCe qu’il fait
--dry-runContrôle préalable, puis affiche le plan qu’il exécuterait — combien de stories il importerait, combien il ignorerait comme déjà présentes — et n’écrit rien. N’exige pas --yes.
--includeQuels types importer, séparés par des virgules : issues,prs,milestones,releases,deps. Vaut issues par défaut, et toute sélection doit le contenir. Ce sont les mêmes options que le tableau de l’étape 6.
--tokenVotre jeton d’accès personnel GitHub (GITHUB_TOKEN dans l’environnement ou un .env compte aussi). Il lui faut repo, ou le droit fin Issues: Read, sur ce dépôt. Obligatoire pour un dépôt privé, pour un serveur sans jeton partagé de repli, et toujours pour --engine direct. Omettez-le sur le moteur par défaut du service hébergé et le Tracker dépense son propre budget partagé — voir Jetons et limites de débit.
--engineserver, la valeur par défaut, envoie un seul appel /import/json et laisse le Tracker récupérer, mapper et écrire. direct exécute ce même pipeline sur votre machine et écrit via l’API publique — il lit donc GitHub lui-même et exige toujours un jeton, sortant en 2 sans lui.
--states, --milestones, --story-type, --no-comments, --no-tasksRestreignent ou surchargent la correspondance pour une exécution ; rien n’est persisté. Chacun implique --engine direct.

Définissez EAT_API_BASE et EAT_APP_BASE pour le pointer vers un Tracker auto-hébergé ou local ; les deux visent le service hébergé par défaut. Le README porte la référence complète des indicateurs, les codes de sortie et le dépannage.

Tout ce qui suit est ce même import piloté appel par appel, ce que vous voulez quand c’est un agent qui le lance.

L’import est réservé au propriétaire — utilisez une clé d’agent au rôle owner, ou votre propre clé si vous avez laissé l’agent en member. Lancez-le d’abord avec dry_run, avant de le laisser écrire :

Fenêtre de terminal
curl -X POST https://eastagiletracker.com/api/v1/projects/$PROJECT_ID/import/json \
-H "X-TrackerToken: $TRACKER_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"source": "github",
"owner": "octocat",
"repo": "hello-world",
"include_pull_requests": true,
"include_milestones": true,
"dry_run": true
}'

Un essai à blanc récupère depuis GitHub, résout et dédoublonne exactement comme la vraie exécution, rapporte les mêmes compteurs — imported, skipped, errors, unmatched — puis annule toute la transaction. Rien ne persiste et aucun événement d’import terminé n’atteint votre journal d’audit. C’est le moyen le moins cher de découvrir que vous vouliez inclure les jalons, ou qu’un dépôt est plus gros que vous ne le pensiez, tant que cela ne coûte encore rien.

Chaque appel à /import/json est asynchrone, essai à blanc compris : l’endpoint renvoie 202 avec un handle de job, pas un résultat, et les compteurs arrivent sur le job quand vous l’interrogez (étape 5). Le job d’un essai à blanc atteint done comme un vrai ; la différence, c’est que rien n’a été écrit.

Retirez dry_run et renvoyez la requête. Comme précédemment, l’endpoint renvoie 202 avec un handle de job :

{ "import_id": "…", "status": "pending" }

Interrogez le job jusqu’à un état terminal :

Fenêtre de terminal
curl https://eastagiletracker.com/api/v1/projects/$PROJECT_ID/imports/$IMPORT_ID \
-H "X-TrackerToken: $TRACKER_TOKEN"

Le statut suit pending → fetching → writing → done | failed. Seuls les deux derniers sont terminaux : done porte les compteurs de résultat, failed porte un message d’erreur et un code machine stable sur lequel brancher. Pendant que la récupération pagine, progress_current et progress_total indiquent la page en cours — utile à afficher si une personne regarde.

Jetons. Passez "token": "github_pat_…". Omettez-le et le serveur substitue le jeton de plateforme partagé, qui ne lit que les dépôts publics et dont le quota est décompté pour tous les appelants du déploiement — Jetons et limites de débit explique ce que cela vous coûte. Quel que soit le jeton utilisé, il pilote les appels GitHub en amont et rien d’autre : il n’est jamais journalisé, jamais audité, jamais stocké, ni renvoyé dans une réponse ou une erreur.

Relancer est sans risque. Une ligne déjà importée est reconnue par son id source et ignorée, pas dupliquée. Un second import complète le tableau avec ce qui est apparu depuis le premier.

Les issues sont importées par défaut. Tout le reste est optionnel, un indicateur par type :

Depuis GitHubDevientIndicateur
IssueUne story. Ouverte → unstarted dans le Backlog. Fermée → accepted, ou rejected quand GitHub dit que l’issue a été fermée en not_planned ou duplicate (la story porte alors un libellé correspondant).par défaut
Checklist du corps d’issueDes tâches — chaque ligne - [ ] / - [x] devient une tâche dans l’ordre du corps, [x] arrivant terminée. La checklist reste aussi dans la description.par défaut
LibellésDes libellés, repris tels quels.par défaut
Pull requestUne story portant le libellé pull-request. Ouverte → started, fusionnée → accepted, fermée sans fusion → rejected.include_pull_requests
JalonUn epic, titré d’après le jalon, dédoublonné par titre — deux issues partageant un jalon atterrissent dans un seul epic. Indicateur désactivé, il suit à la place comme libellé milestone:<titre>.include_milestones
ReleaseUne story de release. Publiée → accepted, brouillon → unstarted.include_releases
Dépendance d’issueUn blocker sur la story. Issues seulement, jamais les pull requests.include_dependencies

Le type de story est déduit quand l’issue ne le dit pas. Un libellé contenant bug, fix ou defect — ou un titre commençant par fix ou bug — en fait un bug ; chore, maintenance, devops ou infra en fait une chore ; tout le reste est une feature. Cela vaut la peine d’être su avant d’importer, car dans East Agile Tracker seules les features portent des points et seules les features alimentent la vélocité. Voir Introduction → Stories.

Un tableau de projet juste après l'import du dépôt d'exemple : les issues deviennent des stories avec leurs libellés, les jalons des epics et les personnes GitHub des propriétaires

Le tableau a maintenant un historique, et l’agent a une clé. La boucle tient désormais en quatre appels.

Trouver une story, ou en écrire une. Filtrez le tableau pour trouver quelque chose à prendre :

Fenêtre de terminal
curl "https://eastagiletracker.com/api/v1/projects/$PROJECT_ID/stories?state=unstarted" \
-H "X-TrackerToken: $TRACKER_TOKEN"

import_source=github restreint le résultat à ce que l’import a apporté. Si l’agent a trouvé un travail que le dépôt n’a jamais capturé, il crée la story à la place — voir Guide de l’API → Créer une story.

Se l’attribuer. Un agent s’ajoute comme propriétaire en postant un corps vide :

Fenêtre de terminal
curl -X POST https://eastagiletracker.com/api/v1/projects/$PROJECT_ID/stories/$STORY_ID/owners \
-H "X-TrackerToken: $TRACKER_TOKEN" \
-H "Content-Type: application/json" \
-d '{}'

Un corps vide signifie l’appelant, l’agent n’a donc pas besoin de connaître son propre id. Le tableau affiche désormais l’agent comme propriétaire, ce qui indique à un humain qui regarde que le travail est pris.

La démarrer.

Fenêtre de terminal
curl -X POST https://eastagiletracker.com/api/v1/projects/$PROJECT_ID/stories/$STORY_ID/transitions \
-H "X-TrackerToken: $TRACKER_TOKEN" \
-H "Content-Type: application/json" \
-d '{"to": "started"}'

Ensuite l’agent va faire le travail — lire le dépôt, écrire le code, ouvrir la pull request. Cette partie-là se passe dans votre outil de développement, pas ici.

Rattacher la pull request.

Fenêtre de terminal
curl -X POST https://eastagiletracker.com/api/v1/projects/$PROJECT_ID/stories/$STORY_ID/links \
-H "X-TrackerToken: $TRACKER_TOKEN" \
-H "Content-Type: application/json" \
-d '{"url": "https://github.com/octocat/hello-world/pull/42"}'

Une URL de pull request GitHub est reconnue comme telle — vous n’avez pas à le préciser. La story et le code qui la clôt sont désormais à un clic l’un de l’autre, dans les deux sens.

La terminer. Passez à finished et arrêtez-vous là. Une feature a encore delivered et accepted devant elle, et ce sont les points de contrôle : quelqu’un d’autre que l’agent décide que le travail est juste. Une chore n’a pas ce contrôle — started → accepted est tout ce qui lui reste.

Une issue fermée importée dont la section CODE pointe vers la pull request qui l'a corrigée, avec les commentaires GitHub à côté

Chaque import s’authentifie. La récupération des issues, des commentaires et des pull requests passe par l’API GraphQL de GitHub, et GraphQL rejette toute requête sans jeton — il n’y a pas de palier anonyme, ni sur un dépôt public ni sur un dépôt privé. La question n’est jamais si un jeton part vers GitHub, seulement lequel.

Passez token sur l’appel d’import, ou --token à GitHub-to-EAT. Un jeton d’accès personnel à droits fins avec un accès en lecture aux issues du dépôt suffit. Il pilote les appels GitHub en amont et rien d’autre : il n’est jamais journalisé, jamais audité, jamais stocké, ni renvoyé dans une réponse ou une erreur.

Apportez le vôtre pour tout ce qui dépasse la démonstration. Vous dépensez alors un budget que personne d’autre ne touche, et aucun contrôle préalable ne peut vous refuser à cause de l’import de quelqu’un d’autre.

--engine direct ne vous laisse pas le choix. Ce moteur lit GitHub depuis votre machine plutôt qu’à travers le Tracker, donc le jeton du serveur est hors de portée ; une exécution sans jeton sort en 2 avec une erreur d’usage avant même de récupérer ou d’écrire quoi que ce soit. GITHUB_TOKEN dans votre environnement ou votre .env compte, au même titre que --token.

Ce qui impose le jeton, c’est le parcours des issues, pas le moteur entier. direct lit les issues, les commentaires et les pull requests via GraphQL, qui n’a aucun mode anonyme ; il ne touche à REST que pour la liste des releases et la sonde gratuite /rate_limit. L’outil embarque encore un ancien lecteur REST anonyme qui menait un import de dépôt public dans le budget de 60 par heure, mais plus aucun chemin de la CLI ne l’atteint et il doit être supprimé : considérez donc --token comme obligatoire pour direct.

N’envoyez aucun token et le serveur substitue le jeton de plateforme configuré par son opérateur (GITHUB_IMPORT_PAT). Trois limites l’accompagnent :

  • C’est une configuration facultative. Le service hébergé eastagiletracker.com en provisionne un, donc un import de dépôt public sans jeton y fonctionne. Une installation auto-hébergée — le binaire téléchargé — n’en a aucun tant que son opérateur n’a pas défini GITHUB_IMPORT_PAT dans l’environnement, et jusque-là elle refuse tout import sans jeton avec 400 import_github_no_token.
  • Il ne lit que les dépôts publics. Le service hébergé l’émet en lecture seule sur les dépôts publics, un dépôt privé exige donc toujours votre propre jeton.
  • Tous les appelants du déploiement partagent un seul budget. Avant qu’un import sans jeton ne démarre, le serveur lit les points GraphQL restants du jeton partagé et refuse avec 400 import_github_shared_quota_low en dessous de 500. Un budget épuisé en cours d’import fait échouer le job avec import_github_rate_limited_platform. Les deux messages nomment le même remède : fournir votre propre jeton.

GitHub compte ses deux API séparément, et le plafond non authentifié est deux ordres de grandeur plus bas.

API GitHubSert àAvec un jetonSans jeton
GraphQLIssues, commentaires, pull requests, sous-issues, dépendances5 000 points par heure, comptés sur les nœuds que la requête renvoieRefusé — GraphQL n’a pas de palier anonyme
RESTReleases (include_releases) et le contrôle préalable /rate_limit5 000 requêtes par heure60 requêtes par heure, comptées par adresse IP et partagées avec tout le monde derrière elle

Un import ne retombe jamais sur ce palier à 60 par heure : faute de jeton à envoyer, la requête est refusée d’emblée plutôt que retentée anonymement. Le chiffre compte pour ce que vous faites autour de l’import — un script qui lit GitHub directement, ou un shell sur le même réseau que d’autres clients, épuise 60 requêtes en quelques secondes.

Lisez votre budget restant quand vous voulez ; GET /rate_limit est exempté des deux limites, la vérification ne coûte donc rien :

Fenêtre de terminal
curl -H "Authorization: Bearer $GITHUB_TOKEN" https://api.github.com/rate_limit

Les points GraphQL ne sont pas des requêtes. GitHub compte une requête sur les nœuds qu’elle renvoie : une page de 100 issues avec leurs commentaires et leurs assignés coûte donc beaucoup de points, et un gros dépôt dépense le budget horaire en bien moins d’appels que les chiffres de l’ère REST ne le laissent croire. --dry-run (étape 3) et dry_run (étape 4) coûtent chacun autant de points que la vraie récupération — c’est ce qui rend leurs compteurs fiables — prévoyez donc deux passes quand vous préparez un gros import.

  • Guide de l’API — la grammaire de recherche, le flux d’événements, les transitions en masse, les écritures idempotentes et le reste de la surface.
  • Mode d’emploi — les mêmes opérations depuis l’interface, et les dix autres importateurs.
  • Introduction — pourquoi la machine à états et les quatre types de story ont cette forme.
  • GitHub-to-EAT — le dépôt de l’importateur : tous les indicateurs, les deux moteurs, et comment y contribuer.