Files
agent-unit-testing/install.sh
T
Pham-Tan-Thien c8edce44ea fix: auto-install in empty or new directories without requiring --force
- Allow seamless 1-line curl installation in empty or newly created test folders
- Prevent early exit when target directory has 2 or fewer files
- Fix argument parsing for target directory and flags

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-08 09:17:38 +07:00

255 lines
11 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/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/<OWNER>/agent-unit-testing/main/install.sh | bash
# Hoặc:
# bash <(curl -fsSL https://raw.githubusercontent.com/<OWNER>/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/<OWNER>/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 <URL>/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 <URL>/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 <URL>/install.sh | bash -s -- --global${NC}"
echo -e " 4. Cài đặt vào thư mục trống:"
echo -e " ${YELLOW}curl -fsSL <URL>/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/<OWNER>/<REPO>.git curl -fsSL <URL>/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 <URL>/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 '<php>' "$TARGET_XML"; then
sed -i.bak '/<php>/a\
<env name="DB_CONNECTION" value="sqlite"/>\
<env name="DB_DATABASE" value=":memory:"/>\
<env name="BCRYPT_ROUNDS" value="4"/>\
<env name="CACHE_STORE" value="array"/>\
<env name="QUEUE_CONNECTION" value="sync"/>\
<env name="MAIL_MAILER" value="array"/>
' "$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}"