Ga naar inhoud

Een project vullen vanuit een GitHub-repo

Richt een agent op een GitHub-repository en je krijgt een werkend board terug: elke issue als story, in de status die zijn historie voorschrijft, met checklists, labels en milestones mee overgenomen. Daarna pakt diezelfde agent een story op, claimt hem, beweegt hem door de toestandsmachine en koppelt de pull request die hij heeft geopend.

Deze pagina beschrijft die lus van begin tot eind. De vulstap heeft twee routes: GitHub-to-EAT, de opensource-importeur van East Agile, doet het in één commando (stap 3); de import-API doet hetzelfde werk aanroep voor aanroep (stappen 4 en 5), en dat is wat een agent aanstuurt als hij de job-handle wil. Alles daarna loopt over de API, want het punt is juist dat een agent de rest onbewaakt kan doen.

Dit is geen aparte «AI-import». De vulstap is dezelfde GitHub-importeur die je met de hand kunt draaien via Projectinstellingen → Importeren / Exporteren, beschreven in Bedieningsinstructies → Importeren uit andere trackers. De agent roept hetzelfde endpoint aan als jij. Wat deze pagina toevoegt, is alles eromheen: wie de sleutel houdt, hoe je de import controleert voordat hij schrijft, en wat de agent met het board doet zodra het bestaat.

De GitHub-bron op het tabblad Import / Export: eigenaar en repository ingevuld, token leeg, pull requests en mijlpalen aangevinkt

  • Een project — en een sessie of een ea_user_…-sleutel om het aan te maken.
  • Een agent-sleutel — een ea_agent_…-sleutel die tot dat project beperkt is. Welke rol hij nodig heeft, hangt af van hoeveel van de lus je de agent wilt laten draaien; zie stap 2. Zie ook API-gids → Twee soorten sleutels.
  • Een GitHub personal access token — met leestoegang tot de issues van de repository. Elke import authenticeert zich, omdat het ophalen via GitHubs GraphQL-API loopt en GraphQL een verzoek zonder token weigert. Je mag hem alleen weglaten wanneer de Tracker namens jou ophaalt: een publieke repository, op een deployment dat een gedeeld terugvaltoken heeft (het gehoste eastagiletracker.com heeft er een; een zelfgehoste installatie heeft er geen totdat de beheerder GITHUB_IMPORT_PAT instelt), en niet met --engine direct van GitHub-to-EAT. Zie Tokens en rate limits.
  • Node.js 22+ — alleen voor de GitHub-to-EAT-route in stap 3. De API-route heeft niets meer nodig dan curl.

Het project moet bestaan vóór de agent-sleutel, en het moet door een mens worden aangemaakt: agent-sleutels zijn bij uitgifte aan één project gebonden en kunnen zelf geen project opstarten. Maak het in de interface, of met je eigen ea_user_…-sleutel:

Terminal window
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}'

Het antwoord draagt de project_id die elke aanroep hieronder nodig heeft.

Een projecteigenaar maakt agent-sleutels aan in Projectinstellingen → Agents. De rol die je kiest bepaalt hoeveel van deze pagina de agent zelfstandig kan doen, en er zijn twee zinnige antwoorden:

  • owner — één sleutel draait de hele lus, import inbegrepen. Importeren is alleen voor de eigenaar, omdat een import de vorm van een project in zijn geheel herschrijft. Een agent met de rol owner uitgeven vereist dat je zelf projecteigenaar bent: de rol van een agent kan die van zijn maker nooit overtreffen.
  • member — minste privilege. De agent claimt stories, beweegt ze, becommentarieert en koppelt pull requests, maar kan niet importeren. De import draai je zelf (stap 5) met je eigen sleutel, en daarna geef je het board aan de agent.

Laat het hoe dan ook niet op de standaardwaarde staan. Een nieuwe agent-sleutel is viewer zolang je niets anders zegt, en een viewer kan het board lezen maar geen story claimen of verplaatsen — en dat is het grootste deel van deze lus.

Agent-sleutels tellen hier om een reden die verder gaat dan toegang. Een agent-sleutel handelt als benoemde deelnemer in één project, dus elke story die hij aanmaakt, elke statuswijziging die hij doet en elke opmerking die hij schrijft wordt in de historie aan die agent toegeschreven — te onderscheiden van je eigen werk in plaats van ermee versmolten.

Terminal window
export TRACKER_TOKEN="ea_agent_xxxxx"

Laat de agent vóór alles /meta lezen:

Terminal window
curl https://eastagiletracker.com/api/v1/meta \
-H "X-TrackerToken: $TRACKER_TOKEN"

Dat beantwoordt de twee vragen waar de agent anders naar zou raden: aan welk project de sleutel gebonden is (auth.project_id), en welke statuswijzigingen per storytype toegestaan zijn (transitions). Een feature loopt unstarted → started → finished → delivered → accepted; een chore is enkel unstarted → started → accepted. De kaart lezen wint het van hem hard coderen.

GitHub-to-EAT is East Agiles eigen opensource-importeur: een MIT-gelicentieerd opdrachtregelprogramma dat de hele vulstap — stappen 4 en 5 hieronder — in één commando doet. Grijp ernaar als er een mens achter een terminal zit. Grijp naar de API eronder als een agent onbewaakt aanstuurt en de job-handle wil om te pollen.

Het vereist Node.js 22+ en heeft geen eigen runtime-afhankelijkheden. Het staat nog niet op npm, dus installeer het vanuit de repository:

Terminal window
git clone git@github.com:EastAgile/GitHub-to-EAT.git
cd GitHub-to-EAT
npm install --global .

Richt het daarna op de sleutel uit stap 2 en het project uit stap 1:

Terminal window
export EAT_AGENT_KEY="ea_agent_xxxxx"
github-to-eat --project $PROJECT_ID --repo octocat/hello-world

Het drukt eerst een mappinglegenda af — precies hoe elk geselecteerd type gaat landen — en vraagt om bevestiging voordat het iets schrijft. Buiten een terminal, in een pipe, in CI of in een agent is er nergens om die vraag te tonen, dus een run die zou schrijven moet --yes meegeven; zonder dat stopt het programma met 2 en schrijft het niets in plaats van je antwoord te raden. Opnieuw draaien is veilig: wat al geïmporteerd is wordt overgeslagen, nooit gedupliceerd.

VlagWat die doet
--dry-runVoorcontrole, daarna het plan afdrukken dat het zou uitvoeren — hoeveel stories het zou importeren, hoeveel het zou overslaan als reeds aanwezig — en niets wegschrijven. Heeft geen --yes nodig.
--includeWelke typen te importeren, kommagescheiden: issues,prs,milestones,releases,deps. Standaard issues, en elke keuze moet dat bevatten. Dit zijn dezelfde opt-ins als de tabel in stap 6.
--tokenJouw GitHub personal access token (GITHUB_TOKEN in de omgeving of in een .env telt ook). Het heeft repo nodig, of fijnmazig Issues: Read, op die repository. Verplicht voor een private repository, voor een server zonder gedeeld terugvaltoken, en altijd voor --engine direct. Laat het weg op de standaardengine van de gehoste dienst en de Tracker geeft zijn eigen gedeelde budget uit — zie Tokens en rate limits.
--engineserver, de standaard, stuurt één /import/json-aanroep en laat de Tracker ophalen, mappen en schrijven. direct draait diezelfde pijplijn op jouw machine en schrijft in plaats daarvan via de publieke API — het leest GitHub dus zelf en heeft altijd een token nodig, anders stopt het met 2.
--states, --milestones, --story-type, --no-comments, --no-tasksBeperken of overschrijven de mapping voor één run; niets wordt bewaard. Elk ervan impliceert --engine direct.

Zet EAT_API_BASE en EAT_APP_BASE om het naar een zelf-gehoste of lokale Tracker te wijzen; beide wijzen standaard naar de gehoste dienst. De README draagt de volledige vlaggenreferentie, de exitcodes en het oplossen van problemen.

Alles hieronder is diezelfde import, aanroep voor aanroep aangestuurd — en dat is wat je wilt wanneer een agent hem draait.

Importeren is alleen voor de eigenaar — gebruik een agent-sleutel met de rol owner, of je eigen sleutel als je de agent op member hebt gelaten. Draai hem eerst met dry_run, voordat je hem laat schrijven:

Terminal window
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
}'

Een proefrun haalt op bij GitHub, herleidt en ontdubbelt precies als de echte, meldt dezelfde tellingen — imported, skipped, errors, unmatched — en draait daarna de hele transactie terug. Niets blijft staan en geen enkele voltooide-import-gebeurtenis bereikt je auditlog. Het is de goedkoopste manier om te ontdekken dat je milestones wilde meenemen, of dat een repo groter is dan je dacht, zolang het je nog niets kost.

Elke aanroep van /import/json is asynchroon, de proefrun inbegrepen: het endpoint geeft 202 terug met een job-handle, geen resultaat, en de tellingen komen op de job binnen wanneer je die opvraagt (stap 5). De job van een proefrun bereikt done net als die van een echte import; het verschil is dat er niets is weggeschreven.

Laat dry_run weg en stuur hem opnieuw. Net als daarvoor geeft het endpoint 202 terug met een job-handle:

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

Poll de job tot hij een eindtoestand bereikt:

Terminal window
curl https://eastagiletracker.com/api/v1/projects/$PROJECT_ID/imports/$IMPORT_ID \
-H "X-TrackerToken: $TRACKER_TOKEN"

De status loopt pending → fetching → writing → done | failed. Alleen de laatste twee zijn eindtoestanden: done draagt de resultaattellingen, failed draagt een foutmelding en een stabiele machinecode waarop je kunt vertakken. Terwijl het ophalen pagineert, vertellen progress_current en progress_total op welke pagina het zit — de moeite waard om te tonen als er een mens meekijkt.

Tokens. Geef "token": "github_pat_…" mee. Laat je hem weg, dan zet de server het gedeelde platformtoken in, dat alleen publieke repositories leest en over elke aanroeper op de deployment wordt afgerekend — Tokens en rate limits beschrijft wat je dat kost. Welk token ook wordt gebruikt: het stuurt de bovenstroomse GitHub-aanroepen aan en verder niets. Het wordt nooit gelogd, nooit in het auditlog gezet, nooit opgeslagen en nooit teruggegeven in een antwoord of een fout.

Opnieuw draaien is veilig. Een rij die al geïmporteerd was, wordt op zijn bron-id herkend en overgeslagen, niet gedupliceerd. Een tweede import vult het board aan met wat er sinds de eerste bij is gekomen.

Issues worden standaard geïmporteerd. Al het andere is opt-in, één vlag per type:

Van GitHubWordtVlag
IssueEen story. Open → unstarted in de Backlog. Gesloten → accepted, of rejected wanneer GitHub zegt dat de issue als not_planned of duplicate is gesloten (de story draagt dan een bijpassend label).standaard
Checklist in de issue-tekstTaken — elke regel - [ ] / - [x] wordt één taak in de volgorde van de tekst, waarbij [x] al voltooid aankomt. De checklist blijft ook in de beschrijving staan.standaard
LabelsLabels, ongewijzigd overgenomen.standaard
Pull requestEen story met het label pull-request. Open → started, gemerged → accepted, ongemerged gesloten → rejected.include_pull_requests
MilestoneEen epic, genoemd naar de milestone en op titel ontdubbeld — twee issues die een milestone delen landen in één epic. Staat de vlag uit, dan reist hij mee als label milestone:<titel>.include_milestones
ReleaseEen release-story. Gepubliceerd → accepted, concept → unstarted.include_releases
Issue-afhankelijkheidEen blocker op de story. Alleen issues, nooit pull requests.include_dependencies

Het storytype wordt afgeleid wanneer de issue het niet zegt. Een label met bug, fix of defect — of een titel die met fix of bug begint — maakt er een bug van; chore, maintenance, devops of infra maken er een chore van; al het andere is een feature. Dat is de moeite waard om te weten vóór je importeert, want in East Agile Tracker dragen alleen features punten en voeden alleen features de velocity. Zie Inleiding → Stories.

Een projectbord direct na het importeren van de voorbeeldrepository: issues als stories met hun labels, mijlpalen als epics en GitHub-mensen als owners

Nu heeft het board historie en de agent een sleutel. De lus is vanaf hier vier aanroepen.

Een story vinden, of er een schrijven. Filter het board op iets om op te pakken:

Terminal window
curl "https://eastagiletracker.com/api/v1/projects/$PROJECT_ID/stories?state=unstarted" \
-H "X-TrackerToken: $TRACKER_TOKEN"

import_source=github beperkt het tot wat de import heeft binnengebracht. Heeft de agent werk gevonden dat de repo nooit heeft vastgelegd, dan maakt hij in plaats daarvan de story aan — zie API-gids → Een story aanmaken.

Hem claimen. Een agent voegt zichzelf als eigenaar toe door een lege body te posten:

Terminal window
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 '{}'

Een lege body betekent de aanroeper, dus de agent hoeft zijn eigen id niet te kennen. Het board toont de agent nu als eigenaar, en zo weet een meekijkende mens dat het werk is opgepakt.

Hem starten.

Terminal window
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"}'

Daarna gaat de agent het werk doen — de repo lezen, de code schrijven, de pull request openen. Dat deel gebeurt in je ontwikkeltool, niet hier.

De pull request koppelen.

Terminal window
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"}'

Een GitHub-pull-request-URL wordt als zodanig herkend — je hoeft het er niet bij te zeggen. De story en de code die hem afsluit liggen nu in beide richtingen één klik uit elkaar.

Hem afronden. Ga naar finished en stop daar. Een feature heeft delivered en accepted nog voor zich, en dat zijn de reviewpoorten: iemand anders dan de agent besluit dat het werk klopt. Een chore heeft die poort niet — started → accepted is haar hele resterende pad.

Een geïmporteerde gesloten issue waarvan de sectie CODE naar de pull request linkt die hem oploste, met de GitHub-reacties ernaast

Elke import authenticeert zich. Het ophalen van issues, opmerkingen en pull requests loopt via GitHubs GraphQL-API, en GraphQL weigert een verzoek zonder token — er is geen anonieme laag, niet bij een publieke repository en niet bij een private. De vraag is nooit of er een token naar GitHub gaat, alleen wiens.

Geef token mee bij de importaanroep, of --token aan GitHub-to-EAT. Een fijnmazig personal access token met leestoegang tot de issues van de repository volstaat. Het stuurt de bovenstroomse GitHub-aanroepen aan en verder niets: het wordt nooit gelogd, nooit in het auditlog gezet, nooit opgeslagen en nooit teruggegeven in een antwoord of een fout.

Neem je eigen token mee voor alles voorbij een demo. Dan geef je een budget uit waar niemand anders aan zit, en kan geen voorcontrole je weigeren vanwege de import van iemand anders.

--engine direct laat je geen keuze. Die engine leest GitHub vanaf jouw machine in plaats van via de Tracker, dus het token van de server is buiten bereik; een run zonder token stopt met 2 en een gebruiksfout voordat hij ophaalt of schrijft. GITHUB_TOKEN in je omgeving of je .env telt net zo goed als --token.

Wat het token afdwingt is de doorloop van de issues, niet de hele engine. direct leest issues, reacties en pull requests via GraphQL, dat geen anonieme modus kent; REST raakt hij alleen aan voor de release-lijst en de gratis /rate_limit-peiling. Het gereedschap levert nog steeds een oudere anonieme REST-ophaler mee die een import van een publieke repository binnen het budget van 60 per uur draaide, maar geen enkel CLI-pad bereikt hem nog en hij wordt verwijderd — beschouw --token dus als verplicht voor direct.

Stuur geen token mee en de server zet het platformtoken in dat de beheerder heeft ingesteld (GITHUB_IMPORT_PAT). Er horen drie grenzen bij:

  • Het is optionele configuratie. Het gehoste eastagiletracker.com voorziet er een, dus daar werkt een import van een publieke repository zonder token. Een zelfgehoste installatie — het gedownloade binaire bestand — heeft er geen totdat de beheerder GITHUB_IMPORT_PAT in de omgeving instelt, en tot die tijd weigert die elke import zonder token met 400 import_github_no_token.
  • Het leest alleen publieke repositories. De gehoste dienst geeft het alleen-lezen uit over publieke repos, dus een private repository heeft altijd je eigen token nodig.
  • Elke aanroeper op de deployment deelt één budget. Voordat een import zonder token draait, leest de server de resterende GraphQL-punten van het gedeelde token en weigert onder de 500 met 400 import_github_shared_quota_low. Een budget dat halverwege de import opraakt, laat de job falen met import_github_rate_limited_platform. Beide meldingen noemen dezelfde oplossing: lever je eigen token aan.

GitHub meet zijn twee API’s afzonderlijk, en het niet-geauthenticeerde plafond ligt twee ordes van grootte lager.

GitHub-APIGebruikt voorMet tokenZonder token
GraphQLIssues, opmerkingen, pull requests, sub-issues, afhankelijkheden5.000 punten per uur, gescoord op de nodes die een query teruggeeftGeweigerd — GraphQL heeft geen anonieme laag
RESTReleases (include_releases) en de /rate_limit-voorcontrole5.000 verzoeken per uur60 verzoeken per uur, per IP-adres geteld en gedeeld met iedereen erachter

Een import valt nooit terug op die laag van 60 per uur: zonder token om te sturen wordt het verzoek meteen geweigerd in plaats van anoniem opnieuw geprobeerd. Het getal doet ertoe voor wat je rondom de import doet — een script dat GitHub rechtstreeks leest, of een shell in hetzelfde netwerk als andere clients, put 60 verzoeken in seconden uit.

Lees je resterende budget wanneer je wilt; GET /rate_limit is van beide limieten vrijgesteld, dus de controle kost niets:

Terminal window
curl -H "Authorization: Bearer $GITHUB_TOKEN" https://api.github.com/rate_limit

GraphQL-punten zijn geen verzoeken. GitHub scoort een query op de nodes die hij teruggeeft, dus één pagina van 100 issues met hun opmerkingen en toegewezen personen kost veel punten, en een grote repository geeft het uurbudget uit in veel minder aanroepen dan de getallen uit het REST-tijdperk doen vermoeden. --dry-run (stap 3) en dry_run (stap 4) kosten elk dezelfde punten als het echte ophalen — dat is wat hun tellingen betrouwbaar maakt — dus reken op twee passages als je een grote import voorbereidt.

  • API-gids — de zoekgrammatica, de gebeurtenisstroom, bulkovergangen, idempotente schrijfacties en de rest van het oppervlak.
  • Bedieningsinstructies — dezelfde handelingen vanuit de interface, en de andere tien importeurs.
  • Inleiding — waarom de toestandsmachine en de vier storytypen deze vorm hebben.
  • GitHub-to-EAT — de repository van de importeur: elke vlag, beide engines, en hoe je eraan bijdraagt.