# Consumer Pipelines — Reference Mallipohjat, esimerkit ja konfiguraatiot. Katso säännöt `SKILL.md`:stä. ## Reititin — täydellinen esimerkki ```yaml jobs: load-config: uses: /gitea-ci-library/.gitea/workflows/config-provider.yml@v1 secrets: inherit : needs: [load-config] uses: ./.gitea/workflows/..yml secrets: inherit with: env_json: ${{ needs.load-config.outputs.env_json }} : needs: [load-config] uses: ./.gitea/workflows/..yml secrets: inherit with: env_json: ${{ needs.load-config.outputs.env_json }} report-summary: needs: [load-config, , ] if: always() uses: /gitea-ci-library/.gitea/workflows/report-summary.yml@v1 with: env_json: ${{ needs.load-config.outputs.env_json }} suites: ``` ## 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. ```yaml name: CI Container Build on: workflow_dispatch: inputs: config_path: required: true type: string default: '.gitea/workflows/.gitea-env.conf' description: 'Polku .gitea-env.conf-tiedostoon' dockerfile_path: required: true type: string default: '/Dockerfile.ci-' description: 'Polku Dockerfileen' image_name: required: true type: string default: 'ci-' description: 'Kontin nimi ilman registry-polkua' tag: required: true type: string default: 'latest' description: 'Image-tägi' jobs: load-config: uses: /gitea-ci-library/.gitea/workflows/config-provider.yml@v1 secrets: inherit with: config_path: ${{ inputs.config_path }} build-push: needs: [load-config] uses: /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. ```yaml jobs: : runs-on: ubuntu-latest container: image: ${{ inputs. }} steps: - uses: actions/checkout@v4 - uses: actions/checkout@v4 with: repository: /gitea-ci-library path: .ci - name: Run shell: bash run: | mkdir -p "reports/" > "reports//results.txt" 2>&1 - name: Post-process reports if: always() run: | - name: Report if: always() run: bash .ci/scripts/ci-report.sh "" ${{ 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 ` 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ä ```yaml - name: Run tests shell: bash run: | mkdir -p "reports/" - name: Report if: always() run: bash .ci/scripts/ci-report.sh "" ${{ job.status }} ``` ### Taso 2: Jälkikäsittely tarvitaan ```yaml - name: Run tests shell: bash run: | mkdir -p "reports/" > "reports//results.txt" 2>&1 - name: Post-process coverage if: always() run: /coverage/-hakemistoon> - name: Post-process test report if: always() run: - name: Report if: always() run: bash .ci/scripts/ci-report.sh "" ${{ job.status }} ``` ### Väärin vs oikein — yksi asia per step ```yaml # 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 }} ``` ### Väärin vs oikein — post-process ```yaml # 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//`-hakemistoa. ### Mitä skannataan | Mitä | Sääntö | |---|---| | **Tiedostot (FILES)** | Kaikki `reports//`-juuressa olevat tiedostot paitsi `index.html` | | **Alihakemistot (SUBDIRS)** | Vain ne, joissa on `index.html` | ### Julkaisukelpoisuus | Tila | Seuraus | |---|---| | `FILES + SUBDIRS = 0` | **Failure** — `ci-report.sh` palauttaa virheen, raporttia ei julkaista | | `FILES + SUBDIRS = 1` | Suora linkki itemiin — ei generoi index-sivua | | `FILES + SUBDIRS > 1` | Generoi `reports//index.html`-sivun, linkit kaikkiin itemeihin | ### Hakemistorakenne ``` reports// ├── results.txt ← testin stdout (skannataan FILES) ├── test-report.html ← generoitu HTML (skannataan FILES) └── / ← alihakemisto (skannataan SUBDIRS) └── index.html ← VAIN jos tämä on olemassa ``` ### Esimerkki: coverage-näkymä ``` reports//coverage/index.html ← on olemassa ``` Coverage-dataa ei siirretä automaattisesti. Testin tai post-process-stepin pitää siirtää coverage `reports//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//`-hakemistoon — `ci-report.sh` päättää julkaisukelpoisuuden ja generoi tarvittavan navigaation. ## Debug-ohje: raportti ei näy ### 1. Aja lokaalisti samalla komennolla kuin CI ```bash 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 ```bash 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 ```ini # .gitea/workflows/gitea-env.conf GITEA_API_URL=https://gitea.example.com GIT_PAGES_URL=https://reports.example.com ``` ### Docker-artifaktin buildaavat projektit ```ini 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 ```ini 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/.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=/package.json` confissa | | Git-tägit sekaisin ellei nimiavaruutta | `GIT_TAG_PREFIX=/` confissa → tägi `/1.2.3` | | Eri julkaisutahdit | Riippumattomat CI-triggerit, omat versiopolut | ### Komponenttikohtainen conf ```ini # .gitea/workflows/.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= DOCKER_UI_URL=https://gitea.example.com/myorg/-/packages/container GIT_TAG_PREFIX=/ # Jompikumpi — JSON (.version-kenttä) tai plain text: VERSION_FILE=/package.json #VERSION_FILE=/VERSION ``` ### Monorepo reititin ```yaml name: CI Main on: push: branches: - main paths: - /** - .gitea/workflows/.* jobs: load-config: uses: /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: /gitea-ci-library/.gitea/workflows/check-version.yml@v1 secrets: inherit with: env_json: ${{ needs.load-config.outputs.env_json }} : needs: [load-config, check-version] if: needs.check-version.outputs.artifact_exists != 'true' uses: ./.gitea/workflows/..yml secrets: inherit with: env_json: ${{ needs.load-config.outputs.env_json }} build-push: needs: [load-config, check-version, ] if: needs.check-version.outputs.artifact_exists != 'true' uses: /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: /gitea-ci-library/.gitea/workflows/report-summary.yml@v1 with: env_json: ${{ needs.load-config.outputs.env_json }} suites: ' ' ``` ### Version elinkaari per komponentti `GIT_TAG_PREFIX` takaa että eri komponenttien versiohistoria pysyy erillään. Git-tägi `/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) | ``-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 "" ${{ 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ä) |