Files
gitea-ci-library/skills/consumer-pipelines/REFERENCE.md
T
niko a5947551d4
CI Main / Load example-gitea-env.conf to pipeline env (push) Successful in 22s
CI Main / Check existing artifact (push) Successful in 20s
CI Git-Pages Main / Load git-pages.gitea-env.conf to pipeline env (push) Successful in 45s
CI Git-Pages Main / Check existing artifact (push) Successful in 31s
ci-helm-build-push Helm push 0.1.4
CI Main / Cucumber tests (push) Successful in 1m10s
CI Git-Pages Main / Build & Push Helm chart (push) Successful in 49s
CI Git-Pages Main / Report Summary (push) Successful in 5s
CI Main / Bats tests (push) Successful in 1m34s
ci-docker-build-push Docker push 0.2.21
CI Main / Build & Push Docker (push) Successful in 48s
CI Main / Report Summary (push) Successful in 6s
CI Main / Move provider version tag (push) Successful in 14s
CI Feature / Load example-gitea-env.conf to pipeline env (push) Successful in 33s
acc-tests Cucumber test report
CI Feature / Cucumber tests (push) Successful in 1m23s
unit-tests Bats test report
CI Feature / Bats tests (push) Successful in 1m34s
CI Feature / Report Summary (push) Successful in 5s
Fix/gitea commit status naming (#36)
Co-authored-by: moilanik <niko.moilanen@tietoevry.com>
Reviewed-on: #36
2026-06-21 08:43:32 +03:00

19 KiB

Consumer Pipelines — Reference

Mallipohjat, esimerkit ja konfiguraatiot. Katso säännöt SKILL.md:stä.

Pre-cache-esimerkit (Offline Container)

Alla Dockerfile-esimerkit kielikohtaisista pre-cacheista. Kaikki ajetaan build-vaiheessa — kontti on täysin itseriittoinen eikä lataa mitään pipeline- tai runtime-vaiheessa.

Go

FROM golang:1.24-alpine AS deps
WORKDIR /build
COPY go.mod go.sum ./
RUN go mod download

FROM deps AS test-build
COPY . .
RUN go test -c -o /tmp/test.bin ./...

FROM alpine:3.21
RUN apk add --no-cache git nodejs
COPY --from=deps /go/pkg/mod /go/pkg/mod
COPY --from=test-build /tmp/test.bin /usr/local/bin/test

Node.js

FROM node:22-alpine AS deps
WORKDIR /build
COPY package.json package-lock.json ./
RUN npm ci --omit=dev

FROM node:22-alpine
RUN apk add --no-cache git
COPY --from=deps /build/node_modules /app/node_modules
COPY . /app
WORKDIR /app

Java / Maven

FROM maven:3.9-eclipse-temurin-21 AS deps
WORKDIR /build
COPY pom.xml ./
RUN mvn dependency:go-offline -B

FROM maven:3.9-eclipse-temurin-21 AS build
COPY --from=deps /root/.m2 /root/.m2
COPY . .
RUN mvn package -B -DskipTests

FROM eclipse-temurin:21-jre
RUN apt-get update && apt-get install -y --no-install-recommends git && rm -rf /var/lib/apt/lists/*
COPY --from=build /build/target/*.jar /app/app.jar
WORKDIR /app

Python

FROM python:3.12-alpine AS deps
WORKDIR /build
COPY requirements.txt ./
RUN pip wheel --wheel-dir=/wheels -r requirements.txt

FROM python:3.12-alpine
RUN apk add --no-cache git
COPY --from=deps /build/wheels /wheels
COPY --from=deps /build/requirements.txt /
RUN pip install --no-index --find-links=/wheels -r /requirements.txt && rm -rf /wheels
COPY . /app
WORKDIR /app

Helm + Node.js (korvaa helm-build-push.yml:n runtime-apk)

FROM alpine/helm:3.16.0 AS helm-bin
FROM node:22-alpine
RUN apk add --no-cache git
COPY --from=helm-bin /usr/bin/helm /usr/local/bin/helm

Tämä kontti korvaa helm-build-push.yml:n alpine/helm:3.19.0-image-riippuvuuden ja poistaa tarpeen asentaa node.js runtime-vaiheessa.

Reititin — täydellinen 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>

CI-kontin build — parametroitu workflow

CI-kontin build on workflow_dispatch-triggeröity job, joka näkyy Gitea Actionsissa kuten Jenkinsin parametroitu job — käyttäjä antaa inputit UI:sta ennen ajoa.

name: CI Container Build <työkalu>
on:
  workflow_dispatch:
    inputs:
      config_path:
        required: true
        type: string
        default: '.gitea/workflows/<komponentti>.gitea-env.conf'
        description: 'Polku .gitea-env.conf-tiedostoon'
      dockerfile_path:
        required: true
        type: string
        default: '<komponentti>/Dockerfile.ci-<työkalu>'
        description: 'Polku Dockerfileen'
      image_name:
        required: true
        type: string
        default: 'ci-<työkalu>'
        description: 'Kontin nimi ilman registry-polkua'
      tag:
        required: true
        type: string
        default: 'latest'
        description: 'Image-tägi'

jobs:
  load-config:
    uses: <owner>/gitea-ci-library/.gitea/workflows/config-provider.yml@v1
    secrets: inherit
    with:
      config_path: ${{ inputs.config_path }}

  build-push:
    needs: [load-config]
    uses: <owner>/gitea-ci-library/.gitea/workflows/ci-container-build-push.yml@v1
    secrets: inherit
    with:
      env_json: ${{ needs.load-config.outputs.env_json }}
      dockerfile_path: ${{ inputs.dockerfile_path }}
      image_name: ${{ inputs.image_name }}
      tag: ${{ inputs.tag }}

CI-kontin ajaminen testijobissa

Ainoa sallittu tapa consumer-puolella on container:-direktiivi. docker run komennolla kontin käynnistäminen stepin sisällä on anti-pattern. container:-direktiivillä kaikki stepit ajetaan samassa kontissa — tiedostot ovat suoraan filesystemillä eikä erillistä volyyminhallintaa tarvita.

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/<suite>"
          <komento> > "reports/<suite>/results.txt" 2>&1

      - name: Post-process reports
        if: always()
        run: |
          <mahdollinen_raporttien_jälkikäsittely>

      - name: Report
        if: always()
        run: |
          bash .ci/scripts/ci-report.sh "<Test type> test report" <context> <suite> ${{ job.status }}

Monorepossa context ja description sisältävät komponentin nimen:

      - name: Report
        if: always()
        run: |
          bash .ci/scripts/ci-report.sh "<Komponentti>: <Test type> test report" <komponentti>.<context> <suite> ${{ job.status }}

Usean runnerin cache-ongelma: Jos eri kerroilla käynnistyy eri runnereita, niillä voi olla eri versio latest-imagen digesteistä. Ratkaisuja:

  • Rebuildaa kontti ja aja docker pull <image> manuaalisesti kaikilla runnereilla
  • Käytä versioitua tagia (v2, v3, ...) ja päivitä workflow'n default buildauksen jälkeen

Mallit:

  • example-cucumber-tests.yml — ei post-processia
  • example-bats-tests.yml — post-process coverage + report

Raporttitasot — tarkat YAML-mallit

Taso 1: Ei jälkikäsittelyä

Single repo:

- name: Run tests
  shell: bash
  run: |
    mkdir -p "reports/<suite>"
    <testikomento>

- name: Report
  if: always()
  run: |
    bash .ci/scripts/ci-report.sh "<Test type> test report" <context> <suite> ${{ job.status }}

Monorepo:

- name: Run tests
  shell: bash
  run: |
    mkdir -p "reports/<suite>"
    <testikomento>

- name: Report
  if: always()
  run: |
    bash .ci/scripts/ci-report.sh "<Komponentti>: <Test type> test report" <komponentti>.<context> <suite> ${{ job.status }}

Taso 2: Jälkikäsittely tarvitaan

Single repo:

- name: Run tests
  shell: bash
  run: |
    mkdir -p "reports/<suite>"
    <testikomento> > "reports/<suite>/results.txt" 2>&1

- name: Post-process coverage
  if: always()
  run: <siirrä coverage-data reports/<suite>/coverage/-hakemistoon>

- name: Post-process test report
  if: always()
  run: <HTML-generointi raa'asta outputista>

- name: Report
  if: always()
  run: |
    bash .ci/scripts/ci-report.sh "<Test type> test report" <context> <suite> ${{ job.status }}

Monorepo:

- name: Run tests
  shell: bash
  run: |
    mkdir -p "reports/<suite>"
    <testikomento> > "reports/<suite>/results.txt" 2>&1

- name: Post-process coverage
  if: always()
  run: <siirrä coverage-data reports/<suite>/coverage/-hakemistoon>

- name: Post-process test report
  if: always()
  run: <HTML-generointi raa'asta outputista>

- name: Report
  if: always()
  run: |
    bash .ci/scripts/ci-report.sh "<Komponentti>: <Test type> test report" <komponentti>.<context> <suite> ${{ job.status }}

Väärin vs oikein — yksi asia per step

# VÄÄRIN — helm template fail → kubeconform jää ajamatta, report jää tekemättä
- name: Run tests
  run: |
    helm template ... > /tmp/manifests.yaml
    kubeconform ... > results.txt 2>&1

# OIKEIN — erilliset stepit
- name: Helm template
  run: helm template platform-helm/ -f values.yaml > /tmp/manifests.yaml 2>&1

- name: Kubeconform
  if: success()
  run: |
    mkdir -p reports/kubeconform
    kubeconform ... > reports/kubeconform/results.txt 2>&1

- name: Report
  if: always()
  run: |
    bash .ci/scripts/ci-report.sh "Helm kubeconform" helm-test kubeconform ${{ job.status }}

Monorepossa:

- name: Report
  if: always()
  run: |
    bash .ci/scripts/ci-report.sh "<Komponentti>: Helm kubeconform" <komponentti>.helm-test kubeconform ${{ job.status }}

Väärin vs oikein — post-process

# VÄÄRIN — jos coverage epäonnistuu, report jää generoimatta
- name: Post-process reports
  run: |
    bash .ci/.gitea/scripts/bats-coverage.sh reports/bats
    bash .ci/.gitea/scripts/bats-report.sh reports/bats

# OIKEIN — erilliset stepit if: always()
- name: Post-process coverage
  if: always()
  run: bash .ci/.gitea/scripts/bats-coverage.sh reports/bats

- name: Post-process test report
  if: always()
  run: bash .ci/.gitea/scripts/bats-report.sh reports/bats

Raportin julkaisukelpoisuus

ci-report.sh päättää onko raportti julkaisukelpoinen skannaamalla reports/<suite>/-hakemistoa.

Mitä skannataan

Mitä Sääntö
Tiedostot (FILES) Kaikki reports/<suite>/-juuressa olevat tiedostot paitsi index.html
Alihakemistot (SUBDIRS) Vain ne, joissa on index.html

Julkaisukelpoisuus

Tila Seuraus
FILES + SUBDIRS = 0 Failureci-report.sh palauttaa virheen, raporttia ei julkaista
FILES + SUBDIRS = 1 Suora linkki itemiin — ei generoi index-sivua
FILES + SUBDIRS > 1 Generoi reports/<suite>/index.html-sivun, linkit kaikkiin itemeihin

Hakemistorakenne

reports/<suite>/
├── results.txt               ← testin stdout (skannataan FILES)
├── test-report.html          ← generoitu HTML (skannataan FILES)
└── <mikä tahansa>/           ← alihakemisto (skannataan SUBDIRS)
    └── index.html            ← VAIN jos tämä on olemassa

Esimerkki: coverage-näkymä

reports/<suite>/coverage/index.html   ← on olemassa

Coverage-dataa ei siirretä automaattisesti. Testin tai post-process-stepin pitää siirtää coverage reports/<suite>/coverage/-hakemistoon ja varmistaa että index.html on mukana.

Provider vastuulla: ci-report.sh (provider-skripti) hoitaa sekä hakemistorakenteen skannauksen, index.html-generoinnin että julkaisun git-pagesiin. Consumer tuottaa vain raakatiedostot reports/<suite>/-hakemistoon — ci-report.sh päättää julkaisukelpoisuuden ja generoi tarvittavan navigaation.

Debug-ohje: raportti ei näy

1. Aja lokaalisti samalla komennolla kuin CI

mkdir -p reports/bats
bashcov -- bats tests/ > reports/bats/results.txt 2>&1
echo "exit: $?"
ls -la reports/bats/

2. Lisää echo "DEBUG: ..." >&2 ennen ja jälkeen kriittisen operaation

echo "DEBUG: coverage exists? $([ -d coverage ] && echo YES || echo NO)" >&2
echo "DEBUG: target/index.html exists? $([ -f reports/suite/coverage/index.html ] && echo YES || echo NO)" >&2

3. Tarkista kutsuparametrit

Yleisin virhe: skripti odottaa $1 = X, mutta kutsuja antaa $1 = Y ja $2 = X.

4. Tarkista tiedostopolut

  1. Onko lähdetiedosto olemassa ennen kopiointia?
  2. Onko kohde olemassa kopioinnin jälkeen?
  3. Onko index.html subdirissä (vaaditaan ci-report.sh:lle)?

5. Poista debug-echot kun ongelma on korjattu

6. Älä kokeile — debuggaa

Kokeilu = arvaus. Debuggaus = lisää echo, aja, lue logi, eristä ongelma. Vasta sitten korjaa.

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

Helm-artifaktin buildaavat projektit

HELM_REGISTRY=gitea.example.com/myorg
GIT_TAG_PREFIX=git-pages/
VERSION_FILE=git-pages/Chart.yaml
Kenttä Pakollinen Kuvaus
HELM_REGISTRY kyllä Registry host + owner, esim. gitea.example.com/myorg. Tyhjä pysäyttää workflow'n.
GIT_TAG_PREFIX ei Etuliite git-tägille. Pakollinen monorepossa.
VERSION_FILE ei Polku version lähteeseen. Oletus: juuren Chart.yaml.

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
HELM_USER Vain jos pushaat Helm chartin OCI-rekisteriin (oletus github.actor)
HELM_PASSWORD Vain jos pushaat Helm chartin OCI-rekisteriin

Monorepo

Monorepossa yhdessä repossa asuu useampi julkaistava komponentti. Jokaiselle komponentille oma conf-tiedosto .gitea/workflows/<komponentti>.gitea-env.conf.

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.

Ongelmat ja ratkaisut

Ongelma Ratkaisu
Monta komponenttia, yksi repo — mikä triggeröi? paths:-filtteri: komponentin hakemisto + sen CI-workflow't ja conf-tiedosto
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>/**
      - .gitea/workflows/<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 }}

  report-summary:
    name: Report Summary
    needs: [load-config, build-push]
    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>'

Commit status -kontekstit monorepossa: Testiraporttien ci-report.sh-kutsussa context ja description sisältävät komponentin nimen:

      - name: Report
        if: always()
        run: |
          bash .ci/scripts/ci-report.sh "<Komponentti>: Unit test report" <komponentti>.unit-tests bats ${{ job.status }}

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
  • Älä rajaa paths: pelkkään komponentin hakemistoon — CI ei triggeröidy workflow- tai conf-muutoksista

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
helm-build-push.yml Paketoi + puskea Helm chartin OCI-rekisteriin, tagittaa commitin
report-summary.yml GITHUB_STEP_SUMMARY-taulukko raporttilinkeillä (Gitea 1.27+)

Skriptit (kutsutaan .ci/scripts/-polun kautta)

Skripti Käyttötarkoitus
ci-report.sh Yhdistetty raportointi: julkaisee git-pagesiin ja asettaa commit-statuksen. Korvaa erilliset publish-git-pages.sh + report-status.sh -kutsut. Käyttö: bash .ci/scripts/ci-report.sh "<kuvaus>" <context> <suite> ${{ job.status }}
report-status.sh POSTaa commit-statuksen linkillä (kutsutaan ci-report.sh:n sisältä)
publish-git-pages.sh Julkaisee raporttihakemiston git-pagesiin (kutsutaan ci-report.sh:n sisältä)
ci-validate.sh Validoi .conf-tiedoston (kutsutaan config-provider.yml:stä)