279 lines
9.4 KiB
Markdown
279 lines
9.4 KiB
Markdown
# Konfiguraatiomalli — `ci-flow-values.yaml`
|
|
|
|
> Kuuluu arkkitehtuuriin: [architecture.md](architecture.md). Tämä dokumentti määrittelee projektikohtaisen konfiguraation skeeman, `isContainerBuild()`-mekanismin ja version check -skriptin.
|
|
|
|
---
|
|
|
|
## Miksi redesign
|
|
|
|
Jenkins-version `ci-flow-values.yaml` oli rakennettu Jenkinsin ympäristömuuttuja- ja credential-mallin ympärille. Gitea Actionsissa konfiguraatio luetaan suoraan YAML:sta workflow'n sisällä — ei tarvita env-muuttujien kautta kierrättämistä. Lisäksi:
|
|
|
|
- `creditentials`-viittaukset korvautuvat Gitea org secrets/variables -mekanismilla
|
|
- `test-flow`-syntaksi yksinkertaistuu (ei enää JSON-serialisointia env-muuttujiin)
|
|
- Docker/NPM-rekisterit MVP:ssä vain Gitea Packages — factory/adapter-pattern valmiina laajennukselle
|
|
- `sonarqube`-konfiguraatio pysyy samankaltaisena
|
|
|
|
---
|
|
|
|
## Skeema
|
|
|
|
```yaml
|
|
# ci-flow-values.yaml — projektin juuressa
|
|
#
|
|
# Pakolliset osiot: docker (jos master-branch buildaa kontin), test-flow (jos ketjutetaan)
|
|
# Vapaaehtoiset: sonarqube, deployment
|
|
|
|
docker:
|
|
registry: gitea # gitea | artifactory | nexus (MVP: vain gitea)
|
|
imageName: temperature-store # kontin nimi, pakollinen
|
|
|
|
sonarqube:
|
|
url: https://sonar.example.com
|
|
projectKey: temperature-store
|
|
|
|
deployment:
|
|
jobName: deploy # deploy-workflown nimi (vakio)
|
|
projectFolder: microservices # polku Helm-repossa
|
|
fileName: values-{.environment}.yaml
|
|
property: container.version
|
|
|
|
test-flow:
|
|
- deploy: development # 1. deploy development-ympäristöön
|
|
wait: true # odota deployn valmistumista
|
|
|
|
- test:
|
|
name: "integration fast"
|
|
environment: integration
|
|
repo: tests/integration # testi-repo (owner/repo)
|
|
workflow: test.yml # workflow-tiedosto testi-repossa
|
|
ref: main # branch
|
|
tags: "@temperature and not @slow"
|
|
|
|
- deploy: staging
|
|
wait: true
|
|
|
|
- test:
|
|
name: e2e
|
|
environment: staging
|
|
repo: tests/e2e
|
|
workflow: test.yml
|
|
ref: main
|
|
tags: "@e2e and not @slow"
|
|
```
|
|
|
|
### Kenttäkuvaukset
|
|
|
|
#### `docker`
|
|
|
|
| Kenttä | Pakollinen | Kuvaus |
|
|
|--------|------------|--------|
|
|
| `registry` | Ei (oletus `gitea`) | Rekisterityyppi. MVP: `gitea`. Factory/adapter-pattern avaa `artifactory`, `nexus` myöhemmin |
|
|
| `imageName` | Kyllä | Kontin nimi. Lopullinen tagi: `{gitea_host}/{owner}/{imageName}:{version}.{run_number}` |
|
|
|
|
#### `sonarqube`
|
|
|
|
| Kenttä | Pakollinen | Kuvaus |
|
|
|--------|------------|--------|
|
|
| `url` | Kyllä | SonarQube-palvelimen URL |
|
|
| `projectKey` | Kyllä | SonarQube-projektin avain |
|
|
|
|
SonarQube-token tulee Gitea org secretsista (`SONAR_TOKEN`). Ei `creditentials`-viittausta.
|
|
|
|
#### `deployment`
|
|
|
|
| Kenttä | Pakollinen | Kuvaus |
|
|
|--------|------------|--------|
|
|
| `jobName` | Ei (oletus `deploy`) | Deploy-workflown tiedostonimi ilman `.yml`-päätettä |
|
|
| `projectFolder` | Kyllä | Polku mikropalvelun kansioon Helm-repossa |
|
|
| `fileName` | Kyllä | YAML-tiedoston nimi. `{.environment}` korvataan ympäristön nimellä |
|
|
| `property` | Kyllä | Päivitettävä avain (piste-eroteltu polku, esim. `container.version`) |
|
|
|
|
Deploy-token (kirjoitusoikeus Helm-repoon) tulee Gitea org secretsista (`DEPLOY_TOKEN`).
|
|
|
|
#### `test-flow`
|
|
|
|
Array testi-steppejä. Jokainen steppi on joko `deploy` tai `test`.
|
|
|
|
**`deploy`-steppi:**
|
|
|
|
| Kenttä | Pakollinen | Kuvaus |
|
|
|--------|------------|--------|
|
|
| `deploy` | Kyllä | Ympäristön nimi (esim. `development`, `staging`) |
|
|
| `wait` | Ei (oletus `true`) | Odotetaanko deployn valmistumista ennen seuraavaa steppiä |
|
|
|
|
**`test`-steppi:**
|
|
|
|
| Kenttä | Pakollinen | Kuvaus |
|
|
|--------|------------|--------|
|
|
| `name` | Kyllä | Testivaiheen nimi (näkyy statusviestissä) |
|
|
| `environment` | Kyllä | Ympäristö jota vasten testataan |
|
|
| `repo` | Kyllä | Testi-repo muodossa `owner/repo` |
|
|
| `workflow` | Kyllä | Workflow-tiedosto testi-repossa |
|
|
| `ref` | Kyllä | Branch (esim. `main`) |
|
|
| `tags` | Ei | Cucumber-tagit (esim. `"@smoke and not @slow"`) |
|
|
| `versionApiUrl` | Ei | URL deployed-version tarkistukseen |
|
|
| `versionCheckScript` | Ei | Polku version check -skriptiin (repossa tai kontissa) |
|
|
|
|
---
|
|
|
|
## `isContainerBuild()`-mekanismi
|
|
|
|
**Ongelma:** Samaa committia vasten voidaan ajaa master-workflow useita kertoja. On mieletöntä buildata kontti uudestaan, koska commit on jo tagätty versiolla ja kontti on olemassa rekisterissä. Uudelleenbuildaus aiheuttaa versiokonflikteja ja tuhlaa CI-aikaa.
|
|
|
|
**Ratkaisu:** Workflow'n alussa tarkistetaan, onko tälle commitille jo olemassa versiotagi:
|
|
|
|
```bash
|
|
# is-container-built.sh
|
|
TAG=$(git tag --points-at HEAD | grep -E '^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$' | head -1)
|
|
if [ -n "$TAG" ]; then
|
|
echo "container_already_built=true" >> $GITHUB_ENV
|
|
echo "container_version=$TAG" >> $GITHUB_ENV
|
|
else
|
|
echo "container_already_built=false" >> $GITHUB_ENV
|
|
fi
|
|
```
|
|
|
|
Workflow käyttää tätä ehtona:
|
|
|
|
```yaml
|
|
jobs:
|
|
build-container:
|
|
if: env.container_already_built != 'true'
|
|
steps:
|
|
- run: docker build ...
|
|
test-flow:
|
|
if: always()
|
|
needs: [build-container]
|
|
steps:
|
|
- run: dispatch-workflow.sh ...
|
|
```
|
|
|
|
**Mitä `isContainerBuild() == true` tarkoittaa käytännössä:**
|
|
- Kontti on jo buildattu ja pushattu rekisteriin
|
|
- Commit on tagätty versiolla (esim. `1.2.3.42`)
|
|
- Build-steppi skipataan → siirrytään suoraan test flow'hun
|
|
- Sama versio deployataan ja testataan — ei uutta konttia
|
|
|
|
**Miksi tämä on välttämätöntä:**
|
|
- Estää versiokonfliktit: `1.2.3.42` ei voi olla kahdesti
|
|
- Säästää CI-aikaa: kontin buildaus on hitain vaihe
|
|
- Pitää commitin ja kontin välisen suhteen yksiselitteisenä: `git tag` kertoo suoraan mikä versio vastaa tätä committia
|
|
|
|
---
|
|
|
|
## Docker-labelit
|
|
|
|
Jenkins-versiossa konttiin injektoitiin metadataa Docker-labelien kautta. Sama käytäntö jatkuu:
|
|
|
|
```bash
|
|
docker build \
|
|
--label "git.commit=${GITHUB_SHA::8}" \
|
|
--label "git.commitBy=${GITHUB_ACTOR}" \
|
|
--label "build.date=$(date -u +'%Y-%m-%dT%H:%M:%SZ')" \
|
|
--label "build.run=${GITHUB_RUN_NUMBER}" \
|
|
--label "version=${DOCKER_VERSION}" \
|
|
-t ${DOCKER_TAG} .
|
|
```
|
|
|
|
| Label | Arvo | Lähde |
|
|
|-------|------|-------|
|
|
| `git.commit` | 8-merkkinen hash | `GITHUB_SHA::8` |
|
|
| `git.commitBy` | Ajon laukaisija | `GITHUB_ACTOR` |
|
|
| `build.date` | ISO 8601 UTC | `date -u` |
|
|
| `build.run` | Ajon järjestysnumero | `GITHUB_RUN_NUMBER` |
|
|
| `version` | Kontin versio | `1.2.3.42` |
|
|
|
|
Näillä labeleilla kontista näkee suoraan: kuka buildasi, milloin, mistä commitista, millä versiolla. Vianjäljitys kontista koodiin on suora.
|
|
|
|
---
|
|
|
|
## Version check (Fibonacci-backoff)
|
|
|
|
Ennen kuin testit ajetaan, pitää varmistua että haluttu konttiversio on oikeasti deployattu ympäristöön. Muuten testataan väärää versiota.
|
|
|
|
**Malli:** Skripti, joka pollaa deployatun version API:a Fibonacci-backoffilla:
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
# check-version.sh <version_api_url> <expected_version>
|
|
# Palauttaa 0 jos versiot täsmäävät, 1 muuten.
|
|
|
|
URL=$1
|
|
EXPECTED=$2
|
|
MAX_RETRIES=10
|
|
|
|
# Fibonacci-sekvenssi: 1 2 3 5 8 13 21 34 55 89
|
|
FIB=(1 2 3 5 8 13 21 34 55 89)
|
|
|
|
for i in $(seq 1 $MAX_RETRIES); do
|
|
ACTUAL=$(curl -s "$URL" | jq -r '.version // empty')
|
|
if [ "$ACTUAL" = "$EXPECTED" ]; then
|
|
echo "Version match: $ACTUAL"
|
|
exit 0
|
|
fi
|
|
echo "Attempt $i/$MAX_RETRIES: $ACTUAL != $EXPECTED, waiting ${FIB[$i-1]}s..."
|
|
sleep ${FIB[$i-1]}
|
|
done
|
|
|
|
echo "Version mismatch after $MAX_RETRIES attempts"
|
|
exit 1
|
|
```
|
|
|
|
**Miksi Fibonacci:** Uusi deploy käynnistyy nopeasti (ensimmäiset pollaukset tiheään). Jos kontin pullaus tai podin käynnistys kestää, pollausväli kasvaa — ei turhaan kuormiteta API:a. Maksimiaika: ~231 sekuntia (summa 1..89).
|
|
|
|
Version check -skripti joko:
|
|
- Asuu testi-repossa (projektin oma toteutus) → `versionCheckScript`-kenttä
|
|
- Tai käyttää geneeristä API:a → `versionApiUrl`-kenttä, skripti on osa kirjastoa
|
|
|
|
---
|
|
|
|
## `doNotDowngrade`
|
|
|
|
Jenkinsin deploy-jobissa oli `doNotDowngrade`-parametri, joka esti vanhemman version deployaamisen uudemman päälle. Gitea Actions -versiossa:
|
|
|
|
- **Ei MVP:ssä.** Deploy tekee sen mitä käsketään. `doNotDowngrade` on lisäturva, joka voidaan lisätä deploy-workflow'hun myöhemmin.
|
|
- **Mekanismi:** Ennen YAML:n muokkausta tarkistetaan nykyinen versio. Jos `new < current`, skipataan ja raportoidaan.
|
|
- **Toteutus:** Yksi `if`-ehto deploy-workflow'n alussa, ei vaadi muutoksia muualle.
|
|
|
|
---
|
|
|
|
## UX-esimerkki: projektin `.gitea/workflows/ci.yml`
|
|
|
|
Näin mikropalvelun kehittäjä käyttää kirjastoa:
|
|
|
|
```yaml
|
|
# .gitea/workflows/ci.yml — projektin juuressa
|
|
|
|
name: CI
|
|
|
|
on:
|
|
push:
|
|
branches: ["**"]
|
|
workflow_dispatch:
|
|
|
|
jobs:
|
|
feature:
|
|
if: github.ref != 'refs/heads/master'
|
|
uses: org/gitea-ci-library/.gitea/workflows/ci-feature.yml@v1
|
|
secrets: inherit
|
|
with:
|
|
config-file: ci-flow-values.yaml
|
|
maven-image: maven:3.9-eclipse-temurin-21
|
|
|
|
master:
|
|
if: github.ref == 'refs/heads/master'
|
|
uses: org/gitea-ci-library/.gitea/workflows/ci-master.yml@v1
|
|
secrets: inherit
|
|
with:
|
|
config-file: ci-flow-values.yaml
|
|
maven-image: maven:3.9-eclipse-temurin-21
|
|
docker-image: docker:26-dind
|
|
```
|
|
|
|
Kehittäjä määrittelee:
|
|
- Millä kontilla buildataan (`maven-image` — koska kirjasto ei tiedä projektin Java-versiota)
|
|
- Mistä konfiguraatio luetaan (`config-file`)
|
|
- Millä docker-versiolla kontit rakennetaan (`docker-image`)
|
|
|
|
Kaikki Git-, raportointi-, SonarQube- ja deploy-konfiguraatio on `ci-flow-values.yaml`:ssa.
|