Compare commits

..

8 Commits

Author SHA1 Message Date
moilanik a039e6637e fix fragile tests
CI Feature / Load example-gitea-env.conf to pipeline env (push) Successful in 19s
acc-tests Cucumber test report
CI Feature / Cucumber tests (push) Failing after 2m11s
unit-tests Bats test report
CI Feature / Bats tests (push) Failing after 7m10s
CI Feature / Report Summary (push) Successful in 5s
2026-06-20 13:34:03 +03:00
moilanik 0a9a9c88f1 konttipolitiikka päivitys 2026-06-20 13:06:15 +03:00
moilanik bfd0428a78 bash -> sh
CI Feature / Load example-gitea-env.conf to pipeline env (push) Successful in 27s
acc-tests Cucumber test report
CI Feature / Cucumber tests (push) Successful in 1m19s
unit-tests Bats test report
CI Feature / Bats tests (push) Failing after 2m0s
CI Feature / Report Summary (push) Successful in 5s
2026-06-20 13:06:02 +03:00
niko 4f20f5ae2f estetään image karkaaminen docker.io kun parametria ei ole asetettu (#33)
CI Main / Load example-gitea-env.conf to pipeline env (push) Successful in 28s
CI Main / Check existing artifact (push) Successful in 21s
acc-tests Cucumber test report
CI Main / Cucumber tests (push) Successful in 57s
unit-tests Bats test report
CI Main / Bats tests (push) Failing after 2m13s
CI Main / Build & Push Docker (push) Has been skipped
CI Main / Move provider version tag (push) Has been skipped
CI Main / Report Summary (push) Successful in 6s
Co-authored-by: moilanik <niko.moilanen@tietoevry.com>
Reviewed-on: #33
2026-06-20 10:54:23 +03:00
niko bd93ef2f8f monorepo ci filter ohje tarkennus (#32)
CI Main / Load example-gitea-env.conf to pipeline env (push) Successful in 26s
CI Main / Check existing artifact (push) Successful in 23s
acc-tests Cucumber test report
CI Main / Cucumber tests (push) Successful in 54s
unit-tests Bats test report
CI Main / Bats tests (push) Successful in 1m52s
ci-docker-build-push Docker build & push 0.2.18 OK
CI Main / Build & Push Docker (push) Successful in 43s
CI Main / Report Summary (push) Successful in 6s
CI Main / Move provider version tag (push) Successful in 14s
Co-authored-by: moilanik <niko.moilanen@tietoevry.com>
Reviewed-on: #32
2026-06-19 14:13:14 +03:00
niko f06cb112d8 Fix/umbrella chart support (#31)
CI Main / Load example-gitea-env.conf to pipeline env (push) Successful in 20s
CI Main / Check existing artifact (push) Successful in 17s
acc-tests Cucumber test report
CI Main / Cucumber tests (push) Successful in 1m4s
unit-tests Bats test report
CI Main / Bats tests (push) Successful in 1m52s
CI Main / Report Summary (push) Successful in 5s
CI Main / Move provider version tag (push) Successful in 13s
ci-docker-build-push Docker build & push 0.2.17 OK
CI Main / Build & Push Docker (push) Successful in 41s
Co-authored-by: moilanik <niko.moilanen@tietoevry.com>
Reviewed-on: #31
2026-06-19 13:13:06 +03:00
niko d57f56f196 dependency update ennen paketointia (#30)
CI Git-Pages Main / Load git-pages.gitea-env.conf to pipeline env (push) Successful in 22s
CI Main / Load example-gitea-env.conf to pipeline env (push) Successful in 24s
CI Git-Pages Main / Check existing artifact (push) Successful in 22s
CI Main / Check existing artifact (push) Successful in 22s
ci-helm-build-push Helm chart 0.1.2
CI Git-Pages Main / Build & Push Helm chart (push) Successful in 42s
CI Git-Pages Main / Report Summary (push) Successful in 5s
acc-tests Cucumber test report
CI Main / Cucumber tests (push) Successful in 1m11s
ci-docker-build-push Docker build & push 0.2.16 OK
CI Main / Build & Push Docker (push) Successful in 31s
CI Main / Report Summary (push) Successful in 6s
CI Main / Move provider version tag (push) Successful in 12s
unit-tests Bats test report
CI Main / Bats tests (push) Successful in 1m55s
Co-authored-by: moilanik <niko.moilanen@tietoevry.com>
Reviewed-on: #30
2026-06-19 10:32:40 +03:00
niko 277c0f882d Update .gitea/workflows/git-pages.ci-main.yml (#29)
CI Git-Pages Main / Load git-pages.gitea-env.conf to pipeline env (push) Successful in 21s
CI Git-Pages Main / Check existing artifact (push) Successful in 21s
unit-tests Bats test report
CI Main / Bats tests (push) Successful in 2m0s
CI Main / Load example-gitea-env.conf to pipeline env (push) Successful in 21s
CI Main / Check existing artifact (push) Successful in 19s
ci-helm-build-push Helm chart 0.1.1
CI Git-Pages Main / Build & Push Helm chart (push) Successful in 46s
acc-tests Cucumber test report
CI Main / Cucumber tests (push) Successful in 1m12s
CI Git-Pages Main / Report Summary (push) Successful in 8s
ci-docker-build-push Docker build & push 0.2.15 OK
CI Main / Move provider version tag (push) Successful in 14s
CI Main / Build & Push Docker (push) Successful in 42s
CI Main / Report Summary (push) Successful in 6s
poistettu dev haaran trigger

Reviewed-on: #29
2026-06-19 10:14:32 +03:00
17 changed files with 365 additions and 115 deletions
+3 -3
View File
@@ -33,7 +33,9 @@ jobs:
DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME || github.actor }} DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME || github.actor }}
DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }} DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}
run: | run: |
REGISTRY="${DOCKER_REGISTRY:?DOCKER_REGISTRY not set in conf}" if [ -z "${DOCKER_REGISTRY}" ]; then echo "ERROR: DOCKER_REGISTRY not set in conf"; exit 1; fi
REGISTRY="${DOCKER_REGISTRY}"
REGISTRY_HOST="${REGISTRY%%/*}"
DOCKERFILE="${{ inputs.dockerfile_path }}" DOCKERFILE="${{ inputs.dockerfile_path }}"
IMAGE_NAME="${{ inputs.image_name }}" IMAGE_NAME="${{ inputs.image_name }}"
TAG="${{ inputs.tag }}" TAG="${{ inputs.tag }}"
@@ -46,8 +48,6 @@ jobs:
-f "${DOCKERFILE}" \ -f "${DOCKERFILE}" \
-t "${IMAGE_NAME}:${TAG}" . -t "${IMAGE_NAME}:${TAG}" .
REGISTRY_HOST="${REGISTRY%%/*}"
FULL_IMAGE="${REGISTRY}/${IMAGE_NAME}:${TAG}" FULL_IMAGE="${REGISTRY}/${IMAGE_NAME}:${TAG}"
echo "Pushing ${FULL_IMAGE} ..." echo "Pushing ${FULL_IMAGE} ..."
+10 -8
View File
@@ -45,29 +45,31 @@ jobs:
DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME || github.actor }} DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME || github.actor }}
DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }} DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}
run: | run: |
if [ -z "${DOCKER_REGISTRY}" ]; then echo "ERROR: DOCKER_REGISTRY not set in env.conf"; exit 1; fi
if [ -z "${DOCKER_IMAGE_NAME}" ]; then echo "ERROR: DOCKER_IMAGE_NAME not set in env.conf"; exit 1; fi
REGISTRY="${DOCKER_REGISTRY}"
IMAGE="${DOCKER_IMAGE_NAME}"
REGISTRY_HOST="${REGISTRY%%/*}"
NOW=$(date -u +%Y-%m-%dT%H:%M:%SZ) NOW=$(date -u +%Y-%m-%dT%H:%M:%SZ)
docker build \ docker build \
--label "git.commit=${{ github.sha }}" \ --label "git.commit=${{ github.sha }}" \
--label "git.commitBy=${{ github.actor }}" \ --label "git.commitBy=${{ github.actor }}" \
--label "build.date=${NOW}" \ --label "build.date=${NOW}" \
-f "${DOCKERFILE}" \ -f "${DOCKERFILE}" \
-t "${DOCKER_IMAGE_NAME}:${VERSION}" \ -t "${IMAGE}:${VERSION}" \
-t "${DOCKER_IMAGE_NAME}:latest" . -t "${IMAGE}:latest" .
REGISTRY="${DOCKER_REGISTRY:?DOCKER_REGISTRY not set in env.conf}"
IMAGE="${DOCKER_IMAGE_NAME:?DOCKER_IMAGE_NAME not set in env.conf}"
REGISTRY_HOST="${REGISTRY%%/*}"
FULL_IMAGE="${REGISTRY}/${IMAGE}:${VERSION}" FULL_IMAGE="${REGISTRY}/${IMAGE}:${VERSION}"
echo "Pushing ${FULL_IMAGE} ..." echo "Pushing ${FULL_IMAGE} ..."
docker tag "${DOCKER_IMAGE_NAME}:${VERSION}" "$FULL_IMAGE" docker tag "${IMAGE}:${VERSION}" "$FULL_IMAGE"
echo "$DOCKER_PASSWORD" | docker login "$REGISTRY_HOST" -u "$DOCKER_USERNAME" --password-stdin echo "$DOCKER_PASSWORD" | docker login "$REGISTRY_HOST" -u "$DOCKER_USERNAME" --password-stdin
docker push "$FULL_IMAGE" docker push "$FULL_IMAGE"
FULL_LATEST="${REGISTRY}/${IMAGE}:latest" FULL_LATEST="${REGISTRY}/${IMAGE}:latest"
echo "Pushing ${FULL_LATEST} ..." echo "Pushing ${FULL_LATEST} ..."
docker tag "${DOCKER_IMAGE_NAME}:latest" "$FULL_LATEST" docker tag "${IMAGE}:latest" "$FULL_LATEST"
docker push "$FULL_LATEST" docker push "$FULL_LATEST"
docker logout "$REGISTRY_HOST" docker logout "$REGISTRY_HOST"
-1
View File
@@ -3,7 +3,6 @@ on:
push: push:
branches: branches:
- main - main
- fix/helm-build-node
paths: paths:
- git-pages/** - git-pages/**
- .gitea/workflows/helm-build-push.yml - .gitea/workflows/helm-build-push.yml
+1
View File
@@ -53,6 +53,7 @@ jobs:
- name: Package Helm chart - name: Package Helm chart
run: | run: |
helm dependency update "${CHART_PATH}"
helm package "${CHART_PATH}" \ helm package "${CHART_PATH}" \
--version "${VERSION}" \ --version "${VERSION}" \
--app-version "${VERSION}" \ --app-version "${VERSION}" \
+2 -2
View File
@@ -4,7 +4,7 @@ set -e
RAW_VERSION="" RAW_VERSION=""
if [ -n "${VERSION_FILE-}" ] && [ -f "${VERSION_FILE-}" ]; then if [ -n "${VERSION_FILE-}" ] && [ -f "${VERSION_FILE-}" ]; then
RAW_VERSION=$(sed -n 's/^version:[[:space:]]*\([^[:space:]]*\).*/\1/p' "${VERSION_FILE}") RAW_VERSION=$(tr -d "$(printf '\xef\xbb\xbf')" < "${VERSION_FILE}" | sed -n 's/^version:[[:space:]]*\([^[:space:]]*\).*/\1/p')
if [ -z "${RAW_VERSION}" ]; then if [ -z "${RAW_VERSION}" ]; then
if echo "${VERSION_FILE}" | grep -q -E '\.json$'; then if echo "${VERSION_FILE}" | grep -q -E '\.json$'; then
RAW_VERSION=$(jq -r '.version' "${VERSION_FILE}") RAW_VERSION=$(jq -r '.version' "${VERSION_FILE}")
@@ -22,7 +22,7 @@ if [ -z "${RAW_VERSION}" ]; then
elif [ -f pom.xml ]; then elif [ -f pom.xml ]; then
RAW_VERSION=$(grep -oP '<version>\K[^<]+' pom.xml | head -1) RAW_VERSION=$(grep -oP '<version>\K[^<]+' pom.xml | head -1)
elif [ -f Chart.yaml ]; then elif [ -f Chart.yaml ]; then
RAW_VERSION=$(sed -n 's/^version:[[:space:]]*\([^[:space:]]*\).*/\1/p' Chart.yaml) RAW_VERSION=$(tr -d "$(printf '\xef\xbb\xbf')" < Chart.yaml | sed -n 's/^version:[[:space:]]*\([^[:space:]]*\).*/\1/p')
else else
echo "ERROR: No version source found (VERSION_FILE, VERSION, package.json, pom.xml, Chart.yaml)" >&2 echo "ERROR: No version source found (VERSION_FILE, VERSION, package.json, pom.xml, Chart.yaml)" >&2
exit 1 exit 1
+64 -41
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env bash #!/usr/bin/env sh
set -euo pipefail set -eu
DESCRIPTION="${1:-}" DESCRIPTION="${1:-}"
CONTEXT="${2:-}" CONTEXT="${2:-}"
@@ -14,53 +14,71 @@ REPORT_DIR="reports/${SUITE}"
if [ ! -d "$REPORT_DIR" ]; then if [ ! -d "$REPORT_DIR" ]; then
echo "ERROR: $REPORT_DIR not found" >&2 echo "ERROR: $REPORT_DIR not found" >&2
bash .ci/scripts/report-status.sh failure "$DESCRIPTION" "$CONTEXT" sh .ci/scripts/report-status.sh failure "$DESCRIPTION" "$CONTEXT"
exit 1 exit 1
fi fi
FILES=() FILE_COUNT=0
while IFS= read -r -d '' f; do SUBDIR_COUNT=0
FILES+=("$(basename "$f")") ENTRIES=""
done < <(find "$REPORT_DIR" -maxdepth 1 -type f ! -name index.html -print0 2>/dev/null || true)
SUBDIRS=() for f in "$REPORT_DIR"/*; do
while IFS= read -r -d '' d; do [ -f "$f" ] || continue
name="${d#$REPORT_DIR/}" base=$(basename "$f")
[ -f "$d/index.html" ] && SUBDIRS+=("$name") [ "$base" = "index.html" ] && continue
done < <(find "$REPORT_DIR" -maxdepth 1 -type d ! -name . -print0 2>/dev/null || true) FILE_COUNT=$((FILE_COUNT + 1))
ENTRIES="${ENTRIES}file:${base}
"
done
TOTAL=$(( ${#FILES[@]} + ${#SUBDIRS[@]} )) for d in "$REPORT_DIR"/*/; do
[ -d "$d" ] || continue
base=$(basename "$d")
[ -f "$d/index.html" ] || continue
SUBDIR_COUNT=$((SUBDIR_COUNT + 1))
ENTRIES="${ENTRIES}dir:${base}
"
done
TOTAL=$((FILE_COUNT + SUBDIR_COUNT))
if [ "$TOTAL" -eq 0 ]; then if [ "$TOTAL" -eq 0 ]; then
echo "ERROR: no reportable items in $REPORT_DIR" >&2 echo "ERROR: no reportable items in $REPORT_DIR" >&2
bash .ci/scripts/report-status.sh failure "$DESCRIPTION" "$CONTEXT" sh .ci/scripts/report-status.sh failure "$DESCRIPTION" "$CONTEXT"
exit 1 exit 1
fi fi
SHA8="${GITHUB_SHA:0:8}" SHA8=$(echo "${GITHUB_SHA:-xxxxxxxx}" | cut -c1-8)
humanize() { humanize() {
local name="$1" name="$1"
name="${name%.*}" name=$(echo "$name" | sed -e 's/\.[^.]*$//' -e 's/[-_]/ /g')
name="${name//-/ }" first=$(echo "$name" | cut -c1 | tr '[:lower:]' '[:upper:]')
name="${name//_/ }" rest=$(echo "$name" | cut -c2-)
echo "${name^}" echo "${first}${rest}"
} }
generate_index() { generate_index() {
local html {
html='<!DOCTYPE html><html lang="en"><head><meta charset="utf-8">' echo '<!DOCTYPE html><html lang="en"><head><meta charset="utf-8">'
html+="<title>$DESCRIPTION</title>" echo "<title>$DESCRIPTION</title>"
html+='<style>body{font-family:sans-serif;margin:2em;max-width:960px}h1{color:#1e293b}ul{list-style:none;padding:0}li{margin:.5em 0;padding:.5em;background:#f8fafc;border-radius:6px}a{color:#2563eb;text-decoration:none}a:hover{text-decoration:underline}</style>' echo '<style>body{font-family:sans-serif;margin:2em;max-width:960px}h1{color:#1e293b}ul{list-style:none;padding:0}li{margin:.5em 0;padding:.5em;background:#f8fafc;border-radius:6px}a{color:#2563eb;text-decoration:none}a:hover{text-decoration:underline}</style>'
html+="</head><body><h1>$DESCRIPTION</h1><ul>" echo "</head><body><h1>$DESCRIPTION</h1><ul>"
for f in "${FILES[@]}"; do
html+="<li><a href=\"$f\">$(humanize "$f")</a></li>" echo "$ENTRIES" | while IFS= read -r entry; do
done [ -z "$entry" ] && continue
for d in "${SUBDIRS[@]}"; do entry_type=$(echo "$entry" | cut -d: -f1)
html+="<li><a href=\"$d/index.html\">${d^}</a></li>" entry_name=$(echo "$entry" | cut -d: -f2-)
done if [ "$entry_type" = "file" ]; then
html+='</ul></body></html>' echo "<li><a href=\"$entry_name\">$(humanize "$entry_name")</a></li>"
printf '%s' "$html" > "$REPORT_DIR/index.html" else
cap=$(echo "$entry_name" | sed 's/\(.\).*/\1/' | tr '[:lower:]' '[:upper:]')$(echo "$entry_name" | sed 's/.//')
echo "<li><a href=\"$entry_name/index.html\">${cap}</a></li>"
fi
done
echo '</ul></body></html>'
} > "$REPORT_DIR/index.html"
} }
STAGED="reports/${SHA8}/${SUITE}" STAGED="reports/${SHA8}/${SUITE}"
@@ -68,20 +86,25 @@ mkdir -p "$STAGED"
if [ "$TOTAL" -eq 1 ]; then if [ "$TOTAL" -eq 1 ]; then
cp -a "$REPORT_DIR/." "$STAGED/" cp -a "$REPORT_DIR/." "$STAGED/"
bash .ci/scripts/publish-git-pages.sh "$SUITE" sh .ci/scripts/publish-git-pages.sh "$SUITE"
if [ ${#FILES[@]} -eq 1 ]; then first_entry=$(echo "$ENTRIES" | head -1)
ENTRY="${FILES[0]}" first_type=$(echo "$first_entry" | cut -d: -f1)
first_name=$(echo "$first_entry" | cut -d: -f2-)
if [ "$first_type" = "file" ]; then
SINGLE_ENTRY="$first_name"
else else
ENTRY="${SUBDIRS[0]}/index.html" SINGLE_ENTRY="${first_name}/index.html"
fi fi
URL="${GIT_PAGES_URL}/${GITHUB_REPOSITORY}/reports/${SHA8}/${SUITE}/${ENTRY}"
bash .ci/scripts/report-status.sh "$STATUS" "$DESCRIPTION" "$CONTEXT" "" "$URL" URL="${GIT_PAGES_URL}/${GITHUB_REPOSITORY}/reports/${SHA8}/${SUITE}/${SINGLE_ENTRY}"
sh .ci/scripts/report-status.sh "$STATUS" "$DESCRIPTION" "$CONTEXT" "" "$URL"
else else
generate_index generate_index
cp -a "$REPORT_DIR/." "$STAGED/" cp -a "$REPORT_DIR/." "$STAGED/"
bash .ci/scripts/publish-git-pages.sh "$SUITE" sh .ci/scripts/publish-git-pages.sh "$SUITE"
bash .ci/scripts/report-status.sh "$STATUS" "$DESCRIPTION" "$CONTEXT" "$SUITE" sh .ci/scripts/report-status.sh "$STATUS" "$DESCRIPTION" "$CONTEXT" "$SUITE"
fi fi
rm -rf "$STAGED" rm -rf "$STAGED"
+39 -21
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env bash #!/usr/bin/env sh
set -euo pipefail set -eu
SUITE_PATH="${1:-}" SUITE_PATH="${1:-}"
@@ -12,7 +12,7 @@ SUITE_PATH="${1:-}"
OWNER="${GITHUB_REPOSITORY%%/*}" OWNER="${GITHUB_REPOSITORY%%/*}"
REPO="${GITHUB_REPOSITORY##*/}" REPO="${GITHUB_REPOSITORY##*/}"
SHA8="${GITHUB_SHA:0:8}" SHA8=$(echo "$GITHUB_SHA" | cut -c1-8)
PAGES_USER="${GIT_PAGES_PUBLISH_USER:-publish}" PAGES_USER="${GIT_PAGES_PUBLISH_USER:-publish}"
REPORT_DIR="reports/${SHA8}/${SUITE_PATH%/}" REPORT_DIR="reports/${SHA8}/${SUITE_PATH%/}"
REPORT_BASE="${GIT_PAGES_URL}/${OWNER}/${REPO}/reports/${SHA8}" REPORT_BASE="${GIT_PAGES_URL}/${OWNER}/${REPO}/reports/${SHA8}"
@@ -33,17 +33,30 @@ else
fi fi
mkdir -p "$TARGET" mkdir -p "$TARGET"
cp -a "$REPORT_DIR/." "$TARGET/" cp -a "$REPORT_DIR/." "$TARGET/"
if [ ! -f "$TARGET/index.html" ]; then
items=()
while IFS= read -r -d '' f; do
items+=("$(basename "$f")")
done < <(find "$TARGET" -maxdepth 1 -type f ! -name index.html -print0 2>/dev/null || true)
while IFS= read -r -d '' d; do
name=$(basename "$d")
[ -f "$d/index.html" ] && items+=("$name")
done < <(find "$TARGET" -maxdepth 1 -type d ! -name . -print0 2>/dev/null || true)
if [ ${#items[@]} -gt 1 ]; then if [ ! -f "$TARGET/index.html" ]; then
ITEM_LIST=""
ITEM_COUNT=0
for f in "$TARGET"/*; do
[ -f "$f" ] || continue
base=$(basename "$f")
[ "$base" = "index.html" ] && continue
ITEM_LIST="${ITEM_LIST}file:${base}
"
ITEM_COUNT=$((ITEM_COUNT + 1))
done
for d in "$TARGET"/*/; do
[ -d "$d" ] || continue
base=$(basename "$d")
[ -f "$d/index.html" ] || continue
ITEM_LIST="${ITEM_LIST}dir:${base}
"
ITEM_COUNT=$((ITEM_COUNT + 1))
done
if [ "$ITEM_COUNT" -gt 1 ]; then
{ {
echo '<!DOCTYPE html><html lang="en"><head><meta charset="utf-8">' echo '<!DOCTYPE html><html lang="en"><head><meta charset="utf-8">'
echo "<title>Test report ${SHA8}</title>" echo "<title>Test report ${SHA8}</title>"
@@ -53,16 +66,21 @@ if [ ! -f "$TARGET/index.html" ]; then
echo 'a{color:#2563eb;text-decoration:none}a:hover{text-decoration:underline}' echo 'a{color:#2563eb;text-decoration:none}a:hover{text-decoration:underline}'
echo '</style></head><body>' echo '</style></head><body>'
echo "<h1>Test report <code>${SHA8}</code></h1><ul>" echo "<h1>Test report <code>${SHA8}</code></h1><ul>"
for item in "${items[@]}"; do
label="${item%.*}" echo "$ITEM_LIST" | while IFS= read -r item; do
label="${label//-/ }" [ -z "$item" ] && continue
label="${label//_/ }" item_type=$(echo "$item" | cut -d: -f1)
if [ -f "$TARGET/$item" ]; then item_name=$(echo "$item" | cut -d: -f2-)
echo "<li><a href=\"$item\">${label^}</a></li>" label=$(echo "$item_name" | sed -e 's/\.[^.]*$//' -e 's/[-_]/ /g')
first=$(echo "$label" | cut -c1 | tr '[:lower:]' '[:upper:]')
rest=$(echo "$label" | cut -c2-)
if [ "$item_type" = "file" ]; then
echo "<li><a href=\"$item_name\">${first}${rest}</a></li>"
else else
echo "<li><a href=\"$item/index.html\">${label^}</a></li>" echo "<li><a href=\"$item_name/index.html\">${first}${rest}</a></li>"
fi fi
done done
echo '</ul></body></html>' echo '</ul></body></html>'
} > "$TARGET/index.html" } > "$TARGET/index.html"
fi fi
@@ -74,7 +92,7 @@ EOF
find "$WORK/$OWNER" \( -type f -o -type l \) -print | sed "s|^${WORK}/||" | tar -cf "$TAR" -C "$WORK" -T - find "$WORK/$OWNER" \( -type f -o -type l \) -print | sed "s|^${WORK}/||" | tar -cf "$TAR" -C "$WORK" -T -
publish() { publish() {
local method="$1" method="$1"
curl -sS -X "$method" "$PUBLISH_SITE_URL" \ curl -sS -X "$method" "$PUBLISH_SITE_URL" \
-u "${PAGES_USER}:${GIT_PAGES_PUBLISH_TOKEN}" \ -u "${PAGES_USER}:${GIT_PAGES_PUBLISH_TOKEN}" \
-H "Content-Type: application/x-tar" \ -H "Content-Type: application/x-tar" \
+6 -6
View File
@@ -1,11 +1,10 @@
#!/usr/bin/env bash #!/usr/bin/env sh
set -euo pipefail set -eu
# https://docs.gitea.com/api/next/#tag/repository/operation/repoCreateStatus
STATE="${1:-}" STATE="${1:-}"
DESCRIPTION="${2:-}" DESCRIPTION="${2:-}"
KEY="${3:-commit-${GITHUB_SHA:0:8}}" SHA8=$(echo "${GITHUB_SHA:-}" | cut -c1-8)
KEY="${3:-commit-${SHA8}}"
SUITE="${4:-}" SUITE="${4:-}"
CUSTOM_URL="${5:-}" CUSTOM_URL="${5:-}"
@@ -18,7 +17,8 @@ if [ -n "$CUSTOM_URL" ]; then
URL="$CUSTOM_URL" URL="$CUSTOM_URL"
elif [ -n "$SUITE" ]; then elif [ -n "$SUITE" ]; then
SUITE="${SUITE%/}/" SUITE="${SUITE%/}/"
URL="${GIT_PAGES_URL}/${GITHUB_REPOSITORY}/reports/${GITHUB_SHA:0:8}/${SUITE}" SHA8_CUT=$(echo "$GITHUB_SHA" | cut -c1-8)
URL="${GIT_PAGES_URL}/${GITHUB_REPOSITORY}/reports/${SHA8_CUT}/${SUITE}"
else else
URL="${GITEA_API_URL}/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}" URL="${GITEA_API_URL}/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}"
fi fi
+48 -6
View File
@@ -32,6 +32,31 @@ Kun kontti on pushattu registryyn, se on muiden pipeline-jobien käytettävissä
`latest`-tägillä — rebuild = käyttöönotto. Mitään versioviittauksia ei tarvitse `latest`-tägillä — rebuild = käyttöönotto. Mitään versioviittauksia ei tarvitse
päivittää. päivittää.
## Offline-periaate (DoD)
CI-kontin **Definition of Done**:
> Kontti ei lataa mitään pipeline-vaiheessa (`workflow run` -stepit) eikä kontin
> runtime-prosessissa (`container:` / `docker run`). Kaikki riippuvuudet
> (kielikohtaiset paketit, työkalut, binäärit) on joko:
> - Pre-cachattu kontin **build-vaiheessa** Dockerfilessä, TAI
> - Kopioitu multi-stage buildilla toisesta imagesta (`COPY --from`)
>
> Ainoa sallittu lataushetki on `docker build`. Sen jälkeen kontti toimii
> ilman verkkoyhteyttä.
**Miksi:** Toistettavuus, air gap -yhteensopivuus, nopeus. Pipeline ei saa
epäonnistua sen takia että ulkoinen registry on alhaalla tai että `go mod download`
joutuu latamaan 100 modulia jokaisella testiajolla.
**Kielikohtaiset pre-cachet:** Jos kontissa ajetaan kielikohtaista testiä
(Go, Java, Node, Python, ...), kaikki kielikohtaiset riippuvuudet on
pre-cachattava Dockerfilessä build-vaiheessa:
- Go: `COPY go.mod go.sum ./``RUN go mod download`
- Java/Maven: `COPY pom.xml ./``RUN mvn dependency:go-offline`
- Node: `COPY package.json package-lock.json ./``RUN npm ci --omit=dev`
- Python: `COPY requirements.txt ./``RUN pip wheel --wheel-dir=/wheels -r requirements.txt``COPY --from` käyttöön
## Nimeäminen ## Nimeäminen
CI-kontin build-workflow noudattaa samaa nimeämiskonventiota kuin muutkin CI-kontin build-workflow noudattaa samaa nimeämiskonventiota kuin muutkin
@@ -123,27 +148,44 @@ tag: latest
### Dockerfile ### Dockerfile
Dockerfile yhdistää tarvitut työkalut yhteen konttiin. Molemmat tavat kelpaavat: Dockerfile yhdistää tarvitut työkalut yhteen konttiin.
**Kaikki riippuvuudet ladataan build-vaiheessa — kontti on täysin itseriittoinen.**
```dockerfile ```dockerfile
# Tapa A: COPY --from toisesta imagesta # Tapa A: COPY --from toisesta imagesta
FROM __BASE_IMAGE__:__VERSION__ FROM __BASE_IMAGE__:__VERSION__
COPY --from=__SOURCE_IMAGE__:__VERSION__ /path/to/binary /usr/local/bin/ COPY --from=__SOURCE_IMAGE__:__VERSION__ /path/to/binary /usr/local/bin/
RUN apk add --no-cache __PAKETIT__ # Ei koskaan git:iä — kloonaus kuuluu pipelinelle RUN apk add --no-cache __PAKETIT__
# Tapa B: curl-lataus (normaali Dockerfilessa) # Tapa B: Build-vaiheen curl-lataus
FROM __BASE_IMAGE__:__VERSION__ FROM __BASE_IMAGE__:__VERSION__
RUN apk add --no-cache curl __PAKETIT__ && \ RUN apk add --no-cache curl __PAKETIT__ && \
curl -fsSL __URL__/__BINARY__.tar.gz | tar xz -C /usr/local/bin && \ curl -fsSL __URL__/__BINARY__.tar.gz | tar xz -C /usr/local/bin && \
apk del curl apk del curl
# Tapa C: Multi-stage + kielikohtainen pre-cache
FROM __BASE_IMAGE__:__VERSION__ AS deps
COPY go.mod go.sum ./
RUN go mod download
FROM deps AS build
COPY . .
RUN go test -c -o /tmp/test.bin ./...
FROM __BASE_IMAGE__:__VERSION__
COPY --from=deps /go/pkg/mod /go/pkg/mod
COPY --from=build /tmp/test.bin /usr/local/bin/test
``` ```
`COPY --from` on kevyempi (ei curl-asennusta). `curl` on selkeämpi kun binääri `COPY --from` on kevyempi (ei curl-asennusta). `curl` (Tapa B) on sallittu
tulee suoraan GitHub Releasesista tai vastaavasta. vain build-vaiheessa — `apk del curl` poistaa työkalun ennen runtimea.
Tapa C pre-cacheaa kielikohtaiset riippuvuudet ja tuottaa täysin
offline-runtime-kontin.
## Mitä EI kannata tehdä ## Mitä EI kannata tehdä
- Älä lisää `workflow_call`-triggariä — CI-konttia ei koskaan buildata automaattisesti - Älä lisää `workflow_call`-triggariä — CI-konttia ei koskaan buildata automaattisesti
- Älä poista `<komponentti>.`-prefiksiä olemassaolevista tiedostoista — ne kuuluvat monorepo-nimeämiskonventioon - Älä poista `<komponentti>.`-prefiksiä olemassaolevista tiedostoista — ne kuuluvat monorepo-nimeämiskonventioon
- Älä sisällytä CI-konttiin mitään sovelluskoodia — vain työkalut - Älä sisällytä CI-konttiin mitään sovelluskoodia — vain työkalut
- Älä koskaan asenna `git`:iä CI-konttiin — repon kloonaus ja checkout ovat Gitea Actionsin natiiveja operaatioita, eivät kontin vastuulla. Git paisuttaa konttia turhaan ja luo harhan että kontti hallitsee repoa - Älä koskaan lataa mitään pipeline- tai runtime-vaiheessa — kaikki lataukset kuuluvat `docker build` -vaiheeseen (Offline-periaate)
- Älä jätä kielikohtaisia riippuvuuksia pre-cachaamatta — `go mod download`, `npm install`, `mvn dependency:go-offline` jne. ajetaan Dockerfilessä, ei pipelinessä
+91 -2
View File
@@ -2,6 +2,93 @@
Mallipohjat, esimerkit ja konfiguraatiot. Katso säännöt `SKILL.md`:stä. Mallipohjat, esimerkit ja konfiguraatiot. Katso säännöt `SKILL.md`:stä.
## Pre-cache-esimerkit (Offline Container)
Alla Dockerfile-esimerkit kielikohtaisista pre-cacheista. Kaikki ajetaan
build-vaiheessa — kontti on täysin itseriittoinen eikä lataa mitään
pipeline- tai runtime-vaiheessa.
### Go
```dockerfile
FROM golang:1.24-alpine AS deps
WORKDIR /build
COPY go.mod go.sum ./
RUN go mod download
FROM deps AS test-build
COPY . .
RUN go test -c -o /tmp/test.bin ./...
FROM alpine:3.21
RUN apk add --no-cache git nodejs
COPY --from=deps /go/pkg/mod /go/pkg/mod
COPY --from=test-build /tmp/test.bin /usr/local/bin/test
```
### Node.js
```dockerfile
FROM node:22-alpine AS deps
WORKDIR /build
COPY package.json package-lock.json ./
RUN npm ci --omit=dev
FROM node:22-alpine
RUN apk add --no-cache git
COPY --from=deps /build/node_modules /app/node_modules
COPY . /app
WORKDIR /app
```
### Java / Maven
```dockerfile
FROM maven:3.9-eclipse-temurin-21 AS deps
WORKDIR /build
COPY pom.xml ./
RUN mvn dependency:go-offline -B
FROM maven:3.9-eclipse-temurin-21 AS build
COPY --from=deps /root/.m2 /root/.m2
COPY . .
RUN mvn package -B -DskipTests
FROM eclipse-temurin:21-jre
RUN apt-get update && apt-get install -y --no-install-recommends git && rm -rf /var/lib/apt/lists/*
COPY --from=build /build/target/*.jar /app/app.jar
WORKDIR /app
```
### Python
```dockerfile
FROM python:3.12-alpine AS deps
WORKDIR /build
COPY requirements.txt ./
RUN pip wheel --wheel-dir=/wheels -r requirements.txt
FROM python:3.12-alpine
RUN apk add --no-cache git
COPY --from=deps /build/wheels /wheels
COPY --from=deps /build/requirements.txt /
RUN pip install --no-index --find-links=/wheels -r /requirements.txt && rm -rf /wheels
COPY . /app
WORKDIR /app
```
### Helm + Node.js (korvaa helm-build-push.yml:n runtime-apk)
```dockerfile
FROM alpine/helm:3.16.0 AS helm-bin
FROM node:22-alpine
RUN apk add --no-cache git
COPY --from=helm-bin /usr/bin/helm /usr/local/bin/helm
```
Tämä kontti korvaa `helm-build-push.yml`:n `alpine/helm:3.19.0`-image-riippuvuuden
ja poistaa tarpeen asentaa node.js runtime-vaiheessa.
## Reititin — täydellinen esimerkki ## Reititin — täydellinen esimerkki
```yaml ```yaml
@@ -349,7 +436,7 @@ pitää komponentit selkeästi erillään, ja tekee repossa navigoinnista suorav
| Ongelma | Ratkaisu | | Ongelma | Ratkaisu |
|---|---| |---|---|
| Monta komponenttia, yksi repo — mikä triggeröi? | `paths:`-filtteri: `push: { paths: ['<komponentti>/**'] }` | | Monta komponenttia, yksi repo — mikä triggeröi? | `paths:`-filtteri: komponentin hakemisto + sen CI-workflow't ja conf-tiedosto |
| Jokaisella komponentilla oma versio | `VERSION_FILE=<komponentti>/package.json` confissa | | Jokaisella komponentilla oma versio | `VERSION_FILE=<komponentti>/package.json` confissa |
| Git-tägit sekaisin ellei nimiavaruutta | `GIT_TAG_PREFIX=<komponentti>/` confissa → tägi `<komponentti>/1.2.3` | | Git-tägit sekaisin ellei nimiavaruutta | `GIT_TAG_PREFIX=<komponentti>/` confissa → tägi `<komponentti>/1.2.3` |
| Eri julkaisutahdit | Riippumattomat CI-triggerit, omat versiopolut | | Eri julkaisutahdit | Riippumattomat CI-triggerit, omat versiopolut |
@@ -378,7 +465,8 @@ on:
branches: branches:
- main - main
paths: paths:
- '<komponentti>/**' - <komponentti>/**
- .gitea/workflows/<komponentti>.*
jobs: jobs:
load-config: load-config:
@@ -435,6 +523,7 @@ jos commitilla on jo tägi, pipeline skipataan `if: artifact_exists != 'true'`.
- Älä aja kaikkia komponentteja samasta triggeristä — `paths:` pitää CI:t erillisinä - Älä aja kaikkia komponentteja samasta triggeristä — `paths:` pitää CI:t erillisinä
- Älä käytä samaa versionhallintatiedostoa usealle komponentille - Älä käytä samaa versionhallintatiedostoa usealle komponentille
- Älä anna monorepo-parametreja pipeline-overrideina — kaikki kuuluu conf-tiedostoon - Älä anna monorepo-parametreja pipeline-overrideina — kaikki kuuluu conf-tiedostoon
- Älä rajaa `paths:` pelkkään komponentin hakemistoon — CI ei triggeröidy workflow- tai conf-muutoksista
## Versionhallinta ## Versionhallinta
+39 -10
View File
@@ -82,7 +82,36 @@ koko stepin ensimmäisellä failaavalla komennolla, ja loput jäävät ajamatta.
CI-kontin build-workflow'n template: `skills/ci-container-build/SKILL.md`. CI-kontin build-workflow'n template: `skills/ci-container-build/SKILL.md`.
### 4.1 CI-kontin ajaminen jobissa ### 4.1 Offline Container -vaatimus (DoD)
CI-kontin (ja kaikkien pipeline-konttien) on oltava täysin itseriittoisia:
> Kontti ei lataa mitään pipeline-vaiheessa (`workflow run` -stepit) eikä
> kontin runtime-prosessissa (`container:` / `docker run`). Kaikki
> riippuvuudet pre-cachataan `docker build` -vaiheessa.
> Ainoa sallittu lataushetki on `docker build`.
**Esimerkkejä rikkomuksista:**
- `apk add`, `apt-get install`, `npm install`, `go mod download`, `pip install`
pipeline-stepissä
- `curl <url> | tar xz` runtime-vaiheessa
- Node.js-konttikuva ilman nodea (joudutaan asentamaan lennossa)
### 4.2 Kielikohtainen pre-cache
Kun kontissa testataan kielikohtaista koodia, kaikki riippuvuudet on
pre-cachattava Dockerfilessä, ei pipeline-stepissä:
| Kieli | Pre-cache Dockerfilessä |
|---|---|
| Go | `COPY go.mod go.sum ./``RUN go mod download` |
| Java/Maven | `COPY pom.xml ./``RUN mvn dependency:go-offline` |
| Node | `COPY package.json package-lock.json ./``RUN npm ci --omit=dev` |
| Python | `COPY requirements.txt ./``RUN pip install -r requirements.txt` |
Katso tarkat Dockerfile-esimerkit `REFERENCE.md`:stä.
### 4.3 CI-kontin ajaminen jobissa
Ainoa sallittu tapa on `container:`-direktiivi. `docker run` komennolla kontin Ainoa sallittu tapa on `container:`-direktiivi. `docker run` komennolla kontin
käynnistäminen stepin sisällä on anti-pattern. käynnistäminen stepin sisällä on anti-pattern.
@@ -91,7 +120,8 @@ Katso CI-kontin template `REFERENCE.md`:stä.
**Huomio `actions/checkout@v4`:stä:** `container:`-direktiivillä kaikki stepit **Huomio `actions/checkout@v4`:stä:** `container:`-direktiivillä kaikki stepit
ajetaan kontin *sisällä* — myös `actions/checkout@v4`. Se on JavaScript-action ajetaan kontin *sisällä* — myös `actions/checkout@v4`. Se on JavaScript-action
joka vaatii sekä `nodejs` että `git`. Varmista että CI-kontin Dockerfilessä on molemmat. joka vaatii sekä `nodejs` että `git`. Varmista että CI-kontin Dockerfilessä on
molemmat — muuten checkout ei toimi ja pipeline failaa.
## 5. Raporttitasot ## 5. Raporttitasot
@@ -243,15 +273,14 @@ helm-build-push:
# chart_path: '.' # oletus, vaihda jos Chart.yaml on alihakemistossa # chart_path: '.' # oletus, vaihda jos Chart.yaml on alihakemistossa
``` ```
**Node.js-kompromissi:** `actions/checkout@v4` on JavaScript-action. **Vanhentunut käytäntö:** Nykyinen `helm-build-push.yml` asentaa node.js:n
Kontissa `alpine/helm` ei ole node.js:ää, joten se asennetaan lennossa lennossa `apk add --no-cache nodejs` ennen checkouttia — tämä rikkoo
`apk add --no-cache nodejs` ennen checkouttia. Offline Container -vaatimusta (4.1).
- Vaatii internet-yhteyden **Korjaustoimenpide:** Rakenna custom CI-kontti `ci-container-build`-skillillä
- Ei toimi air gap -ympäristössä jossa on helm + nodejs + git (katso pre-cache-esimerkit `REFERENCE.md`:stä),
- Korvaa tarvittaessa custom-kontilla (helm + nodejs): päivitä workflow'n `container: image:` osoittamaan omaan konttiin, ja poista
rakenna `ci-container-build`-skillillä ja päivitä workflow'n runtime-apk.
`container: image:` osoittamaan omaan konttiin
**Yksittäisten Helm-UI-linkkien raportointi:** `HELM_UI_URL` on **Yksittäisten Helm-UI-linkkien raportointi:** `HELM_UI_URL` on
tarkoitettu yleiselle registry UI:lle — provider muodostaa linkin tarkoitettu yleiselle registry UI:lle — provider muodostaa linkin
+15 -1
View File
@@ -5,7 +5,6 @@ source "$BATS_TEST_DIRNAME/helpers/mock-api.sh"
setup() { setup() {
export GITEA_TOKEN=test-token export GITEA_TOKEN=test-token
export GIT_TAG_PREFIX="" export GIT_TAG_PREFIX=""
export SERVER_URL="http://localhost:18080"
export REPO="niko/test" export REPO="niko/test"
export SHA="abc123" export SHA="abc123"
rm -rf /tmp/build-ctx rm -rf /tmp/build-ctx
@@ -153,6 +152,21 @@ teardown() {
[ "$NEXT_VERSION" = "0.3.2" ] [ "$NEXT_VERSION" = "0.3.2" ]
} }
@test "VERSION_FILE=Chart-umbrella.yaml extracts only top-level version" {
mock_set_sequence '[{"code": 200, "body": []}]'
mock_start
export VERSION_FILE="$BATS_TEST_DIRNAME/fixtures/check-version/Chart-umbrella.yaml"
run bash scripts/check-version.sh
echo "STATUS=$status"
echo "OUTPUT=$output"
[ "$status" -eq 0 ]
source /tmp/build-ctx/build.env
echo "NEXT_VERSION=$NEXT_VERSION"
[ "$NEXT_VERSION" = "0.1.0" ]
}
@test "no version source exits with error" { @test "no version source exits with error" {
mock_set_sequence '[{"code": 200, "body": []}]' mock_set_sequence '[{"code": 200, "body": []}]'
mock_start mock_start
+7 -7
View File
@@ -19,7 +19,7 @@ teardown() {
{"code":200,"body":{"id":1,"status":"completed","conclusion":"success"}} {"code":200,"body":{"id":1,"status":"completed","conclusion":"success"}}
]' ]'
mock_start mock_start
run bash scripts/dispatch-workflow.sh "test-owner/test-repo" "test.yml" "main" '{"version":"1.2.3"}' "http://localhost:18080" "test-token-abc123" run bash scripts/dispatch-workflow.sh "test-owner/test-repo" "test.yml" "main" '{"version":"1.2.3"}' "$GITEA_API_URL" "test-token-abc123"
[ "$status" -eq 0 ] [ "$status" -eq 0 ]
} }
@@ -31,7 +31,7 @@ teardown() {
{"code":200,"body":{"id":1,"status":"completed","conclusion":"failure"}} {"code":200,"body":{"id":1,"status":"completed","conclusion":"failure"}}
]' ]'
mock_start mock_start
run bash scripts/dispatch-workflow.sh "test-owner/test-repo" "test.yml" "main" '{"version":"1.2.3"}' "http://localhost:18080" "test-token-abc123" run bash scripts/dispatch-workflow.sh "test-owner/test-repo" "test.yml" "main" '{"version":"1.2.3"}' "$GITEA_API_URL" "test-token-abc123"
[ "$status" -eq 1 ] [ "$status" -eq 1 ]
} }
@@ -43,7 +43,7 @@ teardown() {
{"code":200,"body":{"id":1,"status":"completed","conclusion":"cancelled"}} {"code":200,"body":{"id":1,"status":"completed","conclusion":"cancelled"}}
]' ]'
mock_start mock_start
run bash scripts/dispatch-workflow.sh "test-owner/test-repo" "test.yml" "main" '{"version":"1.2.3"}' "http://localhost:18080" "test-token-abc123" run bash scripts/dispatch-workflow.sh "test-owner/test-repo" "test.yml" "main" '{"version":"1.2.3"}' "$GITEA_API_URL" "test-token-abc123"
[ "$status" -eq 1 ] [ "$status" -eq 1 ]
} }
@@ -61,7 +61,7 @@ teardown() {
{"code":200,"body":{"id":1,"status":"running"}} {"code":200,"body":{"id":1,"status":"running"}}
]' ]'
mock_start mock_start
run bash scripts/dispatch-workflow.sh "test-owner/test-repo" "test.yml" "main" '{"version":"1.2.3"}' "http://localhost:18080" "test-token-abc123" "0.001" run bash scripts/dispatch-workflow.sh "test-owner/test-repo" "test.yml" "main" '{"version":"1.2.3"}' "$GITEA_API_URL" "test-token-abc123" "0.001"
[ "$status" -eq 124 ] [ "$status" -eq 124 ]
} }
@@ -70,7 +70,7 @@ teardown() {
{"code":500} {"code":500}
]' ]'
mock_start mock_start
run bash scripts/dispatch-workflow.sh "test-owner/test-repo" "test.yml" "main" '{"version":"1.2.3"}' "http://localhost:18080" "test-token-abc123" run bash scripts/dispatch-workflow.sh "test-owner/test-repo" "test.yml" "main" '{"version":"1.2.3"}' "$GITEA_API_URL" "test-token-abc123"
[ "$status" -eq 1 ] [ "$status" -eq 1 ]
} }
@@ -81,7 +81,7 @@ teardown() {
{"code":200,"body":{"id":1,"status":"completed","conclusion":"success"}} {"code":200,"body":{"id":1,"status":"completed","conclusion":"success"}}
]' ]'
mock_start mock_start
run bash scripts/dispatch-workflow.sh "test-owner/test-repo" "test.yml" "main" '{"version":"1.2.3"}' "http://localhost:18080" "test-token-abc123" run bash scripts/dispatch-workflow.sh "test-owner/test-repo" "test.yml" "main" '{"version":"1.2.3"}' "$GITEA_API_URL" "test-token-abc123"
[ "$status" -eq 0 ] [ "$status" -eq 0 ]
path=$(mock_get_first_request_path) path=$(mock_get_first_request_path)
[[ "$path" == *"/api/v1/repos/test-owner/test-repo/actions/workflows/test.yml/dispatches"* ]] [[ "$path" == *"/api/v1/repos/test-owner/test-repo/actions/workflows/test.yml/dispatches"* ]]
@@ -126,7 +126,7 @@ teardown() {
{"code":200,"body":{"workflow_runs":[]}} {"code":200,"body":{"workflow_runs":[]}}
]' ]'
mock_start mock_start
run bash scripts/dispatch-workflow.sh "test-owner/test-repo" "test.yml" "main" '{}' "http://localhost:18080" "test-token-abc123" run bash scripts/dispatch-workflow.sh "test-owner/test-repo" "test.yml" "main" '{}' "$GITEA_API_URL" "test-token-abc123"
[ "$status" -eq 1 ] [ "$status" -eq 1 ]
[[ "$output" == *"ERROR"* ]] [[ "$output" == *"ERROR"* ]]
} }
+12
View File
@@ -0,0 +1,12 @@
apiVersion: v2
name: agent-platform
description: Agent Platform umbrella chart
type: application
version: 0.1.0
dependencies:
- name: vikunja
version: "0.1.0"
repository: oci://registry.example.com
- name: langfuse
version: "0.2.0"
repository: oci://registry.example.com
+19 -3
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env bash #!/usr/bin/env bash
set -euo pipefail set -euo pipefail
MOCK_PORT=18080 MOCK_PORT=""
MOCK_PID="" MOCK_PID=""
MOCK_REQUEST_FILE="" MOCK_REQUEST_FILE=""
MOCK_RESPONSE_CODE=201 MOCK_RESPONSE_CODE=201
@@ -9,11 +9,17 @@ MOCK_STATE_FILE="/tmp/mock_api_state"
MOCK_SEQUENCE_FILE="" MOCK_SEQUENCE_FILE=""
MOCK_CONFIG_FILE="" MOCK_CONFIG_FILE=""
_free_port() {
python3 -c "import socket; s=socket.socket(); s.bind(('',0)); print(s.getsockname()[1]); s.close()"
}
_kill_port() { _kill_port() {
local pids local pids
pids=$(lsof -ti ":$MOCK_PORT" 2>/dev/null) || true pids=$(lsof -ti ":$MOCK_PORT" 2>/dev/null) || true
[ -n "$pids" ] && kill -9 $pids 2>/dev/null || true [ -n "$pids" ] && kill $pids 2>/dev/null || true
sleep 0.5 sleep 0.5
pids=$(lsof -ti ":$MOCK_PORT" 2>/dev/null) || true
[ -n "$pids" ] && kill -9 $pids 2>/dev/null || true
} }
_wait_port_free() { _wait_port_free() {
@@ -26,10 +32,14 @@ _wait_port_free() {
_wait_port_ready() { _wait_port_ready() {
local i=0 local i=0
while ! lsof -ti ":$MOCK_PORT" >/dev/null 2>&1 && [ $i -lt 5 ]; do while [ $i -lt 50 ]; do
if nc -z localhost "$MOCK_PORT" 2>/dev/null; then
return 0
fi
sleep 0.2 sleep 0.2
i=$((i + 1)) i=$((i + 1))
done done
return 1
} }
mock_set_sequence() { mock_set_sequence() {
@@ -43,6 +53,12 @@ mock_clear_sequence() {
} }
mock_start() { mock_start() {
MOCK_PORT=$(_free_port)
export MOCK_PORT
MOCK_URL="http://localhost:${MOCK_PORT}"
export SERVER_URL="$MOCK_URL"
export GITEA_API_URL="$MOCK_URL"
MOCK_RESPONSE_CODE="${MOCK_RESPONSE_CODE:-201}" MOCK_RESPONSE_CODE="${MOCK_RESPONSE_CODE:-201}"
MOCK_REQUEST_FILE=$(mktemp) MOCK_REQUEST_FILE=$(mktemp)
echo "$MOCK_REQUEST_FILE" > "$MOCK_STATE_FILE" echo "$MOCK_REQUEST_FILE" > "$MOCK_STATE_FILE"
+5 -2
View File
@@ -63,9 +63,10 @@ teardown() {
{"code":200,"body":"published"} {"code":200,"body":"published"}
]' ]'
mock_start mock_start
export GIT_PAGES_URL="http://localhost:${MOCK_PORT}"
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/reports/abc123de" ]] [[ "$output" == "${GIT_PAGES_URL}/test-owner/test-repo/reports/abc123de" ]]
} }
@test "publish with suite subpath" { @test "publish with suite subpath" {
@@ -75,9 +76,10 @@ teardown() {
{"code":200,"body":"published"} {"code":200,"body":"published"}
]' ]'
mock_start mock_start
export GIT_PAGES_URL="http://localhost:${MOCK_PORT}"
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/reports/abc123de" ]] [[ "$output" == "${GIT_PAGES_URL}/test-owner/test-repo/reports/abc123de" ]]
} }
@test "git-pages returns HTTP 500 → exit 1" { @test "git-pages returns HTTP 500 → exit 1" {
@@ -85,6 +87,7 @@ teardown() {
{"code":500,"body":"internal error"} {"code":500,"body":"internal error"}
]' ]'
mock_start mock_start
export GIT_PAGES_URL="http://localhost:${MOCK_PORT}"
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" == *"500"* ]] [[ "$output" == *"500"* ]]
+4 -2
View File
@@ -23,7 +23,8 @@ teardown() {
body=$(mock_get_request_body) body=$(mock_get_request_body)
[[ "$body" == *'"state":"pending"'* ]] [[ "$body" == *'"state":"pending"'* ]]
[[ "$body" == *'"description":"Building project"'* ]] [[ "$body" == *'"description":"Building project"'* ]]
[[ "$body" == *'"target_url":"http://localhost:18080/test-owner/test-repo/actions/runs/42"'* ]] expected_url="${GITEA_API_URL}/test-owner/test-repo/actions/runs/42"
[[ "$body" == *"\"target_url\":\"${expected_url}\""* ]]
method=$(mock_get_request_method) method=$(mock_get_request_method)
[[ "$method" == "POST" ]] [[ "$method" == "POST" ]]
} }
@@ -44,7 +45,8 @@ teardown() {
[ "$status" -eq 0 ] [ "$status" -eq 0 ]
body=$(mock_get_request_body) body=$(mock_get_request_body)
[[ "$body" == *'"state":"failure"'* ]] [[ "$body" == *'"state":"failure"'* ]]
[[ "$body" == *'"target_url":"http://localhost:18080/test-owner/test-repo/actions/runs/42"'* ]] expected_url="${GITEA_API_URL}/test-owner/test-repo/actions/runs/42"
[[ "$body" == *"\"target_url\":\"${expected_url}\""* ]]
} }
@test "default key when not provided" { @test "default key when not provided" {