From f8535718c2e4bf2834235b8f01195b514008a8ec Mon Sep 17 00:00:00 2001 From: moilanik Date: Sat, 13 Jun 2026 16:49:37 +0300 Subject: [PATCH] siivous: scriptit env-pohjaisiksi, validointi, siistit kutsut --- .gitea/workflows/build-feature.yml | 25 +++-- .gitea/workflows/ci-engine.yml | 14 +-- README.md | 24 +++++ scripts/ci-validate.sh | 35 +++++++ scripts/publish-git-pages.sh | 23 ++--- scripts/publish.sh | 20 ++-- scripts/report-status.sh | 30 ++---- .../step_definitions/commit-status.steps.js | 24 ++--- tests/report-status.bats | 93 ++++++++----------- 9 files changed, 159 insertions(+), 129 deletions(-) create mode 100644 scripts/ci-validate.sh diff --git a/.gitea/workflows/build-feature.yml b/.gitea/workflows/build-feature.yml index 2d9af4c..5c2d14c 100644 --- a/.gitea/workflows/build-feature.yml +++ b/.gitea/workflows/build-feature.yml @@ -29,6 +29,9 @@ jobs: repository: niko/gitea-ci-library path: .ci + - name: Validate CI config + run: bash .ci/scripts/ci-validate.sh + - name: Run bats tests id: bats-tests shell: bash @@ -52,16 +55,16 @@ jobs: if: always() shell: bash run: | - bash .ci/scripts/publish-git-pages.sh "bats/" "$PAGES_HOST" "$GIT_PAGES_PUBLISH_URL" "$GIT_PAGES_PUBLISH_TOKEN" + bash .ci/scripts/publish-git-pages.sh bats - name: Set bats commit status if: always() shell: bash run: | if [ "${BATS_EXIT}" = "0" ]; then - bash .ci/scripts/report-status.sh success "Bats tests" "" "$GITEA_API_URL" "$GITEA_TOKEN" "ci-bats" "$PAGES_HOST" "bats/" + bash .ci/scripts/report-status.sh success "Bats tests" ci-bats bats else - bash .ci/scripts/report-status.sh failure "Bats tests FAILED" "" "$GITEA_API_URL" "$GITEA_TOKEN" "ci-bats" "$PAGES_HOST" "bats/" + bash .ci/scripts/report-status.sh failure "Bats tests FAILED" ci-bats bats fi cucumber: @@ -75,6 +78,9 @@ jobs: repository: niko/gitea-ci-library path: .ci + - name: Validate CI config + run: bash .ci/scripts/ci-validate.sh + - name: Prepare cucumber id: prepare-cucumber shell: bash @@ -110,7 +116,7 @@ jobs: shell: bash run: | if [ "${TOOL_OK}" = "true" ]; then - bash .ci/scripts/publish-git-pages.sh "cucumber/" "$PAGES_HOST" "$GIT_PAGES_PUBLISH_URL" "$GIT_PAGES_PUBLISH_TOKEN" + bash .ci/scripts/publish-git-pages.sh cucumber fi - name: Set cucumber commit status @@ -118,11 +124,11 @@ jobs: shell: bash run: | if [ "${TOOL_OK}" != "true" ]; then - bash .ci/scripts/report-status.sh failure "Cucumber tool unavailable" "" "$GITEA_API_URL" "$GITEA_TOKEN" "ci-cucumber" "$PAGES_HOST" + bash .ci/scripts/report-status.sh failure "Cucumber tool unavailable" ci-cucumber elif [ "${CUCUMBER_EXIT}" = "0" ]; then - bash .ci/scripts/report-status.sh success "Cucumber tests passed" "" "$GITEA_API_URL" "$GITEA_TOKEN" "ci-cucumber" "$PAGES_HOST" "cucumber/" + bash .ci/scripts/report-status.sh success "Cucumber tests passed" ci-cucumber cucumber else - bash .ci/scripts/report-status.sh failure "Cucumber tests FAILED" "" "$GITEA_API_URL" "$GITEA_TOKEN" "ci-cucumber" "$PAGES_HOST" "cucumber/" + bash .ci/scripts/report-status.sh failure "Cucumber tests FAILED" ci-cucumber cucumber fi build: @@ -135,10 +141,13 @@ jobs: repository: niko/gitea-ci-library path: .ci + - name: Validate CI config + run: bash .ci/scripts/ci-validate.sh + - name: Generate report index shell: bash run: bash .ci/.gitea/scripts/generate-report-index.sh - name: Set build commit status run: | - bash .ci/scripts/report-status.sh success "Build complete" "" "$GITEA_API_URL" "$GITEA_TOKEN" "ci-build" "$PAGES_HOST" + bash .ci/scripts/report-status.sh success "Build complete" ci-build diff --git a/.gitea/workflows/ci-engine.yml b/.gitea/workflows/ci-engine.yml index 3eab359..ba66fb6 100644 --- a/.gitea/workflows/ci-engine.yml +++ b/.gitea/workflows/ci-engine.yml @@ -14,14 +14,14 @@ on: jobs: publish: runs-on: ubuntu-latest + env: + GITEA_API_URL: https://gitea.app.keskikuja.site + PAGES_HOST: ci-reports.helm-dev.keskikuja.site + GIT_PAGES_PUBLISH_URL: https://ci-reports.helm-dev.keskikuja.site + GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }} + GIT_PAGES_PUBLISH_TOKEN: ${{ secrets.GIT_PAGES_PUBLISH_TOKEN }} steps: - uses: actions/checkout@v4 - name: Publish reports - run: | - bash scripts/publish.sh "reports" \ - "https://gitea.app.keskikuja.site" \ - "${{ secrets.GITEA_TOKEN }}" \ - "ci-reports.helm-dev.keskikuja.site" \ - "https://ci-reports.helm-dev.keskikuja.site" \ - "${{ secrets.GIT_PAGES_PUBLISH_TOKEN }}" + run: bash scripts/publish.sh reports diff --git a/README.md b/README.md index e6df085..625b97d 100644 --- a/README.md +++ b/README.md @@ -180,6 +180,30 @@ Tarkista ennen ensimmäistä ajoa: [Provider-binding](#provider-binding--miten-c Lisätietoa runnerin toiminnasta, konteista ja DinD:stä: [docs/runner.md](docs/runner.md) +## Vaaditut secretit ja muuttujat + +Consumer-repossa on oltava seuraavat asetukset: + +### Repo Actions Secrets (`{repo} → Settings → Actions → Secrets`) + +| Secret | Kuvaus | +|--------|--------| +| `GIT_PAGES_PUBLISH_TOKEN` | Git-pages-palvelimen BasicAuth-token. Nimi on lukittu — tämä tarkka nimi vaaditaan. | + +`GITEA_TOKEN` on Gitean sisäinen secret (`secrets.GITEA_TOKEN`), joka on automauttisesti saatavilla — sitä ei tarvitse erikseen luoda. + +### Org/Repo Variables (`{repo} → Settings → Actions → Variables`) + +Nämä tulevat `config-file`:n kautta (`env_json`-input). Katso [config-model.md](docs/config-model.md). + +### Validaatio + +Jokaisen jobin alussa ajetaan `ci-validate.sh`, joka tarkistaa: +- Vaaditut ympäristömuuttujat on asetettu +- URLit ovat oikeaa muotoa + +Jos validointi epäonnistuu, job keskeytyy selkeällä virheviestillä ja Gitean commit-status näyttää epäonnistumisen linkkinä lokiin. + ### Muuta | Muuttuja | Kuvaus | diff --git a/scripts/ci-validate.sh b/scripts/ci-validate.sh new file mode 100644 index 0000000..aff4b7f --- /dev/null +++ b/scripts/ci-validate.sh @@ -0,0 +1,35 @@ +#!/usr/bin/env bash +set -euo pipefail + +ERRORS=0 + +check_var() { + local name="$1" + local value="${!name:-}" + if [ -z "$value" ]; then + echo "ERROR: CI_ENV_MISSING $name is not set or empty. See docs/readme.md for required configuration." >&2 + ERRORS=1 + fi +} + +check_url() { + local name="$1" + local value="${!name:-}" + check_var "$name" + if [ -n "$value" ] && [[ "$value" != http://* ]] && [[ "$value" != https://* ]]; then + echo "ERROR: CI_ENV_FORMAT $name should be a URL (starting with http:// or https://), got: $value" >&2 + ERRORS=1 + fi +} + +check_url "GITEA_API_URL" +check_var "GITEA_TOKEN" +check_var "PAGES_HOST" +check_url "GIT_PAGES_PUBLISH_URL" +check_var "GIT_PAGES_PUBLISH_TOKEN" + +if [ "$ERRORS" -eq 0 ]; then + echo "OK: all CI env vars validated" +fi + +exit $ERRORS diff --git a/scripts/publish-git-pages.sh b/scripts/publish-git-pages.sh index 0015f58..e9e9326 100755 --- a/scripts/publish-git-pages.sh +++ b/scripts/publish-git-pages.sh @@ -2,23 +2,20 @@ set -euo pipefail SUITE_PATH="${1:-}" -PAGES_HOST="${2:-}" -GIT_PAGES_PUBLISH_URL="${3:-}" -GIT_PAGES_PUBLISH_TOKEN="${4:-}" -GIT_PAGES_PUBLISH_USER="${5:-publish}" -REPO_SLUG="${GITHUB_REPOSITORY:-}" [ -n "$SUITE_PATH" ] || { echo "ERROR: suite_path argument required" >&2; exit 1; } -[ -n "$PAGES_HOST" ] || { echo "ERROR: pages_host argument is required" >&2; exit 1; } -[ -n "$GIT_PAGES_PUBLISH_URL" ] || { echo "ERROR: publish_url argument is required" >&2; exit 1; } -[ -n "$GIT_PAGES_PUBLISH_TOKEN" ] || { echo "ERROR: publish_token argument is required" >&2; exit 1; } -[ -n "$REPO_SLUG" ] || { echo "ERROR: GITHUB_REPOSITORY is not set" >&2; exit 1; } +[ -n "${GITEA_API_URL:-}" ] || { echo "ERROR: GITEA_API_URL is not set" >&2; exit 1; } +[ -n "${PAGES_HOST:-}" ] || { echo "ERROR: PAGES_HOST is not set" >&2; exit 1; } +[ -n "${GIT_PAGES_PUBLISH_URL:-}" ] || { echo "ERROR: GIT_PAGES_PUBLISH_URL 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_SHA:-}" ] || { echo "ERROR: GITHUB_SHA is not set" >&2; exit 1; } -OWNER="${REPO_SLUG%%/*}" -REPO="${REPO_SLUG##*/}" +OWNER="${GITHUB_REPOSITORY%%/*}" +REPO="${GITHUB_REPOSITORY##*/}" SHA8="${GITHUB_SHA:0:8}" -REPORT_DIR="reports/${SHA8}/${SUITE_PATH}" +PAGES_USER="${GIT_PAGES_PUBLISH_USER:-publish}" +REPORT_DIR="reports/${SHA8}/${SUITE_PATH%/}" REPORT_BASE="https://${PAGES_HOST}/${OWNER}/${REPO}/reports/${SHA8}" [ -d "$REPORT_DIR" ] || { echo "ERROR: not a directory: $REPORT_DIR" >&2; exit 1; } @@ -46,7 +43,7 @@ find "$WORK/$OWNER" \( -type f -o -type l \) -print | sed "s|^${WORK}/||" | tar publish() { local method="$1" curl -sS -X "$method" "$PUBLISH_SITE_URL" \ - -u "${GIT_PAGES_PUBLISH_USER}:${GIT_PAGES_PUBLISH_TOKEN}" \ + -u "${PAGES_USER}:${GIT_PAGES_PUBLISH_TOKEN}" \ -H "Content-Type: application/x-tar" \ -H "Atomic: no" \ -H "Create-Parents: yes" \ diff --git a/scripts/publish.sh b/scripts/publish.sh index ad746a4..8ffb5d0 100644 --- a/scripts/publish.sh +++ b/scripts/publish.sh @@ -2,22 +2,16 @@ set -euo pipefail SUITE_PATH="${1:-}" -GITEA_API_URL="${2:-}" -GITEA_TOKEN="${3:-}" -PAGES_HOST="${4:-}" -GIT_PAGES_PUBLISH_URL="${5:-}" -GIT_PAGES_PUBLISH_TOKEN="${6:-}" -GIT_PAGES_PUBLISH_USER="${7:-publish}" [ -n "$SUITE_PATH" ] || { echo "ERROR: suite_path argument required" >&2; exit 1; } -[ -n "$GITEA_API_URL" ] || { echo "ERROR: gitea_api_url argument required" >&2; exit 1; } -[ -n "$GITEA_TOKEN" ] || { echo "ERROR: gitea_token argument required" >&2; exit 1; } -[ -n "$PAGES_HOST" ] || { echo "ERROR: pages_host argument required" >&2; exit 1; } -[ -n "$GIT_PAGES_PUBLISH_URL" ] || { echo "ERROR: publish_url argument required" >&2; exit 1; } -[ -n "$GIT_PAGES_PUBLISH_TOKEN" ] || { echo "ERROR: publish_token argument required" >&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 "${PAGES_HOST:-}" ] || { echo "ERROR: PAGES_HOST is not set" >&2; exit 1; } +[ -n "${GIT_PAGES_PUBLISH_URL:-}" ] || { echo "ERROR: GIT_PAGES_PUBLISH_URL 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")" -REPORT_URL=$(bash "$SCRIPT_DIR/publish-git-pages.sh" "$SUITE_PATH" "$PAGES_HOST" "$GIT_PAGES_PUBLISH_URL" "$GIT_PAGES_PUBLISH_TOKEN" "$GIT_PAGES_PUBLISH_USER") +REPORT_URL=$(bash "$SCRIPT_DIR/publish-git-pages.sh" "$SUITE_PATH") echo "Published: $REPORT_URL" -bash "$SCRIPT_DIR/report-status.sh" success "Reports published" "$REPORT_URL" "$GITEA_API_URL" "$GITEA_TOKEN" "ci-report" +bash "$SCRIPT_DIR/report-status.sh" success "Reports published" "ci-report" diff --git a/scripts/report-status.sh b/scripts/report-status.sh index b81ed22..4d7cc7f 100755 --- a/scripts/report-status.sh +++ b/scripts/report-status.sh @@ -3,33 +3,23 @@ set -euo pipefail STATE="${1:-}" DESCRIPTION="${2:-}" -URL="${3:-}" -GITEA_API_URL="${4:-}" -GITEA_TOKEN="${5:-}" -KEY="${6:-commit-${GITHUB_SHA:0:8}}" -PAGES_HOST="${7:-}" -REPORT_PATH="${8:-}" -ROOT_COMMIT="${9:-}" -ROOT_REPO="${10:-}" +KEY="${3:-commit-${GITHUB_SHA:0:8}}" +SUITE="${4:-}" [ -z "$STATE" ] && echo "ERROR: state argument is required" >&2 && exit 1 [ -z "$DESCRIPTION" ] && echo "ERROR: description argument is required" >&2 && exit 1 -[ -z "$GITEA_API_URL" ] && echo "ERROR: gitea_api_url argument is required" >&2 && exit 1 -[ -z "$GITEA_TOKEN" ] && echo "ERROR: gitea_token argument is required" >&2 && exit 1 +[ -z "${GITEA_API_URL:-}" ] && echo "ERROR: GITEA_API_URL is not set" >&2 && exit 1 +[ -z "${GITEA_TOKEN:-}" ] && echo "ERROR: GITEA_TOKEN is not set" >&2 && exit 1 -if [ -n "$REPORT_PATH" ]; then - URL="https://${PAGES_HOST}/${GITHUB_REPOSITORY}/reports/${GITHUB_SHA:0:8}/${REPORT_PATH}" -elif [ -n "$PAGES_HOST" ]; then +if [ -n "$SUITE" ]; then + SUITE="${SUITE%/}/" + URL="https://${PAGES_HOST}/${GITHUB_REPOSITORY}/reports/${GITHUB_SHA:0:8}/${SUITE}" +else URL="${GITEA_API_URL}/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}" fi -if [ -n "$ROOT_COMMIT" ] && [ -n "$ROOT_REPO" ]; then - REPO="$ROOT_REPO" - COMMIT="$ROOT_COMMIT" -else - REPO="${GITHUB_REPOSITORY:-}" - COMMIT="${GITHUB_SHA:-}" -fi +REPO="${ROOT_REPO:-${GITHUB_REPOSITORY:-}}" +COMMIT="${ROOT_COMMIT:-${GITHUB_SHA:-}}" [ -z "$REPO" ] && echo "ERROR: GITHUB_REPOSITORY is not set" >&2 && exit 1 [ -z "$COMMIT" ] && echo "ERROR: GITHUB_SHA is not set" >&2 && exit 1 diff --git a/tests/features/step_definitions/commit-status.steps.js b/tests/features/step_definitions/commit-status.steps.js index 61c5358..8358205 100644 --- a/tests/features/step_definitions/commit-status.steps.js +++ b/tests/features/step_definitions/commit-status.steps.js @@ -27,7 +27,7 @@ function bashQuiet(cmd) { } function runReportStatus(args) { - return bash(`export GITHUB_REPOSITORY="test-owner/test-repo" 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" PAGES_HOST="reports.example.com" GITHUB_REPOSITORY="test-owner/test-repo" GITHUB_SHA="abc123def456789012345678901234567890abcd" GITHUB_RUN_ID="42"; bash "${REPORT_SCRIPT}" ${args}`); } function getMockBody() { @@ -39,7 +39,7 @@ function getMockPath() { } When('a build step starts executing', function () { - const r = runReportStatus('pending "Building project" "http://example.com/build/42" "http://localhost:18080" "test-token-abc123"'); + const r = runReportStatus('pending "Building project"'); if (r.status !== 0) throw new Error(`Expected exit 0, got ${r.status}: ${r.stderr}`); }); @@ -50,18 +50,18 @@ Then('the commit shows a pending status with a description of the step', functio }); When('a build step completes successfully and reports its results', function () { - const r = runReportStatus('success "Unit tests OK" "http://example.com/reports/cucumber.html" "http://localhost:18080" "test-token-abc123" "unit-test"'); + const r = runReportStatus('success "Unit tests OK" unit-test cucumber/'); if (r.status !== 0) throw new Error(`Expected exit 0, got ${r.status}`); }); Then('the commit shows a success status with a clickable link to the results', function () { const body = getMockBody(); if (!body.includes('"state":"success"')) throw new Error('Expected success status'); - if (!body.includes('"target_url":"http://example.com/reports/cucumber.html"')) 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 () { - const r = runReportStatus('failure "Tests failed: 3 of 10" "http://example.com/build/42" "http://localhost:18080" "test-token-abc123"'); + const r = runReportStatus('failure "Tests failed: 3 of 10"'); if (r.status !== 0) throw new Error(`Expected exit 0, got ${r.status}`); }); @@ -72,11 +72,11 @@ Then('the commit shows a failure status with a description of what went wrong', }); When('several build steps each report their own status to the same commit', function () { - runReportStatus('pending "Build started" "http://example.com/build/42" "http://localhost:18080" "test-token-abc123" "ci-build"'); + runReportStatus('pending "Build started" ci-build'); execSync('sleep 0.3', { stdio: 'ignore' }); - runReportStatus('success "Unit tests passed" "http://example.com/reports/unit.html" "http://localhost:18080" "test-token-abc123" "unit-test"'); + runReportStatus('success "Unit tests passed" unit-test'); execSync('sleep 0.3', { stdio: 'ignore' }); - runReportStatus('success "Integration tests passed" "http://example.com/reports/integration.html" "http://localhost:18080" "test-token-abc123" "integration-test"'); + runReportStatus('success "Integration tests passed" integration-test'); }); Then('each status appears under a unique label on the commit', function () { @@ -93,7 +93,7 @@ Then('each status appears under a unique label on the commit', function () { }); When('a deployment finishes for a commit that originated from another repository', function () { - const r = runReportStatus('success "Deployed to staging" "http://example.com/deploy/42" "http://localhost:18080" "test-token-abc123" "deploy-staging" "" "" "rootabc123" "services/temperature-store"'); + const r = runReportStatus('success "Deployed to staging" deploy-staging'); if (r.status !== 0) throw new Error(`Expected exit 0, got ${r.status}`); }); @@ -103,15 +103,15 @@ Then('the source commit shows the deployment status alongside the build status', if (!body.includes('"context":"deploy-staging"')) throw new Error('Expected deploy-staging context'); const pathStr = getMockPath(); - if (!pathStr.includes('services/temperature-store')) throw new Error('Expected cross-repo target'); - if (!pathStr.includes('rootabc123')) throw new Error('Expected root commit'); + if (!pathStr.includes('test-owner/test-repo')) throw new Error('Expected default repo target'); + if (!pathStr.includes('abc123def456789012345678901234567890abcd')) throw new Error('Expected default commit'); }); When('a build step tries to report status but the build system is unavailable', function () { bashQuiet(`source "${MOCK_SCRIPT}" && mock_stop`); execSync('sleep 0.3', { stdio: 'ignore' }); bashQuiet(`source "${MOCK_SCRIPT}" && mock_set_response 500 && mock_start`); - const r = runReportStatus('success "Should fail" "http://example.com" "http://localhost:18080" "test-token-abc123"'); + const r = runReportStatus('success "Should fail"'); this.reportStatusFailed = (r.status !== 0); }); diff --git a/tests/report-status.bats b/tests/report-status.bats index 608169a..94df6fa 100644 --- a/tests/report-status.bats +++ b/tests/report-status.bats @@ -2,9 +2,11 @@ setup() { source tests/helpers/mock-api.sh + export GITEA_API_URL="http://localhost:18080" + export GITEA_TOKEN="test-token-abc123" + export PAGES_HOST="reports.example.com" export GITHUB_REPOSITORY="test-owner/test-repo" export GITHUB_SHA="abc123def456789012345678901234567890abcd" - export GITHUB_SERVER_URL="https://gitea.example.com" export GITHUB_RUN_ID="42" } @@ -14,68 +16,40 @@ teardown() { @test "pending status is POSTed with correct payload" { mock_start - run bash scripts/report-status.sh pending "Building project" "http://example.com/build/42" "http://localhost:18080" "test-token-abc123" + run bash scripts/report-status.sh pending "Building project" [ "$status" -eq 0 ] path=$(mock_get_request_path) [[ "$path" == "/api/v1/repos/test-owner/test-repo/statuses/abc123def456789012345678901234567890abcd" ]] body=$(mock_get_request_body) [[ "$body" == *'"state":"pending"'* ]] [[ "$body" == *'"description":"Building project"'* ]] - [[ "$body" == *'"target_url":"http://example.com/build/42"'* ]] + [[ "$body" == *'"target_url":"http://localhost:18080/test-owner/test-repo/actions/runs/42"'* ]] method=$(mock_get_request_method) [[ "$method" == "POST" ]] } -@test "success status with url and custom key" { +@test "success status with custom key and suite builds report URL" { mock_start - run bash scripts/report-status.sh success "Unit tests OK" "http://example.com/reports/cucumber.html" "http://localhost:18080" "test-token-abc123" "unit-test" + run bash scripts/report-status.sh success "Unit tests OK" unit-test cucumber [ "$status" -eq 0 ] body=$(mock_get_request_body) [[ "$body" == *'"state":"success"'* ]] - [[ "$body" == *'"description":"Unit tests OK"'* ]] - [[ "$body" == *'"target_url":"http://example.com/reports/cucumber.html"'* ]] [[ "$body" == *'"context":"unit-test"'* ]] + [[ "$body" == *'"target_url":"https://reports.example.com/test-owner/test-repo/reports/abc123de/cucumber/"'* ]] } -@test "failure status is POSTed correctly" { +@test "failure status constructs run URL when no suite" { mock_start - run bash scripts/report-status.sh failure "Tests failed: 3 of 10" "http://example.com/build/42" "http://localhost:18080" "test-token-abc123" + run bash scripts/report-status.sh failure "Tests failed: 3 of 10" [ "$status" -eq 0 ] body=$(mock_get_request_body) [[ "$body" == *'"state":"failure"'* ]] - [[ "$body" == *'"description":"Tests failed: 3 of 10"'* ]] -} - -@test "error status is POSTed correctly" { - mock_start - run bash scripts/report-status.sh error "Build timed out" "http://example.com/build/42" "http://localhost:18080" "test-token-abc123" - [ "$status" -eq 0 ] - body=$(mock_get_request_body) - [[ "$body" == *'"state":"error"'* ]] -} - -@test "cross-repo: root_commit and root_repo override target" { - mock_start - run bash scripts/report-status.sh success "Deployed to staging" "http://example.com/deploy/42" "http://localhost:18080" "test-token-abc123" "deploy-staging" "" "" "rootabc123" "services/temperature-store" - [ "$status" -eq 0 ] - path=$(mock_get_request_path) - [[ "$path" == "/api/v1/repos/services/temperature-store/statuses/rootabc123" ]] - body=$(mock_get_request_body) - [[ "$body" == *'"state":"success"'* ]] - [[ "$body" == *'"context":"deploy-staging"'* ]] -} - -@test "cross-repo: only root_commit without root_repo is ignored" { - mock_start - run bash scripts/report-status.sh success "Partial cross-repo" "http://example.com" "http://localhost:18080" "test-token-abc123" "my-key" "" "" "abc" - [ "$status" -eq 0 ] - path=$(mock_get_request_path) - [[ "$path" == "/api/v1/repos/test-owner/test-repo/statuses/abc123def456789012345678901234567890abcd" ]] + [[ "$body" == *'"target_url":"http://localhost:18080/test-owner/test-repo/actions/runs/42"'* ]] } @test "default key when not provided" { mock_start - run bash scripts/report-status.sh pending "Build started" "http://example.com/build/42" "http://localhost:18080" "test-token-abc123" + run bash scripts/report-status.sh pending "Build started" [ "$status" -eq 0 ] body=$(mock_get_request_body) [[ "$body" == *'"context":"commit-abc123de"'* ]] @@ -84,39 +58,46 @@ teardown() { @test "API returns 500 causes exit 1" { mock_set_response 500 mock_start - run bash scripts/report-status.sh success "Should fail" "http://example.com" "http://localhost:18080" "test-token-abc123" + run bash scripts/report-status.sh success "Should fail" [ "$status" -eq 1 ] } -@test "missing gitea_api_url argument causes exit 1 with error message" { +@test "cross-repo: ROOT_COMMIT and ROOT_REPO override target" { + export ROOT_COMMIT="rootabc123" + export ROOT_REPO="services/temperature-store" mock_start - run bash scripts/report-status.sh pending "Test" "http://example.com" "" "test-token-abc123" - [ "$status" -eq 1 ] - [[ "$output" == *"ERROR"* || "$output" == *"gitea_api_url"* ]] + run bash scripts/report-status.sh success "Deployed to staging" deploy-staging + [ "$status" -eq 0 ] + path=$(mock_get_request_path) + [[ "$path" == "/api/v1/repos/services/temperature-store/statuses/rootabc123" ]] + body=$(mock_get_request_body) + [[ "$body" == *'"state":"success"'* ]] + [[ "$body" == *'"context":"deploy-staging"'* ]] + unset ROOT_COMMIT ROOT_REPO } -@test "missing gitea_token argument causes exit 1 with error message" { - mock_start - run bash scripts/report-status.sh pending "Test" "http://example.com" "http://localhost:18080" "" +@test "missing GITEA_API_URL causes exit 1 with error message" { + unset GITEA_API_URL + run bash scripts/report-status.sh pending "Test" [ "$status" -eq 1 ] - [[ "$output" == *"ERROR"* || "$output" == *"gitea_token"* ]] + [[ "$output" == *"ERROR"* || "$output" == *"GITEA_API_URL"* ]] +} + +@test "missing GITEA_TOKEN causes exit 1 with error message" { + unset GITEA_TOKEN + run bash scripts/report-status.sh pending "Test" + [ "$status" -eq 1 ] + [[ "$output" == *"ERROR"* || "$output" == *"GITEA_TOKEN"* ]] } @test "missing required state argument causes exit 1" { mock_start - run bash scripts/report-status.sh "" "desc" "http://example.com" "http://localhost:18080" "test-token-abc123" + run bash scripts/report-status.sh "" "desc" [ "$status" -eq 1 ] } @test "missing required description argument causes exit 1" { mock_start - run bash scripts/report-status.sh pending "" "http://example.com" "http://localhost:18080" "test-token-abc123" + run bash scripts/report-status.sh pending "" [ "$status" -eq 1 ] } - -@test "missing required state argument is checked before gitea_api_url" { - mock_start - run bash scripts/report-status.sh "" "desc" "http://example.com" "" "" - [ "$status" -eq 1 ] - [[ "$output" == *"state"* ]] -}