# Reusable workflowt > ⚠️ **POC-vaihe.** Toteutettu: `quality-gate.yml`. Suunnitteilla: > `ci-master.yml`, `deploy.yml`, `test.yml`. --- ## Yhteiset konventiot Kaikki workflowt: - Käyttävät `concurrency:`-ryhmää estämään saman branchin rinnakkaiset ajot (vastaa Jenkins `disableConcurrentBuilds()`) - Lukevat konfiguraation `ci-flow-values.yaml`:sta - Raportoivat jokaisen vaiheen Gitea-commitin statukseen `report-status.sh`:lla - Käyttävät projektilta saatuja `with:`-parametreja konttien määrittelyyn (kirjasto ei pakota konttiversioita) --- ## `quality-gate.yml` — Merge-portti **Trigger:** `workflow_call` — consumer kutsuu `uses:`-direktiivillä **Rooli:** Laatuportti, joka ajetaan branch protection -sääntönä ennen PR:n sulkemista mainiin. Pipeline on ajettava (`run > 1`) eikä yhtään jobia saa failata. **Provider-Consumer-malli (ADR 0005):** Provider tarjoaa orkestroinnin (validointi, raporttien julkaisu, commit-status). Consumer omistaa pipeline-stepit — valitsee testityökalunsa, mahdolliset laatu- ja tietoturva-analyy sit sekä niiden järjestyksen. Alla oleva esimerkki kuvaa tyypillistä Java-mikropalvelua Mavenilla; consumer korvaa nämä omalla tekniikkapinollaan. ### Inputs (providerin rajapinta) | Parametri | Pakollinen | Tyyppi | Kuvaus | |-----------|------------|--------|--------| | `env_json` | Kyllä | string | JSON-muotoiset ympäristömuuttujat (`GITEA_API_URL`, `GIT_PAGES_URL`) | | `*` | — | — | Consumer lisää omat parametrinsa (`maven-image`, `docker-image`, jne.) | ### Secrets | Secret | Pakollinen | Kuvaus | |--------|------------|--------| | `GITEA_TOKEN` | Kyllä | Gitea API-kutsuihin (commit-status) | | `GIT_PAGES_PUBLISH_TOKEN` | Kyllä | Raporttien julkaisuun git-pagesiin | ### Steppi-kaavio (Java-esimerkki) ```mermaid %%{init: {'theme': 'base', 'flowchart': {'arrowheadScale': 2}}}%% flowchart TD VAL["validate provider: tarkista CI-konfiguraatio"] --> TEST["test consumer: mvn test → testiraportit + coverage"] VAL --> AI_SCAN["ai-scan \[optional\] consumer: tietoturva- tai laatu-skannaus"] TEST --> SONAR["sonarqube \[optional\] consumer: mvn sonar:sonar → laatupoikkeamat"] TEST --> PUB["publish-reports provider: vie raportit git-pagesiin"] SONAR --> PUB AI_SCAN --> PUB PUB --> STATUS["commit-status provider: aseta status linkillä raporttiin"] FAIL("fail") -. "if: always()" .-> PUB style VAL fill:#2563eb,color:#ffffff style TEST fill:#059669,color:#ffffff style SONAR fill:#7c3aed,color:#ffffff style AI_SCAN fill:#7c3aed,color:#ffffff style PUB fill:#0891b2,color:#ffffff style STATUS fill:#f59e0b,color:#111827 style FAIL fill:#dc2626,color:#ffffff linkStyle default stroke:#9ca3af,stroke-width:3px ``` Consumerin omat stepit (test, sonarqube, ai-scan) ovat esimerkki. Vastaava rakenne toimii millä tahansa kielellä tai työkalulla. ### Optionaaliset laatu- ja tietoturvaskannaukset Consumer voi lisätä pipelineen omia skannaussteppejä testien rinnalle. Nämä ajetaan rinnakkain `validate`-vaiheen jälkeen ja syöttävät raporttinsa providerin `publish-reports`-palveluun. Jokainen skannaus on oma Gitea Actions -jobinsa. ```mermaid %%{init: {'theme': 'base', 'flowchart': {'arrowheadScale': 2}}}%% flowchart LR VAL["validate"] --> SAST["sast semgrep / codeql"] VAL --> SCA["sca snyk / owasp dc"] VAL --> SECRETS["secret-scan gitleaks"] VAL --> LICENSE["license fossa / scancode"] VAL --> AI_REVIEW["ai-review code quality"] SAST --> PUB SCA --> PUB SECRETS --> PUB LICENSE --> PUB AI_REVIEW --> PUB PUB["publish-reports + commit-status"] style VAL fill:#2563eb,color:#ffffff style SAST fill:#7c3aed,color:#ffffff style SCA fill:#7c3aed,color:#ffffff style SECRETS fill:#7c3aed,color:#ffffff style LICENSE fill:#7c3aed,color:#ffffff style AI_REVIEW fill:#7c3aed,color:#ffffff style PUB fill:#0891b2,color:#ffffff linkStyle default stroke:#9ca3af,stroke-width:3px ``` | Kategoria | Esimerkki | Kuvaus | |-----------|-----------|--------| | **SAST** | Semgrep, CodeQL | Staattinen analyysi — bugit ja haavoittuvuudet koodista | | **SCA** | Snyk, OWASP Dependency-Check | Riippuvuuksien tunnetut haavoittuvuudet | | **Secret scan** | Gitleaks, TruffleHog | API-avaimet, tokenit ja salasanat repossa | | **Lisenssit** | FOSSA, ScanCode | Riippuvuuksien lisenssien yhteensopivuus | | **AI review** | — | Automaattinen koodikatselmointi | ### Error handling Providerin julkaisu- ja status-stepit käyttävät `if: always()`-ehtoa, jotta raportit ja commit-status päivittyvät myös failaavista ajoista. Consumerin omat stepit voivat vapaasti päättää `continue-on-error`- tai `if: failure()`-logiikastaan. Provider ei määrittele virheidenkäsittelyä consumerin pipelineen. ### Merge-portti Branch protection -säännössä Giteassa vaaditaan ennen PR:n sulkemista: - **Pipeline on ajettu** (`run > 1`, ei "never run" -tila) - **Kaikki commit-statukset vihreitä** — validate, testit, laatuportit - Jos joku steppi failaa, status asettuu `failure`-tilaan ja PR:n sulkeminen estyy ### Optionaalinen PR-ympäristö (preview app) Consumer voi halutessaan buildata kontin ja deployata sen väliaikaiseen PR-ympäristöön. Tämä on optionaalinen continuation-haara, joka aktivoituu ehdolla: - PR:ssä on tietty label (esim. `preview`) - Commit message sisältää triggerisanan (esim. `[preview]`) **Elinkaari:** ```mermaid %%{init: {'theme': 'base', 'flowchart': {'arrowheadScale': 2}}}%% flowchart LR QG["quality-gate testit + skannaukset ok"] --> BUILD["build-container tag: pr-42"] BUILD --> DEPLOY["deploy-pr-env väliaikainen ympäristö"] DEPLOY --> STATUS["commit-status linkki PR-ympäristöön"] PR_CLOSE["PR merged / closed"] --> CLEANUP["cleanup-pr-env tuhoa ympäristö"] style QG fill:#059669,color:#ffffff style BUILD fill:#0891b2,color:#ffffff style DEPLOY fill:#7c3aed,color:#ffffff style STATUS fill:#f59e0b,color:#111827 style PR_CLOSE fill:#dc2626,color:#ffffff style CLEANUP fill:#dc2626,color:#ffffff linkStyle default stroke:#9ca3af,stroke-width:3px ``` 1. Quality-gate läpäisty (testit + skannaukset ok) 2. Buildaa kontti, tagi sisältää PR-numeron (`pr-42`) 3. Deployaa PR-ympäristöön (preview/review app) 4. Asettaa commit-statuksen linkillä ympäristöön 5. **PR:n sulkeutuessa** (merge/close): cleanup-job tuhoaa ympäristön Tämä on **consumerin vastuulla** — provider tarjoaa tarvittavat skriptit (`publish-git-pages.sh`, `report-status.sh`), mutta trigger-ehto, kontin buildaus ja ympäristön hallinta kuuluvat consumerin pipelineen. --- ## `ci-master.yml` — Main-branch build **Trigger:** `workflow_call` — kutsutaan main-branchiin pushattaessa **Rooli:** Buildaa artifaktin (kontti, JAR, npm-paketti tms.) ja julkaisee sen rekisteriin. Jos sama commit on jo buildattu (version tag on olemassa), build skipataan ja siirrytään suoraan test flow'hun. **Provider-Consumer-malli (ADR 0005):** Provider orkestroi idempotent build-logiikan (`isArtifactBuilt`-tarkistus), mutta consumer omistaa build-stepit — valitsee työkalut ja artifaktityypin. ### isArtifactBuilt-check Ennen buildia tarkistetaan, onko tälle commitille jo olemassa versiotagi: ```bash TAG=$(git tag --points-at HEAD | grep -E '^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$' | head -1) if [ -n "$TAG" ]; then echo "artifact_already_built=true" >> $GITHUB_ENV echo "artifact_version=$TAG" >> $GITHUB_ENV fi ``` Jos tagi löytyy, build- ja push-stepit skipataan. Committia vastaan on jo olemassa artifakti rekisterissä — uudelleenbuildaus aiheuttaisi versiokonflikteja ja tuhlaisi CI-aikaa. ### Steppi-kaavio ```mermaid %%{init: {'theme': 'base', 'flowchart': {'arrowheadScale': 2}}}%% flowchart TD CHECK{"isArtifactBuilt? git tag --points-at HEAD"} CHECK -- "ei" --> QG["quality-gate testit + skannaukset"] QG --> BUILD["build-artifact consumer: docker build / mvn package / npm build"] BUILD --> PUSH["push registry gitea packages / docker registry"] PUSH --> TAG["tag-commit tagittaa commitin versiolla (esim. 1.2.3.${RUN})"] CHECK -- "kyllä" --> K8S["continueToTestFlow (future: K8s-testit test plan -mukaan)"] TAG --> K8S FAIL("fail") -. "quality-gate ei läpäisty" .-> END K8S --> END(["end commit-status"]) style CHECK fill:#f59e0b,color:#111827 style QG fill:#059669,color:#ffffff style BUILD fill:#0891b2,color:#ffffff style PUSH fill:#dc2626,color:#ffffff style TAG fill:#f59e0b,color:#111827 style K8S fill:#7c3aed,color:#ffffff style FAIL fill:#dc2626,color:#ffffff style END fill:#2563eb,color:#ffffff linkStyle default stroke:#9ca3af,stroke-width:3px ``` ### Elinkaari 1. **isArtifactBuilt?** — tarkista onko tagi olemassa 2. **quality-gate** — jos ei tagia, aja `quality-gate.yml` (testit, skannaukset) 3. **build-artifact** — jos quality-gate läpäisty, buildaa artifakti 4. **push registry** — julkaise rekisteriin (Gitea Packages, Docker registry, jne.) 5. **tag-commit** — tagittaa commitin versiolla (esim. `1.2.3.`) 6. **continueToTestFlow** — *(future)* aja K8s-testit test plan -mukaan 7. **commit-status** — aseta lopullinen status ### Concurrency ```yaml concurrency: group: master-${{ github.repository }} cancel-in-progress: false ``` Vain yksi master-build kerrallaan per repo. Ei cancel-in-progress — käynnissä olevan buildin annetaan valmistua. --- ## `deploy.yml` — GitOps-deployment **Trigger:** `workflow_dispatch` (aina dispatchataan toisesta workflow'sta) **Elinkaari:** ``` start → read-yaml → update-value → commit → push → report-cross-repo → end ``` ### Inputs (dispatch-parametrit) | Parametri | Kuvaus | |-----------|--------| | `environment` | Ympäristön nimi (korvaa `{.environment}`) | | `version` | Uusi konttiversio | | `root_commit` | Mikropalvelun commit josta deploy käynnistyi | | `root_repo` | Mikropalvelun repo | | `root_build_url` | URL mikropalvelun buildiin | ### Mitä deploy tekee 1. Lukee `{projectFolder}/{fileName}` YAML-tiedoston (korvaa `{.environment}` → `environment`) 2. Päivittää `{property}`-avaimen arvoksi `{version}` 3. `git add`, `git commit -m "deploy {version} to {environment}"` 4. `git push origin HEAD:master` 5. Raportoi statuksen: - Helm-repon committiin: **"from {root_commit}"**, URL → root-build - Mikropalvelun committiin (`root_commit`): **"deployed to {environment}"**, URL → Helm-commit 6. Palauttaa Helm-commitin hashin (`outputs.commit`) ### Concurrency ```yaml concurrency: group: deploy-${{ github.repository }}-${{ inputs.environment }} cancel-in-progress: false ``` --- ## `test.yml` — Test flow -steppi **Trigger:** `workflow_dispatch` (dispatchataan deploy-workflow'n jälkeen) **Elinkaari:** ``` start → version-check → run-tests → push-reports → report-cross-repo → end ``` ### Inputs (dispatch-parametrit) | Parametri | Kuvaus | |-----------|--------| | `environment` | Testiympäristö | | `version` | Testattava konttiversio | | `tags` | Cucumber-tagit | | `versionApiUrl` | URL version tarkistukseen | | `versionCheckScript` | Polku version check -skriptiin | | `root_commit` | Mikropalvelun commit | | `root_repo` | Mikropalvelun repo | | `deploy_commit` | Helm-repon commit (deployattu versio) | | `deploy_repo` | Helm-repo | ### Version check Ennen testejä varmistetaan, että ympäristössä pyörii oikea versio: ```yaml - name: Check deployed version if: inputs.versionCheckScript || inputs.versionApiUrl run: | if [ -n "${{ inputs.versionCheckScript }}" ]; then bash "${{ inputs.versionCheckScript }}" "${{ inputs.versionApiUrl }}" "${{ inputs.version }}" fi ``` Version check -skripti pollaa Fibonacci-backoffilla — ks. [config-model.md](config-model.md). ### Cross-repo-raportointi Testien jälkeen raportoidaan kolmeen committiin: 1. Testi-repon oma commit: testin status 2. Mikropalvelun commit (`root_commit`): "testit OK/epäonnistui" 3. Helm-repon commit (`deploy_commit`): "testattu v{version}" ### Concurrency ```yaml concurrency: group: test-${{ inputs.environment }} cancel-in-progress: false ```