# Design Rationale — Gitea Actions CI -kirjasto > Miksi kirjasto on rakennettu näin. Arvot, periaatteet ja reunaehdot, joiden varaan arkkitehtuuri nojaa. > > Tämä dokumentti on **normatiivinen** — arkkitehtuurin on noudatettava näitä periaatteita. Jos ehdotettu muutos on ristiriidassa rationalen kanssa, rationalen on muututtava ensin. --- ## Miksi tämä projekti on olemassa Organisaatiolla on tuotannossa Jenkins-pohjainen CI-järjestelmä (`ci-jenkins-library`, 53 lähdetiedostoa, 21 Cucumber-featurea), joka on osoittautunut toimivaksi vuosien ajan. Se integroi Git-commitit, testiraportoinnin, Docker-buildit, deploymentin ja test flow'n yhtenäiseksi putkeksi, jossa jokainen vaihe raportoi tilansa suoraan Git-committiin. Jenkins on kuitenkin raskas ylläpitää Kubernetesissa, ja organisaatio on siirtymässä Giteaan. Tavoitteena on **sama toiminnallisuus, pienemmällä ylläpitotaakalla**, hyödyntäen Gitea Actionsin natiiveja ominaisuuksia. Kirjasto ei ole Jenkins-migraatiotyökalu. Se on Gitea Actions -natiivi uudelleensuunnittelu, joka säilyttää Jenkins-version todistetut patternit mutta hylkää ne osat, jotka olivat sidottuja Jenkinsin arkkitehtuuriin. --- ## Suunnitteluperiaatteet ### 1. Git-commit on universaali statusnäkymä Buildin jokainen vaihe raportoi tilansa Git-committiin. Kehittäjä näkee yhdellä silmäyksellä, missä vaiheessa build on — ei tarvitse navigoida CI-järjestelmän UI:hun. **Miksi:** Jenkins-versio osoitti, että commit-statusviestit poistavat tarpeen CI-dashboardille. Kehittäjä työskentelee Gitissä, joten status kuuluu Gitiin. Statusviestien `url`-kenttä linkittää suoraan raportteihin — Cucumber-tulokset, SonarQube-tulokset, Docker-rekisteri — ilman että URL tarvitsee etsiä erikseen. **Mitä tarkoittaa käytännössä:** Jokainen `testBegin/End`, `buildBegin/End`, `pushBegin/End`-vaihe POSTaa Gitean REST APIin (`/api/v1/repos/{owner}/{repo}/statuses/{sha}`). Uniikki `key` per vaihe estää duplikaatit ja mahdollistaa rinnakkaiset statukset samassa commitissa. ### 2. Reusable workflow — ei omaa runtimea Kirjasto jaetaan Gitea Actionsin reusable workflow -mekanismilla. Ei Docker-pohjaisia custom actioneita, ei erillistä ajonaikaista palvelinta. **Miksi:** Reusable workflow on Gitea Actionsin natiivein tapa jakaa CI-logiikkaa. Se on kevein (ei ylimääräistä runtimea), läpinäkyvin (workflow-tiedosto on luettavissa sellaisenaan) ja teknisesti kestävin (Gitea huolehtii versioinnista ja jakelusta). Custom actionit otetaan käyttöön vain jos reusable workflow'n rajat tulevat vastaan. **Mitä tämä ei ole:** Tämä ei ole monorepo-työkalu, joka asennetaan projekteihin. Tämä on joukko `.gitea/workflows/`-tiedostoja, joihin mikropalvelut viittaavat `uses:`-direktiivillä. ### 3. Konfiguraatio kuuluu repoon Projektikohtainen konfiguraatio (`ci-flow-values.yaml`-tyyppinen tiedosto) asuu mikropalvelun omassa repossa. Reusable workflow lukee sen, ei toisinpäin. **Miksi:** Mikropalvelun kehittäjä omistaa buildinsa. Hän tietää mitä Dockefileä käytetään, mitä SonarQube-projektia, mitä testi-steppejä tarvitaan. Jos konfiguraatio hajautetaan useaan repoon, muutokset vaativat koordinaatiota, ja yhden totuuden lähteen periaate rikkoutuu. **Poikkeus:** Infra-tason asetukset (MinIO-URL, Gitea-instanssin URL) ovat organisaatiotasolla Gitean organization secrets/variables -mekanismissa. Ne eivät ole repokohtaisia, koska DNS voi osoittaa eri paikkaan kuin repo, ja usean repossa toistuva sama arvo on ylläpitoriski. ### 4. Deterministinen testigraafi, vaiheittainen suoritus Test flow on tunnettu ennen buildin alkua, ja testit ajetaan yksi kerrallaan. Jos steppi epäonnistuu, koko flow pysähtyy. **Miksi:** Rinnakkainen suoritus aiheuttaa resurssikilpailua (erityisesti suorituskykytestit) ja piilottaa virheitä. Kun integraatiotesti epäonnistuu, e2e-testien ajaminen on turhaa — konttia ei viedä tuotantoon, eikä kukaan lue niitä tuloksia. Vaiheittainen suoritus on deterministinen, debuggattava ja säästää CI-minuutteja. **Miten:** Orkestroiva workflow käyttää Gitea REST API:a workflow-dispatchiin ja pollaa ajettavan workflow'n tilaa synkronisesti (`GET /api/v1/repos/{owner}/{repo}/actions/runs/{id}`). Tämä vastaa Jenkinsin `buildJob()`-kutsun semantiikkaa, mutta toteutetaan curl + pollaus -silmukalla. ### 5. Raportit ovat selailtavia URL:n takana Testiraportit (Cucumber HTML, Jacoco HTML, JUnit XML) viedään MinIO:hon, jonka staattinen web-hosting renderöi ne selaimessa. URL linkitetään Git-committiin. **Miksi:** Jenkins-versiossa linkki Cucumber-raporttiin oli kriittinen feature — kehittäjä klikkasi commitin statusviestistä ja näki heti mitkä testit epäonnistuivat. Gitea Actionsin sisäänrakennettu artifact-järjestelmä ei tue HTML-selailtavuutta (vain ZIP-lataus). MinIO täyttää tämän aukon: se on kevyt, Kubernetes-natiivi, ja sen S3 API on standardi. URL-rakenne `{BASE}/{repo_slug}/{commit_short}/{report_type}/` on ennustettavissa ilman erillistä URL-generaattoria. ### 6. Yksi CI-alusta, yksi integraatiopiste Kirjasto tukee vain Giteaa. Ei GitLab-, BitBucket- tai GitHub-abstraktioita. **Miksi:** Jenkins-versio tuki neljää Git-alustaa, koska Jenkins itsessään ei tarjonnut commit-statusraportointia. Gitea Actionsissa tilanne on päinvastainen — Gitea on sekä CI-että Git-alusta. Multi-platform-tuesta tulisi pelkkää ylimääräistä abstraktiota ilman konkreettista tarvetta. **Mitä tarkoittaa tulevaisuudessa:** Jos toinen alusta tulee ajankohtaiseksi, Gitea-versiota käytetään joko pohjana redesignille tai mallina erilliselle toteutukselle. Rajapintoja ei suunnitella etukäteen alustariippumattomiksi — se on ennenaikaista optimointia. ### 7. Cross-repo commit traceability Kun build-ketju ylittää reporajat (mikropalvelu → deployment → integraatiotestit → e2e-testit), jokainen vaihe raportoi kahteen suuntaan: omaan committiinsa ja takaisin root-committiin, josta ketju käynnistyi. **Miksi:** Kehittäjän ei pidä arvailla mikä versio on missäkin ympäristössä. Kun mikropalvelun commitista näkee koko ketjun — buildattu, deployattu stagingiin, integraatiotestit ajettu, e2e hyväksytty — virheenjäljitys on suora polku commitista ympäristöön. Vastaavasti Helm-repon commit kertoo mikä konttiversio sinne deployattiin ja kenen mikropalvelu-commitista se tuli. Tämä on Jenkins-version **eniten arvoa tuottanut ominaisuus**. **Mekanismi:** ```mermaid %%{init: {'theme': 'base'}}%% sequenceDiagram participant MR as Mikropalvelu-repo participant HR as Helm-repo participant TR as Testi-repo participant GA as Gitea API Note over MR: commit abc123 Note over MR: build kontti v1.2.3 MR->>GA: POST dispatch deploy-workflow GA->>HR: workflow käyntiin Note over HR: commit def456 Note over HR: container.version = 1.2.3 HR->>GA: POST status "deployed by abc123" GA->>MR: Status: deployed to staging Note right of MR: URL → def456 HR->>GA: POST status "from abc123" GA->>HR: Status: from abc123 Note right of HR: URL → abc123 MR->>GA: POST dispatch integraatiotestit GA->>TR: workflow käyntiin Note over TR: commit ghi789 TR->>GA: POST status "integration OK" GA->>MR: Status: integration OK Note right of MR: URL → ghi789 TR->>GA: POST status "tested v1.2.3" GA->>HR: Status: tested v1.2.3 Note right of HR: URL → def456 TR->>GA: POST status "tested abc123" GA->>MR: Status: tested abc123 (root) Note right of MR: URL → abc123 ``` **Mitä tarkoittaa käytännössä:** Jokaisella workflow'lla on kaksi build-referenssiä: `current` (oma commit) ja `root` (mikropalvelun commit, josta ketju alkoi). Molempiin POSTataan statusviestit. Root-build kulkee workflow-dispatchin `inputs`-parametrina koko ketjun läpi. Deployment-job raportoi sekä Helm-repon committiin ("from abc123") että mikropalvelun committiin ("deployed to staging → def456"). Testi-job raportoi omaan committiinsa, mikropalvelun committiin ja Helm-repon committiin. --- ## Arkkitehtuuriset rajoitteet ### Mitä kirjasto EI tee - **Ei ulkoista orkestraattoria.** Test flow -ketjutus perustuu Gitean REST APIin ja workflowhin itseensä. Ei erillistä palvelinta, joka hallinnoi tilaa. - **Ei Jenkins-migraatiota.** Vanhaa Jenkinsfileä ei voi ajaa Gitea Actionsissa. Tämä on uusi kirjasto uudella konfiguraatioformaatilla. - **Ei reaaliaikaista build-seurantaa.** Commit-statusviestit ovat pollattavia, eivät push-pohjaisia. Gitean UI hoitaa reaaliaikaisuuden. - **Ei multi-repo-monorepo-konfiguraatiota.** Jokainen mikropalvelu omistaa oman `ci-flow-values.yaml`:nsa. Jaettua konfiguraatiota ei ole projektitasolla. --- ## Teknologiavalinnat (seurauksina ylläolevista periaatteista) | Valinta | Miksi | |---------|------| | **Gitea Actions reusable workflows** | Periaate 2: natiivein tapa jakaa CI-logiikkaa ilman omaa runtimea | | **Gitea REST API** (`/api/v1/...`) | Periaate 1: commit-statusraportointi. Periaate 4: workflow-dispatch ja status-pollaus. Periaate 7: cross-repo statusraportointi useaan committiin | | **MinIO** (S3-yhteensopiva) | Periaate 5: HTML-selailtavat raportit ilman ulkoista palvelinta. Kubernetes-natiivi, yksi binääri | | **YAML** konfiguraatioformaattina | Periaate 3: repo omistaa konffinsa. YAML on luettava, versioitava ja tuttu Jenkins-versiosta | | **curl + jq + bash** integraatiokerroksena | Periaate 2: ei custom action -runtimea. Gitea REST API:a kutsutaan suoraan workflow-stepistä | | **Gitea organization secrets/variables** | Periaate 3: infra-tason asetukset (MinIO-URL, tokenit) eivät kuulu reposuuteen | --- ## Mitä tietoisesti hylättiin | Hylätty | Syy | |---------|-----| | Multi-Git-platform-tuki (GitLab, BitBucket) | Vain Gitea on relevantti. Abstraktointi ilman tarvetta on turhaa kompleksisuutta | | Gitea Packages raporttien hostingiin | Ei tue HTML-selailtavuutta — vain binääriartefaktien lataus | | Gitea Releases raporttien hostingiin | Saastuttaa release-historian. Satoja CI-raportteja oikeiden julkaisujen seassa | | Gitea Pages + reports-branch | Race condition rinnakkaisten buildien pushissa samaan branchiin | | Ulkoinen orkestraattoripalvelin | Ylimääräinen ylläpidettävä. Gitean oma API riittää | | Docker-pohjaiset custom actionit | Tuovat riippuvuuden Docker-rekisteriin ja monimutkaistavat jakelua. Otetaan käyttöön vain pakon edessä | | `repository_dispatch` (webhook) test flow -ketjutukseen | Lisää konfiguraatiota vastaanottaviin repoihin. Suora REST API -kutsu on eksplisiittisempi ja debuggattavampi |