mirror of
https://github.com/sipeed/picoclaw.git
synced 2026-05-25 16:00:35 +00:00
123 lines
3.3 KiB
Bash
123 lines
3.3 KiB
Bash
#!/usr/bin/env bash
|
|
|
|
set -euo pipefail
|
|
|
|
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
BASE_COMPOSE="$ROOT_DIR/integration/docker-compose.runner.yml"
|
|
SUITES_DIR="$ROOT_DIR/integration/suites"
|
|
|
|
if [[ ! -f "$BASE_COMPOSE" ]]; then
|
|
echo "missing base compose file: $BASE_COMPOSE" >&2
|
|
exit 1
|
|
fi
|
|
|
|
if [[ ! -d "$SUITES_DIR" ]]; then
|
|
echo "missing integration suites directory: $SUITES_DIR" >&2
|
|
exit 1
|
|
fi
|
|
|
|
sanitize_project_name() {
|
|
printf '%s' "$1" | tr '[:upper:]' '[:lower:]' | tr -cs 'a-z0-9' '-'
|
|
}
|
|
|
|
collect_suite_dirs() {
|
|
if [[ "$#" -gt 0 ]]; then
|
|
local suite
|
|
for suite in "$@"; do
|
|
printf '%s\n' "$SUITES_DIR/$suite"
|
|
done
|
|
return
|
|
fi
|
|
|
|
find "$SUITES_DIR" -mindepth 1 -maxdepth 1 -type d | sort
|
|
}
|
|
|
|
run_suite() {
|
|
local suite_dir="$1"
|
|
local suite_name
|
|
suite_name="$(basename "$suite_dir")"
|
|
local manifest="$suite_dir/suite.env"
|
|
|
|
if [[ ! -f "$manifest" ]]; then
|
|
echo "suite $suite_name is missing manifest: $manifest" >&2
|
|
return 1
|
|
fi
|
|
|
|
local compose_args=()
|
|
compose_args+=(--project-directory "$ROOT_DIR" -p "picoclaw-int-$(sanitize_project_name "$suite_name")")
|
|
compose_args+=(-f "$BASE_COMPOSE")
|
|
|
|
local compose_files=()
|
|
while IFS= read -r compose_file; do
|
|
compose_files+=("$compose_file")
|
|
compose_args+=(-f "$compose_file")
|
|
done < <(find "$suite_dir" -maxdepth 1 -type f \( -name 'docker-compose.yml' -o -name 'docker-compose.*.yml' \) | sort)
|
|
|
|
if [[ "${#compose_files[@]}" -eq 0 ]]; then
|
|
echo "suite $suite_name has no docker-compose file" >&2
|
|
return 1
|
|
fi
|
|
|
|
(
|
|
set -a
|
|
# shellcheck disable=SC1090
|
|
source "$manifest"
|
|
set +a
|
|
export INTEGRATION_REPO_ROOT="$ROOT_DIR"
|
|
|
|
: "${TEST_COMMAND:?suite $suite_name must define TEST_COMMAND in $manifest}"
|
|
runner_service="${RUNNER_SERVICE:-integration-runner}"
|
|
|
|
cleanup() {
|
|
docker compose "${compose_args[@]}" down -v --remove-orphans >/dev/null 2>&1 || true
|
|
}
|
|
trap cleanup EXIT
|
|
|
|
echo "==> [$suite_name] resolving services"
|
|
local services=()
|
|
while IFS= read -r service; do
|
|
services+=("$service")
|
|
done < <(docker compose "${compose_args[@]}" config --services)
|
|
|
|
local dependency_services=()
|
|
for service in "${services[@]}"; do
|
|
if [[ "$service" != "$runner_service" ]]; then
|
|
dependency_services+=("$service")
|
|
fi
|
|
done
|
|
|
|
if [[ "${#dependency_services[@]}" -gt 0 ]]; then
|
|
echo "==> [$suite_name] starting docker services: ${dependency_services[*]}"
|
|
docker compose "${compose_args[@]}" up -d --build --wait "${dependency_services[@]}"
|
|
fi
|
|
|
|
echo "==> [$suite_name] running: $TEST_COMMAND"
|
|
# integration-runner already uses `bash -c` as its entrypoint, so pass the
|
|
# suite command as a single argument for Bash to execute directly.
|
|
docker compose "${compose_args[@]}" run --rm "$runner_service" "$TEST_COMMAND"
|
|
)
|
|
}
|
|
|
|
main() {
|
|
local suite_dirs=()
|
|
while IFS= read -r suite_dir; do
|
|
suite_dirs+=("$suite_dir")
|
|
done < <(collect_suite_dirs "$@")
|
|
|
|
if [[ "${#suite_dirs[@]}" -eq 0 ]]; then
|
|
echo "no integration suites found" >&2
|
|
exit 1
|
|
fi
|
|
|
|
local suite_dir
|
|
for suite_dir in "${suite_dirs[@]}"; do
|
|
if [[ ! -d "$suite_dir" ]]; then
|
|
echo "unknown integration suite: $suite_dir" >&2
|
|
exit 1
|
|
fi
|
|
run_suite "$suite_dir"
|
|
done
|
|
}
|
|
|
|
main "$@"
|