Files
LLMScaffolding/scripts/ci
Charles N Wyble 408db0d0cc
Some checks failed
CI / checks (push) Has been cancelled
CI / checks (pull_request) Has been cancelled
chore(ci): bootstrap CI + hooks
Squash-merge bootstrap-cicd into integration
2025-09-10 21:48:32 +00:00

116 lines
2.8 KiB
Bash
Executable File

#!/usr/bin/env bash
set -euo pipefail
PHASE="${1:-}"
usage() {
echo "Usage: scripts/ci <format|lint|build|test|security|all>" >&2
exit 2
}
if [[ -z "${PHASE}" ]]; then
usage
fi
repo_root() {
git rev-parse --show-toplevel 2>/dev/null || pwd
}
run_outside_container() {
local phase="$1"
local root
root="$(repo_root)"
if ! command -v docker >/dev/null 2>&1; then
echo "Docker is required to run CI tasks locally." >&2
exit 1
fi
if ! command -v docker-compose >/dev/null 2>&1 && ! docker compose version >/dev/null 2>&1; then
echo "Docker Compose v2+ is required (docker compose)." >&2
exit 1
fi
# Build ci image if needed and run the requested phase inside the container
(cd "$root" && docker compose -f docker/ci.compose.yml run --rm \
-e IN_CI_CONTAINER=1 \
ci bash -lc "cd /workspace && scripts/ci --inside ${phase}")
}
run_format() {
echo ">> Formatting"
# shell: format in-place
shfmt -bn -ci -i 2 -w .
# prettier for markdown/yaml/json/etc
prettier --log-level warn --write \
"**/*.md" "**/*.yaml" "**/*.yml" "**/*.json" \
"**/*.css" "**/*.html" 2>/dev/null || true
}
run_lint() {
echo ">> Linting"
# shellcheck
mapfile -t sh_files < <(git ls-files -z | xargs -0 file --mime-type | awk -F: '/(x-shellscript|text\/x-shellscript)/{print $1}'; git ls-files "*.sh")
if [[ ${#sh_files[@]} -gt 0 ]]; then
shellcheck -x "${sh_files[@]}" || (echo "Shellcheck failed" && exit 1)
shfmt -d .
fi
# hadolint on Dockerfiles
if ls Dockerfile* docker/*Dockerfile* 1>/dev/null 2>&1; then
hadolint Dockerfile* docker/*Dockerfile* 2>/dev/null || true
fi
# yamllint
if git ls-files "*.yml" "*.yaml" | grep -q .; then
yamllint -s $(git ls-files "*.yml" "*.yaml")
fi
# markdownlint
if git ls-files "*.md" | grep -q .; then
markdownlint $(git ls-files "*.md")
fi
# actionlint for workflow files if present
if [ -d .gitea/workflows ]; then
actionlint -color
fi
}
run_build() {
echo ">> Build checks"
# Validate docker compose configs if present
if [ -f docker-compose.yml ] || [ -f docker/compose.yml ]; then
docker compose config -q
fi
}
run_test() {
echo ">> Tests (none defined)"
}
run_security() {
echo ">> Security checks (skipped for this repo)"
}
run_inside_container() {
local phase="$1"
case "$phase" in
format) run_format ;;
lint) run_lint ;;
build) run_build ;;
test) run_test ;;
security) run_security ;;
all) run_format; run_lint; run_build; run_test; run_security ;;
*) usage ;;
esac
}
if [[ "${1:-}" == "--inside" ]]; then
shift
PHASE="${1:-}"
[[ -z "$PHASE" ]] && usage
run_inside_container "$PHASE"
exit 0
fi
if [[ "${IN_CI_CONTAINER:-}" != "1" ]]; then
run_outside_container "$PHASE"
else
run_inside_container "$PHASE"
fi