Files
niko 65d385f9b9
CI Main / Load example-gitea-env.conf to pipeline env (push) Successful in 17s
CI Main / Check existing artifact (push) Successful in 13s
unit-tests Link to Bats reports
CI Main / Bats tests (push) Successful in 1m35s
acc-tests Link to Cucumber reports
CI Main / Cucumber tests (push) Successful in 54s
ci-docker-build-push Docker build & push 0.2.8 OK
CI Main / Build & Push Docker (push) Successful in 40s
CI Main / Report Summary (push) Successful in 6s
CI Main / Move provider version tag (push) Successful in 13s
skill päivitetty (#21)
Co-authored-by: moilanik <niko.moilanen@tietoevry.com>
Reviewed-on: #21
2026-06-17 17:02:44 +03:00

16 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
    secrets: inherit
    with:
      env_json: ${{ needs.load-config.outputs.env_json }}

  <test-2>:
    needs: [load-config]
    uses: ./.gitea/workflows/<component>.<test-2>.yml
    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

  1. Julkiset registry-kontit kiinteällä versiollaalpine/helm:3.19.0, node:22, maven:3.9-eclipse-temurin-21. Toistettavuus ja turvallisuus eivät saa riippua ulkoisesta latest:sta
  2. Projektin omat CI-kontit latest-tägillä — buildattu ci-container-build-<kontti>.yml:llä. Kontin build-pipeline päivittää latest:n automaattisesti. Rebuild = käyttöönotto kaikissa pipelineissa ilman versioviittauksien päivittelyä. latest on näille paras käytäntö, ei kompromissi
  3. 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.

4.1 CI-kontin ajaminen jobissa

CI-kontin voi ajaa joko container:-direktiivillä (kaikki stepit kontissa) tai docker run --rm:llä stepin sisällä (checkout natiivisti). Molemmat tavat toimivat.

# Tapa A: container:-direktiivi
jobs:
  <työkalu>:
    runs-on: ubuntu-latest
    container:
      image: ${{ inputs.<image-name> }}
    steps:
      - uses: actions/checkout@v4
      - uses: actions/checkout@v4
        with:
          repository: <owner>/gitea-ci-library
          path: .ci
      - name: Run <työkalu>
        shell: bash
        run: |
          mkdir -p "reports/${GITHUB_SHA:0:8}/<suite>"
          <komento> > "reports/${GITHUB_SHA:0:8}/<suite>/results.txt" 2>&1
          EXIT=$?
          echo "EXIT=${EXIT}" >> "${GITHUB_ENV}"
          exit ${EXIT}
# Tapa B: docker run --rm stepin sisällä (kuten example-bats-tests.yml)
jobs:
  <työkalu>:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/checkout@v4
        with:
          repository: <owner>/gitea-ci-library
          path: .ci

      - name: Run <työkalu>
        shell: bash
        run: |
          docker volume create ws-<suite>
          tar c . | docker run --rm -i -v ws-<suite>:/data alpine tar x -C /data
          mkdir -p "reports/${GITHUB_SHA:0:8}/<suite>"
          set +e
          docker run --rm \
            -v ws-<suite>:/data \
            --entrypoint bash ${{ inputs.<image-name> }} \
            -c 'cd /data && <komento>' \
            > "reports/${GITHUB_SHA:0:8}/<suite>/results.txt" 2>&1
          EXIT=$?
          docker volume rm ws-<suite> > /dev/null 2>&1
          echo "EXIT=${EXIT}" >> "${GITHUB_ENV}"
          exit ${EXIT}

      - name: Publish <suite> reports
        if: always()
        run: bash .ci/scripts/publish-git-pages.sh <suite>

      - name: Report status
        if: always()
        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

Malli: example-bats-tests.yml (tapa B).

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
    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ä.

Paikalliset uses: eivät käytä refiä

Gitea act runner v1.0.8 muodostaa paikallisista uses: ./.gitea/workflows/*.yml@main-viittauksista epävalidin git-refin main@<sha>, joka aiheuttaa virheen Revision invalid : reference must be defined once at the beginning.

Paikallisista uses:-direktiiveistä EI koskaan käytetä @main- tai muuta ref-päätettä:

  • uses: ./.gitea/workflows/chart.helm-lint.yml ← oikein
  • uses: ./.gitea/workflows/chart.helm-lint.yml@main ← väärin

Ilman refiä runner käyttää workflow'ta triggeröivästä commitista. Ulkoisten repojen viittauksissa (niko/...@v1) pääte pysyy. Nämä resolvoidaan eri reittiä ja toimivat oikein.

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.