Compare commits
2 Commits
11ca47cf1b
..
0.2.10
| Author | SHA1 | Date | |
|---|---|---|---|
| 1e10633e60 | |||
| 737b2fc3f2 |
@@ -2,10 +2,28 @@
|
||||
set -euo pipefail
|
||||
|
||||
REPORT_DIR="${1:-}"
|
||||
COVERAGE_DIR="${REPORT_DIR}/coverage"
|
||||
|
||||
[ -n "$REPORT_DIR" ] || { echo "ERROR: report directory required" >&2; exit 1; }
|
||||
|
||||
if [ -d coverage ]; then
|
||||
mkdir -p "$REPORT_DIR/coverage"
|
||||
cp -a coverage/. "$REPORT_DIR/coverage/"
|
||||
mkdir -p "$COVERAGE_DIR"
|
||||
cp -a coverage/. "$COVERAGE_DIR/"
|
||||
fi
|
||||
|
||||
if [ -d "$COVERAGE_DIR" ] && [ ! -f "$COVERAGE_DIR/index.html" ]; then
|
||||
SHA8="${GITHUB_SHA:0:8}"
|
||||
{
|
||||
echo '<!DOCTYPE html><html lang="en"><head><meta charset="utf-8">'
|
||||
echo "<title>Coverage report ${SHA8}</title>"
|
||||
echo '<style>body{font-family:sans-serif;margin:2em}h1{color:#1e293b}ul{list-style:none;padding:0}li{margin:.5em 0}a{color:#2563eb}</style>'
|
||||
echo "</head><body><h1>Coverage report <code>${SHA8}</code></h1><ul>"
|
||||
while IFS= read -r -d '' f; do
|
||||
base=$(basename "$f")
|
||||
name="${base%.*}"
|
||||
name="${name//-/ }"
|
||||
echo "<li><a href=\"${base}\">${name^}</a></li>"
|
||||
done < <(find "$COVERAGE_DIR" -maxdepth 1 -type f \( -name '*.html' -o -name '*.txt' \) ! -name index.html -print0 2>/dev/null || true)
|
||||
echo '</ul></body></html>'
|
||||
} > "$COVERAGE_DIR/index.html"
|
||||
fi
|
||||
|
||||
@@ -6,8 +6,9 @@ on:
|
||||
required: true
|
||||
type: string
|
||||
bats-image:
|
||||
required: true
|
||||
required: false
|
||||
type: string
|
||||
default: gitea.app.keskikuja.site/niko/ci-bats:latest
|
||||
secrets:
|
||||
GITEA_TOKEN:
|
||||
required: true
|
||||
@@ -37,11 +38,13 @@ jobs:
|
||||
mkdir -p reports/bats
|
||||
bashcov -- bats tests/ > reports/bats/results.txt 2>&1
|
||||
|
||||
- name: Post-process reports
|
||||
- name: Post-process coverage
|
||||
if: always()
|
||||
run: |
|
||||
bash .ci/.gitea/scripts/bats-coverage.sh reports/bats
|
||||
bash .ci/.gitea/scripts/bats-report.sh reports/bats
|
||||
run: bash .ci/.gitea/scripts/bats-coverage.sh reports/bats
|
||||
|
||||
- name: Post-process test report
|
||||
if: always()
|
||||
run: bash .ci/.gitea/scripts/bats-report.sh reports/bats
|
||||
|
||||
- name: Report
|
||||
if: always()
|
||||
|
||||
@@ -25,14 +25,14 @@ on:
|
||||
|
||||
jobs:
|
||||
load-config:
|
||||
uses: niko/gitea-ci-library/.gitea/workflows/config-provider.yml@v1
|
||||
uses: niko/gitea-ci-library/.gitea/workflows/config-provider.yml@main
|
||||
secrets: inherit
|
||||
with:
|
||||
config_path: ${{ inputs.config_path }}
|
||||
|
||||
build-push:
|
||||
needs: [load-config]
|
||||
uses: niko/gitea-ci-library/.gitea/workflows/ci-container-build-push.yml@v1
|
||||
uses: niko/gitea-ci-library/.gitea/workflows/ci-container-build-push.yml@main
|
||||
secrets: inherit
|
||||
with:
|
||||
env_json: ${{ needs.load-config.outputs.env_json }}
|
||||
|
||||
@@ -6,8 +6,9 @@ on:
|
||||
required: true
|
||||
type: string
|
||||
cucumber-node-image:
|
||||
required: true
|
||||
required: false
|
||||
type: string
|
||||
default: gitea.app.keskikuja.site/niko/ci-cucumber:latest
|
||||
secrets:
|
||||
GITEA_TOKEN:
|
||||
required: true
|
||||
@@ -37,8 +38,8 @@ jobs:
|
||||
run: |
|
||||
mkdir -p reports/cucumber
|
||||
npx cucumber-js \
|
||||
--format json:reports/cucumber/report.json \
|
||||
--format html:reports/cucumber/report.html 2>&1
|
||||
--format json:reports/cucumber/results.json \
|
||||
--format html:reports/cucumber/test-report.html 2>&1
|
||||
|
||||
- name: Report
|
||||
if: always()
|
||||
|
||||
@@ -20,7 +20,6 @@ jobs:
|
||||
secrets: inherit
|
||||
with:
|
||||
env_json: ${{ needs.load-config.outputs.env_json }}
|
||||
bats-image: gitea.app.keskikuja.site/niko/ci-bats:latest
|
||||
|
||||
cucumber:
|
||||
name: Cucumber tests
|
||||
@@ -29,7 +28,6 @@ jobs:
|
||||
secrets: inherit
|
||||
with:
|
||||
env_json: ${{ needs.load-config.outputs.env_json }}
|
||||
cucumber-node-image: gitea.app.keskikuja.site/niko/ci-cucumber:latest
|
||||
|
||||
report-summary:
|
||||
name: Report Summary
|
||||
|
||||
@@ -29,7 +29,6 @@ jobs:
|
||||
secrets: inherit
|
||||
with:
|
||||
env_json: ${{ needs.load-config.outputs.env_json }}
|
||||
bats-image: gitea.app.keskikuja.site/niko/ci-bats:latest
|
||||
|
||||
cucumber:
|
||||
name: Cucumber tests
|
||||
@@ -39,7 +38,6 @@ jobs:
|
||||
secrets: inherit
|
||||
with:
|
||||
env_json: ${{ needs.load-config.outputs.env_json }}
|
||||
cucumber-node-image: gitea.app.keskikuja.site/niko/ci-cucumber:latest
|
||||
|
||||
build-push:
|
||||
name: Build & Push Docker
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
FROM bats/bats:latest
|
||||
RUN apk add --no-cache lsof python3 jq curl ruby && \
|
||||
FROM bats/bats:1.11.0
|
||||
RUN apk add --no-cache lsof python3 jq curl ruby nodejs && \
|
||||
gem install bashcov -v 3.3.0
|
||||
|
||||
@@ -123,8 +123,8 @@ Hae token Giteasta:
|
||||
|
||||
```bash
|
||||
GITEA_URL="https://<gitea-server-url>"
|
||||
GITEA_ACTIONS_TOKEN="<registration-token>"
|
||||
GITEA_ACTIONS_NAMESPACE="gitea-actions"
|
||||
GITEA_ACTIONS_TOKEN="<registration-token>"
|
||||
```
|
||||
|
||||
### 3. Tee secret vain init install yhteydessä
|
||||
@@ -158,6 +158,7 @@ helm upgrade --install act-runner gitea/actions \
|
||||
--set giteaRootURL="$GITEA_URL" \
|
||||
--set existingSecret=act-runner-token \
|
||||
--set existingSecretKey=token \
|
||||
--set statefulset.replicas=3 \
|
||||
--set statefulset.runner.tag=1.0.8 \
|
||||
--set statefulset.dind.tag=29.5.2-dind \
|
||||
--set-string 'statefulset.runner.config=log:
|
||||
|
||||
@@ -33,7 +33,42 @@ else
|
||||
fi
|
||||
mkdir -p "$TARGET"
|
||||
cp -a "$REPORT_DIR/." "$TARGET/"
|
||||
cat > "$WORK/${OWNER}/${REPO}/reports/${SHA8}/.meta" <<EOF
|
||||
if [ ! -f "$TARGET/index.html" ]; then
|
||||
items=()
|
||||
while IFS= read -r -d '' f; do
|
||||
items+=("$(basename "$f")")
|
||||
done < <(find "$TARGET" -maxdepth 1 -type f ! -name index.html -print0 2>/dev/null || true)
|
||||
while IFS= read -r -d '' d; do
|
||||
name=$(basename "$d")
|
||||
[ -f "$d/index.html" ] && items+=("$name")
|
||||
done < <(find "$TARGET" -maxdepth 1 -type d ! -name . -print0 2>/dev/null || true)
|
||||
|
||||
if [ ${#items[@]} -gt 1 ]; then
|
||||
{
|
||||
echo '<!DOCTYPE html><html lang="en"><head><meta charset="utf-8">'
|
||||
echo "<title>Test report ${SHA8}</title>"
|
||||
echo '<style>body{font-family:sans-serif;margin:2em;max-width:960px}'
|
||||
echo 'h1{color:#1e293b}ul{list-style:none;padding:0}'
|
||||
echo 'li{margin:.5em 0;padding:.5em;background:#f8fafc;border-radius:6px}'
|
||||
echo 'a{color:#2563eb;text-decoration:none}a:hover{text-decoration:underline}'
|
||||
echo '</style></head><body>'
|
||||
echo "<h1>Test report <code>${SHA8}</code></h1><ul>"
|
||||
for item in "${items[@]}"; do
|
||||
label="${item%.*}"
|
||||
label="${label//-/ }"
|
||||
label="${label//_/ }"
|
||||
if [ -f "$TARGET/$item" ]; then
|
||||
echo "<li><a href=\"$item\">${label^}</a></li>"
|
||||
else
|
||||
echo "<li><a href=\"$item/index.html\">${label^}</a></li>"
|
||||
fi
|
||||
done
|
||||
echo '</ul></body></html>'
|
||||
} > "$TARGET/index.html"
|
||||
fi
|
||||
fi
|
||||
|
||||
cat > "$TARGET/.meta" <<EOF
|
||||
{"branch":"${GITHUB_REF_NAME:-}","sha":"${GITHUB_SHA}","published_at":"$(date -u +%Y-%m-%dT%H:%M:%SZ)"}
|
||||
EOF
|
||||
find "$WORK/$OWNER" \( -type f -o -type l \) -print | sed "s|^${WORK}/||" | tar -cf "$TAR" -C "$WORK" -T -
|
||||
|
||||
@@ -102,6 +102,27 @@ ja exit-koodi välittyy natiivisti. Ylimääräistä `EXIT=$?` + `echo >> GITHUB
|
||||
`set -e` ei pelasta pipe-tilanteessa — `|` syö exit-koodin kuten ennenkin. Redirectillä exit-koodi
|
||||
välittyy luonnollisesti.
|
||||
|
||||
**Yksi asia per step:** Älä koskaan niputa useaa post-process-komentoa samaan `run:`-blockiin.
|
||||
`bash -e` pysäyttää koko stepin jos yksi komento epäonnistuu — seuraavat jäävät ajamatta.
|
||||
Käytä erillisiä steppejä `if: always()`:lla, jotta jokainen vaihe ajetaan itsenäisesti:
|
||||
|
||||
```yaml
|
||||
# VÄÄRIN — jos coverage epäonnistuu, report jää generoimatta
|
||||
- name: Post-process reports
|
||||
run: |
|
||||
bash .ci/.gitea/scripts/bats-coverage.sh reports/bats
|
||||
bash .ci/.gitea/scripts/bats-report.sh reports/bats
|
||||
|
||||
# OIKEIN — erilliset stepit if: always()
|
||||
- name: Post-process coverage
|
||||
if: always()
|
||||
run: bash .ci/.gitea/scripts/bats-coverage.sh reports/bats
|
||||
|
||||
- name: Post-process test report
|
||||
if: always()
|
||||
run: bash .ci/.gitea/scripts/bats-report.sh reports/bats
|
||||
```
|
||||
|
||||
## 4. Konttipolitiikka
|
||||
|
||||
1. **Julkiset registry-kontit kiinteällä versiolla** — `alpine/helm:3.19.0`, `node:22`, `maven:3.9-eclipse-temurin-21`.
|
||||
@@ -112,6 +133,9 @@ välittyy luonnollisesti.
|
||||
`latest` on näille paras käytäntö, ei kompromissi
|
||||
3. **Ei koskaan `curl`-latauksia CI-ajon sisällä** — työkalujen asennus CI-stepeissä hidastaa,
|
||||
epäluotettavaa, ja vaikeuttaa toistettavuutta
|
||||
4. **Konttikuva hallitaan workflow'ssa, ei kutsujassa** — jos workflow vaatii tietyn
|
||||
konttikuvan, se määritellään oletuksena (`default:`) workflow'n inputissa.
|
||||
Kutsujan ei tarvitse tietää eikä välittää image-nimeä ellei halua ylikirjoittaa.
|
||||
|
||||
CI-kontin build-workflow'n template: [skills/ci-container-build/SKILL.md](../ci-container-build/SKILL.md) — sisältää
|
||||
valmiin `ci-container-build-<kontti>.yml`-pohjan jossa `workflow_dispatch`-tuki manuaaliajoon.
|
||||
@@ -121,6 +145,15 @@ valmiin `ci-container-build-<kontti>.yml`-pohjan jossa `workflow_dispatch`-tuki
|
||||
Ainoa sallittu tapa on `container:`-direktiivi. `docker run` komennolla kontin
|
||||
käynnistäminen stepin sisällä on anti-pattern.
|
||||
|
||||
**Miksi:** `docker run` erilliskonttina aiheuttaa:
|
||||
- Tiedostojen jako vaatii erillisen volyyminhallinnan (`docker volume create`)
|
||||
- Coverage-data jää volyymiin, ei filesystemille → post-process-skriptit eivät löydä sitä
|
||||
- Ylimääräisiä siirtoja (`tar`, `docker cp`), jotka voivat epäonnistua hiljaa
|
||||
- Vaikeampi debugata (data on kontissa, ei CWD:ssä)
|
||||
|
||||
`container:`-direktiivillä kaikki ajetaan samassa kontissa — tiedostot ovat suoraan
|
||||
filesystemillä, post-process-skriptit näkevät ne ilman erillistä siirtoa.
|
||||
|
||||
```yaml
|
||||
jobs:
|
||||
<työkalu>:
|
||||
@@ -151,7 +184,7 @@ jobs:
|
||||
```
|
||||
|
||||
Jos testi tuottaa raportteja suoraan ilman jälkikäsittelyä, Post-process-steppiä ei tarvita.
|
||||
Jos jälkikäsittely on tarpeen (coverage-extraktio, HTML-generointi raa'asta outputista),
|
||||
Jos jälkikäsittely on tarpeen (coverage-siirto, HTML-generointi raa'asta outputista),
|
||||
se tehdään omassa stepissä `if: always()` — katso tarkemmin [Raporttitasot](#5-raporttitasot).
|
||||
|
||||
**Mallit:**
|
||||
@@ -182,7 +215,8 @@ Kun testi tuottaa raportit suoraan (kuten `pytest --html` tai `cucumber-js --for
|
||||
### Taso 2: Jälkikäsittely tarvitaan
|
||||
|
||||
Kun testi tuottaa raakadataa (stdout, coverage-tiedostot) joka pitää muuntaa tai siirtää
|
||||
`reports/<suite>/`-hakemistoon, käytetään Post-process-steppiä:
|
||||
`reports/<suite>/`-hakemistoon, käytetään Post-process-steppejä. **Jokainen operaatio
|
||||
omassa stepissään** — älä koskaan niputa useaa post-process-komentoa samaan `run:`-blockiin:
|
||||
|
||||
```yaml
|
||||
- name: Run tests
|
||||
@@ -191,18 +225,29 @@ Kun testi tuottaa raakadataa (stdout, coverage-tiedostot) joka pitää muuntaa t
|
||||
mkdir -p "reports/<suite>"
|
||||
<testikomento> > "reports/<suite>/results.txt" 2>&1
|
||||
|
||||
- name: Post-process reports
|
||||
- name: Post-process coverage
|
||||
if: always()
|
||||
run: |
|
||||
<coverage-extraktio>
|
||||
<HTML-generointi raa'asta outputista>
|
||||
run: <siirrä coverage-data reports/<suite>/coverage/-hakemistoon>
|
||||
|
||||
- name: Post-process test report
|
||||
if: always()
|
||||
run: <HTML-generointi raa'asta outputista>
|
||||
|
||||
- name: Report
|
||||
if: always()
|
||||
run: bash .ci/scripts/ci-report.sh "<kuvaus>" <context> <suite>
|
||||
```
|
||||
|
||||
**Malli:** `example-bats-tests.yml`.
|
||||
**Huomio subdir-sisällöstä:** Jos testi tuottaa dataa alihakemistoon (esim.
|
||||
coverage `./coverage/`-kansioon), se pitää erikseen SIIRTÄÄ
|
||||
`reports/<suite>/<subdir>/`-hakemistoon ennen `ci-report.sh`:n ajoa.
|
||||
Ilman siirtoa sisältö ei näy index-sivulla, vaikka työkalu tuottaisi sen oikein.
|
||||
Subdir vaatii lisäksi `index.html`:n, jotta `ci-report.sh` löytää sen.
|
||||
|
||||
**Miksi:** Gitea Actions käyttää `bash -e`-oletusta. Jos yksi post-process-komento
|
||||
epäonnistuu (esim. `set -euo pipefail`-skripti), koko stepi pysähtyy eivätkä seuraavat
|
||||
komennot käynnisty — raportti jää julkaisematta. Erilliset stepit `if: always()` takaavat
|
||||
että jokainen post-process-vaihe ajetaan itsenäisesti.
|
||||
|
||||
### Monta raportoitavaa tiedostoa
|
||||
|
||||
@@ -212,12 +257,92 @@ on enemmän kuin yksi raportoitava item.
|
||||
|
||||
```
|
||||
reports/<suite>/
|
||||
├── results.txt ← testin stdout
|
||||
├── junit.xml ← testin JUnit XML -output
|
||||
└── junit.html ← generoitu HTML (xsltproc, tms.)
|
||||
├── results.txt ← testin stdout (skannataan FILES)
|
||||
├── test-report.html ← generoitu HTML (skannataan FILES)
|
||||
└── <mikä tahansa>/ ← alihakemisto (skannataan SUBDIRS)
|
||||
└── index.html ← VAIN jos tämä on olemassa
|
||||
```
|
||||
|
||||
## 6. Nimeäminen
|
||||
**Subdir-sääntö:** Alihakemisto näkyy indexissä VAIN jos se sisältää `index.html`:n.
|
||||
Pelkkä tyhjä subdir ilman `index.html`:ää ei näy — tämä on yleisin syy miksi
|
||||
jokin raportin osa (kuten coverage) puuttuu indexistä.
|
||||
|
||||
## 6. Raportin julkaisukelpoisuus
|
||||
|
||||
`ci-report.sh` päättää onko raportti julkaisukelpoinen skannaamalla
|
||||
`reports/<suite>/`-hakemistoa.
|
||||
|
||||
### Mitä skannataan
|
||||
|
||||
| Mitä | Sääntö |
|
||||
|---|---|
|
||||
| **Tiedostot (FILES)** | Kaikki `reports/<suite>/`-juuressa olevat tiedostot paitsi `index.html` |
|
||||
| **Alihakemistot (SUBDIRS)** | Vain ne, joissa on `index.html` |
|
||||
|
||||
### Julkaisukelpoisuus
|
||||
|
||||
| Tila | Seuraus |
|
||||
|---|---|
|
||||
| `FILES + SUBDIRS = 0` | **Failure** — `ci-report.sh` palauttaa virheen, raporttia ei julkaista |
|
||||
| `FILES + SUBDIRS = 1` | Suora linkki itemiin — ei generoi index-sivua |
|
||||
| `FILES + SUBDIRS > 1` | Generoi `reports/<suite>/index.html`-sivun, linkit kaikkiin itemeihin |
|
||||
|
||||
### Esimerkki: coverage-näkymä
|
||||
|
||||
```
|
||||
reports/<suite>/coverage/index.html ← on olemassa
|
||||
```
|
||||
|
||||
Coverage-dataa ei siirretä automaattisesti. Testin tai post-process-stepin pitää
|
||||
siirtää coverage `reports/<suite>/coverage/`-hakemistoon ja varmistaa että
|
||||
`index.html` on mukana. Sama periaate pätee mihin tahansa subdir-sisältöön.
|
||||
|
||||
## 7. Debug-ohje: raportti ei näy
|
||||
|
||||
### 1. Aja lokaalisti samalla komennolla kuin CI
|
||||
|
||||
Näet mitä tiedostoja syntyy, mihin ne tulevat ja mikä on työkalun exit-koodi.
|
||||
|
||||
```bash
|
||||
# Esimerkki
|
||||
mkdir -p reports/bats
|
||||
bashcov -- bats tests/ > reports/bats/results.txt 2>&1
|
||||
echo "exit: $?"
|
||||
ls -la reports/bats/
|
||||
```
|
||||
|
||||
### 2. Lisää `echo "DEBUG: ..." >&2` ennen ja jälkeen kriittisen operaation
|
||||
|
||||
Debuggaus stderriin (`>&2`) näkyy CI-logissa eikä häiritse skriptin normaalia outputia.
|
||||
|
||||
```bash
|
||||
echo "DEBUG: coverage exists? $([ -d coverage ] && echo YES || echo NO)" >&2
|
||||
echo "DEBUG: target/index.html exists? $([ -f reports/suite/coverage/index.html ] && echo YES || echo NO)" >&2
|
||||
```
|
||||
|
||||
### 3. Tarkista kutsuparametrit
|
||||
|
||||
Yleisin virhe: skripti odottaa `$1` = X, mutta kutsuja antaa `$1` = Y ja `$2` = X.
|
||||
Skripti lukee väärän parametrin ja etsii dataa väärästä paikasta.
|
||||
|
||||
### 4. Tarkista tiedostopolut
|
||||
|
||||
1. Onko lähdetiedosto olemassa ennen kopiointia?
|
||||
2. Onko kohde olemassa kopioinnin jälkeen?
|
||||
3. Onko `index.html` subdirissä (vaaditaan `ci-report.sh`:lle)?
|
||||
|
||||
Jos vastaus johonkin on "ei" — tiedät mikä pitää korjata.
|
||||
|
||||
### 5. Poista debug-echot kun ongelma on korjattu
|
||||
|
||||
Debug-rivit eivät kuulu tuotantoon.
|
||||
|
||||
### 6. Älä kokeile — debuggaa
|
||||
|
||||
Kokeilu = arvaus. Debuggaus = lisää echo, aja, lue logi, eristä ongelma.
|
||||
Vasta sitten korjaa. Tämä on nopeampi tie oikeaan ratkaisuun.
|
||||
|
||||
## 8. Nimeäminen
|
||||
|
||||
Tiedostonimet `.gitea/workflows/`-kansiossa noudattavat yhtenäistä rakennetta, jotta
|
||||
tiedostot löytyvät nopeasti ja niiden rooli on selvillä:
|
||||
@@ -236,7 +361,7 @@ Single repossa `<komponentti>` jätetään pois — tiedostot ovat suoraan `ci-f
|
||||
Monorepossa prefiksi pitää komponentin tiedostot yhdessä: `ls <komponentti>.*` löytää kaikki
|
||||
kerralla.
|
||||
|
||||
## 7. Artifact-kuri
|
||||
## 9. Artifact-kuri
|
||||
|
||||
Gitea Actionsin `upload-artifact` jättää pysyvän tiedoston. Artifakteja ei käytetä
|
||||
workflow_call:ien väliseen datan siirtoon ellei se ole teknisesti välttämätöntä.
|
||||
|
||||
Reference in New Issue
Block a user