| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363 |
- #!/usr/bin/env bash
- ###############################################################################
- # Installer Test Script
- # Simulates the installer and shows which files would fail to download
- # Usage: ./scripts/tests/test-installer-files.sh [--profile=<profile>] [--verbose]
- ###############################################################################
- set -e
- # Colors
- RED='\033[0;31m'
- GREEN='\033[0;32m'
- YELLOW='\033[1;33m'
- BLUE='\033[0;34m'
- CYAN='\033[0;36m'
- BOLD='\033[1m'
- NC='\033[0m'
- # Configuration
- BRANCH="main"
- RAW_URL="https://raw.githubusercontent.com/darrenhinde/OpenAgentsControl/${BRANCH}"
- TEMP_DIR="/tmp/opencode-installer-test-$$"
- # Allow local testing (useful for CI/CD or when testing changes before pushing)
- USE_LOCAL=false
- LOCAL_REGISTRY="./registry.json"
- # Global variables
- VERBOSE=false
- TEST_PROFILE=""
- FAILED_FILES=()
- SKIPPED_FILES=()
- SUCCESS_COUNT=0
- FAIL_COUNT=0
- # Cleanup function
- # shellcheck disable=SC2329
- cleanup() {
- rm -rf "$TEMP_DIR" 2>/dev/null || true
- }
- trap cleanup EXIT INT TERM
- # Print functions
- print_header() {
- echo -e "${CYAN}${BOLD}"
- echo "╔════════════════════════════════════════════════════════════════╗"
- echo "║ ║"
- echo "║ Installer File Test - v1.0.0 ║"
- echo "║ ║"
- echo "╚════════════════════════════════════════════════════════════════╝"
- echo -e "${NC}"
- }
- print_success() {
- echo -e "${GREEN}✓${NC} $1"
- }
- print_error() {
- echo -e "${RED}✗${NC} $1"
- }
- print_warning() {
- echo -e "${YELLOW}⚠${NC} $1"
- }
- print_info() {
- echo -e "${BLUE}ℹ${NC} $1"
- }
- print_step() {
- echo -e "\n${BOLD}$1${NC}"
- }
- # Check if URL is accessible
- check_url() {
- local url="$1"
- local component="$2"
-
- if curl -fsSL --max-time 10 -I "$url" > /dev/null 2>&1; then
- return 0
- else
- return 1
- fi
- }
- # Test a single file
- test_file() {
- local path="$1"
- local component="$2"
- local url="${RAW_URL}/${path}"
-
- if check_url "$url" "$component"; then
- SUCCESS_COUNT=$((SUCCESS_COUNT + 1))
- if [ "$VERBOSE" = true ]; then
- print_success "Accessible: ${path}"
- fi
- return 0
- else
- FAIL_COUNT=$((FAIL_COUNT + 1))
- FAILED_FILES+=("${component}|${path}")
- print_error "NOT FOUND: ${path}"
- return 1
- fi
- }
- # Test components from a category
- test_category() {
- local category="$1"
- local registry_file="$2"
-
- print_step "Testing ${category}..."
-
- local components
- components=$(jq -r ".components.${category}[]? | \"\(.id)|\(.path)\"" "$registry_file" 2>/dev/null || echo "")
-
- if [ -z "$components" ]; then
- print_warning "No components in category: ${category}"
- return
- fi
-
- while IFS='|' read -r id path; do
- [ -z "$id" ] && continue
- test_file "$path" "${category}:${id}"
- done <<< "$components"
- }
- # Test profile components
- test_profile() {
- local profile="$1"
- local registry_file="$2"
-
- print_step "Testing Profile: ${profile}"
-
- # Get components from profile
- local components
- components=$(jq -r ".profiles.${profile}.components[]?" "$registry_file" 2>/dev/null || echo "")
-
- if [ -z "$components" ]; then
- print_error "Profile not found or empty: ${profile}"
- return 1
- fi
-
- print_info "Profile components:"
-
- while IFS= read -r component; do
- [ -z "$component" ] && continue
-
- local type="${component%%:*}"
- local id="${component##*:}"
-
- # Handle wildcards
- if [[ "$id" == *"*"* ]]; then
- print_info " Wildcard: ${component} (expanding...)"
-
- if [ "$type" = "context" ]; then
- local prefix="${id%%\**}"
- prefix="${prefix%/}"
-
- # Find matching contexts
- local matches
- matches=$(jq -r ".components.contexts[]? | select(.path | startswith(\".opencode/context/${prefix}\")) | \"\(.id)|\(.path)\"" "$registry_file")
-
- while IFS='|' read -r match_id match_path; do
- [ -z "$match_id" ] && continue
- test_file "$match_path" "context:${match_id}"
- done <<< "$matches"
- fi
- continue
- fi
-
- # Get path for component
- local path
- path=$(jq -r ".components.${type}s[]? | select(.id == \"${id}\") | .path" "$registry_file")
-
- if [ -n "$path" ] && [ "$path" != "null" ]; then
- test_file "$path" "${component}"
- else
- print_warning " Component not found in registry: ${component}"
- SKIPPED_FILES+=("${component}|not_in_registry")
- fi
- done <<< "$components"
- }
- # Test all categories
- test_all() {
- local registry_file="$1"
-
- print_step "Testing All Component Categories"
-
- local categories=("agents" "subagents" "commands" "tools" "plugins" "skills" "contexts" "config")
-
- for category in "${categories[@]}"; do
- test_category "$category" "$registry_file"
- done
- }
- # Print summary
- print_summary() {
- echo ""
- echo -e "${BOLD}═══════════════════════════════════════════════════════════════${NC}"
- echo -e "${BOLD}Test Summary${NC}"
- echo -e "${BOLD}═══════════════════════════════════════════════════════════════${NC}"
- echo ""
- echo -e "Total files tested: ${CYAN}$((SUCCESS_COUNT + FAIL_COUNT))${NC}"
- echo -e "Files accessible: ${GREEN}${SUCCESS_COUNT}${NC}"
- echo -e "Files NOT FOUND: ${RED}${FAIL_COUNT}${NC}"
-
- if [ ${#SKIPPED_FILES[@]} -gt 0 ]; then
- echo -e "Skipped: ${YELLOW}${#SKIPPED_FILES[@]}${NC}"
- fi
-
- echo ""
-
- if [ $FAIL_COUNT -gt 0 ]; then
- print_error "Found ${FAIL_COUNT} file(s) that would FAIL during installation:"
- echo ""
- echo "Failed files:"
- for entry in "${FAILED_FILES[@]}"; do
- local component="${entry%%|*}"
- local path="${entry##*|}"
- echo " - ${component}"
- echo " URL: ${RAW_URL}/${path}"
- done
- echo ""
- echo -e "${YELLOW}These files need to be:${NC}"
- echo " 1. Added to the repository, OR"
- echo " 2. Removed from registry.json"
- echo ""
- return 1
- else
- print_success "All files are accessible and would install successfully!"
- return 0
- fi
- }
- # Usage
- usage() {
- echo "Usage: $0 [OPTIONS]"
- echo ""
- echo "Options:"
- echo " --profile=<name> Test a specific profile (essential, developer, business, full, advanced)"
- echo " --all Test all components (default)"
- echo " --verbose Show successful file checks"
- echo " --local Use local registry.json instead of downloading from GitHub"
- echo " --help Show this help message"
- echo ""
- echo "Examples:"
- echo " $0 # Test all components (remote registry)"
- echo " $0 --profile=essential # Test essential profile"
- echo " $0 --profile=developer --verbose # Test developer profile with details"
- echo " $0 --local # Test using local registry.json"
- echo ""
- exit 0
- }
- # Main
- main() {
- print_header
-
- # Parse arguments
- TEST_MODE="all"
-
- while [ $# -gt 0 ]; do
- case "$1" in
- --profile=*)
- TEST_PROFILE="${1#*=}"
- TEST_MODE="profile"
- ;;
- --profile)
- if [ -n "$2" ]; then
- TEST_PROFILE="$2"
- TEST_MODE="profile"
- shift
- else
- echo "Error: --profile requires a profile name"
- exit 1
- fi
- ;;
- --all)
- TEST_MODE="all"
- ;;
- --verbose)
- VERBOSE=true
- ;;
- --local)
- USE_LOCAL=true
- ;;
- --help|-h)
- usage
- ;;
- *)
- echo "Unknown option: $1"
- echo "Run '$0 --help' for usage information"
- exit 1
- ;;
- esac
- shift
- done
-
- # Check dependencies
- if ! command -v curl &> /dev/null; then
- print_error "curl is required but not installed"
- exit 1
- fi
-
- if ! command -v jq &> /dev/null; then
- print_error "jq is required but not installed"
- exit 1
- fi
-
- # Create temp directory
- mkdir -p "$TEMP_DIR"
-
- # Get registry (local or remote)
- if [ "$USE_LOCAL" = true ]; then
- print_step "Using local registry..."
- if [ ! -f "$LOCAL_REGISTRY" ]; then
- print_error "Local registry not found: $LOCAL_REGISTRY"
- exit 1
- fi
- cp "$LOCAL_REGISTRY" "${TEMP_DIR}/registry.json"
- print_success "Local registry loaded"
- else
- print_step "Downloading registry from GitHub..."
- if ! curl -fsSL "${RAW_URL}/registry.json" -o "${TEMP_DIR}/registry.json"; then
- print_error "Failed to download registry from ${RAW_URL}/registry.json"
- exit 1
- fi
- print_success "Registry downloaded successfully"
- fi
-
- # Validate registry JSON
- if ! jq empty "${TEMP_DIR}/registry.json" 2>/dev/null; then
- print_error "Registry is not valid JSON"
- exit 1
- fi
-
- # Run tests
- echo ""
- print_info "Testing file accessibility from: ${RAW_URL}"
- echo ""
-
- case "$TEST_MODE" in
- profile)
- if [ -z "$TEST_PROFILE" ]; then
- print_error "No profile specified. Use --profile=<name>"
- exit 1
- fi
- test_profile "$TEST_PROFILE" "${TEMP_DIR}/registry.json"
- ;;
- all)
- test_all "${TEMP_DIR}/registry.json"
- ;;
- esac
-
- # Print summary
- print_summary
- exit $?
- }
- main "$@"
- # Shellcheck validation passed
|