#!/usr/bin/env bash # ============================================================================== # SMARTGIFT AI - LARAVEL UNIT TESTING TOOLKIT INSTALLER # Cài đặt bộ công cụ Unit Test vào bất kỳ source code Laravel nào mà KHÔNG CẦN clone repo về máy. # # Cách dùng 1 (Khuyên dùng - Đứng trong source code Laravel và chạy): # curl -fsSL https://raw.githubusercontent.com//agent-unit-testing/main/install.sh | bash # Hoặc: # bash <(curl -fsSL https://raw.githubusercontent.com//agent-unit-testing/main/install.sh) # # Cách dùng 2 (Cài Toàn Cục vào máy): # curl -fsSL https://raw.githubusercontent.com//agent-unit-testing/main/install.sh | bash -s -- --global # ============================================================================== set -e GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' RED='\033[0;31m' CYAN='\033[0;36m' BOLD='\033[1m' NC='\033[0m' # Remote Repository URL công khai qua HTTPS (ai cũng truy cập được không cần SSH key) DEFAULT_REPO="https://git.smartgift.io.vn/Smartgift-AI/agent-unit-testing.git" REPO_URL="${LARAVEL_TEST_REPO:-$DEFAULT_REPO}" TARGET_DIR="" GLOBAL_MODE=false FORCE_MODE=false for arg in "$@"; do case "$arg" in --global|-g) GLOBAL_MODE=true ;; --force|-f) FORCE_MODE=true ;; --help|-h) echo -e "${BLUE}===================================================================${NC}" echo -e "${CYAN}${BOLD} SMARTGIFT AI: LARAVEL UNIT TESTING TOOLKIT INSTALLER${NC}" echo -e "${BLUE}===================================================================${NC}" echo -e "Cách dùng:" echo -e " 1. Cài đặt trực tiếp vào source code Laravel hiện tại:" echo -e " ${YELLOW}curl -fsSL /install.sh | bash${NC}" echo -e " 2. Cài đặt vào một source code ở đường dẫn cụ thể:" echo -e " ${YELLOW}curl -fsSL /install.sh | bash -s -- /duong-dan/source-code${NC}" echo -e " 3. Cài đặt Toàn Cục vào máy tính (dùng cho mọi folder):" echo -e " ${YELLOW}curl -fsSL /install.sh | bash -s -- --global${NC}" echo -e " 4. Cài đặt vào thư mục trống:" echo -e " ${YELLOW}curl -fsSL /install.sh | bash -s -- . --force${NC}" exit 0 ;; -*) # Bỏ qua các flag khác ;; *) if [ -z "$TARGET_DIR" ]; then TARGET_DIR="$arg" fi ;; esac done TARGET_DIR="${TARGET_DIR:-.}" echo -e "${BLUE}===================================================================${NC}" echo -e "${CYAN}${BOLD} 🚀 SMARTGIFT AI - LARAVEL UNIT TESTING TOOLKIT INSTALLER${NC}" echo -e "${BLUE}===================================================================${NC}" # 1. Tìm hoặc Tải nguồn tài nguyên (Local nếu có, hoặc tải tạm qua Git) CLEANUP_TEMP=false PACKAGE_ROOT="" SOURCE="${BASH_SOURCE[0]:-$0}" SCRIPT_DIR="" if [ -f "$SOURCE" ]; then SCRIPT_DIR="$(cd -P "$(dirname "$SOURCE")" 2>/dev/null && pwd || echo "")" fi if [ -n "$SCRIPT_DIR" ] && [ -d "$SCRIPT_DIR/.claude/skills" ]; then PACKAGE_ROOT="$SCRIPT_DIR" echo -e "${GREEN}✓ Sử dụng tài nguyên có sẵn tại local.${NC}" else echo -e "${YELLOW}📥 Đang tải bộ công cụ từ remote repository...${NC}" TMP_DIR="$(mktemp -d 2>/dev/null || mktemp -d -t 'sg_unit_testing')" # Thử clone qua git if ! git clone --depth 1 "$REPO_URL" "$TMP_DIR" --quiet 2>/dev/null; then echo -e "${RED}❌ Không thể clone từ repository: $REPO_URL${NC}" echo -e "${YELLOW}💡 Lưu ý dành cho người dùng bên ngoài:${NC}" echo -e " Nếu bạn không phải thành viên có SSH key nội bộ, hãy chạy với URL HTTPS công khai:" echo -e " ${CYAN}LARAVEL_TEST_REPO=https://github.com//.git curl -fsSL /install.sh | bash${NC}" rm -rf "$TMP_DIR" exit 1 fi PACKAGE_ROOT="$TMP_DIR" CLEANUP_TEMP=true echo -e "${GREEN}✓ Tải thành công!${NC}" fi cleanup() { if [ "$CLEANUP_TEMP" = true ] && [ -d "$PACKAGE_ROOT" ]; then rm -rf "$PACKAGE_ROOT" fi } trap cleanup EXIT # ============================================================================== # 2. XỬ LÝ CÀI ĐẶT TOÀN CỤC (GLOBAL MODE: CHO TẤT CẢ FOLDER TRÊN MÁY) # ============================================================================== if [ "$GLOBAL_MODE" = true ]; then echo -e "${YELLOW}⚙️ Đang cài đặt chế độ Toàn Cục vào $HOME/.claude/skills/...${NC}" mkdir -p "$HOME/.claude/skills" cp -R "$PACKAGE_ROOT/.claude/skills/"* "$HOME/.claude/skills/" mkdir -p "$HOME/.claude/laravel-testing-docs/templates" cp -R "$PACKAGE_ROOT/docs/"* "$HOME/.claude/laravel-testing-docs/" cp -R "$PACKAGE_ROOT/rules/"* "$HOME/.claude/laravel-testing-docs/" cp -R "$PACKAGE_ROOT/templates/"* "$HOME/.claude/laravel-testing-docs/templates/" mkdir -p "$HOME/.local/bin" cat << 'EOF' > "$HOME/.local/bin/sg-test-init" #!/usr/bin/env bash TARGET_DIR="${1:-.}" SOURCE_DIR="$HOME/.claude/laravel-testing-docs" if [ ! -d "$TARGET_DIR" ]; then echo "Lỗi: Thư mục '$TARGET_DIR' không tồn tại!" exit 1 fi echo "🚀 Đang khởi tạo test runner cho dự án tại: $TARGET_DIR" if [ -f "$SOURCE_DIR/templates/docker/test-runner.sh" ]; then cp "$SOURCE_DIR/templates/docker/test-runner.sh" "$TARGET_DIR/test-runner.sh" chmod +x "$TARGET_DIR/test-runner.sh" echo " ✓ Đã tạo $TARGET_DIR/test-runner.sh" fi if [ -f "$SOURCE_DIR/templates/setup-dependencies.sh" ]; then cp "$SOURCE_DIR/templates/setup-dependencies.sh" "$TARGET_DIR/setup-test-deps.sh" chmod +x "$TARGET_DIR/setup-test-deps.sh" echo " ✓ Đã tạo $TARGET_DIR/setup-test-deps.sh" fi echo "🎉 Hoàn tất! Mở Claude Code và gõ: /laravel-unit-test --all --run" EOF chmod +x "$HOME/.local/bin/sg-test-init" cp "$HOME/.local/bin/sg-test-init" "$HOME/.local/bin/laravel-test-init" chmod +x "$HOME/.local/bin/laravel-test-init" echo -e "${GREEN}${BOLD}✓ CÀI ĐẶT TOÀN CỤC HOÀN TẤT THÀNH CÔNG!${NC}" echo -e "Kể từ bây giờ, ở bất kỳ source code nào, bạn mở Claude Code là có thể gõ ngay:" echo -e " • ${CYAN}/laravel-test-setup --install${NC}" echo -e " • ${CYAN}/laravel-unit-test --all --run${NC}" exit 0 fi # ============================================================================== # 3. XỬ LÝ CÀI ĐẶT TRỰC TIẾP VÀO SOURCE CODE HIỆN TẠI (PROJECT MODE - KHUYÊN DÙNG) # ============================================================================== TARGET_DIR="$(cd "$TARGET_DIR" 2>/dev/null && pwd || echo "$TARGET_DIR")" if [ ! -d "$TARGET_DIR" ]; then echo -e "${RED}Lỗi: Thư mục '$TARGET_DIR' không tồn tại!${NC}" exit 1 fi if [ ! -f "$TARGET_DIR/artisan" ] && [ ! -f "$TARGET_DIR/composer.json" ]; then # Kiểm tra xem thư mục có trống hoặc là thư mục mới không FILE_COUNT=$(ls -A "$TARGET_DIR" 2>/dev/null | wc -l | tr -d ' ') if [ "$FILE_COUNT" -le 2 ]; then echo -e "${YELLOW}ℹ Thư mục mới/trống: Tự động khởi tạo bộ công cụ Unit Test...${NC}" elif [ "$FORCE_MODE" = false ]; then echo -e "${YELLOW}⚠️ Cảnh báo: Thư mục '$TARGET_DIR' đang chứa dữ liệu khác và chưa có file artisan hoặc composer.json.${NC}" echo -e "Nếu bạn vẫn muốn cài đặt vào thư mục này, hãy chạy:" echo -e " ${CYAN}bash <(curl -fsSL /install.sh) --force${NC}" exit 1 fi fi echo -e "📦 Đang cài đặt công cụ vào source code: ${YELLOW}$TARGET_DIR${NC}" # A. Copy Claude Skills vào .claude/skills/ của source code mkdir -p "$TARGET_DIR/.claude/skills" cp -R "$PACKAGE_ROOT/.claude/skills/"* "$TARGET_DIR/.claude/skills/" echo -e " ${GREEN}✓${NC} Đã cài bộ 4 Claude Code Skills (.claude/skills/)" # B. Copy cẩm nang tài liệu vào .claude/testing-docs/ mkdir -p "$TARGET_DIR/.claude/testing-docs" cp -R "$PACKAGE_ROOT/docs/"* "$TARGET_DIR/.claude/testing-docs/" cp -R "$PACKAGE_ROOT/rules/"* "$TARGET_DIR/.claude/testing-docs/" echo -e " ${GREEN}✓${NC} Đã đồng bộ cẩm nang & rules kiểm thử (.claude/testing-docs/)" # C. Copy Test Runners vào root của source code cp "$PACKAGE_ROOT/templates/docker/test-runner.sh" "$TARGET_DIR/test-runner.sh" chmod +x "$TARGET_DIR/test-runner.sh" echo -e " ${GREEN}✓${NC} Đã tạo smart runner: ./test-runner.sh" cp "$PACKAGE_ROOT/templates/setup-dependencies.sh" "$TARGET_DIR/setup-test-deps.sh" chmod +x "$TARGET_DIR/setup-test-deps.sh" echo -e " ${GREEN}✓${NC} Đã tạo dependency installer: ./setup-test-deps.sh" # D. Tự động cấu hình SQLite In-Memory vào phpunit.xml PHPUNIT_XML="$TARGET_DIR/phpunit.xml" PHPUNIT_DIST="$TARGET_DIR/phpunit.xml.dist" TARGET_XML="" if [ -f "$PHPUNIT_XML" ]; then TARGET_XML="$PHPUNIT_XML" elif [ -f "$PHPUNIT_DIST" ]; then TARGET_XML="$PHPUNIT_DIST" fi if [ -n "$TARGET_XML" ]; then if ! grep -q 'name="DB_CONNECTION"' "$TARGET_XML" || ! grep -q 'value="sqlite"' "$TARGET_XML"; then if grep -q '' "$TARGET_XML"; then sed -i.bak '//a\ \ \ \ \ \ ' "$TARGET_XML" 2>/dev/null || true rm -f "$TARGET_XML.bak" 2>/dev/null || true echo -e " ${GREEN}✓${NC} Đã cấu hình SQLite in-memory (:memory:) an toàn vào phpunit.xml" fi else echo -e " ${GREEN}✓${NC} Cấu hình SQLite in-memory trong phpunit.xml đã chuẩn xác" fi fi # E. Tạo GitHub Actions CI workflow nếu có .git if [ -d "$TARGET_DIR/.git" ]; then mkdir -p "$TARGET_DIR/.github/workflows" if [ ! -f "$TARGET_DIR/.github/workflows/unit-tests.yml" ]; then cp "$PACKAGE_ROOT/templates/ci/github-actions.yml.template" "$TARGET_DIR/.github/workflows/unit-tests.yml" echo -e " ${GREEN}✓${NC} Đã tạo CI/CD Quality Gate (.github/workflows/unit-tests.yml)" fi fi echo -e "\n${GREEN}${BOLD}🎉 CÀI ĐẶT HOÀN TẤT THÀNH CÔNG VÀO SOURCE CODE!${NC}" echo -e "\n${YELLOW}${BOLD}BÂY GIỜ BẠN CÓ THỂ VIẾT UNIT TEST NGAY:${NC}" echo -e "1. Mở Claude Code tại source code này:" echo -e " ${CYAN}claude${NC}" echo -e "2. Gõ 1 lệnh duy nhất để AI viết test toàn bộ và tự chạy test luôn:" echo -e " ${CYAN}/laravel-unit-test --all --run${NC}" echo -e "3. Hoặc chạy test trực tiếp từ terminal:" echo -e " ${CYAN}./test-runner.sh${NC}"