Co-authored-by: moilanik <niko.moilanen@tietoevry.com> Reviewed-on: #20
14 KiB
name, description, activation-gate, category, impact
| name | description | activation-gate | category | impact |
|---|---|---|---|---|
| consumer-pipelines | Creating or modifying consumer CI pipelines, .gitea/workflows/ files, reusable test workflows, monorepo CI configuration, or CI routing files (ci-feature.yml, ci-main.yml, ci-*.yml). Activates when the user asks to build, fix, or change consumer-side Gitea Actions pipelines that use gitea-ci-library providers. | User mentions consumer pipelines, ci-feature.yml, ci-main.yml, test workflows, .gitea/workflows/ files, monorepo CI, routing files, or asks to create/modify CI pipelines on top of gitea-ci-library. | ci | high |
Consumer Pipelines — Pipeline Standards
Säännöt joilla consumer-projektit rakentavat CI-pipelinejä gitea-ci-library-kirjaston päälle.
Nämä eivät ole provider-kirjaston sääntöjä — ne kuvaavat miten consumerin kuuluu käyttää kirjastoa oikein.
1. Reitittimen puhtaus
Reitittimet (ci-feature.yml, ci-main.yml) eivät sisällä run:-steppejä. Ne koostuvat vain:
uses:
needs:
if:
secrets: inherit
with:
env_json:
<parametrit>:
Jokainen job vastaa yhtä loogista testiä tai operaatiota. Reititin on orkestraattori — kaikki suorittava
logiikka on omassa workflow_call-tiedostossaan.
Esimerkki:
jobs:
load-config:
uses: <owner>/gitea-ci-library/.gitea/workflows/config-provider.yml@v1
secrets: inherit
<test-1>:
needs: [load-config]
uses: ./.gitea/workflows/<component>.<test-1>.yml@main
secrets: inherit
with:
env_json: ${{ needs.load-config.outputs.env_json }}
<test-2>:
needs: [load-config]
uses: ./.gitea/workflows/<component>.<test-2>.yml@main
secrets: inherit
with:
env_json: ${{ needs.load-config.outputs.env_json }}
report-summary:
needs: [load-config, <test-1>, <test-2>]
if: always()
uses: <owner>/gitea-ci-library/.gitea/workflows/report-summary.yml@v1
with:
env_json: ${{ needs.load-config.outputs.env_json }}
suites: <suite-1> <suite-2>
2. Yksi asia per tiedosto
Ei monoliittista ci-tests.yml. Jokainen testityyppi tai operaatio on oma workflow_call-tiedostonsa.
Miksi:
- Testit ajetaan rinnakkain (ei keinotekoisia riippuvuuksia)
- Yhden testin fail ei estä muita
- Testattavissa itsenäisesti
workflow_dispatch:llä - Diff näyttää heti mitä testiä muutettiin
3. Exit-koodin käsittely
Jokainen testi kaappaa komentonsa exit-koodin eksplisiittisesti:
- name: Run tests
shell: bash
run: |
<testikomento> > results.txt 2>&1
EXIT=$?
echo "EXIT=${EXIT}" >> "${GITHUB_ENV}"
exit ${EXIT}
Miksi ei pipeä (| tee):
# VÄÄRIN — pipe syö exit-koodin
<komento> | tee results.txt
# OIKEIN — redirect tiedostoon
<komento> > results.txt 2>&1
Ilman EXIT=$? + exit ${EXIT} komento voi feilata mutta job menee läpi vihreänä — container:-modessa
shellin käyttäytyminen vaihtelee.
4. Konttipolitiikka
- Julkiset registry-kontit kiinteällä versiolla —
alpine/helm:3.19.0,node:22,maven:3.9-eclipse-temurin-21. Toistettavuus ja turvallisuus eivät saa riippua ulkoisestalatest:sta - Projektin omat CI-kontit
latest-tägillä — buildattuci-container-build-<kontti>.yml:llä. Kontin build-pipeline päivittäälatest:n automaattisesti. Rebuild = käyttöönotto kaikissa pipelineissa ilman versioviittauksien päivittelyä.lateston näille paras käytäntö, ei kompromissi - Ei koskaan
curl-latauksia CI-ajon sisällä — työkalujen asennus CI-stepeissä hidastaa, epäluotettavaa, ja vaikeuttaa toistettavuutta
CI-kontin build-workflow'n template: skills/ci-container-build/SKILL.md — sisältää
valmiin ci-container-build-<kontti>.yml-pohjan jossa workflow_dispatch-tuki manuaaliajoon.
5. Raporttitasot
Testi tuottaa raportin reports/${GITHUB_SHA:0:8}/<suite>/-hakemistoon. publish-git-pages.sh julkaisee sen,
report-status.sh linkittää commit-statusin siihen. Molemmat if: always().
Taso 1: Pelkkä teksti
Kun testi tuottaa vain stdout/stderr — tallennetaan results.txt:
- name: Run tests
shell: bash
run: |
mkdir -p "reports/${GITHUB_SHA:0:8}/<suite>"
<testikomento> > "reports/${GITHUB_SHA:0:8}/<suite>/results.txt" 2>&1
EXIT=$?
echo "EXIT=${EXIT}" >> "${GITHUB_ENV}"
exit ${EXIT}
- name: Publish reports
if: always()
shell: bash
run: bash .ci/scripts/publish-git-pages.sh <suite>
- name: Report status
if: always()
shell: bash
run: |
if [ "${EXIT}" = "0" ]; then
bash .ci/scripts/report-status.sh success "<kuvaus>" <context> <suite>
else
bash .ci/scripts/report-status.sh failure "<kuvaus>" <context> <suite>
fi
Taso 2: HTML-raportti
Kun testi tuottaa strukturoitua dataa (JUnit XML, coverage, tms.) — generoidaan HTML ja index.html:
reports/<sha8>/<suite>/
├── index.html ← generoitu: linkit alla oleviin
├── results.txt ← testin stdout
├── junit.xml ← testin JUnit XML -output
└── junit.html ← generoitu HTML (xsltproc, tms.)
index.html linkittää kaikkiin raporttitiedostoihin. Selain avaa sen ja navigoi sieltä
yksittäisiin raportteihin.
6. Nimeäminen
Tiedostonimet .gitea/workflows/-kansiossa noudattavat yhtenäistä rakennetta, jotta
tiedostot löytyvät nopeasti ja niiden rooli on selvillä:
<komponentti>.ci-feature.yml ← feature-haaran reititin
<komponentti>.ci-main.yml ← main-haaran reititin
<komponentti>.<testityyppi>.yml ← yksittäinen testi tai operaatio
<komponentti>.ci-container-build-<kontti>.yml ← CI-kontin build-workflow
<komponentti>.gitea-env.conf ← komponenttikohtainen konfiguraatio
Single repossa <komponentti> jätetään pois — tiedostot ovat suoraan ci-feature.yml,
ci-main.yml, <testityyppi>.yml, ci-container-build-<kontti>.yml.
Monorepossa prefiksi pitää komponentin tiedostot yhdessä: ls <komponentti>.* löytää kaikki
kerralla.
7. Artifact-kuri
Gitea Actionsin upload-artifact jättää pysyvän tiedoston. Artifakteja ei käytetä
workflow_call:ien väliseen datan siirtoon ellei se ole teknisesti välttämätöntä.
Ensisijainen ratkaisu: jokainen testi tuottaa tarvitsemansa datan itse. Ei
upload-artifact + download-artifact -riippuvuuksia.
# OIKEIN — molemmat testit tuottavat oman datansa
- name: Prepare data
run: <komento> > /tmp/data
- name: Validate data
run: <validointikomento> /tmp/data
Miksi:
- Testit pysyvät itsenäisinä — yhden testin fail ei estä muita
- Ei "artifact expired" -virheitä myöhemmin
- Ei pysyviä artifakteja siivoamatta
Konfiguraatiotiedosto (.gitea-env.conf)
Tiedosto on key=value-muotoinen (kuten .env). Kommentit ja tyhjät rivit sallittuja.
Single repo
# .gitea/workflows/gitea-env.conf
GITEA_API_URL=https://gitea.example.com
GIT_PAGES_URL=https://reports.example.com
Docker-artifaktin buildaavat projektit
DOCKER_REGISTRY=gitea.example.com/myorg
DOCKER_IMAGE_NAME=my-service
DOCKER_UI_URL=https://gitea.example.com/myorg/-/packages/container
#DOCKERFILE=Dockerfile.platform # valinnainen, oletus Dockerfile
DOCKER_UI_URL ei sisällä image-nimeä — se on puhdas container-registryn osoite.
Image-nimi lisätään automaattisesti URL:iin docker-build-push.yml:ssä.
Salaisuudet (Gitea Settings → Secrets)
| Secret | Pakollinen |
|---|---|
GITEA_TOKEN |
Aina (Gitean sisäinen, automaattisesti saatavilla) |
GIT_PAGES_PUBLISH_TOKEN |
Aina |
DOCKER_USERNAME |
Vain jos buildaat kontteja |
DOCKER_PASSWORD |
Vain jos buildaat kontteja |
Monorepo
Monorepossa yhdessä repossa asuu useampi julkaistava komponentti. Jokaiselle komponentille
oma conf-tiedosto .gitea/workflows/<komponentti>.gitea-env.conf, jossa on kaikki
komponenttikohtainen tieto.
Suositus: komponentit omiin juurihakemistoihin
On suositeltavaa sijoittaa jokaisen komponentin koko lähdekoodi omaan juuritason
hakemistoonsa (api/, frontend/, shared/). Tämä helpottaa paths:-filtteröintiä,
pitää komponentit selkeästi erillään, ja tekee repossa navigoinnista suoraviivaista.
Tämä on kuitenkin vain suositus — ei pakottava sääntö.
Ongelmat ja ratkaisut
| Ongelma | Ratkaisu |
|---|---|
| Monta komponenttia, yksi repo — mikä triggeröi? | paths:-filtteri: push: { paths: ['<komponentti>/**'] } |
| Jokaisella komponentilla oma versio | VERSION_FILE=<komponentti>/package.json confissa |
| Git-tägit sekaisin ellei nimiavaruutta | GIT_TAG_PREFIX=<komponentti>/ confissa → tägi <komponentti>/1.2.3 |
| Eri julkaisutahdit | Riippumattomat CI-triggerit, omat versiopolut |
Komponenttikohtainen conf
# .gitea/workflows/<komponentti>.gitea-env.conf
GITEA_API_URL=https://gitea.example.com
GIT_PAGES_URL=https://reports.example.com
DOCKER_REGISTRY=gitea.example.com/myorg
DOCKER_IMAGE_NAME=<image-nimi>
DOCKER_UI_URL=https://gitea.example.com/myorg/-/packages/container
GIT_TAG_PREFIX=<komponentti>/
# Jompikumpi — JSON (.version-kenttä) tai plain text:
VERSION_FILE=<komponentti>/package.json
#VERSION_FILE=<komponentti>/VERSION
Monorepo reititin
name: CI <Komponentti> Main
on:
push:
branches:
- main
paths:
- '<komponentti>/**'
jobs:
load-config:
uses: <owner>/gitea-ci-library/.gitea/workflows/config-provider.yml@v1
secrets: inherit
with:
config_path: .gitea/workflows/<komponentti>.gitea-env.conf
check-version:
needs: [load-config]
uses: <owner>/gitea-ci-library/.gitea/workflows/check-version.yml@v1
secrets: inherit
with:
env_json: ${{ needs.load-config.outputs.env_json }}
<testit>:
needs: [load-config, check-version]
if: needs.check-version.outputs.artifact_exists != 'true'
uses: ./.gitea/workflows/<komponentti>.<testi>.yml@main
secrets: inherit
with:
env_json: ${{ needs.load-config.outputs.env_json }}
build-push:
needs: [load-config, check-version, <testit>]
if: needs.check-version.outputs.artifact_exists != 'true'
uses: <owner>/gitea-ci-library/.gitea/workflows/docker-build-push.yml@v1
secrets: inherit
with:
env_json: ${{ needs.load-config.outputs.env_json }}
version: ${{ needs.check-version.outputs.version }}
Version elinkaari per komponentti
GIT_TAG_PREFIX takaa että eri komponenttien versiohistoria pysyy erillään.
Git-tägi <komponentti>/0.2.3 ei sekoitu toisen komponentin tägeihin.
check-version.yml suodattaa ja laskee seuraavan patchin vain kyseisen
komponentin etuliitteellä. Idempotenttius toimii komponenttikohtaisesti:
jos commitilla on jo tägi, pipeline skipataan if: artifact_exists != 'true'.
Mitä EI kannata tehdä monorepossa
- Älä aja kaikkia komponentteja samasta triggeristä —
paths:pitää CI:t erillisinä - Älä käytä samaa versionhallintatiedostoa usealle komponentille
- Älä anna monorepo-parametreja pipeline-overrideina — kaikki kuuluu conf-tiedostoon
Versionhallinta
check-version.yml lukee version automaattisesti prioriteettijärjestyksessä:
| # | Lähde | Formaatti |
|---|---|---|
| 1 | VERSION_FILE confissa |
Määritelty polku |
| 2 | VERSION-tiedosto (root) |
Plain text |
| 3 | package.json (root) |
.version-kenttä |
| 4 | pom.xml (root) |
<version>-elementti |
major.minor otetaan tästä. Patch lasketaan automaattisesti git-tageista.
Esim. VERSION = 0.2, tagit = 0.2.0, 0.2.1 → seuraava 0.2.2.
Branch protection (PR-gate)
Gitean Settings → Branches → Add Rule:
- Branch:
main - Enable Require Status Checks: päälle
- Status checks: valitse testijobien nimet
Provider-rajapinnat — referenssi
Workflowt
| Workflow | Käyttötarkoitus |
|---|---|
config-provider.yml |
Lataa + validoi .conf, tuottaa env_json |
check-version.yml |
Tarkistaa onko commit buildattu, laskee version |
docker-build-push.yml |
Buildaa + puskea Docker-imagen, tagittaa commitin |
report-summary.yml |
GITHUB_STEP_SUMMARY-taulukko raporttilinkeillä (Gitea 1.27+) |
Skriptit (kutsutaan .ci/scripts/-polun kautta)
| Skripti | Käyttötarkoitus |
|---|---|
report-status.sh |
POSTaa commit-statuksen linkillä |
publish-git-pages.sh |
Julkaisee raporttihakemiston git-pagesiin |
ci-validate.sh |
Validoi .conf-tiedoston (kutsutaan config-provider.yml:stä) |
ADR-yhteenveto — consumerin kannalta oleelliset säännöt
Reititin ei sisällä suorittavaa koodia (ADR 0010)
ci-feature.yml ja ci-main.yml koostuvat vain uses:, needs: ja if:-avainsanoista.
Ei run:-komentoja, ei inline-skriptejä, ei actions/checkout.
Yksi steppi = yksi workflow_call-tiedosto
Jokainen job reitittimessä on oma workflow_call-tiedostonsa.
Ei kahta eri komentoa samassa workflow'ssa.
Provider-versio on @v1 (ADR 0009)
Kaikki provider-viittaukset käyttävät @v1-tagia. @main on vain providerin oman repon
sisäiseen dogfood-käyttöön. Breaking changet kielletty — v1-rajapinta on pysyvä.
Exit-koodi on ainoa onnistumisen mittari (ADR 0008)
Ei pipeä (|) komennon perässä — se syö exit-koodin. Käytä redirectiä (> file 2>&1).
Commit-status vain raporttilinkille (ADR 0007)
report-status.sh-skriptiä käytetään VAIN kun on raportti linkitettäväksi.
Tool-jobit (build, deploy) luottavat Gitean natiiviin job-statukseen.
Providerin checkout ei kuulu consumerille
Providerin scriptit haetaan actions/checkout-stepillä .ci/-polkuun.
Consumer ei kopioi eikä muokkaa providerin tiedostoja.