391 lines
12 KiB
Markdown
391 lines
12 KiB
Markdown
# 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.<run_number>`)
|
|
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
|
|
```
|