diff --git a/.gitea/workflows/check-version.yml b/.gitea/workflows/check-version.yml index d84575b..edd0fad 100644 --- a/.gitea/workflows/check-version.yml +++ b/.gitea/workflows/check-version.yml @@ -28,7 +28,16 @@ jobs: - name: Check existing artifact and calculate version run: | - RAW_VERSION=$(jq -r '.version' package.json) + if [ -f VERSION ]; then + RAW_VERSION=$(cat VERSION | tr -d '[:space:]') + elif [ -f package.json ]; then + RAW_VERSION=$(jq -r '.version' package.json) + elif [ -f pom.xml ]; then + RAW_VERSION=$(grep -oP '\K[^<]+' pom.xml | head -1) + else + echo "ERROR: No VERSION file, package.json, or pom.xml found" >&2 + exit 1 + fi BASE_VERSION=$(echo "$RAW_VERSION" | cut -d'.' -f1-2) echo "gitea-ci-library - Tunnistettu Major.Minor versio: $BASE_VERSION" diff --git a/.gitea/workflows/docker-build-push.yml b/.gitea/workflows/docker-build-push.yml index 88c4096..17e4deb 100644 --- a/.gitea/workflows/docker-build-push.yml +++ b/.gitea/workflows/docker-build-push.yml @@ -22,6 +22,7 @@ env: DOCKER_REGISTRY: ${{ fromJson(inputs.env_json).DOCKER_REGISTRY || '' }} DOCKER_IMAGE_NAME: ${{ fromJson(inputs.env_json).DOCKER_IMAGE_NAME || '' }} DOCKER_UI_URL: ${{ fromJson(inputs.env_json).DOCKER_UI_URL || '' }} + DOCKERFILE: ${{ fromJson(inputs.env_json).DOCKERFILE || 'Dockerfile' }} VERSION: ${{ inputs.version }} concurrency: @@ -48,6 +49,7 @@ jobs: --label "git.commit=${{ github.sha }}" \ --label "git.commitBy=${{ github.actor }}" \ --label "build.date=${NOW}" \ + -f "${DOCKERFILE}" \ -t "${DOCKER_IMAGE_NAME}:${VERSION}" . REGISTRY="${DOCKER_REGISTRY:?DOCKER_REGISTRY not set in env.conf}" diff --git a/.gitea/workflows/example-gitea-env.conf b/.gitea/workflows/example-gitea-env.conf index 42dfada..51c5644 100644 --- a/.gitea/workflows/example-gitea-env.conf +++ b/.gitea/workflows/example-gitea-env.conf @@ -3,3 +3,4 @@ GIT_PAGES_URL=https://ci-reports.helm-dev.keskikuja.site DOCKER_REGISTRY=gitea.app.keskikuja.site/niko DOCKER_IMAGE_NAME=gitea-ci-library-test-image DOCKER_UI_URL=https://gitea.app.keskikuja.site/niko/-/packages/container/gitea-ci-library-test-image +#DOCKERFILE=Dockerfile.platform diff --git a/docs/config-model.md b/docs/config-model.md index c2a9876..5b41f5b 100644 --- a/docs/config-model.md +++ b/docs/config-model.md @@ -1,269 +1,124 @@ -# Konfiguraatiomalli — `ci-flow-values.yaml` +# Konfiguraatiomalli — `gitea-env.conf` -> ⚠️ **POC-vaihe.** Tämä dokumentti on peritty Jenkins-versiosta ja sisältää -> Docker-spesifistä legacyä (isContainerBuild, Docker-labelit). POC osoitti, -> että provider on agnostinen consumerin build-ekosysteemille. -> -> Uusi ajattelu: `isContainerBuild()` → `isArtifactBuild()`. Provider ei -> tiedä eikä tarvitse tietää, buildaako consumer kontin, JARin, npm-paketin -> vai mitään muuta. Dokumentti odottaa uudelleenkirjoitusta. -> -> Normatiivinen lähde: `docs/design-rationale.md`, ADR 0005. +> Consumer määrittelee ympäristökohtaiset arvot KEY=VALUE-muotoisessa +> `.conf`-tiedostossa. Providerin `config-provider.yml` validoi tiedoston +> ja muuntaa sen JSON:ksi (`env_json`), jota kaikki downstream-workflowt +> käyttävät. --- -## Miksi redesign +## Tiedoston sijainti ja nimi -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: +Consumerin repossa: `.gitea/workflows/gitea-env.conf` (nimi vapaasti +valittavissa — `config-provider.yml`:n `config_path`-input määrittää polun). -- `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 - ---- +Esimerkki (tämän repon dogfood): +``` +.gitea/workflows/example-gitea-env.conf +``` ## Skeema +``` +KEY=VALUE +``` + +Yksi `KEY=VALUE` per rivi. Kommentit `#`-merkillä. Tyhjät rivit ohitetaan. + +### Pakolliset avaimet + +| Avain | Kuvaus | Esimerkki | +|---|---|---| +| `GITEA_API_URL` | Gitea-instanssin URL | `https://gitea.example.com` | +| `GIT_PAGES_URL` | Raporttihostauksen URL | `https://reports.example.com` | + +### Docker-spesifit avaimet (vain jos käytetään `docker-build-push.yml`) + +| Avain | Pakollinen | Kuvaus | +|---|---|---| +| `DOCKER_REGISTRY` | Kyllä | Rekisterin host/path, esim. `gitea.example.com/org` | +| `DOCKER_IMAGE_NAME` | Kyllä | Kontin nimi ilman registry-prefixiä | +| `DOCKER_UI_URL` | Ei | Linkki kontin UI-näkymään registryssä | +| `DOCKERFILE` | Ei | Dockerfile-nimi, oletus `Dockerfile` | + +### Esimerkki + +```ini +GITEA_API_URL=https://gitea.example.com +GIT_PAGES_URL=https://reports.example.com +DOCKER_REGISTRY=gitea.example.com/myorg +DOCKER_IMAGE_NAME=temperature-store +DOCKER_UI_URL=https://gitea.example.com/myorg/-/packages/container/temperature-store +#DOCKERFILE=Dockerfile.platform +``` + +--- + +## Salaisuudet + +Salaisuudet eivät ole `.conf`-tiedostossa. Ne määritellään Gitean +organization/repository secrets -mekanismissa ja välitetään workflowlle +`secrets: inherit` -direktiivillä. + +| Secret | Pakollinen | Käyttäjä | +|---|---|---| +| `GITEA_TOKEN` | Kyllä | `report-status.sh`, `check-version.yml`, `docker-build-push.yml` | +| `GIT_PAGES_PUBLISH_TOKEN` | Kyllä | `publish-git-pages.sh`, `config-provider.yml` (validointi) | +| `DOCKER_USERNAME` | Ei | `docker-build-push.yml` (oletus: `github.actor`, ei pakollinen kaikissa registryissä) | +| `DOCKER_PASSWORD` | Kyllä | `docker-build-push.yml` | + +--- + +## `config-provider.yml` — lataus ja validointi + +Provider-workflow joka lukee `.conf`-tiedoston, validoi sen ja palauttaa +JSON-muotoisen `env_json`:n. + +**Input:** `config_path` (polku `.conf`-tiedostoon) + +**Output:** `env_json` (JSON-string), `config_path` (sama polku takaisin) + +**Validointi:** +- `.conf`-tiedosto on olemassa +- Jokaisella `KEY=VALUE`-rivillä on arvo (ei tyhjää) +- URL-tyyppiset avaimet alkavat `http://` tai `https://` +- Pakolliset secretit (`GITEA_TOKEN`, `GIT_PAGES_PUBLISH_TOKEN`) on asetettu + +Kutsu: ```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) | - ---- - -## `isArtifactBuild()`-mekanismi (POC: suunniteltu, ei toteutettu) - -> **Jenkins-legacy:** Jenkins-versiossa tämä oli `isContainerBuild()`. POC -> osoitti, että provider ei tiedä eikä tarvitse tietää, buildaako consumer -> kontin, JARin vai npm-paketin. Siksi `isContainerBuild()` → -> `isArtifactBuild()`. - -**Ongelma:** Samaa committia vasten voidaan ajaa master-workflow useita -kertoja. On mieletöntä buildata artifakti uudestaan, koska commit on jo -tagätty versiolla ja artifakti 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: artifaktin buildaus on hitain vaihe -- Pitää commitin ja artifaktin välisen suhteen yksiselitteisenä: `git tag` kertoo suoraan mikä versio vastaa tätä committia - ---- - -## 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 -# 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 +load-config: + uses: org/gitea-ci-library/.gitea/workflows/config-provider.yml@main 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 + config_path: .gitea/workflows/gitea-env.conf ``` -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. +## `check-version.yml` — version päättely + +Provider-workflow joka etsii version prioriteettijärjestyksessä: + +1. `VERSION`-tiedosto (plain text, esim. `0.2`) +2. `package.json` → `.version`-kenttä (Node.js) +3. `pom.xml` → ``-elementti (Maven) + +Hakee git-tagit Gitea API:sta ja laskee seuraavan vapaan patch-version. + +**Output:** `artifact_exists` (true/false), `version` (string) + +**Idempotentti:** Jos commitilla on jo versiotagi, `artifact_exists=true` ja +build-vaiheet skipataan. Samaa committia ei buildata kahdesti. + +--- + +## `env_json`-propagointi + +``` +gitea-env.conf → config-provider.yml → env_json (JSON-string) + ↓ + ci.yml with: env_json → kaikki downstream-workflowt +``` + +Jokainen provider-workflow purkaa tarvitsemansa arvot `fromJson(inputs.env_json).KEY`:lla. +Consumerin ei tarvitse tietää mitä avaimia kukin provider käyttää. diff --git a/docs/consumer-guide.md b/docs/consumer-guide.md new file mode 100644 index 0000000..9d60fe5 --- /dev/null +++ b/docs/consumer-guide.md @@ -0,0 +1,390 @@ +# 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`: + +```ini +GITEA_API_URL=https://gitea.example.com +GIT_PAGES_URL=https://reports.example.com +``` + +Jos buildaat Docker-kontteja, lisää: + +```ini +DOCKER_REGISTRY=gitea.example.com/myorg +DOCKER_IMAGE_NAME=my-service +DOCKER_UI_URL=https://gitea.example.com/myorg/-/packages/container/my-service +#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`: + +```yaml +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: + +```yaml +name: CI Feature +on: + push: + branches-ignore: + - main + workflow_dispatch: + +jobs: + load-config: + uses: org/gitea-ci-library/.gitea/workflows/config-provider.yml@main + 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@main + 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ä**: + +```yaml +name: CI Main +on: + push: + branches: + - main + workflow_dispatch: + +jobs: + load-config: + uses: org/gitea-ci-library/.gitea/workflows/config-provider.yml@main + 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@main + 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@main + 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@main + with: + env_json: ${{ needs.load-config.outputs.env_json }} + suites: junit cucumber +``` + +Mihin kiinnittää huomiota: +- `check-version` on **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.yml` on yksi + esimerkki. Voit korvata sen Maven-deploylla, npm-publishilla, tai millä + tahansa omalla build-workflow'lla. Rajapinta on `version`-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` | `` | `0.2.0` | + +`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 ` — oma suite-nimi +- `report-status.sh ... ` — 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 + +1. **Exit-koodi aina ylös:** + ```bash + run-tests + EXIT=$? + echo "EXIT=${EXIT}" >> "${GITHUB_ENV}" + exit ${EXIT} + ``` + +2. **Ei pipeä testikomennon perään.** `command | tee file` syö exit-koodin. + Käytä `command > file 2>&1` jos haluat logit talteen. + +3. **Status vain jos on raportti.** Testijobit käyttävät commit-status API:a + raporttilinkin takia. Tool-jobit luottavat Gitean natiiviin job-statukseen. + +4. **`if: always()`** publish- ja status-stepeissä — raportti julkaistaan + ja status asetetaan vaikka testit feilaisivat. + +### Raporttien generointi + +`publish-git-pages.sh ` odottaa hakemiston `reports/${SHA8}//` +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: + +```bash +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 + └── ... +``` + +```bash +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' + + +

Bats Test Reports

+ + +EOF +``` + +Yhteistä molemmille: `publish-git-pages.sh `-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` + +--- + +## 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ä) | diff --git a/docs/design-rationale.md b/docs/design-rationale.md index 1be0113..2a61245 100644 --- a/docs/design-rationale.md +++ b/docs/design-rationale.md @@ -1,150 +1,195 @@ # Design Rationale — Gitea Actions CI -kirjasto -> Miksi kirjasto on rakennettu näin. Arvot, periaatteet ja reunaehdot, joiden varaan arkkitehtuuri nojaa. +> Miksi kirjasto on rakennettu näin. Arvot, periaatteet ja reunaehdot, joiden +> varaan arkkitehtuuri nojaa. > -> Tämä dokumentti on **normatiivinen** — arkkitehtuurin on noudatettava näitä periaatteita. Jos ehdotettu muutos on ristiriidassa rationalen kanssa, rationalen on muututtava ensin. +> Tämä dokumentti on **normatiivinen** — arkkitehtuurin on noudatettava näitä +> periaatteita. Jos ehdotettu muutos on ristiriidassa rationalen kanssa, +> rationalen on muututtava ensin. --- ## Miksi tämä projekti on olemassa -Organisaatiolla on tuotannossa Jenkins-pohjainen CI-järjestelmä (`ci-jenkins-library`, 53 lähdetiedostoa, 21 Cucumber-featurea), joka on osoittautunut toimivaksi vuosien ajan. Se integroi Git-commitit, testiraportoinnin, Docker-buildit, deploymentin ja test flow'n yhtenäiseksi putkeksi, jossa jokainen vaihe raportoi tilansa suoraan Git-committiin. +Mikropalveluarkkitehtuurissa jokainen palvelu tarvitsee CI-putken: testit, +laatutarkistukset, buildin, kontituksen ja julkaisun. Ilman jaettua +kirjastoa jokainen tiimi kopioi saman YAML-boilerplaten, tekee omat +virheensä ja ylläpitää omaa versiotaan. Ajan myötä putket ajautuvat erilleen +— toisessa on `shell: bash`, toisessa ei; toinen käyttää `set -o pipefail`, +toinen kadottaa exit-koodin `tee`:hen. -Jenkins on kuitenkin raskas ylläpitää Kubernetesissa, ja organisaatio on siirtymässä Giteaan. Tavoitteena on **sama toiminnallisuus, pienemmällä ylläpitotaakalla**, hyödyntäen Gitea Actionsin natiiveja ominaisuuksia. - -Kirjasto ei ole Jenkins-migraatiotyökalu. Se on Gitea Actions -natiivi -uudelleensuunnittelu, joka säilyttää Jenkins-version todistetut patternit -mutta hylkää ne osat, jotka olivat sidottuja Jenkinsin arkkitehtuuriin. -Gitea Actionsin ja Gitean natiiveja ominaisuuksia hyödynnetään aina kun -mahdollista — uutta kilpailevaa toteutusta ei kirjoiteta, jos toimiva -ratkaisu on jo olemassa. +Tämä kirjasto on se mitä kopioidaan. Se tarjoaa valmiit, testatut, +dokumentoidut rakennuspalikat joista jokainen tiimi kokoaa oman putkensa. +Palikat ovat Gitea Actionsin `uses:`-direktiivillä kutsuttavia reusable +workflow'ta — ei asennusta, ei runtime-riippuvuutta, ei versiopäivityksiä +projekteihin. --- ## Suunnitteluperiaatteet -### 1. Hyödynnä natiivia +### 1. Palikka-arkkitehtuuri: pieniä, vaihdettavia, yhden vastuun workflow'ta -Gitea Actionsin ja Gitean natiiveja ominaisuuksia käytetään aina kun ne -riittävät. Uutta kilpailevaa toteutusta ei kirjoiteta, jos toimiva ratkaisu -on jo olemassa. +Jokainen provider-workflow tekee yhden asian: -**Miksi:** Oma toteutus on aina ylläpidettävä, testattava ja -dokumentoitava. Natiivi ominaisuus tulee ilmaiseksi, kehittyy alustan -mukana ja on käyttäjälle tuttu. +| Workflow | Vastuu | +|---|---| +| `config-provider.yml` | Lataa ja validoi konfiguraatio | +| `check-version.yml` | Tarkistaa onko commit buildattu, laskee version | +| `docker-build-push.yml` | Buildaa, puskea ja tagittaa kontin | -**Esimerkkejä:** -- Gitea Actions näyttää jobien statuksen automaattisesti — omaa - commit-status API -kutsua ei tarvita jokaiselle vaiheelle -- Gitea organization secrets/variables korvaa erillisen credential-hallinnan -- Reusable workflow -mekanismi korvaa custom action -runtimen +Mikään workflow ei kutsu toista provider-workflowta. Consumer +— siis mikropalvelun oma pipeline-tiedosto — on ainoa paikka joka +tietää mitä palikoita tarvitaan ja missä järjestyksessä. -### 2. Git-commit on universaali statusnäkymä +**Miksi:** Tämä on sama periaate kuin Unix-putkissa tai mikropalveluissa: +pieniä, itsenäisiä komponentteja jotka tekevät yhden asian hyvin. +Consumer voi vaihtaa yhden palikan toiseen — esimerkiksi Docker-buildin +tilalle Maven-paketoinnin — ilman että muut palikat muuttuvat. +Ratkaisu ei ole se että kaikki ajetaan, vaan se että jokainen tiimi +valitsee mitä tarvitsee. Monoliittinen "kaikki yhdessä" -workflow +pakottaisi jokaisen tiimin ajamaan tarpeettomia vaiheita. -Buildin jokainen vaihe raportoi tilansa Git-committiin. Kehittäjä näkee yhdellä silmäyksellä, missä vaiheessa build on — ei tarvitse navigoida CI-järjestelmän UI:hun. +### 2. Gitea ensin — hyödynnä alustaa, älä taistele sitä vastaan -**Miksi:** Jenkins-versio osoitti, että commit-statusviestit poistavat tarpeen CI-dashboardille. Kehittäjä työskentelee Gitissä, joten status kuuluu Gitiin. Statusviestien `url`-kenttä linkittää suoraan raportteihin — Cucumber-tulokset, SonarQube-tulokset, Docker-rekisteri — ilman että URL tarvitsee etsiä erikseen. +Gitea Actions tarjoaa kolme asiaa ilmaiseksi: -**Mitä tarkoittaa käytännössä:** Gitea Actions näyttää jobien tilan -(checkmark/risti/spinner) commit-näkymässä automaattisesti. API:a -(`/api/v1/repos/{owner}/{repo}/statuses/{sha}`) käytetään vain -custom-raporttilinkin välittämiseen. ADR 0004. +1. **Jobien visuaalinen status** — jokainen jobi näkyy automaattisesti + commit-näkymässä checkmarkilla, spinnerillä tai ristillä. +2. **Cross-job riippuvuudet** — `needs` hoitaa virheiden propagointin: + jos edeltävä jobi feilaa, riippuvat jobit skipataan. +3. **Reusable workflow -jakelu** — `uses: org/repo/.gitea/workflows/file.yml@v1` + on natiivisti versioitu, skopattu ja välimuistitettu. -### 3. Reusable workflow — ei omaa runtimea +Kirjasto käyttää näitä kaikkia. Ei omaa tilakonetta, ei custom +action -runtimea, ei ulkoista orkestraattoria. -Kirjasto jaetaan Gitea Actionsin reusable workflow -mekanismilla. Ei Docker-pohjaisia custom actioneita, ei erillistä ajonaikaista palvelinta. +**Esimerkki:** Tool-jobit eivät kutsu commit-status API:a lainkaan. +Gitean oma job-status riittää — `success`/`failure`/`running` näkyy +automaattisesti. API:a käytetään vain kun tarvitaan **custom-linkki** +(testiraporttiin tai Docker registryyn), jota natiivistaatus ei tarjoa. +Tämä linjaus on dokumentoitu ADR 0004 ja 0007:ssä. -**Miksi:** Reusable workflow on Gitea Actionsin natiivein tapa jakaa CI-logiikkaa. Se on kevein (ei ylimääräistä runtimea), läpinäkyvin (workflow-tiedosto on luettavissa sellaisenaan) ja teknisesti kestävin (Gitea huolehtii versioinnista ja jakelusta). Custom actionit otetaan käyttöön vain jos reusable workflow'n rajat tulevat vastaan. +### 3. Status näkyy siellä missä työ tehdään — Git-commitissa -**Mitä tämä ei ole:** Tämä ei ole monorepo-työkalu, joka asennetaan projekteihin. Tämä on joukko `.gitea/workflows/`-tiedostoja, joihin mikropalvelut viittaavat `uses:`-direktiivillä. +Kehittäjä työskentelee Gitissä. `git log`, `git blame`, PR-näkymä — +nämä ovat päivittäiset työkalut. CI-statuksen kuuluu näkyä siellä, +ei erillisessä dashboardissa. -### 4. Konfiguraatio kuuluu repoon +Gitea Actionsin natiivi job-status tekee tämän automaattisesti: +jokainen commit näyttää välittömästi mitkä jobit on ajettu ja millä +tuloksella. Testiraportteihin pääsee yhdellä klikkauksella commitin +status-kuvakkeesta — koska `report-status.sh` asettaa `target_url`:n +osoittamaan suoraan HTML-raporttiin git-pagesissa. -Projektikohtainen konfiguraatio (`ci-flow-values.yaml`-tyyppinen tiedosto) asuu mikropalvelun omassa repossa. Reusable workflow lukee sen, ei toisinpäin. +Tämä ei ole kosmeettinen yksityiskohta. Se on devops-käytännön +ydin: palautesilmukka on lyhin mahdollinen. Commit → build → status +näkyy samassa näkymässä jossa kehittäjä jo on. -**Miksi:** Mikropalvelun kehittäjä omistaa buildinsa. Hän tietää mitä Dockefileä käytetään, mitä SonarQube-projektia, mitä testi-steppejä tarvitaan. Jos konfiguraatio hajautetaan useaan repoon, muutokset vaativat koordinaatiota, ja yhden totuuden lähteen periaate rikkoutuu. +### 4. Exit-koodi on ainoa totuus -**Poikkeus:** Infra-tason asetukset (git-pages host, Gitea-instanssin URL) -ovat organisaatiotasolla Gitean organization secrets/variables --mekanismissa. Ne eivät ole repokohtaisia. +CI-putken jokaisen `run`-stepin onnistuminen määräytyy **vain ja +ainoastaan** exit-koodin perusteella. Ei tiedoston olemassaolon, ei +stdout-tulosteen, ei arvauksen. `0` = ok, kaikki muu = ei ok. -### 5. Deterministinen testigraafi, vaiheittainen suoritus +Tämä kuulostaa itsestään selvältä, mutta YAML-pipelineissa se rikkoutuu +helposti. Pipe (`|`) `tee`:hen syö exit-koodin. Tiedoston olemassaolon +tarkistus (`[ -f results.xml ]`) ei kerro testien läpimenosta. -Test flow on tunnettu ennen buildin alkua, ja testit ajetaan yksi kerrallaan. Jos steppi epäonnistuu, koko flow pysähtyy. +**Käytännössä:** Jokainen `run`-steppi ottaa exit-koodin talteen +`$?`-muuttujaan ennen kuin mikään muu komento ehtii muuttaa sitä, +ja stepin viimeinen rivi on `exit ${EXIT}`. Pipeä ei käytetä +työvaiheen viimeisenä komentona. Ks. ADR 0008. -**Miksi:** Rinnakkainen suoritus aiheuttaa resurssikilpailua (erityisesti suorituskykytestit) ja piilottaa virheitä. Kun integraatiotesti epäonnistuu, e2e-testien ajaminen on turhaa — konttia ei viedä tuotantoon, eikä kukaan lue niitä tuloksia. Vaiheittainen suoritus on deterministinen, debuggattava ja säästää CI-minuutteja. +### 5. Pienin mahdollinen pinta-ala -**Miten:** Orkestroiva workflow käyttää Gitea REST API:a workflow-dispatchiin ja pollaa ajettavan workflow'n tilaa synkronisesti (`GET /api/v1/repos/{owner}/{repo}/actions/runs/{id}`). Tämä vastaa Jenkinsin `buildJob()`-kutsun semantiikkaa, mutta toteutetaan curl + pollaus -silmukalla. +Jokainen ylimääräinen riippuvuus on ylimääräinen vikaantumispiste. +Kirjaston ainoat riippuvuudet: -### 6. Raporttien hallinta erillisellä palvelulla +- Gitea Actions (alusta) +- `bash`, `curl`, `jq` (ubuntu-latest runnerissa valmiina) +- Docker (runnerissa valmiina) +- git-pages (raporttien hostaus, erillinen palvelu) -Raporttien selailtavuudesta ja elinkaaresta vastaa erillinen palvelu, joka -asennetaan git-pages Helm-chartilla. Raportit ovat julkisia URL:lla -(osoite tunnettava). URL linkitetään Git-committiin. +Ei Pythonia, ei Node.js:ää ajonaikaisesti (testit omissa konteissaan). +Ei tietokantaa. Ei ulkoista tilanhallintaa. Kirjasto on joukko +YAML-tiedostoja ja shell-skriptejä — samat työkalut jotka jokainen +devops-ihminen jo osaa. -**Miksi:** Jenkins-versiossa linkki Cucumber-raporttiin oli kriittinen -feature. Gitea Actionsin artifact-järjestelmä ei tue HTML-selailtavuutta -(vain ZIP-lataus). Erillinen palvelu mahdollistaa hallitun retention ja -pääsyn ilman CI-alustan rajoitteita. +### 6. Konfiguraatio repoon, salaisuudet Giteaan -### 7. Yksi CI-alusta, yksi integraatiopiste +Projektikohtainen konfiguraatio (`.gitea/workflows/gitea-env.conf`) +asuu mikropalvelun omassa repossa. Kehittäjä omistaa sen — hän tietää +mikä on Docker-imagen nimi, mihin registryyn puskea, mikä on +testiympäristön URL. -Kirjasto tukee vain Giteaa. Ei GitLab-, BitBucket- tai GitHub-abstraktioita. +Salaisuudet (tokenit, salasanat) elävät Gitean secrets-mekanismissa, +eivät repon tiedostoissa. `secrets: inherit` välittää ne providerin +workflow'hun ilman että consumerin tarvitsee tietää mitä salaisuuksia +mikäkin provider tarvitsee. -**Miksi:** Jenkins-versio tuki neljää Git-alustaa, koska Jenkins itsessään ei tarjonnut commit-statusraportointia. Gitea Actionsissa tilanne on päinvastainen — Gitea on sekä CI-että Git-alusta. Multi-platform-tuesta tulisi pelkkää ylimääräistä abstraktiota ilman konkreettista tarvetta. +Poikkeus: infra-tason asetukset (`GIT_PAGES_URL`, `GITEA_API_URL`) +ovat Gitean organization secrets/variables -mekanismissa. Ne eivät +ole repokohtaisia. -**Mitä tarkoittaa tulevaisuudessa:** Jos toinen alusta tulee ajankohtaiseksi, Gitea-versiota käytetään joko pohjana redesignille tai mallina erilliselle toteutukselle. Rajapintoja ei suunnitella etukäteen alustariippumattomiksi — se on ennenaikaista optimointia. +### 7. Consumer omistaa orkestroinnin, provider tarjoaa palikat -### 8. Cross-repo commit traceability +Tämä on kirjaston tärkein arkkitehtuurinen päätös (ADR 0005). -Kun build-ketju ylittää reporajat (mikropalvelu → deployment → integraatiotestit → e2e-testit), jokainen vaihe raportoi kahteen suuntaan: omaan committiinsa ja takaisin root-committiin, josta ketju käynnistyi. +Provider (`gitea-ci-library`) ei tiedä mitä testejä ajetaan, missä +järjestyksessä, tai millä branchilla. Se tarjoaa kolme reusable +workflow'ta ja joukon skriptejä. -**Miksi:** Kehittäjän ei pidä arvailla mikä versio on missäkin ympäristössä. Kun mikropalvelun commitista näkee koko ketjun — buildattu, deployattu stagingiin, integraatiotestit ajettu, e2e hyväksytty — virheenjäljitys on suora polku commitista ympäristöön. Vastaavasti Helm-repon commit kertoo mikä konttiversio sinne deployattiin ja kenen mikropalvelu-commitista se tuli. Tämä on Jenkins-version **eniten arvoa tuottanut ominaisuus**. +Consumer (mikropalvelun `example-feature.yml` / `example-main.yml`) +päättää: +- Mitkä palikat kutsutaan +- Missä järjestyksessä (`needs`) +- Millä branch-ehdoilla (`if`) +- Mitkä testikontit käytetään (input-parametrit) -**Mekanismi:** +Tämä on tarkoituksellinen vallanjako. Provider ei voi tietää jokaisen +tiimin tarpeita — eikä sen pidäkään. Consumer ei voi muuttaa providerin +sisäistä toteutusta — eikä sen pidäkään. Rajapinta on `workflow_call` ja +se on molemmille osapuolille selvä. -```mermaid -%%{init: {'theme': 'base'}}%% -sequenceDiagram - participant MR as Mikropalvelu-repo - participant HR as Helm-repo - participant TR as Testi-repo - participant GA as Gitea API +### 8. Branch-kohtainen reititys, ei yhtä kaikille - Note over MR: commit abc123 - Note over MR: build kontti v1.2.3 +Eri brancheilla on eri tavoite: - MR->>GA: POST dispatch deploy-workflow - GA->>HR: workflow käyntiin - Note over HR: commit def456 - Note over HR: container.version = 1.2.3 +- **Feature-haara:** Onko koodi laadukasta? → testit, validointi +- **Main-haara:** Onko tästä versiosta jo artifakti? Jos ei → + testit + build + push + tag. Jos on → ei tehdä mitään (tai + jatketaan klusteritesteihin). - HR->>GA: POST status "deployed by abc123" - GA->>MR: Status: deployed to staging - Note right of MR: URL → def456 +Tämä logiikka elää consumerin pipeline-tiedostossa, ei providerissa. +Se on puhdasta `if`-ehtoa ja `needs`-ketjutusta — ei skriptausta, +ei monimutkaisia ehtoja providerin sisällä. - HR->>GA: POST status "from abc123" - GA->>HR: Status: from abc123 - Note right of HR: URL → abc123 +### 9. Raportit erillisellä palvelulla, linkit commitissa - MR->>GA: POST dispatch integraatiotestit - GA->>TR: workflow käyntiin - Note over TR: commit ghi789 +Gitea Actionsin artifact-järjestelmä on binääriarkisto — ZIP-lataus, +ei HTML-selailtavuutta. Testiraportit (Cucumber HTML, Bats-coverage) +on voitava avata selaimessa yhdellä klikkauksella. - TR->>GA: POST status "integration OK" - GA->>MR: Status: integration OK - Note right of MR: URL → ghi789 +Ratkaisu: git-pages Helm-chartti, joka tarjoaa staattista +tiedostohostingia HTTP:llä. `publish-git-pages.sh` vie raportit +sinne; `report-status.sh` linkittää commit-statuksen suoraan +raporttiin. Retention hoitaa git-pagesin sidecar automaattisesti. - TR->>GA: POST status "tested v1.2.3" - GA->>HR: Status: tested v1.2.3 - Note right of HR: URL → def456 +Tulevaisuudessa `GITHUB_STEP_SUMMARY` (Gitea 1.27+) tarjoaa +vaihtoehtoisen kanavan: jobin Summary-välilehdelle renderöityvä +Markdown-taulukko kaikista raporttilinkeistä. - TR->>GA: POST status "tested abc123" - GA->>MR: Status: tested abc123 (root) - Note right of MR: URL → abc123 -``` +### 10. Vain Gitea — ei monialustatukea ilman tarvetta -**Mitä tarkoittaa käytännössä:** Jokaisella workflow'lla on kaksi build-referenssiä: `current` (oma commit) ja `root` (mikropalvelun commit, josta ketju alkoi). Molempiin POSTataan statusviestit. Root-build kulkee workflow-dispatchin `inputs`-parametrina koko ketjun läpi. Deployment-job raportoi sekä Helm-repon committiin ("from abc123") että mikropalvelun committiin ("deployed to staging → def456"). Testi-job raportoi omaan committiinsa, mikropalvelun committiin ja Helm-repon committiin. +Yhden alustan tukeminen kunnolla on vaikeampaa kuin kolmen tukeminen +huonosti. Gitea Actionsin `uses:`-mekanismi, `needs`-semantiikka, +`secrets: inherit`, `gitea`-konteksti — nämä ovat alustakohtaisia +ominaisuuksia joita abstraktiokerros vain haittaisi. + +Jos toinen alusta tulee ajankohtaiseksi, sille kirjoitetaan oma +toteutus. Siihen asti yksi alusta riittää. Ennenaikainen yleistys +on devopsissa yhtä haitallista kuin ohjelmistosuunnittelussa. --- @@ -152,23 +197,31 @@ sequenceDiagram ### Mitä kirjasto EI tee -- **Ei ulkoista orkestraattoria.** Test flow -ketjutus perustuu Gitean REST APIin ja workflowhin itseensä. Ei erillistä palvelinta, joka hallinnoi tilaa. -- **Ei Jenkins-migraatiota.** Vanhaa Jenkinsfileä ei voi ajaa Gitea Actionsissa. Tämä on uusi kirjasto uudella konfiguraatioformaatilla. -- **Ei reaaliaikaista build-seurantaa.** Commit-statusviestit ovat pollattavia, eivät push-pohjaisia. Gitean UI hoitaa reaaliaikaisuuden. -- **Ei multi-repo-monorepo-konfiguraatiota.** Jokainen mikropalvelu omistaa oman `ci-flow-values.yaml`:nsa. Jaettua konfiguraatiota ei ole projektitasolla. +- **Ei ulkoista orkestraattoria.** Pipeline-ohjaus on Gitea Actionsin + `needs`-ketjuissa ja consumerin `if`-ehdoissa. +- **Ei custom actioneita.** Reusable workflow on kevyempi, versioitu + ja jaeltu Gitean oman mekanismin kautta. +- **Ei asennusta projekteihin.** Consumer viittaa `uses:`-direktiivillä + suoraan tämän repon workflow-tiedostoihin. Ei npm-pakettia, ei + git-submodulea, ei kopioitavia tiedostoja. +- **Ei runtime-riippuvuuksia.** Provider-skriptit käyttävät vain + työkaluja jotka ovat Gitea Actionsin `ubuntu-latest` runnerissa + valmiina: `bash`, `curl`, `jq`. +- **Ei monorepo-konfiguraatiota.** Jokainen mikropalvelu omistaa + oman pipeline-tiedostonsa ja konfiguraationsa. --- ## Mitä tietoisesti hylättiin -## Mitä tietoisesti hylättiin - | Hylätty | Syy | -|---------|-----| -| Multi-Git-platform-tuki (GitLab, BitBucket) | Vain Gitea on relevantti. Abstraktointi ilman tarvetta on turhaa kompleksisuutta | -| Gitea Packages raporttien hostingiin | Ei tue HTML-selailtavuutta — vain binääriartefaktien lataus | -| Gitea Releases raporttien hostingiin | Saastuttaa release-historian. Satoja CI-raportteja oikeiden julkaisujen seassa | -| Gitea Pages + reports-branch | Race condition rinnakkaisten buildien pushissa samaan branchiin | -| Ulkoinen orkestraattoripalvelin | Ylimääräinen ylläpidettävä. Gitean oma API riittää | -| Docker-pohjaiset custom actionit | Tuovat riippuvuuden Docker-rekisteriin ja monimutkaistavat jakelua. Otetaan käyttöön vain pakon edessä | -| `repository_dispatch` (webhook) test flow -ketjutukseen | Lisää konfiguraatiota vastaanottaviin repoihin. Suora REST API -kutsu on eksplisiittisempi ja debuggattavampi | +|---|---| +| Monoliittinen "kaikki yhdessä" -workflow | Pakottaa kaikille samat vaiheet. Palikka-arkkitehtuuri antaa jokaiselle tiimille vain mitä se tarvitsee | +| Oma orkestraattoripalvelin | Ylimääräinen ylläpidettävä. Gitean `needs` ja `if` riittävät | +| Docker-pohjaiset custom actionit | Tuovat riippuvuuden Docker-rekisteriin. Reusable workflow on natiivimpi | +| Commit-status API jokaiselle vaiheelle | Duplikointia — Gitea näyttää job-statuksen automaattisesti. API vain custom-linkeille | +| `tee`-putki debug-näkyvyyteen | Syö exit-koodin. stdout ohjataan tiedostoon `>` ilman pipeä | +| Multi-Git-platform-tuki | Ennenaikaista optimointia ilman tarvetta | +| Gitea Packages raporttien hostingiin | Ei HTML-selailtavuutta — vain binäärilataus | +| Gitea Pages + reports-branch | Race condition rinnakkaisten pushien kanssa | +| `repository_dispatch` ketjutukseen | Lisää konfiguraatiota vastaanottaviin repoihin. Suora API-kutsu eksplisiittisempi | diff --git a/docs/requirements.md b/docs/requirements.md index f1bdd91..952ba6c 100644 --- a/docs/requirements.md +++ b/docs/requirements.md @@ -1,8 +1,6 @@ # Vaatimukset — Gitea Actions CI -kirjasto > Funktionaaliset vaatimukset käyttäjän näkökulmasta. Muoto: käyttötapaukset (use cases). -> -> Linkittyy: [design-rationale.md](design-rationale.md), [architecture.md](architecture.md), [report-hosting.md](report-hosting.md) --- @@ -13,130 +11,89 @@ **Main success:** - Kehittäjä avaa commitin Giteassa -- Näkee statusviestit: "Building...", "Unit tests OK", "Docker build OK", "Docker pushed" -- Jokainen statusviesti on klikattavissa → vie buildin sivuun tai raporttiin -- Epäonnistunut steppi näkyy punaisella — kehittäjä klikkaa ja näkee mikä meni vikaan +- Näkee job-statukset automaattisesti: spinner (käynnissä), checkmark (ok), risti (feilasi) +- Testijobit näyttävät statuksen linkillä: "unit-tests Link to Bats reports", "acc-tests Link to Cucumber reports" +- Klikkaamalla testistatusta kehittäjä pääsee suoraan HTML-raporttiin git-pagesissa +- Docker-build näyttää linkin konttirekisteriin **Poikkeukset:** - Statusviesti puuttuu (workflow kaatui ennen raportointia) → commitissa näkyy timeout/error -- Useampi workflow samalle commitille → statukset erottuvat `key`-arvolla +- Useampi workflow samalle commitille → statukset erottuvat `context`-avaimella --- ## UC2: Kehittäjä lukee testiraportteja selaimessa **Actor:** Kehittäjä -**Precondition:** Build on valmistunut, raportit pushattu Minioon +**Precondition:** Build on valmistunut, raportit julkaistu git-pagesiin **Main success:** -- Kehittäjä klikkaa commitin statusviestin URL:ää ("Unit tests OK" → URL) -- Selain avautuu, OIDC-kirjautuminen (Gitea-tunnuksilla) -- Cucumber-raportti renderöityy HTML:nä selaimessa -- Raportissa näkyy: mitkä testit menivät läpi, mitkä epäonnistuivat, stack tracet -- Yläreunassa linkki "← Back to build" → palaa buildin raportti-indeksiin +- Kehittäjä klikkaa commitin status-kuvaketta (esim. "unit-tests") +- Selain avautuu suoraan HTML-raporttiin git-pagesissa +- Bats-raportissa näkyy: testitulokset, code coverage +- Cucumber-raportissa näkyy: mitkä testit menivät läpi, mitkä epäonnistuivat, stack tracet **Poikkeukset:** -- Raporttia ei ole (testit skipattiin, workflow kaatui ennen pushausta) → 404 -- OIDC-sessio vanhentunut → uudelleenohjaus kirjautumiseen +- Raporttia ei ole (testit skipattiin, workflow kaatui ennen julkaisua) → 404 --- -## UC3: Kehittäjä selaa projektin build-historiaa - -**Actor:** Kehittäjä -**Precondition:** Projektilla on vähintään yksi build - -**Main success:** -- Kehittäjä menee `{MINIO_BASE}/{repo_slug}/index.html` -- Näkee listan kaikista buildeista aikajärjestyksessä (uusin ensin) -- Jokaisella buildilla: commitin 8-merkkinen hash, päivämäärä, branch, status (✅/❌) -- Klikkaa buildia → siirtyy `{commit_short}/index.html` — buildin raporttilistaukseen -- Buildin sivulla: lista kaikista raporteista (Cucumber, JaCoCo, Maven Site) linkkeinä -- "← Back to builds" → palaa projektin build-indeksiin - -**Poikkeukset:** -- Projekti poistettu / siivottu retention policyn mukaan → 404 -- Indeksitiedosto puuttuu (ensimmäinen build kesken) → 404, generoituu seuraavalla pushauksella - ---- - -## UC4: Kehittäjä jäljittää kontin koko ketjun commitista - -**Actor:** Kehittäjä -**Precondition:** Mikropalvelun commitista on ajettu vähintään deployment - -**Main success:** -- Kehittäjä avaa mikropalvelun commitin abc123 -- Näkee statusviestit: "Build OK", "Deployed to staging → def456", "Integration tests OK → ghi789" -- Klikkaa "Deployed to staging → def456" → siirtyy Helm-repon committiin def456 -- Helm-repon commitissa näkyy: "from abc123", "tested v1.2.3", "tested abc123" -- Klikkaa "tested abc123" → palaa mikropalvelun committiin -- Koko ketju on navigoitavissa edestakaisin commit-statuslinkkien kautta - -**Poikkeukset:** -- Välivaiheen commit siivottu → statusviesti jää, mutta linkki vie 404:ään -- Deploytty versio ei vastaa odotettua → statusviestissä näkyy ristiriita - ---- - -## UC5: Kehittäjä näkee deployatun version ympäristössä - -**Actor:** Kehittäjä -**Precondition:** Deployment on suoritettu, Helm-repon commit tehty - -**Main success:** -- Kehittäjä avaa Helm-repon commitin def456 -- Näkee: "container.version = 1.2.3", "Deployed by abc123" -- Tietää heti mikä konttiversio on missäkin ympäristössä -- Voi verrata mikropalvelun uusimpaan commitin — onko ympäristö ajan tasalla? - -**Poikkeukset:** -- `doNotDowngrade` esti deploymentin → statusviesti "Skipped: newer version already deployed" - ---- - -## UC6: Testi-insinööri näkee mitä konttia testattiin - -**Actor:** Testi-insinööri -**Precondition:** Integraatio- tai e2e-testit on ajettu - -**Main success:** -- Avaa testi-repon commitin ghi789 -- Näkee: "Tested v1.2.3" (mikä kontti), "Tested abc123" (mikä mikropalvelun commit) -- Klikkaa testiraporttiin → näkee tulokset -- Näkee myös mitkä tagit olivat käytössä (`@smoke and not @slow`) -- Voi todentaa että testattiin oikeaa versiota - -**Poikkeukset:** -- Version check epäonnistui (haluttu versio ei ollut ympäristössä) → status: "Version mismatch" -- Testit keskeytyivät timeoutiin → status: timeout, osittaiset tulokset raportissa - ---- - -## UC7: Kehittäjä vertailee kahden buildin raportteja +## UC3: Kehittäjä vertailee kahden buildin raportteja **Actor:** Kehittäjä **Precondition:** Projektilla on vähintään kaksi buildia **Main success:** -- Kehittäjä avaa projektin build-indeksin `{MINIO_BASE}/{repo}/index.html` -- Näkee viimeisimmät buildit vierekkäin -- Avaa kaksi buildia eri välilehtiin +- Kehittäjä avaa kaksi buildia Gitean Actions-näkymässä eri välilehtiin - Voi verrata Cucumber-tuloksia: "build #42 vs #41 — mikä testi meni rikki?" -**Poikkeukset:** -- Vanha build siivottu → ei näy indeksissä +--- + +## UC4: Kehittäjä jäljittää kontin koko ketjun commitista (tuleva) + +**Actor:** Kehittäjä +**Precondition:** Mikropalvelun commitista on ajettu deployment ja klusteritestit + +**Main success:** +- Kehittäjä avaa mikropalvelun commitin +- Näkee statusviestit: "Build OK", "Deployed to staging", "Integration tests OK" +- Klikkaamalla statusta siirtyy toisen repon committiin +- Koko ketju on navigoitavissa edestakaisin commit-statuslinkkien kautta + +--- + +## UC5: Kehittäjä näkee deployatun version ympäristössä (tuleva) + +**Actor:** Kehittäjä +**Precondition:** Deployment on suoritettu + +**Main success:** +- Avaa Helm-repon commitin +- Näkee suoraan mikä konttiversio on deployattu +- Voi verrata mikropalvelun uusimpaan commitiin — onko ympäristö ajan tasalla? + +--- + +## UC6: Kehittäjä saa Gitea 1.27+ Summary-näkymän raporttilinkeistä (tuleva) + +**Actor:** Kehittäjä +**Precondition:** Gitea 1.27+ ja päivitetty runner + +**Main success:** +- Avaa workflow'n Gitea Actionsissa +- "Report Summary" -jobin Summary-välilehdellä näkyy taulukko linkeillä kaikkiin raportteihin +- Yhdellä silmäyksellä näkee mitä testejä ajettiin ja pääsee klikkaamalla raportteihin --- ## Ei-toiminnalliset vaatimukset | Vaatimus | Toteutus | -|----------|----------| -| Raportit selailtavissa HTML:nä | MinIO static web hosting | -| Linkki commitista suoraan raporttiin | Statusviestin `url`-kenttä | -| Build-indeksi per projekti | Generoitu `index.html` Minioon | -| Navigaatio raporttien välillä | "Back to build" / "Back to builds" — linkit indeksisivuilla | -| Cross-repo-navigaatio | Statusviestit linkittävät repoja ristiin | -| Raporttien pysyvyys | ConfigMap-pohjainen retention policy | -| Autentikointi | OIDC (Traefik middleware, Gitea OAuth2) | +|---|---| +| Raportit selailtavissa HTML:nä | git-pages static hosting | +| Linkki commitista suoraan raporttiin | Commit-status API:n `target_url` | +| Raporttien pysyvyys | git-pages retention sidecar | +| Virheiden propagointi | Gitea Actions `needs`-ketju | +| Pipeline-pysäytys virhetilanteessa | `needs` automaattinen skip | +| Exit-koodi ainoa totuus | ADR 0008 | +| Statusraportointi vain raporttilinkeille | ADR 0007 | diff --git a/docs/runner.md b/docs/runner.md index 665250d..348978e 100644 --- a/docs/runner.md +++ b/docs/runner.md @@ -18,7 +18,7 @@ Runnerilla on yksi vastuu: **suorittaa workflow-steppejä**. Kaikki runtime-ymp ## Kontit ja palvelut -Jokainen job voi määritellä käyttämänsä kontit. Tämä vastaa Jenkinsin pod template -konseptia, mutta on yksinkertaisempi: +Jokainen job voi määritellä käyttämänsä kontit. Eri jobeilla voi olla eri kontti: ### `container:` — ajonaikainen ympäristö @@ -99,13 +99,3 @@ Eri labelit mahdollistavat erikoistuneet runnerit (ARM, GPU, Windows), mutta MVP |------|-------|-------|--------------| | **Global** | Kaikki organisaatiot ja repot | Token-vuoto → hyökkääjä voi ajaa koodia missä tahansa | Jaettu infra, keskitetty hallinta | | **Organization** | Yhden organisaation repot | Rajoittuu yhteen orgiin | Per organisaatio, eristetty — **suositeltu** | - -## Jenkins-vertailu - -| Jenkins | Gitea Actions | -|---------|--------------| -| Pod template (YAML) määrittelee kontit | `container:` + `services:` per job | -| Jokaiselle jobille oma pod | Jokaiselle jobille omat konttimääritykset | -| DinD sidecar-podissa | `services: docker:dind` samassa jobissa | -| Agentti = erillinen JVM-prosessi | Runner = kevyt Go-binääri tai K8s-pod | -| Labelit Jenkins-nodessa | Labelit runner-rekisteröinnissä | diff --git a/docs/shared-scripts.md b/docs/shared-scripts.md index b50fa25..f173037 100644 --- a/docs/shared-scripts.md +++ b/docs/shared-scripts.md @@ -1,197 +1,141 @@ # Jaetut skriptit -> ⚠️ **POC-vaihe.** Osa kuvatuista skripteistä (push-reports.sh, tag-commit.sh) -> on suunniteltu mutta ei toteutettu. Toteutetut: `publish-git-pages.sh`, -> `report-status.sh`, `dispatch-workflow.sh` (POC-taso). -> -> Uudelleenkirjoitus odottaa: skriptien määrä ja rajapinnat voivat muuttua. - -Skriptit asuvat `gitea-ci-library/scripts/`-hakemistossa. +> Provider-skriptit asuvat `scripts/`-hakemistossa. Consumer-skriptit +> asuvat `.gitea/scripts/`-hakemistossa. ADR 0006. --- ## `report-status.sh` -POSTaa build-statuksen Gitea-commitin REST APIin. +POSTaa commit-statuksen Gitea REST APIin. Käytetään **vain** kun tarvitaan +custom-linkki (testiraportti, Docker registry). Tool-jobit luottavat +Gitean natiiviin job-statukseen. ADR 0007. ### Rajapinta ```bash -report-status.sh [key] [root_commit] [root_repo] +report-status.sh [suite] [custom_url] ``` | Parametri | Pakollinen | Kuvaus | -|-----------|------------|--------| -| `state` | Kyllä | `pending`, `success`, `failure`, `error` | -| `description` | Kyllä | Ihmisluettava kuvaus (esim. "Unit tests passed") | -| `url` | Kyllä | Linkki buildiin tai raporttiin | -| `key` | Ei | Uniikki avain. Oletus: `commit-{sha_short}` | -| `root_commit` | Ei | Root-buildin commit-hash (cross-repo-raportointia varten) | -| `root_repo` | Ei | Root-buildin repo (cross-repo-raportointia varten) | +|---|---|---| +| `state` | Kyllä | `pending`, `success`, `failure` | +| `description` | Kyllä | Ihmisluettava kuvaus | +| `context` | Kyllä | Uniikki avain (`unit-tests`, `acc-tests`, `ci-docker-build-push`) | +| `suite` | Ei | Julkaistun raportin suite-nimi → linkki git-pagesiin | +| `custom_url` | Ei | Oma URL (ohittaa oletus-URL:n generoinnin) | ### Kutsuesimerkkejä ```bash -# Buildin aloitus -report-status.sh pending "Building..." "$GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID" +# Testijobi, linkki git-pages-raporttiin +report-status.sh success "Link to Bats reports" unit-tests bats -# Testivaihe valmis, linkki raporttiin -report-status.sh success "Unit tests OK" "$MINIO_BASE_URL/$GITHUB_REPOSITORY/${GITHUB_SHA::8}/cucumber/overview-features.html" "unit-test" - -# Deployment valmis, cross-repo: raportoi takaisin mikropalvelun committiin -report-status.sh success "Deployed to staging" "$GITHUB_SERVER_URL/$GITHUB_REPOSITORY/commit/$GITHUB_SHA" "deploy-staging" "$ROOT_COMMIT" "$ROOT_REPO" +# Docker build, custom URL registryyn +report-status.sh success "Docker build & push 1.2.0 OK" ci-docker-build-push "" \ + "https://gitea.example.com/org/-/packages/container/app/1.2.0" ``` +### URL-generointi + +- Jos `suite` annettu → URL: `${GIT_PAGES_URL}/${repo}/reports/${sha8}/${suite}/` +- Jos `custom_url` annettu → käytetään sellaisenaan +- Muuten → URL: `${GITEA_API_URL}/${repo}/actions/runs/${run_id}` (Gitea Actions -loki) + ### Gitea API -kutsu ```bash curl -X POST "$GITEA_API_URL/api/v1/repos/$REPO/statuses/$COMMIT" \ -H "Authorization: token $GITEA_TOKEN" \ -H "Content-Type: application/json" \ - -d "{ - \"state\": \"$STATE\", - \"target_url\": \"$URL\", - \"description\": \"$DESCRIPTION\", - \"context\": \"$KEY\" - }" + -d "{\"state\":\"$STATE\",\"target_url\":\"$URL\",\"description\":\"$DESCRIPTION\",\"context\":\"$CONTEXT\"}" ``` -Status-arvot mapataan Gitean skeemaan: `pending` (INPROGRESS), `success` (SUCCESS), `failure` (FAILURE), `error` (STOPPED). +--- + +## `publish-git-pages.sh` + +Julkaisee raporttihakemiston git-pages-palveluun PATCH-tar:na. + +### Rajapinta + +```bash +publish-git-pages.sh +``` + +| Parametri | Pakollinen | Kuvaus | +|---|---|---| +| `suite` | Kyllä | Raporttihakemiston nimi (`bats`, `cucumber`, `junit`, ...) | + +### Toiminta + +1. Lukee raportit hakemistosta `reports/${SHA8}/${suite}/` +2. Pakkaa tar:ksi ja PATCHaa git-pagesiin BasicAuthilla +3. Tulostaa raportin base-URL:n stdoutiin + +### Vaaditut env-muuttujat + +| Muuttuja | Lähde | +|---|---| +| `GITEA_API_URL` | `env_json` → workflow `env:` | +| `GIT_PAGES_URL` | `env_json` → workflow `env:` | +| `GIT_PAGES_PUBLISH_TOKEN` | Gitea secret → `env:` | +| `GITHUB_REPOSITORY` | Automaattinen | +| `GITHUB_SHA` | Automaattinen | + +--- + +## `ci-validate.sh` + +Validoi `.conf`-tiedoston ja tarkistaa että pakolliset secretit on asetettu. +Kutsutaan `config-provider.yml`:stä osana konfiguraation latausta. + +### Rajapinta + +```bash +ci-validate.sh +``` + +Lukee tiedoston polun `CI_CONF_FILE`-env-muuttujasta (oletus: `.gitea/workflows/gitea-env.conf`). + +### Validointisäännöt + +- `.conf`-tiedosto on olemassa +- Jokaisella `KEY=VALUE`-rivillä on arvo (ei tyhjää) +- URL-tyyppiset avaimet alkavat `http://` tai `https://` +- `GITEA_TOKEN` on asetettu +- `GIT_PAGES_PUBLISH_TOKEN` on asetettu --- ## `dispatch-workflow.sh` Dispatchaa workflow'n toisessa repossa ja pollaa sen valmistumista synkronisesti. +Käytetään GitOps-deploymentissa ja klusteritestien ketjutuksessa (tuleva). ### Rajapinta ```bash -dispatch-workflow.sh [timeout_minutes] +dispatch-workflow.sh [timeout_minutes] ``` -| Parametri | Pakollinen | Kuvaus | -|-----------|------------|--------| -| `target_repo` | Kyllä | `owner/repo` | -| `workflow_file` | Kyllä | Workflow-tiedoston nimi (esim. `test.yml`) | -| `ref` | Kyllä | Branch | -| `inputs_json` | Kyllä | JSON-objekti input-parametreina | -| `gitea_api_url` | Kyllä | Gitean API-URL (esim. `https://gitea.example.com`) | -| `gitea_token` | Kyllä | Gitea API -token | -| `timeout_minutes` | Ei | Oletus: 360 (6 tuntia) | - ### Toiminta 1. **Dispatch:** `POST /api/v1/repos/{target_repo}/actions/workflows/{workflow_file}/dispatches` -2. **Etsi run:** `GET /api/v1/repos/{target_repo}/actions/runs?status=running` → etsi uusin (aikaleimasta) -3. **Poll:** `GET /api/v1/repos/{target_repo}/actions/runs/{run_id}` 10s välein -4. **Lopeta:** Kun `status == "completed"` → palauta `conclusion` (`success`/`failure`/`cancelled`) -5. **Timeout:** Jos kestää yli `timeout_minutes` → palauta `timeout` - -### Kutsuesimerkki - -```bash -dispatch-workflow.sh "tests/integration" "test.yml" "main" \ - '{"version":"1.2.3","tags":"@smoke","root_commit":"abc123","root_repo":"services/temperature-store"}' \ - "https://gitea.example.com" "gtp_abc123" -``` - ---- - -## `push-reports.sh` (vanhentunut — korvattu `publish-git-pages.sh`:lla) - -Puskaa raporttihakemiston git-pagesiin. - -### Rajapinta - -```bash -push-reports.sh [index_title] -``` - -| Parametri | Pakollinen | Kuvaus | -|-----------|------------|--------| -| `report_type` | Kyllä | Raportin tyyppi (`cucumber`, `jacoco`, `junit`, `site`) | -| `source_dir` | Kyllä | Paikallinen hakemisto, jossa raporttitiedostot | -| `index_title` | Ei | Näkyvä nimi indeksisivulla (esim. "Cucumber Reports") | - -### Toiminta - -1. Kopioi raportit: `mc cp --recursive {source_dir} minio/reports/{repo}/{commit_short}/{report_type}/` -2. Päivitä `/reports/{repo}/{commit_short}/index.html` — lisää linkki tähän raporttiin -3. Päivitä `/reports/{repo}/index.html` — varmista että tämä build on listalla -4. Palauta URL: `{MINIO_BASE_URL}/{repo}/{commit_short}/{report_type}/index.html` - -### Indeksisivut - -**Projektin build-indeksi** (`/reports/{repo}/index.html`): -- Lista buildeista aikajärjestyksessä (uusin ensin) -- Jokainen rivi: commit hash (linkki), päivämäärä, status (✅/❌), branch - -**Buildin raportti-indeksi** (`/reports/{repo}/{commit_short}/index.html`): -- Lista raporteista linkkeinä -- Linkki "← Back to builds" → projektin build-indeksiin - -Molemmat generoidaan uudestaan jokaisen pushauksen yhteydessä. Staattinen HTML, ei vaadi palvelinpuolen logiikkaa. - -### Kutsuesimerkki - -```bash -push-reports.sh cucumber target/cucumber-report "Cucumber Reports" -# → https://reports.example.com/temperature-store/abc12345/cucumber/overview-features.html - -push-reports.sh jacoco target/jacoco-report "JaCoCo Coverage" -# → https://reports.example.com/temperature-store/abc12345/jacoco/index.html -``` - ---- - -## `tag-commit.sh` - -Tagittaa commitin versiolla Gitea REST API:n kautta. - -### Rajapinta - -```bash -tag-commit.sh -``` - -### Toiminta - -```bash -curl -X POST "$GITEA_API_URL/api/v1/repos/$GITHUB_REPOSITORY/tags" \ - -H "Authorization: token $GITEA_TOKEN" \ - -H "Content-Type: application/json" \ - -d "{ - \"tag_name\": \"$VERSION\", - \"message\": \"Build #$GITHUB_RUN_NUMBER\", - \"target\": \"$GITHUB_SHA\" - }" -``` - -### Kutsu - -```bash -tag-commit.sh "1.2.3.$GITHUB_RUN_NUMBER" -``` - -Tagataan vain onnistuneen buildin ja pushin jälkeen. Tämän jälkeen `isContainerBuilt()` palauttaa `true` samalle commitille. +2. **Poll:** `GET /api/v1/repos/{target_repo}/actions/runs` → odota valmistumista +3. **Palauta:** `conclusion` (`success`/`failure`/`timeout`) --- ## Muuttujat, joita skriptit olettavat -Skriptit lukevat nämä Gitea Actionsin ympäristömuuttujat: - | Muuttuja | Lähde | Käyttäjä | -|----------|-------|----------| -| `GITEA_API_URL` | Org variable | `report-status.sh` | -| `GITEA_TOKEN` | Org secret | `report-status.sh`, `tag-commit.sh` | -| `MINIO_BASE_URL` | Org variable | `push-reports.sh` | -| `MINIO_ACCESS_KEY` | Org secret | `push-reports.sh` | -| `MINIO_SECRET_KEY` | Org secret | `push-reports.sh` | +|---|---|---| +| `GITEA_API_URL` | `env_json` | `report-status.sh`, `ci-validate.sh` | +| `GIT_PAGES_URL` | `env_json` | `publish-git-pages.sh`, `report-status.sh` | +| `GITEA_TOKEN` | Gitea secret | `report-status.sh`, `check-version.yml`, `docker-build-push.yml` | +| `GIT_PAGES_PUBLISH_TOKEN` | Gitea secret | `publish-git-pages.sh` | | `GITHUB_REPOSITORY` | Automaattinen | Kaikki skriptit | | `GITHUB_SHA` | Automaattinen | Kaikki skriptit | -| `GITHUB_SERVER_URL` | Automaattinen | `report-status.sh` | -| `GITHUB_RUN_ID` | Automaattinen | `report-status.sh`, `tag-commit.sh` | -| `GITHUB_RUN_NUMBER` | Automaattinen | `tag-commit.sh` | -| `GITHUB_ACTOR` | Automaattinen | Docker-labelit | +| `GITHUB_RUN_ID` | Automaattinen | `report-status.sh` | +| `GITHUB_RUN_NUMBER` | Automaattinen | `docker-build-push.yml` (tag-commit) | diff --git a/docs/tech-stack.md b/docs/tech-stack.md index 11217d4..94ff569 100644 --- a/docs/tech-stack.md +++ b/docs/tech-stack.md @@ -1,7 +1,6 @@ # Tech Stack — Gitea Actions CI -kirjasto -> ⚠️ POC-vaihe. Osa teknologiavalinnoista voi muuttua uudelleenkirjoituksen -> myötä. Katso myös `git-pages/docs/tech-stack.md`. +> Katso myös `git-pages/docs/tech-stack.md`. --- @@ -21,19 +20,22 @@ Raportit hostataan git-pages-palvelulla (`git-pages/`-Helm-chartti). Julkaisu: `scripts/publish-git-pages.sh` → PATCH tar. Tarkemmat teknologiavalinnat: `git-pages/docs/tech-stack.md`. +Tulevaisuus: `GITHUB_STEP_SUMMARY` (Gitea 1.27+) tarjoaa Summary-näkymän +suoraan Gitea UI:ssa. + ## Tuetut ulkoiset palvelut | Palvelu | Rajapinta | Käyttötarkoitus | |---|---|---| -| **Gitea REST API** | `/api/v1/` | Commit-status, workflow-dispatch, branch-listaus (retention) | -| **git-pages** | HTTP | Raporttien hostaus | +| **Gitea REST API** | `/api/v1/` | Commit-status, git-tagit, workflow-dispatch | +| **git-pages** | HTTP (PATCH tar) | Raporttien hostaus | | **Gitea Packages** | Container registry API | Docker-imagen push | -## Mitä EI tueta (verrattuna Jenkins-versioon) +## Mitä EI tueta | Teknologia | Syy | |---|---| -| **MinIO** | Korvattu git-pagesilla | -| **Multi-Git-platform** | Vain Gitea | -| **Jenkins** (shared library, plugins) | Gitea Actions korvaa | -| **Artifactory/Nexus** | MVP:ssä ei, factory/adapter-pattern valmiina | +| **Multi-Git-platform** | Vain Gitea — yksi alusta kunnolla (periaate 10) | +| **Custom actionit** | Reusable workflow on kevyempi ja natiivimpi (periaate 2) | +| **Ulkoinen orkestraattori** | Gitean `needs` + `if` hoitaa ohjauksen | +| **Artifactory/Nexus** | Gitea Packages riittää MVP:ssä |