Files
niko 14a411e340
CI Main / Load example-gitea-env.conf to pipeline env (push) Successful in 18s
CI Main / Check existing artifact (push) Successful in 12s
unit-tests Link to Bats reports
CI Main / Bats tests (push) Successful in 1m41s
acc-tests Link to Cucumber reports
CI Main / Cucumber tests (push) Successful in 1m7s
ci-docker-build-push Docker build & push 0.2.1 OK
CI Main / Build & Push Docker (push) Successful in 34s
CI Main / Report Summary (push) Successful in 4s
consumer project käyttöönotossa tulleitea muutoksia (#12)
Co-authored-by: moilanik <niko.moilanen@tietoevry.com>
Reviewed-on: #12
2026-06-16 04:48:05 +03:00

10 KiB

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

Mikropalveluarkkitehtuurissa jokainen palvelu tarvitsee CI-putken: testit, laatutarkistukset, buildin, kontituksen ja julkaisun. Ilman jaettua kirjastoa jokainen tiimi kopioi saman YAML-boilerplaten, tekee omat virheensä ja ylläpitää omaa versiotaan. Ajan myötä putket ajautuvat erilleen — toisessa on shell: bash, toisessa ei; toinen käyttää set -o pipefail, toinen kadottaa exit-koodin tee:hen.

Tämä kirjasto on se mitä kopioidaan. Se tarjoaa valmiit, testatut, dokumentoidut rakennuspalikat joista jokainen tiimi kokoaa oman putkensa. Palikat ovat Gitea Actionsin uses:-direktiivillä kutsuttavia reusable workflow'ta — ei asennusta, ei runtime-riippuvuutta, ei versiopäivityksiä projekteihin.


Suunnitteluperiaatteet

1. Palikka-arkkitehtuuri: pieniä, vaihdettavia, yhden vastuun workflow'ta

Jokainen provider-workflow tekee yhden asian:

Workflow Vastuu
config-provider.yml Lataa ja validoi konfiguraatio
check-version.yml Tarkistaa onko commit buildattu, laskee version
docker-build-push.yml Buildaa, puskea ja tagittaa kontin

Mikään workflow ei kutsu toista provider-workflowta. Consumer — siis mikropalvelun oma pipeline-tiedosto — on ainoa paikka joka tietää mitä palikoita tarvitaan ja missä järjestyksessä.

Miksi: Tämä on sama periaate kuin Unix-putkissa tai mikropalveluissa: pieniä, itsenäisiä komponentteja jotka tekevät yhden asian hyvin. Consumer voi vaihtaa yhden palikan toiseen — esimerkiksi Docker-buildin tilalle Maven-paketoinnin — ilman että muut palikat muuttuvat. Ratkaisu ei ole se että kaikki ajetaan, vaan se että jokainen tiimi valitsee mitä tarvitsee. Monoliittinen "kaikki yhdessä" -workflow pakottaisi jokaisen tiimin ajamaan tarpeettomia vaiheita.

2. Gitea ensin — hyödynnä alustaa, älä taistele sitä vastaan

Gitea Actions tarjoaa kolme asiaa ilmaiseksi:

  1. Jobien visuaalinen status — jokainen jobi näkyy automaattisesti commit-näkymässä checkmarkilla, spinnerillä tai ristillä.
  2. Cross-job riippuvuudetneeds hoitaa virheiden propagointin: jos edeltävä jobi feilaa, riippuvat jobit skipataan.
  3. Reusable workflow -jakeluuses: org/repo/.gitea/workflows/file.yml@v1 on natiivisti versioitu, skopattu ja välimuistitettu.

Kirjasto käyttää näitä kaikkia. Ei omaa tilakonetta, ei custom action -runtimea, ei ulkoista orkestraattoria.

Esimerkki: Tool-jobit eivät kutsu commit-status API:a lainkaan. Gitean oma job-status riittää — success/failure/running näkyy automaattisesti. API:a käytetään vain kun tarvitaan custom-linkki (testiraporttiin tai Docker registryyn), jota natiivistaatus ei tarjoa. Tämä linjaus on dokumentoitu ADR 0004 ja 0007:ssä.

3. Status näkyy siellä missä työ tehdään — Git-commitissa

Kehittäjä työskentelee Gitissä. git log, git blame, PR-näkymä — nämä ovat päivittäiset työkalut. CI-statuksen kuuluu näkyä siellä, ei erillisessä dashboardissa.

Gitea Actionsin natiivi job-status tekee tämän automaattisesti: jokainen commit näyttää välittömästi mitkä jobit on ajettu ja millä tuloksella. Testiraportteihin pääsee yhdellä klikkauksella commitin status-kuvakkeesta — koska report-status.sh asettaa target_url:n osoittamaan suoraan HTML-raporttiin git-pagesissa.

Tämä ei ole kosmeettinen yksityiskohta. Se on devops-käytännön ydin: palautesilmukka on lyhin mahdollinen. Commit → build → status näkyy samassa näkymässä jossa kehittäjä jo on.

4. Exit-koodi on ainoa totuus

CI-putken jokaisen run-stepin onnistuminen määräytyy vain ja ainoastaan exit-koodin perusteella. Ei tiedoston olemassaolon, ei stdout-tulosteen, ei arvauksen. 0 = ok, kaikki muu = ei ok.

Tämä kuulostaa itsestään selvältä, mutta YAML-pipelineissa se rikkoutuu helposti. Pipe (|) tee:hen syö exit-koodin. Tiedoston olemassaolon tarkistus ([ -f results.xml ]) ei kerro testien läpimenosta.

Käytännössä: Jokainen run-steppi ottaa exit-koodin talteen $?-muuttujaan ennen kuin mikään muu komento ehtii muuttaa sitä, ja stepin viimeinen rivi on exit ${EXIT}. Pipeä ei käytetä työvaiheen viimeisenä komentona. Ks. ADR 0008.

5. Pienin mahdollinen pinta-ala

Jokainen ylimääräinen riippuvuus on ylimääräinen vikaantumispiste. Kirjaston ainoat riippuvuudet:

  • Gitea Actions (alusta)
  • bash, curl, jq (ubuntu-latest runnerissa valmiina)
  • Docker (runnerissa valmiina)
  • git-pages (raporttien hostaus, erillinen palvelu)

Ei Pythonia, ei Node.js:ää ajonaikaisesti (testit omissa konteissaan). Ei tietokantaa. Ei ulkoista tilanhallintaa. Kirjasto on joukko YAML-tiedostoja ja shell-skriptejä — samat työkalut jotka jokainen devops-ihminen jo osaa.

6. Konfiguraatio repoon, salaisuudet Giteaan

Projektikohtainen konfiguraatio (.gitea/workflows/gitea-env.conf) asuu mikropalvelun omassa repossa. Kehittäjä omistaa sen — hän tietää mikä on Docker-imagen nimi, mihin registryyn puskea, mikä on testiympäristön URL.

Salaisuudet (tokenit, salasanat) elävät Gitean secrets-mekanismissa, eivät repon tiedostoissa. secrets: inherit välittää ne providerin workflow'hun ilman että consumerin tarvitsee tietää mitä salaisuuksia mikäkin provider tarvitsee.

Poikkeus: infra-tason asetukset (GIT_PAGES_URL, GITEA_API_URL) ovat Gitean organization secrets/variables -mekanismissa. Ne eivät ole repokohtaisia.

7. Consumer omistaa orkestroinnin, provider tarjoaa palikat

Tämä on kirjaston tärkein arkkitehtuurinen päätös (ADR 0005).

Provider (gitea-ci-library) ei tiedä mitä testejä ajetaan, missä järjestyksessä, tai millä branchilla. Se tarjoaa kolme reusable workflow'ta ja joukon skriptejä.

Consumer (mikropalvelun example-feature.yml / example-main.yml) päättää:

  • Mitkä palikat kutsutaan
  • Missä järjestyksessä (needs)
  • Millä branch-ehdoilla (if)
  • Mitkä testikontit käytetään (input-parametrit)

Tämä on tarkoituksellinen vallanjako. Provider ei voi tietää jokaisen tiimin tarpeita — eikä sen pidäkään. Consumer ei voi muuttaa providerin sisäistä toteutusta — eikä sen pidäkään. Rajapinta on workflow_call ja se on molemmille osapuolille selvä.

8. Branch-kohtainen reititys, ei yhtä kaikille

Eri brancheilla on eri tavoite:

  • Feature-haara: Onko koodi laadukasta? → testit, validointi
  • Main-haara: Onko tästä versiosta jo artifakti? Jos ei → testit + build + push + tag. Jos on → ei tehdä mitään (tai jatketaan klusteritesteihin).

Tämä logiikka elää consumerin pipeline-tiedostossa, ei providerissa. Se on puhdasta if-ehtoa ja needs-ketjutusta — ei skriptausta, ei monimutkaisia ehtoja providerin sisällä.

9. Raportit erillisellä palvelulla, linkit commitissa

Gitea Actionsin artifact-järjestelmä on binääriarkisto — ZIP-lataus, ei HTML-selailtavuutta. Testiraportit (Cucumber HTML, Bats-coverage) on voitava avata selaimessa yhdellä klikkauksella.

Ratkaisu: git-pages Helm-chartti, joka tarjoaa staattista tiedostohostingia HTTP:llä. publish-git-pages.sh vie raportit sinne; report-status.sh linkittää commit-statuksen suoraan raporttiin. Retention hoitaa git-pagesin sidecar automaattisesti.

Tulevaisuudessa GITHUB_STEP_SUMMARY (Gitea 1.27+) tarjoaa vaihtoehtoisen kanavan: jobin Summary-välilehdelle renderöityvä Markdown-taulukko kaikista raporttilinkeistä.

10. Vain Gitea — ei monialustatukea ilman tarvetta

Yhden alustan tukeminen kunnolla on vaikeampaa kuin kolmen tukeminen huonosti. Gitea Actionsin uses:-mekanismi, needs-semantiikka, secrets: inherit, gitea-konteksti — nämä ovat alustakohtaisia ominaisuuksia joita abstraktiokerros vain haittaisi.

Jos toinen alusta tulee ajankohtaiseksi, sille kirjoitetaan oma toteutus. Siihen asti yksi alusta riittää. Ennenaikainen yleistys on devopsissa yhtä haitallista kuin ohjelmistosuunnittelussa.


Arkkitehtuuriset rajoitteet

Mitä kirjasto EI tee

  • Ei ulkoista orkestraattoria. Pipeline-ohjaus on Gitea Actionsin needs-ketjuissa ja consumerin if-ehdoissa.
  • Ei custom actioneita. Reusable workflow on kevyempi, versioitu ja jaeltu Gitean oman mekanismin kautta.
  • Ei asennusta projekteihin. Consumer viittaa uses:-direktiivillä suoraan tämän repon workflow-tiedostoihin. Ei npm-pakettia, ei git-submodulea, ei kopioitavia tiedostoja.
  • Ei runtime-riippuvuuksia. Provider-skriptit käyttävät vain työkaluja jotka ovat Gitea Actionsin ubuntu-latest runnerissa valmiina: bash, curl, jq.
  • Ei monorepo-konfiguraatiota. Jokainen mikropalvelu omistaa oman pipeline-tiedostonsa ja konfiguraationsa.

Mitä tietoisesti hylättiin

Hylätty Syy
Monoliittinen "kaikki yhdessä" -workflow Pakottaa kaikille samat vaiheet. Palikka-arkkitehtuuri antaa jokaiselle tiimille vain mitä se tarvitsee
Oma orkestraattoripalvelin Ylimääräinen ylläpidettävä. Gitean needs ja if riittävät
Docker-pohjaiset custom actionit Tuovat riippuvuuden Docker-rekisteriin. Reusable workflow on natiivimpi
Commit-status API jokaiselle vaiheelle Duplikointia — Gitea näyttää job-statuksen automaattisesti. API vain custom-linkeille
tee-putki debug-näkyvyyteen Syö exit-koodin. stdout ohjataan tiedostoon > ilman pipeä
Multi-Git-platform-tuki Ennenaikaista optimointia ilman tarvetta
Gitea Packages raporttien hostingiin Ei HTML-selailtavuutta — vain binäärilataus
Gitea Pages + reports-branch Race condition rinnakkaisten pushien kanssa
repository_dispatch ketjutukseen Lisää konfiguraatiota vastaanottaviin repoihin. Suora API-kutsu eksplisiittisempi