Compare commits

..

6 Commits

Author SHA1 Message Date
moilanik 038e5405b6 secret ohje päivittynyt
CI Feature / Load example-gitea-env.conf to pipeline env (push) Successful in 17s
CI Feature / Bats tests (push) Failing after 1m23s
CI Feature / Cucumber tests (push) Failing after 1m23s
CI Feature / Report Summary (push) Successful in 3s
2026-06-28 05:54:31 +03:00
moilanik 179f6a1b43 publish -> link -> read testattu "e2e"
port forward, local publish ja luettu tämän repon linkin luomisen mallisella url julkaistu raportti
2026-06-28 05:27:42 +03:00
moilanik 5e2c50d67e v4 2026-06-28 04:40:58 +03:00
moilanik c354afc8d7 v3 2026-06-28 04:27:38 +03:00
moilanik d01866fcfb v2 2026-06-28 04:02:23 +03:00
moilanik 7d83ea42f1 v1 2026-06-28 04:02:17 +03:00
43 changed files with 401 additions and 268 deletions
+2 -2
View File
@@ -8,7 +8,7 @@ on:
secrets: secrets:
GITEA_TOKEN: GITEA_TOKEN:
required: true required: true
REPORTS_PUBLISH_TOKEN: GIT_PAGES_PUBLISH_TOKEN:
required: true required: true
outputs: outputs:
env_json: env_json:
@@ -19,7 +19,7 @@ on:
env: env:
CI_CONF_FILE: ${{ inputs.config_path }} CI_CONF_FILE: ${{ inputs.config_path }}
GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }} GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
REPORTS_PUBLISH_TOKEN: ${{ secrets.REPORTS_PUBLISH_TOKEN }} GIT_PAGES_PUBLISH_TOKEN: ${{ secrets.GIT_PAGES_PUBLISH_TOKEN }}
jobs: jobs:
parse-config: parse-config:
+2 -2
View File
@@ -12,14 +12,14 @@ on:
secrets: secrets:
GITEA_TOKEN: GITEA_TOKEN:
required: true required: true
REPORTS_PUBLISH_TOKEN: GIT_PAGES_PUBLISH_TOKEN:
required: true required: true
env: env:
GITEA_API_URL: ${{ fromJson(inputs.env_json).GITEA_API_URL }} GITEA_API_URL: ${{ fromJson(inputs.env_json).GITEA_API_URL }}
GIT_PAGES_URL: ${{ fromJson(inputs.env_json).GIT_PAGES_URL }} GIT_PAGES_URL: ${{ fromJson(inputs.env_json).GIT_PAGES_URL }}
GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }} GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
REPORTS_PUBLISH_TOKEN: ${{ secrets.REPORTS_PUBLISH_TOKEN }} GIT_PAGES_PUBLISH_TOKEN: ${{ secrets.GIT_PAGES_PUBLISH_TOKEN }}
jobs: jobs:
bats: bats:
+2 -2
View File
@@ -12,14 +12,14 @@ on:
secrets: secrets:
GITEA_TOKEN: GITEA_TOKEN:
required: true required: true
REPORTS_PUBLISH_TOKEN: GIT_PAGES_PUBLISH_TOKEN:
required: true required: true
env: env:
GITEA_API_URL: ${{ fromJson(inputs.env_json).GITEA_API_URL }} GITEA_API_URL: ${{ fromJson(inputs.env_json).GITEA_API_URL }}
GIT_PAGES_URL: ${{ fromJson(inputs.env_json).GIT_PAGES_URL }} GIT_PAGES_URL: ${{ fromJson(inputs.env_json).GIT_PAGES_URL }}
GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }} GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
REPORTS_PUBLISH_TOKEN: ${{ secrets.REPORTS_PUBLISH_TOKEN }} GIT_PAGES_PUBLISH_TOKEN: ${{ secrets.GIT_PAGES_PUBLISH_TOKEN }}
jobs: jobs:
cucumber: cucumber:
@@ -1,11 +1,11 @@
name: CI Gitea Reports Main name: CI Git-Pages Main
on: on:
push: push:
branches: branches:
- main - main
paths: paths:
- gitea-reports/** - git-pages/**
- ".gitea/workflows/gitea-reports.*" - .gitea/workflows/git-pages.*
workflow_dispatch: workflow_dispatch:
jobs: jobs:
@@ -14,7 +14,7 @@ jobs:
uses: niko/gitea-ci-library/.gitea/workflows/config-provider.yml@main uses: niko/gitea-ci-library/.gitea/workflows/config-provider.yml@main
secrets: inherit secrets: inherit
with: with:
config_path: .gitea/workflows/gitea-reports.gitea-env.conf config_path: .gitea/workflows/git-pages.gitea-env.conf
check-version: check-version:
name: Latest version name: Latest version
@@ -33,7 +33,7 @@ jobs:
with: with:
env_json: ${{ needs.load-config.outputs.env_json }} env_json: ${{ needs.load-config.outputs.env_json }}
version: ${{ needs.check-version.outputs.version }} version: ${{ needs.check-version.outputs.version }}
chart_path: gitea-reports chart_path: git-pages
chart-gitops: chart-gitops:
name: GitOps name: GitOps
@@ -44,7 +44,7 @@ jobs:
env_json: ${{ needs.load-config.outputs.env_json }} env_json: ${{ needs.load-config.outputs.env_json }}
version: ${{ needs.check-version.outputs.version }} version: ${{ needs.check-version.outputs.version }}
GITOPS_FILE: dev/Chart.yaml GITOPS_FILE: dev/Chart.yaml
GITOPS_YQ_TPL: '(.dependencies[] | select(.name == "gitea-reports") | .version) = "{{VERSION}}"' GITOPS_YQ_TPL: '(.dependencies[] | select(.name == "git-pages") | .version) = "{{VERSION}}"'
GITOPS_REPO: niko/gitea-ci-gitops-tests GITOPS_REPO: niko/gitea-ci-gitops-tests
report-summary: report-summary:
@@ -1,5 +1,6 @@
GITEA_API_URL=https://gitea.app.keskikuja.site GITEA_API_URL=https://gitea.app.keskikuja.site
HELM_REGISTRY=gitea.app.keskikuja.site/niko HELM_REGISTRY=gitea.app.keskikuja.site/niko
HELM_UI_URL=https://gitea.app.keskikuja.site/niko/-/packages/container HELM_UI_URL=https://gitea.app.keskikuja.site/niko/-/packages/container
GIT_TAG_PREFIX=gitea-reports/ GIT_TAG_PREFIX=git-pages/
VERSION_FILE=gitea-reports/Chart.yaml VERSION_FILE=git-pages/Chart.yaml
+2 -2
View File
@@ -264,7 +264,7 @@ Consumer-repossa on oltava seuraavat asetukset:
| Secret | Kuvaus | | Secret | Kuvaus |
|--------|--------| |--------|--------|
| `REPORTS_PUBLISH_TOKEN` | Git-pages-palvelimen BasicAuth-token. Nimi on lukittu — tämä tarkka nimi vaaditaan. | | `GIT_PAGES_PUBLISH_TOKEN` | Git-pages-palvelimen BasicAuth-token. Nimi on lukittu — tämä tarkka nimi vaaditaan. |
`GITEA_TOKEN` on Gitean automaattisesti jokaiselle workflow-runille generoima token (`secrets.GITEA_TOKEN`). Se on scopeutettu **siihen repoon**, jossa workflow ajaa — ei toimi toiseen repoon dispatchaukseen eikä toisen repon commit-statusin asettamiseen. Ei tarvitse erikseen luoda. `GITEA_TOKEN` on Gitean automaattisesti jokaiselle workflow-runille generoima token (`secrets.GITEA_TOKEN`). Se on scopeutettu **siihen repoon**, jossa workflow ajaa — ei toimi toiseen repoon dispatchaukseen eikä toisen repon commit-statusin asettamiseen. Ei tarvitse erikseen luoda.
@@ -300,7 +300,7 @@ GIT_PAGES_URL=https://ci-reports.example.com
Jokaisen jobin alussa `ci-validate.sh` tarkistaa: Jokaisen jobin alussa `ci-validate.sh` tarkistaa:
- `.gitea/workflows/gitea-env.conf` on olemassa ja sen arvot ovat validit - `.gitea/workflows/gitea-env.conf` on olemassa ja sen arvot ovat validit
- `GITEA_TOKEN` ja `REPORTS_PUBLISH_TOKEN` on asetettu - `GITEA_TOKEN` ja `GIT_PAGES_PUBLISH_TOKEN` on asetettu
Jos validointi epäonnistuu, job keskeytyy exit-koodilla 1 ja Gitean commit-status näyttää epäonnistumisen linkkinä lokiin. Jos validointi epäonnistuu, job keskeytyy exit-koodilla 1 ja Gitean commit-status näyttää epäonnistumisen linkkinä lokiin.
+1 -1
View File
@@ -26,7 +26,7 @@ Consumer:
- Omistaa pipeline-logiikan (mitä testejä ajetaan, missä järjestyksessä) - Omistaa pipeline-logiikan (mitä testejä ajetaan, missä järjestyksessä)
- Luo raportit omiin polkuihinsa (`reports/{sha8}/{step}/`) - Luo raportit omiin polkuihinsa (`reports/{sha8}/{step}/`)
- Luo `.meta`-tiedostot per step - Luo `.meta`-tiedostot per step
- Määrittelee Gitea-secretit (`REPORTS_PUBLISH_TOKEN`, `GITEA_TOKEN`) - Määrittelee Gitea-secretit (`GIT_PAGES_PUBLISH_TOKEN`, `GITEA_TOKEN`)
### Provider → Consumer (mitä provider tarjoaa) ### Provider → Consumer (mitä provider tarjoaa)
+1 -1
View File
@@ -96,7 +96,7 @@ Avainkomponentit:
- **workflow `env:`** — ainoa tapa jakaa arvot kaikkiin jobeihin. - **workflow `env:`** — ainoa tapa jakaa arvot kaikkiin jobeihin.
`fromJson(inputs.env_json).KEY` purkaa yksittäiset arvot ilman toistoa. `fromJson(inputs.env_json).KEY` purkaa yksittäiset arvot ilman toistoa.
- **Per-job `env:`** — sisältää vain secretit (`GITEA_TOKEN`, - **Per-job `env:`** — sisältää vain secretit (`GITEA_TOKEN`,
`REPORTS_PUBLISH_TOKEN`), ei config-arvoja. `GIT_PAGES_PUBLISH_TOKEN`), ei config-arvoja.
## 5. Pipeline Provides All Dependencies ## 5. Pipeline Provides All Dependencies
+2 -2
View File
@@ -69,7 +69,7 @@ org-tason token.
| Secret | Pakollinen | Käyttäjä | | Secret | Pakollinen | Käyttäjä |
|---|---|---| |---|---|---|
| `GITEA_TOKEN` | Kyllä | `report-status.sh`, `check-version.yml`, `docker-build-push.yml`, `gitops-update.sh` (GitOps-repossa) | | `GITEA_TOKEN` | Kyllä | `report-status.sh`, `check-version.yml`, `docker-build-push.yml`, `gitops-update.sh` (GitOps-repossa) |
| `REPORTS_PUBLISH_TOKEN` | Kyllä | `publish-git-pages.sh`, `config-provider.yml` (validointi) | | `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_USERNAME` | Ei | `docker-build-push.yml` (oletus: `github.actor`, ei pakollinen kaikissa registryissä) |
| `DOCKER_PASSWORD` | Kyllä | `docker-build-push.yml` | | `DOCKER_PASSWORD` | Kyllä | `docker-build-push.yml` |
@@ -88,7 +88,7 @@ JSON-muotoisen `env_json`:n.
- `.conf`-tiedosto on olemassa - `.conf`-tiedosto on olemassa
- Jokaisella `KEY=VALUE`-rivillä on arvo (ei tyhjää) - Jokaisella `KEY=VALUE`-rivillä on arvo (ei tyhjää)
- URL-tyyppiset avaimet alkavat `http://` tai `https://` - URL-tyyppiset avaimet alkavat `http://` tai `https://`
- Pakolliset secretit (`GITEA_TOKEN`, `REPORTS_PUBLISH_TOKEN`) on asetettu - Pakolliset secretit (`GITEA_TOKEN`, `GIT_PAGES_PUBLISH_TOKEN`) on asetettu
Kutsu: Kutsu:
```yaml ```yaml
+2 -2
View File
@@ -268,7 +268,7 @@ set -eu
SUITE_PATH="${1:-}" SUITE_PATH="${1:-}"
[ -n "$SUITE_PATH" ] || { echo "ERROR: suite_path required" >&2; exit 1; } [ -n "$SUITE_PATH" ] || { echo "ERROR: suite_path required" >&2; exit 1; }
[ -n "${GIT_PAGES_URL:-}" ] || { echo "ERROR: GIT_PAGES_URL is not set" >&2; exit 1; } [ -n "${GIT_PAGES_URL:-}" ] || { echo "ERROR: GIT_PAGES_URL is not set" >&2; exit 1; }
[ -n "${REPORTS_PUBLISH_TOKEN:-}" ] || { echo "ERROR: REPORTS_PUBLISH_TOKEN is not set" >&2; exit 1; } [ -n "${GIT_PAGES_PUBLISH_TOKEN:-}" ] || { echo "ERROR: GIT_PAGES_PUBLISH_TOKEN is not set" >&2; exit 1; }
[ -n "${GITHUB_REPOSITORY:-}" ] || { echo "ERROR: GITHUB_REPOSITORY is not set" >&2; exit 1; } [ -n "${GITHUB_REPOSITORY:-}" ] || { echo "ERROR: GITHUB_REPOSITORY is not set" >&2; exit 1; }
[ -n "${GITHUB_SHA:-}" ] || { echo "ERROR: GITHUB_SHA is not set" >&2; exit 1; } [ -n "${GITHUB_SHA:-}" ] || { echo "ERROR: GITHUB_SHA is not set" >&2; exit 1; }
[ -n "${GITHUB_REF_NAME:-}" ] || { echo "ERROR: GITHUB_REF_NAME is not set" >&2; exit 1; } [ -n "${GITHUB_REF_NAME:-}" ] || { echo "ERROR: GITHUB_REF_NAME is not set" >&2; exit 1; }
@@ -312,7 +312,7 @@ tar czf "$TAR" -C "$WORK/$SUITE" .
# PUT upload-sidecariin # PUT upload-sidecariin
PUBLISH_URL="${GIT_PAGES_URL}/${OWNER}/${REPO}/${BRANCH}/${SHA8}/${SUITE}/" PUBLISH_URL="${GIT_PAGES_URL}/${OWNER}/${REPO}/${BRANCH}/${SHA8}/${SUITE}/"
HTTP_CODE=$(curl -sS -X PUT "$PUBLISH_URL" \ HTTP_CODE=$(curl -sS -X PUT "$PUBLISH_URL" \
-u "${PAGES_USER}:${REPORTS_PUBLISH_TOKEN}" \ -u "${PAGES_USER}:${GIT_PAGES_PUBLISH_TOKEN}" \
-H "Content-Type: application/tar+gz" \ -H "Content-Type: application/tar+gz" \
--data-binary @"$TAR" \ --data-binary @"$TAR" \
-o /tmp/git-pages-publish-response.txt \ -o /tmp/git-pages-publish-response.txt \
+3 -3
View File
@@ -79,7 +79,7 @@ publish-git-pages.sh <suite>
|---|---| |---|---|
| `GITEA_API_URL` | `env_json` → workflow `env:` | | `GITEA_API_URL` | `env_json` → workflow `env:` |
| `GIT_PAGES_URL` | `env_json` → workflow `env:` | | `GIT_PAGES_URL` | `env_json` → workflow `env:` |
| `REPORTS_PUBLISH_TOKEN` | Gitea secret → `env:` | | `GIT_PAGES_PUBLISH_TOKEN` | Gitea secret → `env:` |
| `GITHUB_REPOSITORY` | Automaattinen | | `GITHUB_REPOSITORY` | Automaattinen |
| `GITHUB_SHA` | Automaattinen | | `GITHUB_SHA` | Automaattinen |
@@ -104,7 +104,7 @@ Lukee tiedoston polun `CI_CONF_FILE`-env-muuttujasta (oletus: `.gitea/workflows/
- Jokaisella `KEY=VALUE`-rivillä on arvo (ei tyhjää) - Jokaisella `KEY=VALUE`-rivillä on arvo (ei tyhjää)
- URL-tyyppiset avaimet alkavat `http://` tai `https://` - URL-tyyppiset avaimet alkavat `http://` tai `https://`
- `GITEA_TOKEN` on asetettu - `GITEA_TOKEN` on asetettu
- `REPORTS_PUBLISH_TOKEN` on asetettu - `GIT_PAGES_PUBLISH_TOKEN` on asetettu
--- ---
@@ -155,7 +155,7 @@ dispatch-workflow.sh <target_repo> <workflow_file> <ref> <inputs_json> <gitea_ap
| `GITEA_API_URL` | `env_json` | `report-status.sh`, `ci-validate.sh` | | `GITEA_API_URL` | `env_json` | `report-status.sh`, `ci-validate.sh` |
| `GIT_PAGES_URL` | `env_json` | `publish-git-pages.sh`, `report-status.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` | | `GITEA_TOKEN` | Gitea secret | `report-status.sh`, `check-version.yml`, `docker-build-push.yml` |
| `REPORTS_PUBLISH_TOKEN` | Gitea secret | `publish-git-pages.sh` | | `GIT_PAGES_PUBLISH_TOKEN` | Gitea secret | `publish-git-pages.sh` |
| `GITHUB_REPOSITORY` | Automaattinen | Kaikki skriptit | | `GITHUB_REPOSITORY` | Automaattinen | Kaikki skriptit |
| `GITHUB_SHA` | Automaattinen | Kaikki skriptit | | `GITHUB_SHA` | Automaattinen | Kaikki skriptit |
| `GITHUB_RUN_ID` | Automaattinen | `report-status.sh` | | `GITHUB_RUN_ID` | Automaattinen | `report-status.sh` |
+1 -1
View File
@@ -32,7 +32,7 @@ Kaikki workflowt:
| Secret | Pakollinen | Kuvaus | | Secret | Pakollinen | Kuvaus |
|--------|------------|--------| |--------|------------|--------|
| `GITEA_TOKEN` | Kyllä | Validointia varten | | `GITEA_TOKEN` | Kyllä | Validointia varten |
| `REPORTS_PUBLISH_TOKEN` | Kyllä | Validointia varten | | `GIT_PAGES_PUBLISH_TOKEN` | Kyllä | Validointia varten |
**Outputs:** **Outputs:**
+1 -1
View File
@@ -1,5 +1,5 @@
apiVersion: v2 apiVersion: v2
name: gitea-reports name: git-pages
description: Nginx + upload-sidecar for CI HTML reports (static serving, Traefik BasicAuth publish) description: Nginx + upload-sidecar for CI HTML reports (static serving, Traefik BasicAuth publish)
type: application type: application
version: 0.2.0 version: 0.2.0
+3 -3
View File
@@ -64,7 +64,7 @@ open "https://gitea.app.keskikuja.site/${REPO_OWNER}/${REPO_NAME}/settings/actio
# Linux: xdg-open "https://gitea.app.keskikuja.site/${REPO_OWNER}/${REPO_NAME}/settings/actions/secrets" # Linux: xdg-open "https://gitea.app.keskikuja.site/${REPO_OWNER}/${REPO_NAME}/settings/actions/secrets"
``` ```
**Gitea UI:ssa:** New Secret → Name: `REPORTS_PUBLISH_TOKEN` → Value: **liitä leikepöydältä** → Save **Gitea UI:ssa:** New Secret → Name: `GIT_PAGES_PUBLISH_TOKEN` → Value: **liitä leikepöydältä** → Save
> 💡 **Monelle repoille:** Toista vaiheet 34, tai katso [automatisointi](docs/secrets.md#automatisointi-useamman-repon-salaisuuden-lis%C3%A4%C3%A4miseen). > 💡 **Monelle repoille:** Toista vaiheet 34, tai katso [automatisointi](docs/secrets.md#automatisointi-useamman-repon-salaisuuden-lis%C3%A4%C3%A4miseen).
@@ -132,7 +132,7 @@ Julkaisu DNS-osoitteeseen BasicAuthilla:
```bash ```bash
# Esimerkki: julkaise raportti # Esimerkki: julkaise raportti
curl -X PUT \ curl -X PUT \
-u publish:$REPORTS_PUBLISH_TOKEN \ -u publish:$GIT_PAGES_PUBLISH_TOKEN \
-H "Content-Type: application/tar+gz" \ -H "Content-Type: application/tar+gz" \
--data-binary @report.tar.gz \ --data-binary @report.tar.gz \
https://ci-reports.helm-dev.keskikuja.site/{owner}/{repo}/{branch}/{sha8}/{suite}/ https://ci-reports.helm-dev.keskikuja.site/{owner}/{repo}/{branch}/{sha8}/{suite}/
@@ -142,7 +142,7 @@ curl -X PUT \
| Missä | Arvo | | Missä | Arvo |
|-------|------| |-------|------|
| Gitea Actions secret | `REPORTS_PUBLISH_TOKEN` (sama kuin K8s `gitea-reports-publish-token` `token`-avain) | | Gitea Actions secret | `GIT_PAGES_PUBLISH_TOKEN` (sama kuin K8s `gitea-reports-publish-token` `token`-avain) |
| Scriptissä | `bash scripts/publish-gitea-reports.sh <suite>` | | Scriptissä | `bash scripts/publish-gitea-reports.sh <suite>` |
**K8s secretit (Traefik-yhteensopivuus):** **K8s secretit (Traefik-yhteensopivuus):**
+2 -2
View File
@@ -1,6 +1,6 @@
# Architecture — Nginx + upload-sidecar # Architecture — Nginx + upload-sidecar
> gitea-reports on korvattu. Uusi arkkitehtuuri: Nginx palvelee staattisia tiedostoja PV:ltä, upload-sidecar (busybox httpd + CGI) ottaa vastaan tar.gz-PUTit. > git-pages on korvattu. Uusi arkkitehtuuri: Nginx palvelee staattisia tiedostoja PV:ltä, upload-sidecar (busybox httpd + CGI) ottaa vastaan tar.gz-PUTit.
## Yleiskuvaus ## Yleiskuvaus
@@ -16,7 +16,7 @@ Ei Host-header-kikkaa, ei slugia, ei rewritea.
| **PVC** | Raporttisisältö suoraan FS-muodossa | | **PVC** | Raporttisisältö suoraan FS-muodossa |
| **Service** | ClusterIP :8080 (read), :8081 (write) | | **Service** | ClusterIP :8080 (read), :8081 (write) |
| **Traefik IngressRoute** | PATCH/PUT → upload:8081 (BasicAuth), GET/HEAD → nginx:8080 | | **Traefik IngressRoute** | PATCH/PUT → upload:8081 (BasicAuth), GET/HEAD → nginx:8080 |
| **Traefik Middleware** | `gitea-reports-publish-auth` (BasicAuth), HTTPS-redirect | | **Traefik Middleware** | `git-pages-publish-auth` (BasicAuth), HTTPS-redirect |
| **cert-manager Certificate** | TLS | | **cert-manager Certificate** | TLS |
## URL ja sisältö ## URL ja sisältö
+170 -62
View File
@@ -1,90 +1,198 @@
# Design Rationale — gitea-reports # Design Rationale — git-pages
Miksi gitea-reports on rakennettu näin. Periaatteet, jotka pitävät arkkitehtuurin koossa. > Miksi git-pages on rakennettu näin. Arvot, periaatteet ja reunaehdot.
Teknologiavalinnat ovat näiden periaatteiden seurauksia — eivät erillisiä preferenssejä. >
> Tämä dokumentti on **normatiivinen** `git-pages/`-alikansiolle. Se ei kuvaa juuren
> `gitea-ci-library`-kirjastoa eikä sen workfloweja.
>
> Liittyvät dokumentit: [architecture.md](architecture.md), [tech-stack.md](tech-stack.md), [secrets.md](secrets.md).
Tämä dokumentti on normatiivinen. Arkkitehtuurin tulee noudattaa sen periaatteita. ---
Ehdotus, joka on ristiriidassa dokumentin kanssa, on konflikti — ei hiljainen ohitus.
## The problem this solves ## Miksi tämä on olemassa
CI-testiajoista syntyy HTML-raportteja. Gitea ei tarjoa web-selaimella selattavaa arkistoa ### Ongelma
näille raporteille.
Vaihtoehdot eivät sovi: CI-testiajoista syntyy HTML-raportteja. Esimerkiksi Cucumber-testiraportti toimii
- **Gitea Actions artifactit**: vain ZIP-lataus — HTML ei renderöidy selaimessa elävänä dokumentaationa git commitin tilasta.
- **Gitea pages-branch**: yksi branch per repo; rinnakkaiset buildit törmäävät
- **Gitea Releases**: sotkee julkaisuhistorian sadoilla CI-buildien raporteilla
## How this is solved Gitea ei tarjoa web-selaimella selattavaa arkistoa näille HTML-raporteille.
Yksi klusteri, yksi apex-host, monta Gitea-repoa. URL on suoraan FS-polku: git-pages ratkaisee tämän ongelman.
`/{owner}/{repo}/{branch}/{sha8}/{suite}/`. Ei rewritea, ei subdomain-per-owner,
ei slugia.
Palvelu on read/write -jaettu: luku ja julkaisu eri sovelluksilla, eri porteilla, | Vaihtoehto | Miksi ei riitä |
eri Traefik-säännöillä. |---|---|
| **Gitea Actions -artifactit** | Vain ZIP-lataus — HTML ei renderöidy selaimessa |
| **Gitea `pages`-branch** | Yksi branch per repo; rinnakkaiset buildit törmäävät saman branchin pushissa |
| **Gitea Releases** | Sotkee julkaisuhistorian satojen CI-buildien raporteilla |
## Why selvä URL + Gitea-yhteensopiva polku ### Ongelma URL:ssa (hylätty malli)
Repo tunnistetaan polusta `/{owner}/{repo}/...`, ei hostista. Kaikki URL-taso Alkuvaiheen malli sitoi hostin repoon: `https://{owner}.{host}/{repo}/...`
(branch, sha8, suite) on suoraan FS-polku. Tämä mahdollistaa yhden TLS-sertifikaatin, (subdomain per owner). Julkinen linkki piti sitten “kääntää” Gitea-tyyliseksi poluksi
yhden IngressRouten ja URL:n, joka on suoraan kopioitavissa commit-statusiin ilman Traefik-rewritellä (`/{owner}/{repo}/...` → eri `Host` + lyhyempi polku).
rewritea.
**Hylätty:** subdomain-per-owner (`{owner}.pages...`). Vaati per-owner Traefik- Tämä oli ongelmallinen:
rewritea ja wildcard-TLS:ää. Julkaisu-URL ja luku-URL olivat eri muodossa — kehittäjälle
vaikea ymmärtää ja debugata.
## Why luku ja kirjoitus eri sovelluksilla - per-owner middleware / rewrite kube-resursseina
- julkaisu-URL ja lukemis-URL eri muodossa
- wildcard-TLS tai monimutkainen cert-hallinta
- vaikea selittää kehittäjälle mistä host tulee
Yksi binary, joka palvelee sekä lukua että kirjoitusta samassa prosessissa, on ### Ratkaisu — `selvä_url` + Gitea-yhteensopiva polku
yksinkertainen mutta yhdistää kaksi eri asiaa. Tässä arkkitehtuurissa nginx palvelee
staattisia tiedostoja; Python-skripti purkaa tar.gz-julkaisun PV:lle. Ne eivät tiedä
toisistaan.
Luku ei tarvitse julkaisulogiikkaa. Julkaisu ei tarvitse optimoitua staattista URL rakennetaan kahdesta erillisestä osasta, ei yhdestä sekavasta kaavasta:
palvelua. Erottamalla ne kumpikin voidaan valita parhaaseen tarkoitukseensa.
## Why security klusterin reunalla — ei sovelluksessa | Osa | Mistä | Esimerkki |
|-----|-------|-----------|
| **Selvä URL** | Organisaation kiinteä pages-host | `https://pages.example.com` |
| **Gitea-yhteensopiva polku** | Repo (`{owner}/{repo}`) + commit | `/acme-corp/backend-api/reports/abc12345/index.html` |
Sovellus on "tyhmä": se palvelee mitä PV:llä on ja kirjoittaa mitä sille annetaan. **Julkinen linkki** = selvä URL + polku (yksi merkkijono commit-statusiin, ei rewritea):
Valtuutus tapahtuu yksinomaan Traefik BasicAuth -middlewaressa.
Tämä mahdollistaa: `https://pages.example.com/acme-corp/backend-api/reports/abc12345/index.html`
- Julkaisu- ja lukuoikeuksien erillisen hallinnan eri Traefik-säännöillä
- Sovelluksen vaihtamisen ilman turvallisuusauditointia
- Token-rotaation ilman sovelluksen uudelleenkäynnistystä
**Hylätty:** sovelluksen sisäinen forge-auth (Gitea PAT, DNS TXT -haaste). Polku vastaa Gitea Pages -käytäntöä (`/{owner}/{repo}/...`). Host on aina sama —
Sitoo sovelluksen tiettyyn autentikointimekanismiin ja vaatii laajat oikeudet ei `{owner}.pages...`-subdomainia.
(`write:repository`) pelkkää raporttijulkaisua varten.
## Why retention erillisenä CronJobina **Konkreettinen esimerkki (nykyinen ympäristö):**
Retention ei tarvitse olla aina käynnissä — se ajetaan kerran vuorokaudessa. | Elementti | Arvo |
CronJob lukee PV:tä suoraan (find, ls, stat), ei HTTP API:n kautta. Tämä pitää |-----------|------|
retention poissa podin kriittiseltä polulta (luku/julkaisu). | **Gitea-instanssi** | `gitea.app.keskikuja.site` |
| **Repo** | `niko/gitea-ci-library` |
| **Haara** | `plan/0003-alkaa-käyttämään-itseään-commit-raportti` |
| **Commit SHA** | `14cf2eaeed8a4033bc37c52b0b4c29f25b253ceb` |
| **Raportin nimi** | `cucumber` (esim.) |
| **Gitea commit -URL** | `https://gitea.app.keskikuja.site/niko/gitea-ci-library/commit/14cf2eaeed8a4033bc37c52b0b4c29f25b253ceb` |
| **Raportin julkinen URL** | `https://ci-reports.helm-dev.keskikuja.site/niko/gitea-ci-library/commit/14cf2eaeed8a4033bc37c52b0b4c29f25b253ceb/cucumber/index.html` |
**Hylätty:** sidecar samassa podissa. Sidecar kuluttaa resursseja aina, ja Tämä varmistaa, että CI-statuslinkki on suoraan luettavissa ilman domain-rewriteä: raportin polku peilaa täsmälleen Gitean commit-polun rakennetta (`/{owner}/{repo}/commit/{sha}/{raportin-nimi}/`). Koska yksi ajo tuottaa useita raportteja, raportin nimi erottaa ne toisistaan.
retention-logiikka sekoittuu julkaisu- ja lukukoodiin.
## Why yksi token, kaksi säilöä Julkaisija (CI tai muu asiakas) lähettää tar-arkiston PATCH/PUT:lla. Lukija hakee
HTML:n GET:llä. Ei Gitea-git-integraatiota eikä `pages`-branchia.
Sama plaintext-arvo: htpasswd-hashina K8s Secretissä (Traefik lukee), plaintextina **Codebergin security-malli ei sovellu tähän käyttöön** — forge-auth (Gitea PAT +
Gitea Actions Secretissä (julkaisija lukee). Yksi rotaatio päivittää molemmat. `write:repository`), DNS TXT -haaste ja muut git-pagesin sisäänrakennetut valtuutus-
mekanismit on ohitettu kokonaan (`PAGES_INSECURE=1`). Niiden sijaan Kubernetes-kerros
hoitaa rajauksen: Traefik BasicAuth julkaisuun, cert-manager TLS:ään, erillinen
publish-token ([secrets.md](secrets.md)). Sovellus palvelee sisältöä; klusteri päättää
kuka saa kirjoittaa.
Token antaa vain julkaisuoikeuden tähän palveluun — ei Gitea PAT:ia eikä ---
`write:repository`-oikeutta.
## Why PVC suoraan FS-muodossa ## Suunnitteluperiaatteet
Ei objektivarastoa, ei HTTP API:a retentionille. Sisältö on suoraan luettavissa ### 1. Selvä URL + Gitea-yhteensopiva polku
kubectl exec + ls/find. Yksinkertaisin mahdollinen tallennusmuoto. Yksi replica,
ei synkronointia.
## References Julkinen osoite = kiinteä apex-host + polku `/{owner}/{repo}/reports/{sha8}/...`.
Apex-juuri `/` on tyhjä tarkoituksella — ei landing-sivua.
- [architecture.md](architecture.md) — komponentit ja vuokaavio **Miksi:** Kehittäjä näkee Gitea-tyylisen polun; infra näkee yhden hostin. Ei Traefik-
- [tech-stack.md](tech-stack.md) — teknologiavalinnat listana rewritea, ei per-owner subdomaineja, ei erillistä “julkaisu-URL vs. lukemis-URL” -kaavaa.
- [secrets.md](secrets.md) — secret-arkkitehtuuri ja käyttöönotto Yksi TLS-sertifikaatti, yksi IngressRoute, yksi PVC.
### 2. Sovelluksen sisäinen security kytketty pois, Traefik hoitaa rajauksen
`git-pages`-sovelluksen koko sisäinen security-mekanismi on kytketty pois päältä (`PAGES_INSECURE=1`). Kirjoitusoikeuden validointi tapahtuu yksinomaan Kubernetes-reunalla Traefik BasicAuth -middlewaren avulla. Sovellus palvelee sisältöä sokeana; klusteri päättää, kuka saa kirjoittaa.
### 3. Julkaisu ja luku erotettu
Julkaisu (PATCH/PUT) vaatii Traefik BasicAuthin. Luku (GET/HEAD) on erillinen reitti — katso [Luku-auth](#luku-auth) alla.
**Miksi:** Koska sovellus ei validoi julkaisuoikeuksia, kirjoitusoikeus on eksplisiittisesti eriytetty Traefik Middlewaressä (`git-pages-publish-auth`).
### 4. Yksi publish-token, kaksi säilöä
Sama plaintext-token: klusterin Secretissä htpasswd-hashina, julkaisijan secret-holvissa
(esim. CI-alustan Actions-secret).
**Miksi:** Ei Gitea PAT:ia eikä `write:repository` -oikeutta. Token antaa vain
julkaisuoikeuden tähän palveluun. Yksi arvo, kaksi paikkaa — ks. [secrets.md](secrets.md).
### 5. Secretit erillisessä hallinnassa
`git-pages-publish-auth` luodaan ennen käyttöönottoa — ei osana sovelluksen konfiguraatiotiedostoja.
**Miksi:** Salaisuudet eivät kulje versionoiduissa arvoissa. Rotaatio ja SealedSecrets
pysyvät operaattorin hallussa. Ks. [secrets.md](secrets.md).
### 6. Minimaalinen parametrisointi
Instance-arvot (`host`, `issuer`, PVC) `{env}-values.yaml`:ssa. Resurssinimet,
secret-nimet ja Traefik-wire kovakoodattu templatessa.
**Miksi:** Parametrisoi vain se, mikä vaihtelee instanssien välillä (host, TLS-issuer,
levy). Vakioidut nimet ja wire pysyvät ennustettavina kaikissa asennuksissa.
---
## Puutteet
Tietoisesti avoimet asiat — eivät estä nykyistä julkaisu- ja lukumallia.
### Luku-auth
Julkaisu on suojattu (Traefik BasicAuth). **Luku ei ole:** GET/HEAD on julkinen — kuka
tuntee URL:n voi lukea raportin.
Tavoite: Traefik OIDC GET/HEAD-reitille (Gitea OAuth2 -provider). Session säilyy —
commit-statuslinkki toimii kirjautumisen jälkeen ilman uutta julkaisuoikeutta.
Ei toteutettu. Julkaisu- ja luku-reitit pysyvät erillisinä; OIDC lisätään vain lukupuolelle.
### Retention
Sidecar samassa podissa (HTTP localhost:3000), ajaa retention-cleanup.sh
24h välein:
| Sääntö | Konfiguroitavissa? | Kuvaus |
|--------|-------------------|--------|
| **Poistettu branch** | Ei — aina | Jos `.meta.branch` ei ole Giteassa enää, raportti poistetaan |
| **maxAgeDays** | Kyllä (`dev-values`) | Aktiivisen branchin raportit vanhemmat kuin N päivää |
| **keepMin** | Kyllä (`dev-values`) | Aktiivisella branchilla pidetään vähintään N uusinta |
Poistettujen branchien siivous ei tarvitse parametreja. Jäljelle jääneille
branchille säännöt tulevat `retention.rules` (`branches.default` +
`branches.{name}`).
Ei PVC-skaalausta — sidecar lukee manifestin HTTP:lla ja poistaa whiteout
PATCHilla. Ei K8s API -oikeuksia.
Secret: `git-pages-retention-gitea` — Gitea PAT branch-tarkistukseen.
Ks. [secrets.md](secrets.md).
---
## Rajat
- **Ei forge-integraatiota** — ei `pages`-branchia, ei Gitea API -hakua, ei forge-authia
- **Ei julkaisijalogiikkaa** — kuka julkaisee ja milloin on julkaisijan vastuulla
- **Ei sisäverkon ohitusjulkaisua** — julkaisu kulkee julkisen ingressin kautta (BasicAuth)
---
## Teknologiavalinnat
| Valinta | Miksi |
|---------|-------|
| **Codeberg git-pages** `0.9.1` | Natiivi apex index-site + tar-pohjainen PATCH/PUT -julkaisu |
| **Filesystem + PVC** | Yksinkertainen, yksi replica, ei erillistä objektivarastoa |
| **Traefik IngressRoute + Middleware** | Julkaisuauth erillään sovelluksesta; GET/HEAD eri säännöllä |
| **cert-manager** | TLS automaattisesti (`git-pages-tls`) |
| **Helm v3** | Toistettava asennus; instanssikohtaiset arvot erillisessä values-tiedostossa |
---
## Mitä tietoisesti hylättiin
| Hylätty | Syy |
|---------|-----|
| **deadnews/gitea-pages** | Vetää sisällön Gitea API:sta — ei sopinut CI-push-malliin |
| **Gitea `pages`-branch** | Race condition rinnakkaisissa buildeissa |
| **Per-owner subdomain** (`{owner}.pages...`) | Ongelmallinen URL; vaatii rewrite-middlewarea polun kääntämiseen |
| **Traefik path→host -rewrite** | Korvattu apex + Gitea-polulla — yksi selvä URL commit-linkissä |
| **Gitea forge-auth / PAT** | `write:repository` liian laaja oikeus vain raporttijulkaisuun |
| **DNS TXT -haaste julkaisuun** | Operatiivinen kompleksisuus ilman hyötyä BasicAuthiin verrattuna |
| **Helm-managed publish Secret** | Arvot values-tiedostoihin on kielletty; manuaalinen lähde totuudelle |
| **Image tag `v0.9.1`** | Oikea tagi on `0.9.1` (ei `v`-etuliitettä) |
@@ -0,0 +1,43 @@
# Implementation Notes
Teknisiä huomioita git-pages 0.9.1:n käyttäytymisestä, joita ei ole ilmeistä
dokumentaatiosta.
## Storage v2 (Protobuf manifest)
Git-pages 0.9.1 käyttää v2-arkkitehtuuria. Kaikki sisältö on pakattu
Protobuf-manifestiin (`site/{host}/.index`), ei flat-FS:nä. Tästä seuraa:
- Tiedostoja ei voi etsiä tai poistaa `find`/`rm`-komennoilla
- `.git-pages/manifest.json` listaa kaikki tiedostot (ProtoJSON)
- `.git-pages/archive.tar` antaa koko sisällön (saattaa truncata HTTP/2:ssa)
## Host-header
Git-pages valitsee sivuston Host-headerin perusteella. Ilman oikeaa Hostia
palauttaa 404.
- Ulkoiset requestit: Traefik välittää alkuperäisen Hostin automaattisesti
- Sidecar/localhost: `-H "Host: ci-reports.helm-dev.keskikuja.site"`
## PATCH ja directory-entryt
Jos PATCH-tar sisältää directory-entryn (tyyppi directory, tar typeflag '5'),
se **korvaa** koko hakemiston dokumentaation mukaan. Tar saa sisältää vain
file- ja symlink-entryjä, jotta PATCH toimii odotetusti.
## Whiteout — tiedostojen poisto
Ainoa tapa poistaa tiedostoja ilman koko sivuston PUT-korvausta:
- Tarissa character device entry (`CHRTYPE`, tar typeflag '4')
- `devmajor=0`, `devminor=0`
- PATCH:ataan sivuston juureen
## .init — ensimmäinen julkaisu
Ensimmäinen julkaisu vaatii PUTin, joka luo `.index`-tiedoston. Tämän jälkeen
PATCH riittää.
Helm-chartin post-install -job hoitaa tämän automaattisesti:
consumerien publish-scriptien ei tarvitse tuntea asennuksen tilaa.
+37 -37
View File
@@ -1,4 +1,4 @@
# Secrets — gitea-reports # Secrets — git-pages
## Quick Start ## Quick Start
@@ -8,9 +8,9 @@ Järjestelmässä on kaksi loogista salaista arvoa. Publish-token jaetaan kahtee
| Looginen nimi | K8s | Gitea | | Looginen nimi | K8s | Gitea |
|---|---|---| |---|---|---|
| `report_publish_api_token` (htpasswd) | `gitea-reports-publish-auth` (users) | - | | `report_publish_api_token` (htpasswd) | `git-pages-publish-auth` (users) | - |
| `report_publish_api_token` (plaintext) | `gitea-reports-publish-token` (token) | Actions Secret: `REPORTS_PUBLISH_TOKEN` | | `report_publish_api_token` (plaintext) | `git-pages-publish-token` (token) | Actions Secret: `GIT_PAGES_PUBLISH_TOKEN` |
| `reports_retention_read_token` | `gitea-reports-retention-gitea` (token) | PAT: `CI-REPORTS_READ_FOR_RETENTION` | | `reports_retention_read_token` | `git-pages-retention-gitea` (token) | PAT: `CI-REPORTS_READ_FOR_RETENTION` |
**Huomio:** Publish-token jaetaan kahteen secretiin, koska Traefik BasicAuth middleware vaatii single-key secretin sekä on muodossa, missä sitä ei saa takaisin. Jokainen repo mikä raportteja käyttää, tarvitsee selväkielisen arvon, joka on "ylimääräisessä" secretissä. **Huomio:** Publish-token jaetaan kahteen secretiin, koska Traefik BasicAuth middleware vaatii single-key secretin sekä on muodossa, missä sitä ei saa takaisin. Jokainen repo mikä raportteja käyttää, tarvitsee selväkielisen arvon, joka on "ylimääräisessä" secretissä.
@@ -32,9 +32,9 @@ Järjestelmässä on kaksi loogista salaista arvoa. Publish-token jaetaan kahtee
```bash ```bash
GITEA_RETENTION_TOKEN="<from Gitea>" GITEA_RETENTION_TOKEN="<from Gitea>"
REPORTS_PUBLISH_TOKEN="$(openssl rand -base64 24)" GIT_PAGES_PUBLISH_TOKEN="$(openssl rand -base64 24)"
echo "Publish-token generoitu. Tallennetaan K8s-secretiin Vaiheessa 4." echo "Publish-token generoitu. Tallennetaan K8s-secretiin Vaiheessa 4."
echo "$REPORTS_PUBLISH_TOKEN" echo "$GIT_PAGES_PUBLISH_TOKEN"
``` ```
### Vaihe 4: Luo K8s secrets ### Vaihe 4: Luo K8s secrets
@@ -43,17 +43,17 @@ echo "$REPORTS_PUBLISH_TOKEN"
NS=gitea-reports NS=gitea-reports
# 1. Publish-auth: htpasswd (Traefik BasicAuth - vaatii single-key secretin) # 1. Publish-auth: htpasswd (Traefik BasicAuth - vaatii single-key secretin)
kubectl create secret generic gitea-reports-publish-auth \ kubectl create secret generic git-pages-publish-auth \
--from-literal=users="$(docker run --rm httpd:2-alpine htpasswd -nb publish "$REPORTS_PUBLISH_TOKEN")" \ --from-literal=users="$(docker run --rm httpd:2-alpine htpasswd -nb publish "$GIT_PAGES_PUBLISH_TOKEN")" \
-n "$NS" -n "$NS"
# 2. Publish-token: plaintext (luetaan README:stä Giteaan viedessä) # 2. Publish-token: plaintext (luetaan README:stä Giteaan viedessä)
kubectl create secret generic gitea-reports-publish-token \ kubectl create secret generic git-pages-publish-token \
--from-literal=token="$REPORTS_PUBLISH_TOKEN" \ --from-literal=token="$GIT_PAGES_PUBLISH_TOKEN" \
-n "$NS" -n "$NS"
# 3. Retention (käyttää Vaiheessa 2 luotua PAT:ia) # 3. Retention (käyttää Vaiheessa 2 luotua PAT:ia)
kubectl create secret generic gitea-reports-retention-gitea \ kubectl create secret generic git-pages-retention-gitea \
--from-literal=token="$GITEA_RETENTION_TOKEN" \ --from-literal=token="$GITEA_RETENTION_TOKEN" \
-n "$NS" -n "$NS"
@@ -68,20 +68,20 @@ Token näkyy terminaalissa Vaiheen 3 `echo`sta. Jos se on jo kadonnut näkyvist
```bash ```bash
NS=gitea-reports NS=gitea-reports
kubectl get secret gitea-reports-publish-token -n "$NS" -o jsonpath='{.data.token}' | base64 -d; echo kubectl get secret git-pages-publish-token -n "$NS" -o jsonpath='{.data.token}' | base64 -d; echo
``` ```
Vie kopioitu secret Gitea Actions Secrets: Vie kopioitu secret Gitea Actions Secrets:
Kannattaa viedä tämä token ORG tason secretiksi Gitea Actions. Muuten joudut tekemään tämän jokaiselle rapositorylle erikseen. Kannattaa viedä tämä token ORG tason secretiksi Gitea Actions. Muuten joudut tekemään tämän jokaiselle rapositorylle erikseen.
Luo `REPORTS_PUBLISH_TOKEN` secret, ja terminaalista kopioitu arvo `values` kenttään. Luo `GIT_PAGES_PUBLISH_TOKEN` secret, ja terminaalista kopioitu arvo `values` kenttään.
Description voi olla esim: Description voi olla esim:
> Julkaisuun liittyvä salaisuus, jonka gitea-pages auth tarkistaa, että saako julkaista raporttia. > Julkaisuun liittyvä salaisuus, jonka ci-reports auth tarkistaa, että saako julkaista raporttia.
**Gitea UI:ssa:** New Secret → Name: `REPORTS_PUBLISH_TOKEN` → Value: **liitä token** → Save **Gitea UI:ssa:** New Secret → Name: `GIT_PAGES_PUBLISH_TOKEN` → Value: **liitä token** → Save
Toista jokaiselle repolle, joka julkaisee raportteja. Toista jokaiselle repolle, joka julkaisee raportteja.
@@ -99,23 +99,23 @@ Palaa takaisin [README.md](../README.md#käyttöönotto) ja jatka kohdasta "Inst
| Looginen nimi | K8s | Gitea | | Looginen nimi | K8s | Gitea |
|---|---|---| |---|---|---|
| `report_publish_api_token` | `gitea-reports-publish-auth` (htpasswd) | Actions Secret: `REPORTS_PUBLISH_TOKEN` | | `report_publish_api_token` | `git-pages-publish-auth` (htpasswd) | Actions Secret: `GIT_PAGES_PUBLISH_TOKEN` |
| `reports_retention_read_token` | `gitea-reports-retention-gitea` (token) | PAT: `CI-REPORTS_READ_FOR_RETENTION` | | `reports_retention_read_token` | `git-pages-retention-gitea` (token) | PAT: `CI-REPORTS_READ_FOR_RETENTION` |
### Secret Reference Architecture ### Secret Reference Architecture
```mermaid ```mermaid
graph TD graph TD
subgraph "Publish Flow" subgraph "Publish Flow"
P1["Actions Secret<br/>REPORTS_PUBLISH_TOKEN"] P1["Actions Secret<br/>GIT_PAGES_PUBLISH_TOKEN"]
P2["K8s Secret<br/>gitea-reports-publish-auth"] P2["K8s Secret<br/>git-pages-publish-auth"]
P1 -->|token| TRAEFIK P1 -->|token| TRAEFIK
P2 -->|htpasswd| TRAEFIK P2 -->|htpasswd| TRAEFIK
TRAEFIK["Traefik BasicAuth"] TRAEFIK["Traefik BasicAuth"]
end end
subgraph "Retention Flow" subgraph "Retention Flow"
R1["K8s Secret<br/>gitea-reports-retention-gitea"] R1["K8s Secret<br/>git-pages-retention-gitea"]
R2["Gitea PAT<br/>CI-REPORTS_READ_FOR_RETENTION"] R2["Gitea PAT<br/>CI-REPORTS_READ_FOR_RETENTION"]
R1 -->|token| SC["Sidecar"] R1 -->|token| SC["Sidecar"]
SC -->|API auth| GITEA["Gitea API"] SC -->|API auth| GITEA["Gitea API"]
@@ -133,8 +133,8 @@ graph TD
sequenceDiagram sequenceDiagram
participant Actions as Gitea Actions participant Actions as Gitea Actions
participant Traefik as Traefik participant Traefik as Traefik
participant K8sAuth as K8s Secret<br/>gitea-reports-publish-auth participant K8sAuth as K8s Secret<br/>git-pages-publish-auth
participant K8sToken as K8s Secret<br/>gitea-reports-publish-token participant K8sToken as K8s Secret<br/>git-pages-publish-token
participant Upload as upload-sidecar participant Upload as upload-sidecar
participant PV as PVC /app/data participant PV as PVC /app/data
@@ -158,8 +158,8 @@ sequenceDiagram
``` ```
**Kaksi secretiä (Traefik-yhteensopivuus):** **Kaksi secretiä (Traefik-yhteensopivuus):**
- `gitea-reports-publish-auth` = `users` (htpasswd, Traefik käyttää) - `git-pages-publish-auth` = `users` (htpasswd, Traefik käyttää)
- `gitea-reports-publish-token` = `token` (plaintext, luetaan Giteaan viedessä) - `git-pages-publish-token` = `token` (plaintext, luetaan Giteaan viedessä)
--- ---
@@ -189,7 +189,7 @@ GET/HEAD-reitillä ei ole Middlewarea. Luku on julkinen, jos URL tunnetaan.
```mermaid ```mermaid
sequenceDiagram sequenceDiagram
participant CronJob as Retention CronJob participant CronJob as Retention CronJob
participant K8sSecret as K8s Secret<br/>gitea-reports-retention-gitea participant K8sSecret as K8s Secret<br/>git-pages-retention-gitea
participant GiteaAPI as Gitea API participant GiteaAPI as Gitea API
participant PV as PVC /app/data participant PV as PVC /app/data
@@ -218,23 +218,23 @@ joista raportteja on PVC:llä.
- **"secret not found"** — luiko secretit ennen Helm-asennusta? - **"secret not found"** — luiko secretit ennen Helm-asennusta?
- **"401 Unauthorized"** — onko Gitea Actions secret oikea? - **"401 Unauthorized"** — onko Gitea Actions secret oikea?
- **"found 2 elements for secret"** — Traefik vaatii single-key secretin. Varmista että `gitea-reports-publish-auth` sisältää vain `users`-avaimen. - **"found 2 elements for secret"** — Traefik vaatii single-key secretin. Varmista että `git-pages-publish-auth` sisältää vain `users`-avaimen.
- **"token hukkuu"** — generoi uusi token (Vaihe 3) ja päivitä molemmat publish-secretit: - **"token hukkuu"** — generoi uusi token (Vaihe 3) ja päivitä molemmat publish-secretit:
```bash ```bash
# 1. Generoi uusi # 1. Generoi uusi
REPORTS_PUBLISH_TOKEN="$(openssl rand -base64 24)" GIT_PAGES_PUBLISH_TOKEN="$(openssl rand -base64 24)"
# 2. Päivitä K8s secrets (molemmat) # 2. Päivitä K8s secrets (molemmat)
NS=gitea-reports NS=gitea-reports
kubectl delete secret gitea-reports-publish-auth -n "$NS" kubectl delete secret git-pages-publish-auth -n "$NS"
kubectl delete secret gitea-reports-publish-token -n "$NS" kubectl delete secret git-pages-publish-token -n "$NS"
kubectl create secret generic gitea-reports-publish-auth \ kubectl create secret generic git-pages-publish-auth \
--from-literal=users="$(docker run --rm httpd:2-alpine htpasswd -nb publish "$REPORTS_PUBLISH_TOKEN")" \ --from-literal=users="$(docker run --rm httpd:2-alpine htpasswd -nb publish "$GIT_PAGES_PUBLISH_TOKEN")" \
-n "$NS" -n "$NS"
kubectl create secret generic gitea-reports-publish-token \ kubectl create secret generic git-pages-publish-token \
--from-literal=token="$REPORTS_PUBLISH_TOKEN" \ --from-literal=token="$GIT_PAGES_PUBLISH_TOKEN" \
-n "$NS" -n "$NS"
# 3. Päivitä Gitea Actions secret jokaisessa repoissa (luke README:stä) # 3. Päivitä Gitea Actions secret jokaisessa repoissa (luke README:stä)
@@ -249,19 +249,19 @@ ADMIN_TOKEN="<gitea-admin-token>"
NS=gitea-reports NS=gitea-reports
# Lue plaintext-token erillisestä secretistä # Lue plaintext-token erillisestä secretistä
TOKEN=$(kubectl get secret gitea-reports-publish-token -n "$NS" -o jsonpath='{.data.token}' | base64 -d) TOKEN=$(kubectl get secret git-pages-publish-token -n "$NS" -o jsonpath='{.data.token}' | base64 -d)
for repo in "owner/repo1" "owner/repo2" "owner/repo3"; do for repo in "owner/repo1" "owner/repo2" "owner/repo3"; do
curl -X POST "https://gitea.example.com/api/v1/repos/$repo/actions/secrets" \ curl -X POST "https://gitea.example.com/api/v1/repos/$repo/actions/secrets" \
-H "Authorization: token $ADMIN_TOKEN" \ -H "Authorization: token $ADMIN_TOKEN" \
-H "Content-Type: application/json" \ -H "Content-Type: application/json" \
-d "{\"name\":\"REPORTS_PUBLISH_TOKEN\",\"data\":\"$TOKEN\"}" -d "{\"name\":\"GIT_PAGES_PUBLISH_TOKEN\",\"data\":\"$TOKEN\"}"
done done
``` ```
Tai `tea` CLI:lla (Gitea:n virallinen CLI): Tai `tea` CLI:lla (Gitea:n virallinen CLI):
```bash ```bash
tea actions secrets add --repo owner/repo1 REPORTS_PUBLISH_TOKEN "$TOKEN" tea actions secrets add --repo owner/repo1 GIT_PAGES_PUBLISH_TOKEN "$TOKEN"
tea actions secrets add --repo owner/repo2 REPORTS_PUBLISH_TOKEN "$TOKEN" tea actions secrets add --repo owner/repo2 GIT_PAGES_PUBLISH_TOKEN "$TOKEN"
``` ```
+15 -11
View File
@@ -1,7 +1,7 @@
# Tech Stack — gitea-reports # Tech Stack — git-pages
> Mitä teknologioita `gitea-reports/` Helm chart käyttää ja edellyttää. Tämä dokumentti koskee vain > Mitä teknologioita `git-pages/` Helm chart käyttää ja edellyttää. Tämä dokumentti koskee vain
> `gitea-reports/`-alikansiota monorepossa — ei juuren `gitea-ci-library`-kirjastoa. > `git-pages/`-alikansiota monorepossa — ei juuren `gitea-ci-library`-kirjastoa.
--- ---
@@ -9,9 +9,13 @@
| Teknologia | Versio | Käyttö | | Teknologia | Versio | Käyttö |
|---|---|---| |---|---|---|
| **nginx** | alpine | Staattinen tiedostopalvelin (GET/HEAD) | | **git-pages** (Codeberg) | `0.9.1` | Staattinen sisältö, apex index-site (`/.index`), HTTP PATCH/PUT -julkaisu |
| **Python** | 3-alpine | PUT-vastaanotto + tar.gz-purku PV:lle | | **Filesystem storage** | — | Sisältö PVC:llä (`/app/data`) |
| **Filesystem storage** | — | Sisältö PVC:llä | | **TOML** | — | Sovellusconfig ConfigMapissa (`config.toml`) |
Image: `codeberg.org/git-pages/git-pages:0.9.1` (ei `v`-etuliitettä tagissa).
Chart ajaa `PAGES_INSECURE=1` — julkaisuvaltuutus Traefik Middlewaressä, ei forge-authia.
--- ---
@@ -22,7 +26,7 @@
| **Kubernetes** | 1.24+ | Deployment, Service, PVC, Secret | | **Kubernetes** | 1.24+ | Deployment, Service, PVC, Secret |
| **Helm** | v3 | Chart asennus ja päivitys | | **Helm** | v3 | Chart asennus ja päivitys |
| **Traefik** | CRD `traefik.io/v1alpha1` | IngressRoute, Middleware (`basicAuth`, HTTPS-redirect) | | **Traefik** | CRD `traefik.io/v1alpha1` | IngressRoute, Middleware (`basicAuth`, HTTPS-redirect) |
| **cert-manager** | — | TLS-sertifikaatti (`gitea-reports-tls`) | | **cert-manager** | — | TLS-sertifikaatti (`git-pages-tls`) |
--- ---
@@ -39,8 +43,8 @@
| Resurssi | Lähde | Dokumentti | | Resurssi | Lähde | Dokumentti |
|---|---|---| |---|---|---|
| `gitea-reports-publish-auth` | Manuaalinen Secret | [secrets.md](secrets.md) | | `git-pages-publish-auth` | Manuaalinen Secret | [secrets.md](secrets.md) |
| `gitea-reports-tls` | cert-manager Certificate | Automaattinen asennuksessa | | `git-pages-tls` | cert-manager Certificate | Automaattinen asennuksessa |
| `ClusterIssuer` | Klusteri (esim. `letsencrypt-prod`) | `dev-values.yaml` | | `ClusterIssuer` | Klusteri (esim. `letsencrypt-prod`) | `dev-values.yaml` |
--- ---
@@ -70,8 +74,8 @@ Esimerkki: `helm upgrade --install gitea-reports ./gitea-reports -n gitea-report
| Teknologia | Syy | | Teknologia | Syy |
|---|---| |---|---|
| **Gitea `pages`-branch** | Ei Gitea gitea-reports -integraatiota | | **Gitea `pages`-branch** | Ei Gitea git-pages -integraatiota |
| **deadnews/gitea-pages** | Ei Gitea API -hakua | | **deadnews/gitea-pages** | Ei Gitea API -hakua |
| **MinIO / S3** | Erillinen raporttivarasto — ei tämän chartin scope | | **MinIO / S3** | Erillinen raporttivarasto — ei tämän chartin scope |
| **Gitea forge-auth / PAT** | Julkaisu BasicAuth-tokenilla (`gitea-reports-publish-auth`) | | **Gitea forge-auth / PAT** | Julkaisu BasicAuth-tokenilla (`git-pages-publish-auth`) |
| **Helm-managed publish Secret** | `publishAuth.create: false` — secret manuaalisesti | | **Helm-managed publish Secret** | `publishAuth.create: false` — secret manuaalisesti |
+2 -2
View File
@@ -3,7 +3,7 @@ Nginx + upload-sidecar installed.
See docs/secrets.md for secret prerequisites (K8s + Gitea Actions). See docs/secrets.md for secret prerequisites (K8s + Gitea Actions).
Install: Install:
helm upgrade --install gitea-reports ./gitea-reports -n {{ .Release.Namespace }} --create-namespace -f dev-values.yaml helm upgrade --install git-pages ./git-pages -n {{ .Release.Namespace }} --create-namespace -f dev-values.yaml
Host: https://{{ .Values.ingress.host }} Host: https://{{ .Values.ingress.host }}
Reports: https://{{ .Values.ingress.host }}/{owner}/{repo}/{branch}/{sha8}/{suite}/ Reports: https://{{ .Values.ingress.host }}/{owner}/{repo}/{branch}/{sha8}/{suite}/
@@ -15,5 +15,5 @@ Publish (CI):
--data-binary @report.tar.gz \ --data-binary @report.tar.gz \
https://{{ .Values.ingress.host }}/{owner}/{repo}/{branch}/{sha8}/{suite}/ https://{{ .Values.ingress.host }}/{owner}/{repo}/{branch}/{sha8}/{suite}/
Upgrade: helm upgrade {{ .Release.Name }} ./gitea-reports -n {{ .Release.Namespace }} -f dev-values.yaml Upgrade: helm upgrade {{ .Release.Name }} ./git-pages -n {{ .Release.Namespace }} -f dev-values.yaml
Uninstall: helm uninstall {{ .Release.Name }} -n {{ .Release.Namespace }} Uninstall: helm uninstall {{ .Release.Name }} -n {{ .Release.Namespace }}
+10 -10
View File
@@ -1,8 +1,8 @@
{{- define "gitea-reports.name" -}} {{- define "git-pages.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
{{- end }} {{- end }}
{{- define "gitea-reports.fullname" -}} {{- define "git-pages.fullname" -}}
{{- if .Values.fullnameOverride }} {{- if .Values.fullnameOverride }}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} {{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
{{- else }} {{- else }}
@@ -15,25 +15,25 @@
{{- end }} {{- end }}
{{- end }} {{- end }}
{{- define "gitea-reports.chart" -}} {{- define "git-pages.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
{{- end }} {{- end }}
{{- define "gitea-reports.labels" -}} {{- define "git-pages.labels" -}}
helm.sh/chart: {{ include "gitea-reports.chart" . }} helm.sh/chart: {{ include "git-pages.chart" . }}
{{ include "gitea-reports.selectorLabels" . }} {{ include "git-pages.selectorLabels" . }}
{{- if .Chart.AppVersion }} {{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }} {{- end }}
app.kubernetes.io/managed-by: {{ .Release.Service }} app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }} {{- end }}
{{- define "gitea-reports.selectorLabels" -}} {{- define "git-pages.selectorLabels" -}}
app.kubernetes.io/name: {{ include "gitea-reports.name" . }} app.kubernetes.io/name: {{ include "git-pages.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }} app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }} {{- end }}
{{- define "gitea-reports.componentLabels" -}} {{- define "git-pages.componentLabels" -}}
{{ include "gitea-reports.labels" . }} {{ include "git-pages.labels" . }}
app.kubernetes.io/component: pages-server app.kubernetes.io/component: pages-server
{{- end }} {{- end }}
+3 -3
View File
@@ -2,11 +2,11 @@
apiVersion: cert-manager.io/v1 apiVersion: cert-manager.io/v1
kind: Certificate kind: Certificate
metadata: metadata:
name: {{ include "gitea-reports.fullname" . }}-tls name: {{ include "git-pages.fullname" . }}-tls
labels: labels:
{{- include "gitea-reports.componentLabels" . | nindent 4 }} {{- include "git-pages.componentLabels" . | nindent 4 }}
spec: spec:
secretName: {{ include "gitea-reports.fullname" . }}-tls secretName: git-pages-tls
dnsNames: dnsNames:
- {{ .Values.ingress.host | quote }} - {{ .Values.ingress.host | quote }}
issuerRef: issuerRef:
+4 -5
View File
@@ -1,9 +1,9 @@
apiVersion: v1 apiVersion: v1
kind: ConfigMap kind: ConfigMap
metadata: metadata:
name: {{ include "gitea-reports.fullname" . }}-config name: {{ include "git-pages.fullname" . }}-config
labels: labels:
{{- include "gitea-reports.componentLabels" . | nindent 4 }} {{- include "git-pages.componentLabels" . | nindent 4 }}
data: data:
default.conf: | default.conf: |
client_max_body_size {{ .Values.nginx.bodySize }}; client_max_body_size {{ .Values.nginx.bodySize }};
@@ -20,15 +20,14 @@ data:
} }
upload-server.py: | upload-server.py: |
#!/usr/bin/env python3 #!/usr/bin/env python3
import http.server, os, sys, tarfile, io, urllib.parse import http.server, os, sys, tarfile, io
PORT = int(os.environ.get("UPLOAD_PORT", "8081")) PORT = int(os.environ.get("UPLOAD_PORT", "8081"))
DATA_ROOT = "/app/data" DATA_ROOT = "/app/data"
class Handler(http.server.BaseHTTPRequestHandler): class Handler(http.server.BaseHTTPRequestHandler):
def do_PUT(self): def do_PUT(self):
path = urllib.parse.unquote(self.path) dest = DATA_ROOT + self.path.rstrip("/")
dest = DATA_ROOT + path.rstrip("/")
os.makedirs(dest, exist_ok=True) os.makedirs(dest, exist_ok=True)
length = int(self.headers.get("Content-Length", 0)) length = int(self.headers.get("Content-Length", 0))
body = self.rfile.read(length) body = self.rfile.read(length)
+7 -7
View File
@@ -1,18 +1,18 @@
apiVersion: apps/v1 apiVersion: apps/v1
kind: Deployment kind: Deployment
metadata: metadata:
name: {{ include "gitea-reports.fullname" . }} name: {{ include "git-pages.fullname" . }}
labels: labels:
{{- include "gitea-reports.componentLabels" . | nindent 4 }} {{- include "git-pages.componentLabels" . | nindent 4 }}
spec: spec:
replicas: 1 replicas: 1
selector: selector:
matchLabels: matchLabels:
{{- include "gitea-reports.selectorLabels" . | nindent 6 }} {{- include "git-pages.selectorLabels" . | nindent 6 }}
template: template:
metadata: metadata:
labels: labels:
{{- include "gitea-reports.componentLabels" . | nindent 8 }} {{- include "git-pages.componentLabels" . | nindent 8 }}
spec: spec:
securityContext: securityContext:
fsGroup: 1000 fsGroup: 1000
@@ -57,13 +57,13 @@ spec:
volumes: volumes:
- name: nginx-conf - name: nginx-conf
configMap: configMap:
name: {{ include "gitea-reports.fullname" . }}-config name: {{ include "git-pages.fullname" . }}-config
items: items:
- key: default.conf - key: default.conf
path: default.conf path: default.conf
- name: upload-script - name: upload-script
configMap: configMap:
name: {{ include "gitea-reports.fullname" . }}-config name: {{ include "git-pages.fullname" . }}-config
defaultMode: 0755 defaultMode: 0755
items: items:
- key: upload-server.py - key: upload-server.py
@@ -71,5 +71,5 @@ spec:
{{- if .Values.persistence.enabled }} {{- if .Values.persistence.enabled }}
- name: data - name: data
persistentVolumeClaim: persistentVolumeClaim:
claimName: {{ include "gitea-reports.fullname" . }}-data claimName: {{ include "git-pages.fullname" . }}-data
{{- end }} {{- end }}
+10 -10
View File
@@ -2,9 +2,9 @@
apiVersion: traefik.io/v1alpha1 apiVersion: traefik.io/v1alpha1
kind: IngressRoute kind: IngressRoute
metadata: metadata:
name: {{ include "gitea-reports.fullname" . }} name: {{ include "git-pages.fullname" . }}
labels: labels:
{{- include "gitea-reports.componentLabels" . | nindent 4 }} {{- include "git-pages.componentLabels" . | nindent 4 }}
spec: spec:
entryPoints: entryPoints:
- {{ .Values.ingress.entryPoints.websecure }} - {{ .Values.ingress.entryPoints.websecure }}
@@ -14,24 +14,24 @@ spec:
(Method(`PATCH`) || Method(`PUT`)) (Method(`PATCH`) || Method(`PUT`))
kind: Rule kind: Rule
middlewares: middlewares:
- name: {{ include "gitea-reports.fullname" . }}-publish-auth - name: {{ include "git-pages.fullname" . }}-publish-auth
services: services:
- name: {{ include "gitea-reports.fullname" . }} - name: {{ include "git-pages.fullname" . }}
port: {{ .Values.upload.port }} port: {{ .Values.upload.port }}
- match: Host(`{{ .Values.ingress.host }}`) && (Method(`GET`) || Method(`HEAD`)) - match: Host(`{{ .Values.ingress.host }}`) && (Method(`GET`) || Method(`HEAD`))
kind: Rule kind: Rule
services: services:
- name: {{ include "gitea-reports.fullname" . }} - name: {{ include "git-pages.fullname" . }}
port: {{ .Values.nginx.port }} port: {{ .Values.nginx.port }}
tls: tls:
secretName: {{ include "gitea-reports.fullname" . }}-tls secretName: git-pages-tls
--- ---
apiVersion: traefik.io/v1alpha1 apiVersion: traefik.io/v1alpha1
kind: IngressRoute kind: IngressRoute
metadata: metadata:
name: {{ include "gitea-reports.fullname" . }}-http name: {{ include "git-pages.fullname" . }}-http
labels: labels:
{{- include "gitea-reports.componentLabels" . | nindent 4 }} {{- include "git-pages.componentLabels" . | nindent 4 }}
spec: spec:
entryPoints: entryPoints:
- {{ .Values.ingress.entryPoints.web }} - {{ .Values.ingress.entryPoints.web }}
@@ -41,8 +41,8 @@ spec:
!PathPrefix(`/.well-known/acme-challenge/`) !PathPrefix(`/.well-known/acme-challenge/`)
kind: Rule kind: Rule
middlewares: middlewares:
- name: {{ include "gitea-reports.fullname" . }}-https-redirect - name: {{ include "git-pages.fullname" . }}-https-redirect
services: services:
- name: {{ include "gitea-reports.fullname" . }} - name: {{ include "git-pages.fullname" . }}
port: {{ .Values.nginx.port }} port: {{ .Values.nginx.port }}
{{- end }} {{- end }}
+5 -5
View File
@@ -2,19 +2,19 @@
apiVersion: traefik.io/v1alpha1 apiVersion: traefik.io/v1alpha1
kind: Middleware kind: Middleware
metadata: metadata:
name: {{ include "gitea-reports.fullname" . }}-publish-auth name: {{ include "git-pages.fullname" . }}-publish-auth
labels: labels:
{{- include "gitea-reports.componentLabels" . | nindent 4 }} {{- include "git-pages.componentLabels" . | nindent 4 }}
spec: spec:
basicAuth: basicAuth:
secret: {{ include "gitea-reports.fullname" . }}-publish-auth secret: git-pages-publish-auth
--- ---
apiVersion: traefik.io/v1alpha1 apiVersion: traefik.io/v1alpha1
kind: Middleware kind: Middleware
metadata: metadata:
name: {{ include "gitea-reports.fullname" . }}-https-redirect name: {{ include "git-pages.fullname" . }}-https-redirect
labels: labels:
{{- include "gitea-reports.componentLabels" . | nindent 4 }} {{- include "git-pages.componentLabels" . | nindent 4 }}
spec: spec:
redirectScheme: redirectScheme:
scheme: https scheme: https
@@ -2,9 +2,9 @@
apiVersion: v1 apiVersion: v1
kind: Secret kind: Secret
metadata: metadata:
name: {{ include "gitea-reports.fullname" . }}-publish-auth name: git-pages-publish-auth
labels: labels:
{{- include "gitea-reports.componentLabels" . | nindent 4 }} {{- include "git-pages.componentLabels" . | nindent 4 }}
type: Opaque type: Opaque
stringData: stringData:
users: | users: |
+2 -2
View File
@@ -2,9 +2,9 @@
apiVersion: v1 apiVersion: v1
kind: PersistentVolumeClaim kind: PersistentVolumeClaim
metadata: metadata:
name: {{ include "gitea-reports.fullname" . }}-data name: {{ include "git-pages.fullname" . }}-data
labels: labels:
{{- include "gitea-reports.componentLabels" . | nindent 4 }} {{- include "git-pages.componentLabels" . | nindent 4 }}
spec: spec:
accessModes: accessModes:
- {{ .Values.persistence.accessMode }} - {{ .Values.persistence.accessMode }}
@@ -2,9 +2,9 @@
apiVersion: v1 apiVersion: v1
kind: ConfigMap kind: ConfigMap
metadata: metadata:
name: {{ include "gitea-reports.fullname" . }}-retention name: git-pages-retention
labels: labels:
{{- include "gitea-reports.componentLabels" . | nindent 4 }} {{- include "git-pages.componentLabels" . | nindent 4 }}
data: data:
retention.json: | retention.json: |
{{- .Values.retention.rules | toJson | nindent 4 }} {{- .Values.retention.rules | toJson | nindent 4 }}
@@ -2,9 +2,9 @@
apiVersion: batch/v1 apiVersion: batch/v1
kind: CronJob kind: CronJob
metadata: metadata:
name: {{ include "gitea-reports.fullname" . }}-retention name: git-pages-retention
labels: labels:
{{- include "gitea-reports.componentLabels" . | nindent 4 }} {{- include "git-pages.componentLabels" . | nindent 4 }}
spec: spec:
schedule: {{ .Values.retention.schedule | quote }} schedule: {{ .Values.retention.schedule | quote }}
concurrencyPolicy: Forbid concurrencyPolicy: Forbid
@@ -16,10 +16,10 @@ spec:
template: template:
metadata: metadata:
labels: labels:
app.kubernetes.io/name: {{ include "gitea-reports.fullname" . }}-retention app.kubernetes.io/name: git-pages-retention
app.kubernetes.io/instance: {{ .Release.Name }} app.kubernetes.io/instance: {{ .Release.Name }}
spec: spec:
serviceAccountName: {{ include "gitea-reports.fullname" . }}-retention serviceAccountName: git-pages-retention
restartPolicy: OnFailure restartPolicy: OnFailure
containers: containers:
- name: retention - name: retention
@@ -46,7 +46,7 @@ spec:
- name: GITEA_TOKEN - name: GITEA_TOKEN
valueFrom: valueFrom:
secretKeyRef: secretKeyRef:
name: {{ include "gitea-reports.fullname" . }}-retention-gitea name: git-pages-retention-gitea
key: token key: token
volumeMounts: volumeMounts:
- name: data - name: data
@@ -58,14 +58,14 @@ spec:
volumes: volumes:
- name: data - name: data
persistentVolumeClaim: persistentVolumeClaim:
claimName: {{ include "gitea-reports.fullname" . }}-data claimName: {{ include "git-pages.fullname" . }}-data
- name: scripts - name: scripts
configMap: configMap:
name: {{ include "gitea-reports.fullname" . }}-retention name: git-pages-retention
defaultMode: 0755 defaultMode: 0755
- name: config - name: config
configMap: configMap:
name: {{ include "gitea-reports.fullname" . }}-retention name: git-pages-retention
items: items:
- key: retention.json - key: retention.json
path: retention.json path: retention.json
+8 -8
View File
@@ -2,16 +2,16 @@
apiVersion: v1 apiVersion: v1
kind: ServiceAccount kind: ServiceAccount
metadata: metadata:
name: {{ include "gitea-reports.fullname" . }}-retention name: git-pages-retention
labels: labels:
{{- include "gitea-reports.componentLabels" . | nindent 4 }} {{- include "git-pages.componentLabels" . | nindent 4 }}
--- ---
apiVersion: rbac.authorization.k8s.io/v1 apiVersion: rbac.authorization.k8s.io/v1
kind: Role kind: Role
metadata: metadata:
name: {{ include "gitea-reports.fullname" . }}-retention name: git-pages-retention
labels: labels:
{{- include "gitea-reports.componentLabels" . | nindent 4 }} {{- include "git-pages.componentLabels" . | nindent 4 }}
rules: rules:
- apiGroups: ["apps"] - apiGroups: ["apps"]
resources: ["deployments", "deployments/scale"] resources: ["deployments", "deployments/scale"]
@@ -23,15 +23,15 @@ rules:
apiVersion: rbac.authorization.k8s.io/v1 apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding kind: RoleBinding
metadata: metadata:
name: {{ include "gitea-reports.fullname" . }}-retention name: git-pages-retention
labels: labels:
{{- include "gitea-reports.componentLabels" . | nindent 4 }} {{- include "git-pages.componentLabels" . | nindent 4 }}
roleRef: roleRef:
apiGroup: rbac.authorization.k8s.io apiGroup: rbac.authorization.k8s.io
kind: Role kind: Role
name: {{ include "gitea-reports.fullname" . }}-retention name: git-pages-retention
subjects: subjects:
- kind: ServiceAccount - kind: ServiceAccount
name: {{ include "gitea-reports.fullname" . }}-retention name: git-pages-retention
namespace: {{ .Release.Namespace }} namespace: {{ .Release.Namespace }}
{{- end }} {{- end }}
+3 -3
View File
@@ -1,13 +1,13 @@
apiVersion: v1 apiVersion: v1
kind: Service kind: Service
metadata: metadata:
name: {{ include "gitea-reports.fullname" . }} name: {{ include "git-pages.fullname" . }}
labels: labels:
{{- include "gitea-reports.componentLabels" . | nindent 4 }} {{- include "git-pages.componentLabels" . | nindent 4 }}
spec: spec:
type: {{ .Values.service.type }} type: {{ .Values.service.type }}
selector: selector:
{{- include "gitea-reports.selectorLabels" . | nindent 4 }} {{- include "git-pages.selectorLabels" . | nindent 4 }}
ports: ports:
- name: http-read - name: http-read
port: {{ .Values.nginx.port }} port: {{ .Values.nginx.port }}
+5 -4
View File
@@ -81,10 +81,11 @@ generate_index() {
} > "$REPORT_DIR/index.html" } > "$REPORT_DIR/index.html"
} }
mkdir -p "$SUITE" STAGED="reports/${SHA8}/${SUITE}"
mkdir -p "$STAGED"
if [ "$TOTAL" -eq 1 ]; then if [ "$TOTAL" -eq 1 ]; then
cp -a "$REPORT_DIR/." "$SUITE/" cp -a "$REPORT_DIR/." "$STAGED/"
sh .ci/scripts/publish-git-pages.sh "$SUITE" sh .ci/scripts/publish-git-pages.sh "$SUITE"
first_entry=$(echo "$ENTRIES" | head -1) first_entry=$(echo "$ENTRIES" | head -1)
@@ -101,9 +102,9 @@ if [ "$TOTAL" -eq 1 ]; then
sh .ci/scripts/report-status.sh "$STATUS" "$DESCRIPTION" "$CONTEXT" "" "$URL" sh .ci/scripts/report-status.sh "$STATUS" "$DESCRIPTION" "$CONTEXT" "" "$URL"
else else
generate_index generate_index
cp -a "$REPORT_DIR/." "$SUITE/" cp -a "$REPORT_DIR/." "$STAGED/"
sh .ci/scripts/publish-git-pages.sh "$SUITE" sh .ci/scripts/publish-git-pages.sh "$SUITE"
sh .ci/scripts/report-status.sh "$STATUS" "$DESCRIPTION" "$CONTEXT" "$SUITE" sh .ci/scripts/report-status.sh "$STATUS" "$DESCRIPTION" "$CONTEXT" "$SUITE"
fi fi
rm -rf "$SUITE" rm -rf "$STAGED"
+1 -1
View File
@@ -21,7 +21,7 @@ while IFS='=' read -r key value || [ -n "$key" ]; do
done < "$CONF_FILE" done < "$CONF_FILE"
[ -z "${GITEA_TOKEN:-}" ] && echo "ERROR: GITEA_TOKEN secret is not set" >&2 && ERRORS=1 [ -z "${GITEA_TOKEN:-}" ] && echo "ERROR: GITEA_TOKEN secret is not set" >&2 && ERRORS=1
[ -z "${REPORTS_PUBLISH_TOKEN:-}" ] && echo "ERROR: REPORTS_PUBLISH_TOKEN secret is not set" >&2 && ERRORS=1 [ -z "${GIT_PAGES_PUBLISH_TOKEN:-}" ] && echo "ERROR: GIT_PAGES_PUBLISH_TOKEN secret is not set" >&2 && ERRORS=1
if [ "$ERRORS" -ne 0 ]; then if [ "$ERRORS" -ne 0 ]; then
echo "FATAL: CI config validation failed" >&2 echo "FATAL: CI config validation failed" >&2
+2 -8
View File
@@ -5,7 +5,7 @@ SUITE_PATH="${1:-}"
[ -n "$SUITE_PATH" ] || { echo "ERROR: suite_path argument required" >&2; exit 1; } [ -n "$SUITE_PATH" ] || { echo "ERROR: suite_path argument required" >&2; exit 1; }
[ -n "${GIT_PAGES_URL:-}" ] || { echo "ERROR: GIT_PAGES_URL is not set" >&2; exit 1; } [ -n "${GIT_PAGES_URL:-}" ] || { echo "ERROR: GIT_PAGES_URL is not set" >&2; exit 1; }
[ -n "${REPORTS_PUBLISH_TOKEN:-}" ] || { echo "ERROR: REPORTS_PUBLISH_TOKEN is not set" >&2; exit 1; } [ -n "${GIT_PAGES_PUBLISH_TOKEN:-}" ] || { echo "ERROR: GIT_PAGES_PUBLISH_TOKEN is not set" >&2; exit 1; }
[ -n "${GITHUB_REPOSITORY:-}" ] || { echo "ERROR: GITHUB_REPOSITORY is not set" >&2; exit 1; } [ -n "${GITHUB_REPOSITORY:-}" ] || { echo "ERROR: GITHUB_REPOSITORY is not set" >&2; exit 1; }
[ -n "${GITHUB_SHA:-}" ] || { echo "ERROR: GITHUB_SHA is not set" >&2; exit 1; } [ -n "${GITHUB_SHA:-}" ] || { echo "ERROR: GITHUB_SHA is not set" >&2; exit 1; }
[ -n "${GITHUB_REF_NAME:-}" ] || { echo "ERROR: GITHUB_REF_NAME is not set" >&2; exit 1; } [ -n "${GITHUB_REF_NAME:-}" ] || { echo "ERROR: GITHUB_REF_NAME is not set" >&2; exit 1; }
@@ -19,12 +19,6 @@ PAGES_USER="${GIT_PAGES_PUBLISH_USER:-publish}"
[ -d "$SUITE" ] || { echo "ERROR: not a directory: $SUITE" >&2; exit 1; } [ -d "$SUITE" ] || { echo "ERROR: not a directory: $SUITE" >&2; exit 1; }
EMPTY=1
for _f in "$SUITE"/* "$SUITE"/.*; do
[ -e "$_f" ] && { EMPTY=0; break; }
done
[ "$EMPTY" -eq 0 ] || { echo "ERROR: no files to publish in $SUITE" >&2; exit 1; }
WORK=$(mktemp -d) WORK=$(mktemp -d)
TAR=$(mktemp) TAR=$(mktemp)
trap 'rm -rf "$WORK" "$TAR"' EXIT trap 'rm -rf "$WORK" "$TAR"' EXIT
@@ -99,7 +93,7 @@ tar czf "$TAR" -C "$WORK/$SUITE" .
# PUT upload-sidecariin # PUT upload-sidecariin
PUBLISH_URL="${GIT_PAGES_URL}/${OWNER}/${REPO}/${BRANCH}/${SHA8}/${SUITE}/" PUBLISH_URL="${GIT_PAGES_URL}/${OWNER}/${REPO}/${BRANCH}/${SHA8}/${SUITE}/"
HTTP_CODE=$(curl -sS -X PUT "$PUBLISH_URL" \ HTTP_CODE=$(curl -sS -X PUT "$PUBLISH_URL" \
-u "${PAGES_USER}:${REPORTS_PUBLISH_TOKEN}" \ -u "${PAGES_USER}:${GIT_PAGES_PUBLISH_TOKEN}" \
-H "Content-Type: application/tar+gz" \ -H "Content-Type: application/tar+gz" \
--data-binary @"$TAR" \ --data-binary @"$TAR" \
-o /tmp/git-pages-publish-response.txt \ -o /tmp/git-pages-publish-response.txt \
+1 -1
View File
@@ -7,7 +7,7 @@ SUITE_PATH="${1:-}"
[ -n "${GITEA_API_URL:-}" ] || { echo "ERROR: GITEA_API_URL is not set" >&2; exit 1; } [ -n "${GITEA_API_URL:-}" ] || { echo "ERROR: GITEA_API_URL is not set" >&2; exit 1; }
[ -n "${GITEA_TOKEN:-}" ] || { echo "ERROR: GITEA_TOKEN is not set" >&2; exit 1; } [ -n "${GITEA_TOKEN:-}" ] || { echo "ERROR: GITEA_TOKEN is not set" >&2; exit 1; }
[ -n "${GIT_PAGES_URL:-}" ] || { echo "ERROR: GIT_PAGES_URL is not set" >&2; exit 1; } [ -n "${GIT_PAGES_URL:-}" ] || { echo "ERROR: GIT_PAGES_URL is not set" >&2; exit 1; }
[ -n "${REPORTS_PUBLISH_TOKEN:-}" ] || { echo "ERROR: REPORTS_PUBLISH_TOKEN is not set" >&2; exit 1; } [ -n "${GIT_PAGES_PUBLISH_TOKEN:-}" ] || { echo "ERROR: GIT_PAGES_PUBLISH_TOKEN is not set" >&2; exit 1; }
SCRIPT_DIR="$(dirname "$0")" SCRIPT_DIR="$(dirname "$0")"
+1 -1
View File
@@ -473,7 +473,7 @@ VERSION_FILE=git-pages/Chart.yaml
| Secret | Pakollinen | | Secret | Pakollinen |
|---|---| |---|---|
| `GITEA_TOKEN` | Aina (Gitean sisäinen, automaattisesti saatavilla) | | `GITEA_TOKEN` | Aina (Gitean sisäinen, automaattisesti saatavilla) |
| `REPORTS_PUBLISH_TOKEN` | Aina | | `GIT_PAGES_PUBLISH_TOKEN` | Aina |
| `DOCKER_USERNAME` | Vain jos buildaat kontteja | | `DOCKER_USERNAME` | Vain jos buildaat kontteja |
| `DOCKER_PASSWORD` | Vain jos buildaat kontteja | | `DOCKER_PASSWORD` | Vain jos buildaat kontteja |
| `HELM_USER` | Vain jos pushaat Helm chartin OCI-rekisteriin (oletus `github.actor`) | | `HELM_USER` | Vain jos pushaat Helm chartin OCI-rekisteriin (oletus `github.actor`) |
+5 -5
View File
@@ -44,15 +44,15 @@ EOF
[[ "$output" == *"GITEA_TOKEN"* ]] [[ "$output" == *"GITEA_TOKEN"* ]]
} }
@test "missing REPORTS_PUBLISH_TOKEN secret → exit 1" { @test "missing GIT_PAGES_PUBLISH_TOKEN secret → exit 1" {
cat > "$CONF_FILE" <<EOF cat > "$CONF_FILE" <<EOF
SOME_KEY=ok SOME_KEY=ok
EOF EOF
export GITEA_TOKEN="sometoken" export GITEA_TOKEN="sometoken"
unset REPORTS_PUBLISH_TOKEN unset GIT_PAGES_PUBLISH_TOKEN
run bash scripts/ci-validate.sh run bash scripts/ci-validate.sh
[ "$status" -eq 1 ] [ "$status" -eq 1 ]
[[ "$output" == *"REPORTS_PUBLISH_TOKEN"* ]] [[ "$output" == *"GIT_PAGES_PUBLISH_TOKEN"* ]]
} }
@test "valid config and all secrets → exit 0" { @test "valid config and all secrets → exit 0" {
@@ -61,7 +61,7 @@ API_URL=https://example.com
ANOTHER=https://test.fi ANOTHER=https://test.fi
EOF EOF
export GITEA_TOKEN="sometoken" export GITEA_TOKEN="sometoken"
export REPORTS_PUBLISH_TOKEN="sometoken" export GIT_PAGES_PUBLISH_TOKEN="sometoken"
run bash scripts/ci-validate.sh run bash scripts/ci-validate.sh
[ "$status" -eq 0 ] [ "$status" -eq 0 ]
} }
@@ -73,7 +73,7 @@ EOF
VALID_URL=https://example.com VALID_URL=https://example.com
EOF EOF
export GITEA_TOKEN="sometoken" export GITEA_TOKEN="sometoken"
export REPORTS_PUBLISH_TOKEN="sometoken" export GIT_PAGES_PUBLISH_TOKEN="sometoken"
run bash scripts/ci-validate.sh run bash scripts/ci-validate.sh
[ "$status" -eq 0 ] [ "$status" -eq 0 ]
} }
@@ -27,7 +27,7 @@ function bashQuiet(cmd) {
} }
function runReportStatus(args) { function runReportStatus(args) {
return bash(`export GITEA_API_URL="http://localhost:18080" GITEA_TOKEN="test-token-abc123" GIT_PAGES_URL="https://reports.example.com" GITHUB_REPOSITORY="test-owner/test-repo" GITHUB_REF_NAME="main" GITHUB_SHA="abc123def456789012345678901234567890abcd" GITHUB_RUN_ID="42"; bash "${REPORT_SCRIPT}" ${args}`); return bash(`export GITEA_API_URL="http://localhost:18080" GITEA_TOKEN="test-token-abc123" GIT_PAGES_URL="https://reports.example.com" GITHUB_REPOSITORY="test-owner/test-repo" GITHUB_SHA="abc123def456789012345678901234567890abcd" GITHUB_RUN_ID="42"; bash "${REPORT_SCRIPT}" ${args}`);
} }
function getMockBody() { function getMockBody() {
@@ -57,7 +57,7 @@ When('a build step completes successfully and reports its results', function ()
Then('the commit shows a success status with a clickable link to the results', function () { Then('the commit shows a success status with a clickable link to the results', function () {
const body = getMockBody(); const body = getMockBody();
if (!body.includes('"state":"success"')) throw new Error('Expected success status'); if (!body.includes('"state":"success"')) throw new Error('Expected success status');
if (!body.includes('"target_url":"https://reports.example.com/test-owner/test-repo/main/abc123de/cucumber/"')) throw new Error('Expected URL'); if (!body.includes('"target_url":"https://reports.example.com/test-owner/test-repo/reports/abc123de/cucumber/"')) throw new Error('Expected URL');
}); });
When('a build step fails', function () { When('a build step fails', function () {
-8
View File
@@ -67,14 +67,6 @@ class H(http.server.BaseHTTPRequestHandler):
self.end_headers() self.end_headers()
self.wfile.write(body.encode()) self.wfile.write(body.encode())
def do_PUT(self):
self._log_request('PUT')
code, body = self._get_response()
self.send_response(code)
self.send_header('Content-Type', 'application/json')
self.end_headers()
self.wfile.write(body.encode())
def do_PATCH(self): def do_PATCH(self):
self._log_request('PATCH') self._log_request('PATCH')
code, body = self._get_response() code, body = self._get_response()
+15 -23
View File
@@ -4,18 +4,18 @@ setup() {
source tests/helpers/mock-api.sh source tests/helpers/mock-api.sh
export GITEA_API_URL="http://localhost:18080" export GITEA_API_URL="http://localhost:18080"
export GIT_PAGES_URL="http://localhost:18080" export GIT_PAGES_URL="http://localhost:18080"
export REPORTS_PUBLISH_TOKEN="publish-token-abc" export GIT_PAGES_PUBLISH_TOKEN="publish-token-abc"
export GITHUB_REPOSITORY="test-owner/test-repo" export GITHUB_REPOSITORY="test-owner/test-repo"
export GITHUB_SHA="abc123def456789012345678901234567890abcd" export GITHUB_SHA="abc123def456789012345678901234567890abcd"
export GITHUB_REF_NAME="main"
mkdir -p "unit-tests" REPORT_DIR="reports/abc123de/unit-tests"
echo "<html>test</html>" > "unit-tests/index.html" mkdir -p "$REPORT_DIR"
echo "<html>test</html>" > "$REPORT_DIR/index.html"
} }
teardown() { teardown() {
mock_stop mock_stop
rm -rf "unit-tests" "sub" "empty-suite" rm -rf "reports/abc123de"
} }
@test "missing suite_path argument → exit 1" { @test "missing suite_path argument → exit 1" {
@@ -24,11 +24,11 @@ teardown() {
[[ "$output" == *"ERROR"* ]] [[ "$output" == *"ERROR"* ]]
} }
@test "missing GITHUB_REF_NAME → exit 1" { @test "missing GITEA_API_URL → exit 1" {
unset GITHUB_REF_NAME unset GITEA_API_URL
run bash scripts/publish-git-pages.sh "unit-tests" run bash scripts/publish-git-pages.sh "unit-tests"
[ "$status" -eq 1 ] [ "$status" -eq 1 ]
[[ "$output" == *"GITHUB_REF_NAME"* ]] [[ "$output" == *"GITEA_API_URL"* ]]
} }
@test "missing GIT_PAGES_URL → exit 1" { @test "missing GIT_PAGES_URL → exit 1" {
@@ -38,11 +38,11 @@ teardown() {
[[ "$output" == *"GIT_PAGES_URL"* ]] [[ "$output" == *"GIT_PAGES_URL"* ]]
} }
@test "missing REPORTS_PUBLISH_TOKEN → exit 1" { @test "missing GIT_PAGES_PUBLISH_TOKEN → exit 1" {
unset REPORTS_PUBLISH_TOKEN unset GIT_PAGES_PUBLISH_TOKEN
run bash scripts/publish-git-pages.sh "unit-tests" run bash scripts/publish-git-pages.sh "unit-tests"
[ "$status" -eq 1 ] [ "$status" -eq 1 ]
[[ "$output" == *"REPORTS_PUBLISH_TOKEN"* ]] [[ "$output" == *"GIT_PAGES_PUBLISH_TOKEN"* ]]
} }
@test "missing GITHUB_REPOSITORY → exit 1" { @test "missing GITHUB_REPOSITORY → exit 1" {
@@ -58,14 +58,6 @@ teardown() {
[[ "$output" == *"not a directory"* ]] [[ "$output" == *"not a directory"* ]]
} }
@test "empty directory → exit 1" {
mkdir -p "empty-suite"
run bash scripts/publish-git-pages.sh "empty-suite"
[ "$status" -eq 1 ]
[[ "$output" == *"no files to publish"* ]]
rm -rf "empty-suite"
}
@test "valid publish returns report base URL" { @test "valid publish returns report base URL" {
mock_set_sequence '[ mock_set_sequence '[
{"code":200,"body":"published"} {"code":200,"body":"published"}
@@ -73,19 +65,19 @@ teardown() {
mock_start mock_start
run bash scripts/publish-git-pages.sh "unit-tests" run bash scripts/publish-git-pages.sh "unit-tests"
[ "$status" -eq 0 ] [ "$status" -eq 0 ]
[[ "$output" == "http://localhost:18080/test-owner/test-repo/main/abc123de/unit-tests/" ]] [[ "$output" == "http://localhost:18080/test-owner/test-repo/reports/abc123de" ]]
} }
@test "publish with suite subpath" { @test "publish with suite subpath" {
mkdir -p "sub/suite" mkdir -p "reports/abc123de/sub/suite"
echo "sub" > "sub/suite/result.html" echo "sub" > "reports/abc123de/sub/suite/result.html"
mock_set_sequence '[ mock_set_sequence '[
{"code":200,"body":"published"} {"code":200,"body":"published"}
]' ]'
mock_start mock_start
run bash scripts/publish-git-pages.sh "sub/suite" run bash scripts/publish-git-pages.sh "sub/suite"
[ "$status" -eq 0 ] [ "$status" -eq 0 ]
[[ "$output" == "http://localhost:18080/test-owner/test-repo/main/abc123de/sub/suite/" ]] [[ "$output" == "http://localhost:18080/test-owner/test-repo/reports/abc123de" ]]
} }
@test "git-pages returns HTTP 500 → exit 1" { @test "git-pages returns HTTP 500 → exit 1" {
+4 -4
View File
@@ -4,7 +4,7 @@ setup() {
export GITEA_API_URL="http://localhost:18080" export GITEA_API_URL="http://localhost:18080"
export GITEA_TOKEN="test-token-abc" export GITEA_TOKEN="test-token-abc"
export GIT_PAGES_URL="http://localhost:18080" export GIT_PAGES_URL="http://localhost:18080"
export REPORTS_PUBLISH_TOKEN="publish-token-abc" export GIT_PAGES_PUBLISH_TOKEN="publish-token-abc"
export GITHUB_REPOSITORY="test-owner/test-repo" export GITHUB_REPOSITORY="test-owner/test-repo"
export GITHUB_SHA="abc123def456789012345678901234567890abcd" export GITHUB_SHA="abc123def456789012345678901234567890abcd"
} }
@@ -36,9 +36,9 @@ setup() {
[[ "$output" == *"GIT_PAGES_URL"* ]] [[ "$output" == *"GIT_PAGES_URL"* ]]
} }
@test "missing REPORTS_PUBLISH_TOKEN → exit 1" { @test "missing GIT_PAGES_PUBLISH_TOKEN → exit 1" {
unset REPORTS_PUBLISH_TOKEN unset GIT_PAGES_PUBLISH_TOKEN
run bash scripts/publish.sh "unit-tests" run bash scripts/publish.sh "unit-tests"
[ "$status" -eq 1 ] [ "$status" -eq 1 ]
[[ "$output" == *"REPORTS_PUBLISH_TOKEN"* ]] [[ "$output" == *"GIT_PAGES_PUBLISH_TOKEN"* ]]
} }
+1 -2
View File
@@ -8,7 +8,6 @@ setup() {
export GITHUB_REPOSITORY="test-owner/test-repo" export GITHUB_REPOSITORY="test-owner/test-repo"
export GITHUB_SHA="abc123def456789012345678901234567890abcd" export GITHUB_SHA="abc123def456789012345678901234567890abcd"
export GITHUB_RUN_ID="42" export GITHUB_RUN_ID="42"
export GITHUB_REF_NAME="main"
} }
teardown() { teardown() {
@@ -36,7 +35,7 @@ teardown() {
body=$(mock_get_request_body) body=$(mock_get_request_body)
[[ "$body" == *'"state":"success"'* ]] [[ "$body" == *'"state":"success"'* ]]
[[ "$body" == *'"context":"unit-test"'* ]] [[ "$body" == *'"context":"unit-test"'* ]]
[[ "$body" == *'"target_url":"https://reports.example.com/test-owner/test-repo/main/abc123de/cucumber/"'* ]] [[ "$body" == *'"target_url":"https://reports.example.com/test-owner/test-repo/reports/abc123de/cucumber/"'* ]]
} }
@test "failure status constructs run URL when no suite" { @test "failure status constructs run URL when no suite" {