diff --git a/.gitea/scripts/bats-coverage.sh b/.gitea/scripts/bats-coverage.sh
index 43c76d9..2529621 100755
--- a/.gitea/scripts/bats-coverage.sh
+++ b/.gitea/scripts/bats-coverage.sh
@@ -1,37 +1,11 @@
#!/usr/bin/env bash
set -euo pipefail
-WORKSPACE_VOLUME="${1:-}"
-REPORT_DIR="${2:-}"
+REPORT_DIR="${1:-}"
-[ -n "$WORKSPACE_VOLUME" ] || { echo "ERROR: workspace volume name required" >&2; exit 1; }
[ -n "$REPORT_DIR" ] || { echo "ERROR: report directory required" >&2; exit 1; }
-HAS_COVERAGE=false
-COVERAGE_SRC=""
-if docker run --rm -v "$WORKSPACE_VOLUME":/data alpine sh -c '[ -d /data/coverage ] && ls -A /data/coverage | grep -q .' 2>/dev/null; then
- COVERAGE_SRC="/data/coverage"
-fi
-
-if [ -n "$COVERAGE_SRC" ]; then
+if [ -d coverage ]; then
mkdir -p "$REPORT_DIR/coverage"
- docker run --rm -v "$WORKSPACE_VOLUME":/data alpine tar c -C "$COVERAGE_SRC" . | tar x -C "$REPORT_DIR/coverage"
- HAS_COVERAGE=true
+ cp -a coverage/. "$REPORT_DIR/coverage/"
fi
-
-cat > "$REPORT_DIR/index.html" << EOF
-
-Bats report ${GITHUB_SHA:0:8}
-
-Bats report ${GITHUB_SHA:0:8}
-' >> "$REPORT_DIR/index.html"
diff --git a/.gitea/workflows/example-bats-tests.yml b/.gitea/workflows/example-bats-tests.yml
index 9557334..8b78bc1 100644
--- a/.gitea/workflows/example-bats-tests.yml
+++ b/.gitea/workflows/example-bats-tests.yml
@@ -23,6 +23,8 @@ env:
jobs:
bats:
runs-on: ubuntu-latest
+ container:
+ image: ${{ inputs.bats-image }}
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v4
@@ -31,34 +33,16 @@ jobs:
path: .ci
- name: Run bats tests
- id: bats-tests
- shell: bash
run: |
- docker volume create bats-workspace
- tar c . | docker run --rm -i -v bats-workspace:/data alpine tar x -C /data
- mkdir -p "reports/${GITHUB_SHA:0:8}/bats"
- set +e
- docker run --rm \
- -v bats-workspace:/data \
- --entrypoint bash ${{ inputs.bats-image }} \
- -c 'cd /data && bashcov -- bats tests/' \
- > "reports/${GITHUB_SHA:0:8}/bats/results.txt" 2>&1
- BATS_EXIT=$?
- bash .ci/.gitea/scripts/bats-coverage.sh bats-workspace "reports/${GITHUB_SHA:0:8}/bats"
- docker volume rm bats-workspace > /dev/null 2>&1
- bash .ci/.gitea/scripts/bats-report.sh "reports/${GITHUB_SHA:0:8}/bats"
- echo "BATS_EXIT=${BATS_EXIT}" >> "${GITHUB_ENV}"
- exit ${BATS_EXIT}
+ mkdir -p reports/bats
+ bashcov -- bats tests/ > reports/bats/results.txt 2>&1
- - name: Publish bats reports
- if: always()
- run: bash .ci/scripts/publish-git-pages.sh bats
-
- - name: Report status
+ - name: Post-process reports
if: always()
run: |
- if [ "${BATS_EXIT}" = "0" ]; then
- bash .ci/scripts/report-status.sh success "Link to Bats reports" unit-tests bats
- else
- bash .ci/scripts/report-status.sh failure "Link to Bats reports" unit-tests bats
- fi
+ bash .ci/.gitea/scripts/bats-coverage.sh reports/bats
+ bash .ci/.gitea/scripts/bats-report.sh reports/bats
+
+ - name: Report
+ if: always()
+ run: bash .ci/scripts/ci-report.sh "Bats test report" unit-tests bats
diff --git a/.gitea/workflows/example-cucumber-tests.yml b/.gitea/workflows/example-cucumber-tests.yml
index 88fb68b..24acb58 100644
--- a/.gitea/workflows/example-cucumber-tests.yml
+++ b/.gitea/workflows/example-cucumber-tests.yml
@@ -33,36 +33,14 @@ jobs:
path: .ci
- name: Run cucumber tests
- id: cucumber-tests
shell: bash
run: |
- mkdir -p "reports/${GITHUB_SHA:0:8}/cucumber"
- set +e
+ mkdir -p reports/cucumber
npx cucumber-js \
- --format json:"reports/${GITHUB_SHA:0:8}/cucumber/report.json" \
- --format html:"reports/${GITHUB_SHA:0:8}/cucumber/index.html" 2>&1
- CUCUMBER_EXIT=$?
- echo "CUCUMBER_EXIT=${CUCUMBER_EXIT}" >> "${GITHUB_ENV}"
- exit ${CUCUMBER_EXIT}
+ --format json:reports/cucumber/report.json \
+ --format html:reports/cucumber/report.html 2>&1
- - name: Publish cucumber reports
- if: always()
- run: bash .ci/scripts/publish-git-pages.sh cucumber
-
- - name: Report status
+ - name: Report
if: always()
shell: bash
- run: |
- if [ "${CUCUMBER_EXIT}" = "0" ]; then
- if [ -f "reports/${GITHUB_SHA:0:8}/cucumber/index.html" ]; then
- bash .ci/scripts/report-status.sh success "Link to Cucumber reports" acc-tests cucumber
- else
- bash .ci/scripts/report-status.sh success "Link to Cucumber reports" acc-tests
- fi
- else
- if [ -f "reports/${GITHUB_SHA:0:8}/cucumber/index.html" ]; then
- bash .ci/scripts/report-status.sh failure "Link to Cucumber reports" acc-tests cucumber
- else
- bash .ci/scripts/report-status.sh failure "Link to Cucumber reports" acc-tests
- fi
- fi
+ run: bash .ci/scripts/ci-report.sh "Cucumber test report" acc-tests cucumber
diff --git a/scripts/ci-report.sh b/scripts/ci-report.sh
new file mode 100644
index 0000000..1e833ed
--- /dev/null
+++ b/scripts/ci-report.sh
@@ -0,0 +1,88 @@
+#!/usr/bin/env bash
+set -euo pipefail
+
+DESCRIPTION="${1:-}"
+CONTEXT="${2:-}"
+SUITE="${3:-}"
+
+[ -n "$DESCRIPTION" ] || { echo "ERROR: description argument required" >&2; exit 1; }
+[ -n "$CONTEXT" ] || { echo "ERROR: context argument required" >&2; exit 1; }
+[ -n "$SUITE" ] || { echo "ERROR: suite argument required" >&2; exit 1; }
+
+REPORT_DIR="reports/${SUITE}"
+
+if [ ! -d "$REPORT_DIR" ]; then
+ echo "ERROR: $REPORT_DIR not found" >&2
+ bash .ci/scripts/report-status.sh failure "$DESCRIPTION" "$CONTEXT"
+ exit 1
+fi
+
+cd "$REPORT_DIR"
+
+FILES=()
+while IFS= read -r -d '' f; do
+ FILES+=("$(basename "$f")")
+done < <(find . -maxdepth 1 -type f ! -name index.html -print0 2>/dev/null || true)
+
+SUBDIRS=()
+while IFS= read -r -d '' d; do
+ name="${d#./}"
+ [ -f "$name/index.html" ] && SUBDIRS+=("$name")
+done < <(find . -maxdepth 1 -type d ! -name . -print0 2>/dev/null || true)
+
+TOTAL=$(( ${#FILES[@]} + ${#SUBDIRS[@]} ))
+
+if [ "$TOTAL" -eq 0 ]; then
+ echo "ERROR: no reportable items in $REPORT_DIR" >&2
+ bash .ci/scripts/report-status.sh failure "$DESCRIPTION" "$CONTEXT"
+ exit 1
+fi
+
+SHA8="${GITHUB_SHA:0:8}"
+
+humanize() {
+ local name="$1"
+ name="${name%.*}"
+ name="${name//-/ }"
+ name="${name//_/ }"
+ echo "${name^}"
+}
+
+generate_index() {
+ local html
+ html=''
+ html+="$DESCRIPTION"
+ html+=''
+ html+="$DESCRIPTION
"
+ for f in "${FILES[@]}"; do
+ html+="- $(humanize "$f")
"
+ done
+ for d in "${SUBDIRS[@]}"; do
+ html+="- ${d^}
"
+ done
+ html+='
'
+ printf '%s' "$html" > index.html
+}
+
+cd - > /dev/null
+
+# Stage reports for backward-compatible publish
+STAGED="reports/${SHA8}/${SUITE}"
+mkdir -p "$STAGED"
+cp -a "$REPORT_DIR/." "$STAGED/"
+
+if [ "$TOTAL" -eq 1 ]; then
+ if [ ${#FILES[@]} -eq 1 ]; then
+ ENTRY="${FILES[0]}"
+ else
+ ENTRY="${SUBDIRS[0]}/index.html"
+ fi
+ bash .ci/scripts/publish-git-pages.sh "$SUITE"
+ URL="${GIT_PAGES_URL}/${GITHUB_REPOSITORY}/reports/${SHA8}/${SUITE}/${ENTRY}"
+ bash .ci/scripts/report-status.sh success "$DESCRIPTION" "$CONTEXT" "" "$URL"
+else
+ bash .ci/scripts/publish-git-pages.sh "$SUITE"
+ bash .ci/scripts/report-status.sh success "$DESCRIPTION" "$CONTEXT" "$SUITE"
+fi
+
+rm -rf "$STAGED"
diff --git a/skills/consumer-pipelines/SKILL.md b/skills/consumer-pipelines/SKILL.md
index 92ba264..732b99c 100644
--- a/skills/consumer-pipelines/SKILL.md
+++ b/skills/consumer-pipelines/SKILL.md
@@ -79,16 +79,14 @@ Ei monoliittista `ci-tests.yml`. Jokainen testityyppi tai operaatio on oma `work
## 3. Exit-koodin käsittely
-Jokainen testi kaappaa komentonsa exit-koodin eksplisiittisesti:
+`set -e` on oletuksena käytössä Gitea Actions -stepeissä — ensimmäinen feilaava komento pysäyttää stepin
+ja exit-koodi välittyy natiivisti. Ylimääräistä `EXIT=$?` + `echo >> GITHUB_ENV` -käärettä ei tarvita.
```yaml
- name: Run tests
shell: bash
run: |
> results.txt 2>&1
- EXIT=$?
- echo "EXIT=${EXIT}" >> "${GITHUB_ENV}"
- exit ${EXIT}
```
**Miksi ei pipeä (`| tee`):**
@@ -101,8 +99,8 @@ Jokainen testi kaappaa komentonsa exit-koodin eksplisiittisesti:
> results.txt 2>&1
```
-Ilman `EXIT=$?` + `exit ${EXIT}` komento voi feilata mutta job menee läpi vihreänä — `container:`-modessa
-shellin käyttäytyminen vaihtelee.
+`set -e` ei pelasta pipe-tilanteessa — `|` syö exit-koodin kuten ennenkin. Redirectillä exit-koodi
+välittyy luonnollisesti.
## 4. Konttipolitiikka
@@ -120,38 +118,15 @@ valmiin `ci-container-build-.yml`-pohjan jossa `workflow_dispatch`-tuki
### 4.1 CI-kontin ajaminen jobissa
-CI-kontin voi ajaa joko `container:`-direktiivillä (kaikki stepit kontissa)
-tai `docker run --rm`:llä stepin sisällä (checkout natiivisti). Molemmat tavat
-toimivat.
+Ainoa sallittu tapa on `container:`-direktiivi. `docker run` komennolla kontin
+käynnistäminen stepin sisällä on anti-pattern.
```yaml
-# Tapa A: container:-direktiivi
jobs:
:
runs-on: ubuntu-latest
container:
image: ${{ inputs. }}
- steps:
- - uses: actions/checkout@v4
- - uses: actions/checkout@v4
- with:
- repository: /gitea-ci-library
- path: .ci
- - name: Run
- shell: bash
- run: |
- mkdir -p "reports/${GITHUB_SHA:0:8}/"
- > "reports/${GITHUB_SHA:0:8}//results.txt" 2>&1
- EXIT=$?
- echo "EXIT=${EXIT}" >> "${GITHUB_ENV}"
- exit ${EXIT}
-```
-
-```yaml
-# Tapa B: docker run --rm stepin sisällä (kuten example-bats-tests.yml)
-jobs:
- :
- runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v4
@@ -162,86 +137,86 @@ jobs:
- name: Run
shell: bash
run: |
- docker volume create ws-
- tar c . | docker run --rm -i -v ws-:/data alpine tar x -C /data
- mkdir -p "reports/${GITHUB_SHA:0:8}/"
- set +e
- docker run --rm \
- -v ws-:/data \
- --entrypoint bash ${{ inputs. }} \
- -c 'cd /data && ' \
- > "reports/${GITHUB_SHA:0:8}//results.txt" 2>&1
- EXIT=$?
- docker volume rm ws- > /dev/null 2>&1
- echo "EXIT=${EXIT}" >> "${GITHUB_ENV}"
- exit ${EXIT}
+ mkdir -p "reports/"
+ > "reports//results.txt" 2>&1
- - name: Publish reports
- if: always()
- run: bash .ci/scripts/publish-git-pages.sh
-
- - name: Report status
+ - name: Post-process reports
if: always()
run: |
- if [ "${EXIT}" = "0" ]; then
- bash .ci/scripts/report-status.sh success ""
- else
- bash .ci/scripts/report-status.sh failure ""
- fi
+
+
+ - name: Report
+ if: always()
+ run: bash .ci/scripts/ci-report.sh ""
```
-**Malli:** `example-bats-tests.yml` (tapa B).
+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),
+se tehdään omassa stepissä `if: always()` — katso tarkemmin [Raporttitasot](#5-raporttitasot).
+
+**Mallit:**
+- `example-cucumber-tests.yml` — ei post-processia
+- `example-bats-tests.yml` — post-process coverage + report
## 5. Raporttitasot
-Testi tuottaa raportin `reports/${GITHUB_SHA:0:8}//`-hakemistoon. `publish-git-pages.sh` julkaisee sen,
-`report-status.sh` linkittää commit-statusin siihen. Molemmat `if: always()`.
+Testi tuottaa raportin `reports//`-hakemistoon. Yksi `ci-report.sh`-kutsu hoitaa sekä
+julkaisun että commit-statuksen — erillistä Publish + Report Status -kaksivaiheisuutta ei tarvita.
-### Taso 1: Pelkkä teksti
+### Taso 1: Ei jälkikäsittelyä
-Kun testi tuottaa vain stdout/stderr — tallennetaan `results.txt`:
+Kun testi tuottaa raportit suoraan (kuten `pytest --html` tai `cucumber-js --format html`):
```yaml
- name: Run tests
shell: bash
run: |
- mkdir -p "reports/${GITHUB_SHA:0:8}/"
- > "reports/${GITHUB_SHA:0:8}//results.txt" 2>&1
- EXIT=$?
- echo "EXIT=${EXIT}" >> "${GITHUB_ENV}"
- exit ${EXIT}
+ mkdir -p "reports/"
+
-- name: Publish reports
+- name: Report
if: always()
- shell: bash
- run: bash .ci/scripts/publish-git-pages.sh
+ run: bash .ci/scripts/ci-report.sh ""
+```
-- name: Report status
- if: always()
+### Taso 2: Jälkikäsittely tarvitaan
+
+Kun testi tuottaa raakadataa (stdout, coverage-tiedostot) joka pitää muuntaa tai siirtää
+`reports//`-hakemistoon, käytetään Post-process-steppiä:
+
+```yaml
+- name: Run tests
shell: bash
run: |
- if [ "${EXIT}" = "0" ]; then
- bash .ci/scripts/report-status.sh success ""
- else
- bash .ci/scripts/report-status.sh failure ""
- fi
+ mkdir -p "reports/"
+ > "reports//results.txt" 2>&1
+
+- name: Post-process reports
+ if: always()
+ run: |
+
+
+
+- name: Report
+ if: always()
+ run: bash .ci/scripts/ci-report.sh ""
```
-### Taso 2: HTML-raportti
+**Malli:** `example-bats-tests.yml`.
-Kun testi tuottaa strukturoitua dataa (JUnit XML, coverage, tms.) — generoidaan HTML ja `index.html`:
+### Monta raportoitavaa tiedostoa
+
+Kun `reports//`-hakemistossa on useita tiedostoja tai alihakemistoja,
+`ci-report.sh` generoi automaattisesti `reports//index.html` jos hakemistossa
+on enemmän kuin yksi raportoitava item.
```
-reports///
-├── index.html ← generoitu: linkit alla oleviin
+reports//
├── results.txt ← testin stdout
├── junit.xml ← testin JUnit XML -output
└── junit.html ← generoitu HTML (xsltproc, tms.)
```
-`index.html` linkittää kaikkiin raporttitiedostoihin. Selain avaa sen ja navigoi sieltä
-yksittäisiin raportteihin.
-
## 6. Nimeäminen
Tiedostonimet `.gitea/workflows/`-kansiossa noudattavat yhtenäistä rakennetta, jotta
@@ -457,8 +432,9 @@ Gitean Settings → Branches → Add Rule:
| Skripti | Käyttötarkoitus |
|---|---|
-| `report-status.sh` | POSTaa commit-statuksen linkillä |
-| `publish-git-pages.sh` | Julkaisee raporttihakemiston git-pagesiin |
+| `ci-report.sh` | Yhdistetty raportointi: julkaisee git-pagesiin ja asettaa commit-statuksen. Korvaa erilliset `publish-git-pages.sh` + `report-status.sh` -kutsut. Käyttö: `bash .ci/scripts/ci-report.sh "" ` |
+| `report-status.sh` | POSTaa commit-statuksen linkillä (kutsutaan `ci-report.sh`:n sisältä) |
+| `publish-git-pages.sh` | Julkaisee raporttihakemiston git-pagesiin (kutsutaan `ci-report.sh`:n sisältä) |
| `ci-validate.sh` | Validoi `.conf`-tiedoston (kutsutaan `config-provider.yml`:stä) |
---
@@ -499,7 +475,7 @@ Ei pipeä (`|`) komennon perässä — se syö exit-koodin. Käytä redirectiä
### Commit-status vain raporttilinkille (ADR 0007)
-`report-status.sh`-skriptiä käytetään VAIN kun on raportti linkitettäväksi.
+`ci-report.sh`-skriptiä käytetään VAIN kun on raportti linkitettäväksi.
Tool-jobit (build, deploy) luottavat Gitean natiiviin job-statukseen.
### Providerin checkout ei kuulu consumerille