18 KiB
Consumer Guide — Kirjaston käyttöönotto
Anna tämä dokumentti AI:lle kun haluat ottaa
gitea-ci-library:n käyttöön uudessa projektissa tai muokata olemassa olevia pipelineja.
Rakenneperiaate
Pipeline-tiedostot (ci-feature.yml, ci-main.yml) eivät saa sisältää
varsinaista logiikkaa. Ne ovat puhtaita reitittimiä: pelkkiä uses:-kutsuja
if- ja needs-ehdoilla. Kaikki testien ajaminen, buildaus ja raportointi
kuuluu omiin workflow_call-tiedostoihinsa.
ci-unit-tests.yml ← testien ajaminen (varsinainen logiikka)
ci-acc-tests.yml ← hyväksymätestit (varsinainen logiikka)
ci-feature.yml ← reititin: load-config → test-workflow't → summary
ci-main.yml ← reititin: load-config → check-version → testit → build → summary
Provider tarjoaa 3 reusable workflow'ta ja joukon skriptejä.
Consumer omistaa orkestroinnin: mitä palikoita käytetään, missä järjestyksessä,
millä branch-ehdoilla. Consumer ei kopioi providerin koodia — se viittaa
uses:-direktiivillä.
Vaihe 1: Konfiguraatiotiedosto
Luo .gitea/workflows/gitea-env.conf:
GITEA_API_URL=https://gitea.example.com
GIT_PAGES_URL=https://reports.example.com
Jos buildaat Docker-kontteja, lisää:
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
Salaisuudet määritellään Gitean Settings → Secrets -näkymässä:
| Secret | Pakollinen |
|---|---|
GITEA_TOKEN |
Aina |
GIT_PAGES_PUBLISH_TOKEN |
Aina |
DOCKER_USERNAME |
Vain jos buildaat kontteja (ei pakollinen kaikissa registryissä) |
DOCKER_PASSWORD |
Vain jos buildaat kontteja |
Vaihe 2: Test-workflow't (varsinainen logiikka)
Jokainen testityyppi omaan workflow_call-tiedostoonsa. Tässä esimerkki
Maven-yksikkötesteistä. Luo .gitea/workflows/ci-unit-tests.yml:
name: Unit Tests
on:
workflow_call:
inputs:
env_json:
required: true
type: string
secrets:
GITEA_TOKEN:
required: true
GIT_PAGES_PUBLISH_TOKEN:
required: true
env:
GITEA_API_URL: ${{ fromJson(inputs.env_json).GITEA_API_URL }}
GIT_PAGES_URL: ${{ fromJson(inputs.env_json).GIT_PAGES_URL }}
GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
GIT_PAGES_PUBLISH_TOKEN: ${{ secrets.GIT_PAGES_PUBLISH_TOKEN }}
jobs:
test:
runs-on: ubuntu-latest
container: maven:3.9-eclipse-temurin-21
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v4
with:
repository: org/gitea-ci-library
path: .ci
- name: Run tests
shell: bash
run: |
mvn test
EXIT=$?
echo "EXIT=${EXIT}" >> "${GITHUB_ENV}"
exit ${EXIT}
- name: Publish reports
if: always()
run: bash .ci/scripts/publish-git-pages.sh junit
- name: Report status
if: always()
shell: bash
run: |
if [ "${EXIT}" = "0" ]; then
bash .ci/scripts/report-status.sh success "Link to JUnit reports" unit-tests junit
else
bash .ci/scripts/report-status.sh failure "Link to JUnit reports" unit-tests junit
fi
Hyväksymätesteille vastaava tiedosto ci-acc-tests.yml (Cucumber, Playwright
tms.), jossa oma container:, oma testikomento ja oma suite-nimi.
Tärkeää: mvn test korvataan omalla testikomennolla. container: ja
publish-git-pages.sh-suite ovat projektikohtaisia. Muu runko pysyy samana.
Vaihe 3: Feature-haaran CI (puhdas reititin)
Luo .gitea/workflows/ci-feature.yml. Ei sisällä yhtään run:-steppiä
— pelkkiä uses:-kutsuja:
name: CI Feature
on:
push:
branches-ignore:
- main
workflow_dispatch:
jobs:
load-config:
uses: org/gitea-ci-library/.gitea/workflows/config-provider.yml@v1
secrets: inherit
with:
config_path: .gitea/workflows/gitea-env.conf
unit-tests:
needs: [load-config]
uses: ./.gitea/workflows/ci-unit-tests.yml@main
secrets: inherit
with:
env_json: ${{ needs.load-config.outputs.env_json }}
acc-tests:
needs: [load-config]
uses: ./.gitea/workflows/ci-acc-tests.yml@main
secrets: inherit
with:
env_json: ${{ needs.load-config.outputs.env_json }}
report-summary:
needs: [load-config, unit-tests, acc-tests]
if: always()
uses: org/gitea-ci-library/.gitea/workflows/report-summary.yml@v1
with:
env_json: ${{ needs.load-config.outputs.env_json }}
suites: junit cucumber
Vaihe 4: Main-haaran CI (puhdas reititin)
Luo .gitea/workflows/ci-main.yml. Ei sisällä yhtään run:-steppiä:
name: CI Main
on:
push:
branches:
- main
workflow_dispatch:
jobs:
load-config:
uses: org/gitea-ci-library/.gitea/workflows/config-provider.yml@v1
secrets: inherit
with:
config_path: .gitea/workflows/gitea-env.conf
check-version:
needs: [load-config]
uses: org/gitea-ci-library/.gitea/workflows/check-version.yml@v1
secrets: inherit
with:
env_json: ${{ needs.load-config.outputs.env_json }}
unit-tests:
needs: [load-config, check-version]
if: needs.check-version.outputs.artifact_exists != 'true'
uses: ./.gitea/workflows/ci-unit-tests.yml@main
secrets: inherit
with:
env_json: ${{ needs.load-config.outputs.env_json }}
acc-tests:
needs: [load-config, check-version]
if: needs.check-version.outputs.artifact_exists != 'true'
uses: ./.gitea/workflows/ci-acc-tests.yml@main
secrets: inherit
with:
env_json: ${{ needs.load-config.outputs.env_json }}
build-push:
needs: [load-config, check-version, unit-tests, acc-tests]
if: needs.check-version.outputs.artifact_exists != 'true'
uses: org/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 }}
report-summary:
needs: [load-config, unit-tests, acc-tests]
if: always()
uses: org/gitea-ci-library/.gitea/workflows/report-summary.yml@v1
with:
env_json: ${{ needs.load-config.outputs.env_json }}
suites: junit cucumber
Mihin kiinnittää huomiota:
check-versionon idempotentti — jos commitilla on jo tagi, kaikki sen jälkeiset jobit skipataan (if: artifact_exists != 'true')needs-ketju takaa järjestyksen ja virheiden propagointin- Artifakti voi olla mitä tahansa —
docker-build-push.ymlon yksi esimerkki. Voit korvata sen Maven-deploylla, npm-publishilla, tai millä tahansa omalla build-workflow'lla. Rajapinta onversion-input.
Versionhallinta
check-version.yml lukee version automaattisesti prioriteettijärjestyksessä:
| # | Lähde | Formaatti | Esimerkki |
|---|---|---|---|
| 1 | VERSION-tiedosto |
Plain text | 0.2 |
| 2 | package.json |
.version |
"version": "0.2.0" |
| 3 | pom.xml |
<version> |
<version>0.2.0</version> |
major.minor otetaan tästä. Patch (kolmas numero) lasketaan automaattisesti
git-tageista. Esim. jos VERSION on 0.2 ja tagit ovat 0.2.0, 0.2.1,
niin seuraava on 0.2.2.
Testien lisääminen — oma työkalu
Kopioi ci-unit-tests.yml:n rakenne uudelle testityypille ja muuta:
container:— oma testikonttisi- Testikomento — oma testityökalusi (
npm test,pytest,go test, ...) publish-git-pages.sh <suite>— oma suite-nimireport-status.sh ... <context> <suite>— oma uniikki konteksti
Lisää uusi jobi reititintiedostoihin (ci-feature.yml, ci-main.yml)
samalla uses:-kaavalla.
Testijobit ajetaan rinnakkain — ne kaikki needs: [load-config] ilman
keskinäisiä riippuvuuksia.
Tärkeimmät säännöt
-
Exit-koodi aina ylös:
run-tests EXIT=$? echo "EXIT=${EXIT}" >> "${GITHUB_ENV}" exit ${EXIT} -
Ei pipeä testikomennon perään.
command | tee filesyö exit-koodin. Käytäcommand > file 2>&1jos haluat logit talteen. -
Status vain jos on raportti. Testijobit käyttävät commit-status API:a raporttilinkin takia. Tool-jobit luottavat Gitean natiiviin job-statukseen.
-
if: always()publish- ja status-stepeissä — raportti julkaistaan ja status asetetaan vaikka testit feilaisivat.
Raporttien generointi
publish-git-pages.sh <suite> odottaa hakemiston reports/${SHA8}/<suite>/
olevan olemassa. Sen sisältö sellaisenaan julkaistaan git-pagesiin.
report-status.sh linkittää statuksen suoraan tähän hakemistoon — selain
avaa sieltä index.html:n.
Test-workflow'n vastuulla on tuottaa raportit oikeaan polkuun. Kaksi tyypillistä patternia:
Pattern 1: Yksi raporttitiedosto (Cucumber)
Testityökalu tuottaa suoraan HTML-raportin. Yksinkertaisin tapaus:
mkdir -p "reports/${GITHUB_SHA:0:8}/cucumber"
npx cucumber-js \
--format html:"reports/${GITHUB_SHA:0:8}/cucumber/index.html"
Pattern 2: Monta raporttitiedostoa (Bats + coverage)
Eri työkalut tuottavat eri tiedostoja. Generoi index.html joka linkittää
ne yhteen:
reports/${SHA8}/bats/
├── index.html ← generoitu: linkit alla oleviin
├── results.txt ← bats-testien stdout
├── coverage/ ← bashcov-coverage HTML
│ └── index.html
└── ...
mkdir -p "reports/${GITHUB_SHA:0:8}/bats"
# Aja testit → results.txt
bats tests/ > "reports/${GITHUB_SHA:0:8}/bats/results.txt" 2>&1
# Generoi coverage → coverage-hakemisto
bashcov -- bats tests/
# Generoi index.html joka linkittää kaikkiin raportteihin
cat > "reports/${GITHUB_SHA:0:8}/bats/index.html" <<'EOF'
<!DOCTYPE html>
<html><body>
<h1>Bats Test Reports</h1>
<ul>
<li><a href="results.txt">Test results (raw)</a></li>
<li><a href="coverage/index.html">Code coverage</a></li>
</ul>
</body></html>
EOF
Yhteistä molemmille: publish-git-pages.sh <suite>-kutsun jälkeen raportit
ovat julkisesti selailtavissa. report-status.sh-kutsu suite-parametrilla
linkittää commit-statuksen suoraan index.html:ään.
Jos testit feilasivat, raportti generoidaan silti — se kertoo MITKÄ testit
feilasivat. Siksi publish- ja status-stepit käyttävät if: always().
Branch protection (PR-gate)
Gitean Settings → Branches → Add Rule:
- Branch:
main - Enable Require Status Checks: päälle
- Status checks: valitse
unit-tests,acc-tests
Monorepo
Monorepossa yhdestä repossa asuu useampi julkaistava komponentti (esim.
api/, frontend/). Ratkaisu on yksinkertainen: jokaiselle komponentille
oma conf-tiedosto, jossa on kaikki komponenttikohtainen tieto. Ei
ylöslyöntejä pipelinessa — pelkkä config_path: riittää.
Ongelmat ja ratkaisut
| Ongelma | Ratkaisu |
|---|---|
| Monta komponenttia, yksi repo — mikä triggeröi? | paths:-filtteri consumer-workflowssa: push: { paths: ['api/**'] } |
| Jokaisella komponentilla oma versio | VERSION_FILE=api/package.json conf-tiedostossa, check-version.yml lukee tämän |
| Git-tägit sekaisin ellei nimiavaruutta | GIT_TAG_PREFIX=api/ confissa → tägi api/1.2.3 |
| Eri julkaisutahdit — api voi mennä 3.1 samalla kun frontend on 1.5 | Riippumattomat CI-triggerit, omat versiopolut |
Kaikki komponenttikohtainen tieto on conf-tiedostossa. config-provider.yml
lukee confin sellaisenaan → GIT_TAG_PREFIX, VERSION_FILE, DOCKER_IMAGE_NAME
menevät env_json:ään automaattisesti. check-version.yml ja
docker-build-push.yml lukevat ne sieltä.
Komponenttikohtainen conf-tiedosto
Kaikki conf-tiedostot ovat .gitea/workflows/-kansiossa, komponenttikohtaisesti
nimettynä:
.gitea/workflows/api.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=agent-platform-api
DOCKER_UI_URL=https://gitea.example.com/myorg/-/packages/container
GIT_TAG_PREFIX=api/
VERSION_FILE=api/package.json
.gitea/workflows/frontend.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=agent-platform-frontend
DOCKER_UI_URL=https://gitea.example.com/myorg/-/packages/container
GIT_TAG_PREFIX=frontend/
VERSION_FILE=frontend/package.json
Consumer-workflow monorepolle
Jokainen komponentti saa oman CI-tiedoston. Ainoa parametri on config_path:
ci-api-main.yml:
name: CI API Main
on:
push:
branches:
- main
paths:
- 'api/**'
jobs:
load-config:
uses: org/gitea-ci-library/.gitea/workflows/config-provider.yml@v1
secrets: inherit
with:
config_path: .gitea/workflows/api.gitea-env.conf
check-version:
needs: [load-config]
uses: org/gitea-ci-library/.gitea/workflows/check-version.yml@v1
secrets: inherit
with:
env_json: ${{ needs.load-config.outputs.env_json }}
unit-tests:
needs: [load-config, check-version]
if: needs.check-version.outputs.artifact_exists != 'true'
uses: ./.gitea/workflows/ci-api-tests.yml@main
secrets: inherit
with:
env_json: ${{ needs.load-config.outputs.env_json }}
build-push:
needs: [load-config, check-version, unit-tests]
if: needs.check-version.outputs.artifact_exists != 'true'
uses: org/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 api/0.2.3 ei sekoitu frontendin tägiin frontend/1.5.0 —
vaikka molemmat asuvat samassa repossa.
check-version.yml suodattaa ja laskee seuraavan patchin vain kyseisen
komponentin etuliitteellä. Kun api/:n package.json on 0.2 ja tägit
ovat api/0.2.0, api/0.2.1 → seuraava on api/0.2.2. Frontendin
1.5.0 jätetään huomiotta tässä laskennassa — eri komponentti, täysin
itsenäinen.
Artifaktin tallennus ja idempotenttius
Idempotenttius toimii komponenttikohtaisesti: jos commitilla on jo
api/0.2.3-tägi, api:n pipeline skipataan if: artifact_exists != 'true'.
Frontendin tägit eivät vaikuta api:n idempotenttiuteen — jokainen
komponentti tarkistaa vain omat täginsä.
Mitä EI kannata tehdä
- Älä aja kaikkia komponentteja samasta triggeristä —
paths:pitää CI:t erillisinä ja julkaisutahdit itsenäisinä - Älä käytä samaa versionhallintatiedostoa usealle komponentille — jokaisella
oma
package.json/VERSION - Älä sekoita
DOCKER_UI_URL:ään image-nimeä confissa — URL on puhdas container-registryn osoite, image-nimi lisätään automaattisesti - Älä anna monorepo-parametreja
config-provider.yml:n kautta — kaikki kuuluu komponentin omaan conf-tiedostoon
Raporttien koonti (Gitea 1.27+)
Kun Gitea päivittyy versioon 1.27, GITHUB_STEP_SUMMARY-tuki mahdollistaa
raporttilinkkien koontinäkymän suoraan Gitea UI:ssa. report-summary-jobi
on mukana molemmissa reititinesimerkeissä yllä — forward-compatibeli, ei
hajota vanhemmilla versioilla.
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 |
report-summary.yml |
GITHUB_STEP_SUMMARY-taulukko raporttilinkeillä |
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
Nämä säännöt on formalisoitu docs/adr/-hakemistossa. Tässä tiivistelmä consumer-näkökulmasta:
Reititin ei sisällä suorittavaa koodia (ADR 0010)
ci-feature.yml ja ci-main.yml ovat puhtaita reitittimiä:
- Vain
uses:,needs:jaif:sallittu - Ei
run:-komentoja, ei inline-skriptejä, eiactions/checkout
Kaikki suorittava koodi on omissa workflow_call-tiedostoissaan:
ci-unit-tests.yml— testikomento, publish, statusci-acc-tests.yml— testikomento, publish, status- Provider-workflowt (
config-provider.yml,check-version.yml, …)
Yksi steppi = yksi workflow_call-tiedosto
Jokainen pipeline-steppi (testityyppi, build, deploy) on oma tiedostonsa. Ei kahta eri komentoa samassa workflow'ssa. Tämä pitää reitittimet ohuina ja steppitiedostot itsenäisinä — testattavissa erikseen.
Provider-versio on @v1 (ADR 0009)
Kaikki org/gitea-ci-library/…-viittaukset käyttävät @v1-tagia:
uses: org/gitea-ci-library/.gitea/workflows/config-provider.yml@v1
@main on vain providerin oman repon sisäiseen dogfood-käyttöön.
Breaking changet on kielletty — v1-rajapinta on pysyvä.
Exit-koodi on ainoa onnistumisen mittari (ADR 0008)
Älä käytä pipeä (|) komennon perässä — se syö exit-koodin.
Käytä redirectiä (> file 2>&1) jos haluat logit talteen.
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ä. Consumer käyttää
providerin määrittelemää polkua (.ci/scripts/). Consumer ei kopioi eikä
muokkaa providerin tiedostoja.
Testattavuus
Jokainen workflow_call-tiedosto on testattavissa itsenäisesti — consumer
voi ajaa ci-unit-tests.yml:n paikallisesti act:lla tai Gitean
workflow_dispatch:llä ilman koko pipelineä.