renovate-ci / validate-renovate (push) Skipped
ci / lint-compose (push) Successful in 8s
ci / lint-actionlint (push) Successful in 5s
ci / lint-shellcheck (push) Successful in 14s
ci / lint-prettier (push) Successful in 15s
ci / lint-ruff (push) Successful in 5s
ci / lint-yaml (push) Successful in 9s
ci / lint-dockerfiles (push) Successful in 7s
ci / validate (push) Successful in 6s
ci / build (push) Skipped
ci / lint-compose (pull_request) Successful in 11s
ci / lint-actionlint (pull_request) Successful in 7s
ci / lint-shellcheck (pull_request) Successful in 12s
ci / lint-prettier (pull_request) Successful in 14s
ci / lint-ruff (pull_request) Successful in 5s
ci / lint-yaml (pull_request) Successful in 11s
ci / lint-dockerfiles (pull_request) Successful in 6s
ci / validate (pull_request) Successful in 6s
ci / build (pull_request) Skipped
renovate-ci / validate-renovate (pull_request) Successful in 8s
81 lines
3.5 KiB
Bash
Executable File
81 lines
3.5 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Local regressions only: kubectl is mocked and Docker is used for config parsing.
|
|
set -euo pipefail
|
|
repo="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
|
scratch="$(mktemp -d)"
|
|
trap 'rm -rf "$scratch"' EXIT
|
|
|
|
mkdir -p "$scratch/repo/app" "$scratch/repo/postgres" "$scratch/repo/netbird" "$scratch/repo/renovate"
|
|
git -C "$scratch/repo" init -q
|
|
for file in app/compose.yaml postgres/shared-compose.yaml netbird/client.compose.yaml renovate/renovate-compose.yaml; do
|
|
touch "$scratch/repo/$file"
|
|
done
|
|
git -C "$scratch/repo" add .
|
|
# shellcheck source=../workflows/compose-lint.sh
|
|
source "$repo/.gitea/workflows/compose-lint.sh"
|
|
actual="$(cd "$scratch/repo" && compose_files)"
|
|
expected=$'app/compose.yaml\nnetbird/client.compose.yaml\npostgres/shared-compose.yaml\nrenovate/renovate-compose.yaml'
|
|
[ "$actual" = "$expected" ] || { echo 'Compose discovery missed a file' >&2; exit 1; }
|
|
|
|
cat >"$scratch/compose.yaml" <<'YAML'
|
|
services:
|
|
example:
|
|
image: busybox:1.37.0
|
|
environment:
|
|
REQUIRED: ${HOMELAB_TEST_REQUIRED:?required for this regression}
|
|
YAML
|
|
unset HOMELAB_TEST_REQUIRED
|
|
if validate_compose_file "$scratch/compose.yaml" >"$scratch/config.log" 2>&1; then
|
|
echo 'Full Compose validation accepted a missing variable' >&2
|
|
exit 1
|
|
fi
|
|
grep -q 'required for this regression' "$scratch/config.log"
|
|
HOMELAB_TEST_REQUIRED=present validate_compose_file "$scratch/compose.yaml"
|
|
|
|
cat >"$scratch/resources.json" <<'JSON'
|
|
{"kind":"List","items":[
|
|
{"kind":"Deployment","metadata":{"namespace":"app"},"spec":{"template":{"spec":{
|
|
"containers":[{"envFrom":[{"secretRef":{"name":"credentials"}},{"secretRef":{"name":"optional","optional":true}}],"env":[{"valueFrom":{"secretKeyRef":{"name":"credentials","key":"password"}}}]}],
|
|
"initContainers":[{"envFrom":[{"secretRef":{"name":"init"}}]}],
|
|
"imagePullSecrets":[{"name":"registry"}],
|
|
"volumes":[{"secret":{"secretName":"mounted"}},{"projected":{"sources":[{"secret":{"name":"projected"}},{"secret":{"name":"optional-projected","optional":true}}]}}]
|
|
}}}},
|
|
{"kind":"CronJob","metadata":{},"spec":{"jobTemplate":{"spec":{"template":{"spec":{"containers":[{"envFrom":[{"secretRef":{"name":"cron"}}]}]}}}}}},
|
|
{"kind":"IngressRoute","metadata":{"namespace":"app"},"spec":{"tls":{"secretName":"controller-issued-tls"}}}
|
|
]}
|
|
JSON
|
|
actual="$(jq -r -f "$repo/.gitea/workflows/secret-references.jq" "$scratch/resources.json" | sort)"
|
|
expected=$'app credentials\napp init\napp mounted\napp projected\napp registry\ndefault cron'
|
|
[ "$actual" = "$expected" ] || { echo "Unexpected Secret references: $actual" >&2; exit 1; }
|
|
|
|
REPO="$repo"
|
|
# shellcheck source=../workflows/deploy-lib.sh
|
|
source "$repo/.gitea/workflows/deploy-lib.sh"
|
|
K8S_MANIFESTS=("$scratch/resources.json")
|
|
KUSTOMIZE_APPS=()
|
|
# No live cluster access. Reject credentials in app even if they exist elsewhere.
|
|
kubectl() {
|
|
case "$1" in
|
|
create) cat "$scratch/resources.json" ;;
|
|
get)
|
|
if [ "$3" = credentials ] && [ "$5" = app ]; then
|
|
return 1
|
|
fi
|
|
return 0
|
|
;;
|
|
*) echo "Unexpected kubectl invocation: $*" >&2; return 1 ;;
|
|
esac
|
|
}
|
|
if check_referenced_secrets >"$scratch/secrets.log"; then
|
|
echo 'Namespace-scoped Secret check accepted a missing Secret' >&2
|
|
exit 1
|
|
fi
|
|
grep -q 'MISSING OR UNREADABLE: app/credentials' "$scratch/secrets.log"
|
|
# API/rendering errors must not produce an empty reference list and pass.
|
|
kubectl() { return 1; }
|
|
if check_referenced_secrets >"$scratch/secrets.log"; then
|
|
echo 'Secret check accepted a failed manifest render' >&2
|
|
exit 1
|
|
fi
|
|
printf '%s\n' 'Deploy validation regressions passed.'
|