From b6d97f8a739d76b37bf0df9c7d60ab7a39cbc947 Mon Sep 17 00:00:00 2001 From: shop Date: Sat, 16 May 2026 17:38:35 +0300 Subject: [PATCH] =?UTF-8?q?fix:=20check.sh=20=E2=80=94=20=D0=BD=D0=B5=20?= =?UTF-8?q?=D0=BF=D0=B0=D0=B4=D0=B0=D1=82=D1=8C=20=D0=B4=D0=BE=20docker=20?= =?UTF-8?q?compose,=20=D0=BF=D1=80=D0=BE=D0=B2=D0=B5=D1=80=D0=BA=D0=B0=20?= =?UTF-8?q?=D0=BF=D0=BE=D1=81=D0=BB=D0=B5=20=D1=81=D1=82=D0=B0=D1=80=D1=82?= =?UTF-8?q?=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Cursor --- README.md | 10 ++--- check.ps1 | 15 ++++++- check.sh | 69 ++++++++++++++++++++++++++++--- cmd/check/main.go | 90 ++++++++++++++++++++++++++++++----------- install.sh | 0 internal/setup/setup.go | 3 +- 6 files changed, 151 insertions(+), 36 deletions(-) mode change 100644 => 100755 check.sh mode change 100644 => 100755 install.sh diff --git a/README.md b/README.md index 98bc694..33116b4 100644 --- a/README.md +++ b/README.md @@ -25,17 +25,17 @@ cd shop3 chmod +x install.sh check.sh ./install.sh -# 3. Проверка версий -./check.sh - -# 4. Запуск +# 3. Запуск docker compose up --build -d + +# 4. Проверка (после старта контейнеров) +./check.sh --after-start ``` Одной цепочкой (после клона введите ответы установщика): ```bash -git clone https://git.evilfox.cc/test/shop3.git && cd shop3 && chmod +x install.sh check.sh && ./install.sh && ./check.sh && docker compose up --build -d +git clone https://git.evilfox.cc/test/shop3.git && cd shop3 && chmod +x install.sh check.sh && ./install.sh && docker compose up --build -d && ./check.sh --after-start ``` С Go на сервере вместо `install.sh`: diff --git a/check.ps1 b/check.ps1 index 8be1d6b..d384887 100644 --- a/check.ps1 +++ b/check.ps1 @@ -1,4 +1,15 @@ -# Проверка версий: Go, Docker, PostgreSQL +# Проверка версий (до или после docker compose) +param([switch]$AfterStart) + $ErrorActionPreference = "Stop" Set-Location $PSScriptRoot -go run ./cmd/check + +if ($AfterStart) { + & "$PSScriptRoot\check.sh" --after-start +} else { + & bash "$PSScriptRoot\check.sh" 2>$null + if ($LASTEXITCODE -ne 0) { + $env:CHECK_SKIP_DB = "1" + go run ./cmd/check + } +} diff --git a/check.sh b/check.sh old mode 100644 new mode 100755 index 794f77e..4d2b039 --- a/check.sh +++ b/check.sh @@ -1,8 +1,67 @@ #!/bin/sh set -e cd "$(dirname "$0")" -if command -v go >/dev/null 2>&1; then - go run ./cmd/check -else - docker run --rm -v "$(pwd):/app" -w /app golang:1.22-alpine go run ./cmd/check -fi + +MODE="${1:-pre}" + +host_docker_check() { + if command -v docker >/dev/null 2>&1; then + if docker version >/dev/null 2>&1; then + echo " ✓ docker: $(docker version --format '{{.Server.Version}}' 2>/dev/null || docker --version)" + else + echo " ! docker: установлен, но демон недоступен (запустите docker)" + fi + if docker compose version >/dev/null 2>&1; then + echo " ✓ docker_compose: $(docker compose version --short 2>/dev/null || docker compose version)" + else + echo " ! docker_compose: не найден" + fi + else + echo " ! docker: не найден на хосте" + echo " ! docker_compose: не найден на хосте" + fi +} + +run_go_check() { + if command -v go >/dev/null 2>&1; then + CHECK_HOST_TOOLS=1 "$@" go run ./cmd/check + else + CHECK_HOST_TOOLS=0 "$@" docker run --rm -v "$(pwd):/app" -w /app golang:1.22-alpine go run ./cmd/check + fi +} + +post_start_check() { + echo "=== Проверка после запуска ===" + host_docker_check + echo "" + if docker compose ps 2>/dev/null | grep -qE 'shop-app|running'; then + if docker compose exec -T app wget -qO- http://127.0.0.1:8080/health 2>/dev/null; then + echo "" + echo " ✓ app /health: OK" + fi + elif command -v curl >/dev/null 2>&1; then + if curl -sf "http://127.0.0.1:${HTTP_PORT:-80}/health" 2>/dev/null; then + echo "" + echo " ✓ /health: OK" + else + echo " ✗ /health: сервис не отвечает — проверьте: docker compose ps" + exit 1 + fi + fi + CHECK_SKIP_DB=0 CHECK_HOST_TOOLS=1 run_go_check +} + +case "$MODE" in + --after-start|post) + post_start_check + ;; + *) + echo "=== Проверка перед запуском (БД будет проверена после docker compose) ===" + host_docker_check + echo "" + CHECK_SKIP_DB=1 run_go_check + echo "" + echo "Далее: docker compose up --build -d" + echo "Затем: ./check.sh --after-start" + ;; +esac diff --git a/cmd/check/main.go b/cmd/check/main.go index cdabf09..7a4e4b2 100644 --- a/cmd/check/main.go +++ b/cmd/check/main.go @@ -4,8 +4,10 @@ import ( "context" "encoding/json" "fmt" + "net/url" "os" "path/filepath" + "strings" "github.com/jackc/pgx/v5/pgxpool" @@ -15,38 +17,30 @@ import ( func main() { loadDotEnv() + skipDB := os.Getenv("CHECK_SKIP_DB") == "1" + hostTools := os.Getenv("CHECK_HOST_TOOLS") != "0" + ctx := context.Background() report := check.AppInfo() - report.Items = append(report.Items, check.ToolVersions(ctx)...) + if hostTools { + report.Items = append(report.Items, check.ToolVersions(ctx)...) + } dbURL := os.Getenv("DATABASE_URL") - if dbURL == "" { + if skipDB { report.Items = append(report.Items, check.Item{ Name: "database", Status: check.StatusWarn, - Detail: "DATABASE_URL не задан — запустите: go run ./cmd/install", + Detail: "проверка отложена — сначала выполните: docker compose up -d, затем ./check.sh --after-start", + }) + } else if dbURL == "" { + report.Items = append(report.Items, check.Item{ + Name: "database", + Status: check.StatusWarn, + Detail: "DATABASE_URL не задан — запустите: ./install.sh", }) } else { - pool, err := pgxpool.New(ctx, dbURL) - if err != nil { - report.Items = append(report.Items, check.Item{ - Name: "database", - Status: check.StatusError, - Detail: err.Error(), - }) - } else { - defer pool.Close() - dbItems, err := check.Database(ctx, pool) - if err != nil { - report.Items = append(report.Items, check.Item{ - Name: "database", - Status: check.StatusError, - Detail: err.Error(), - }) - } else { - report.Items = append(report.Items, dbItems...) - } - } + appendDBChecks(ctx, &report, dbURL) } enc := json.NewEncoder(os.Stdout) @@ -61,6 +55,56 @@ func main() { } } +func appendDBChecks(ctx context.Context, report *check.Report, dbURL string) { + pool, err := pgxpool.New(ctx, dbURL) + if err != nil { + report.Items = append(report.Items, dbCheckItem(err, dbURL)) + return + } + defer pool.Close() + + dbItems, err := check.Database(ctx, pool) + if err != nil { + report.Items = append(report.Items, check.Item{ + Name: "database", + Status: dbCheckStatus(err, dbURL), + Detail: err.Error(), + }) + return + } + report.Items = append(report.Items, dbItems...) +} + +func dbCheckItem(err error, dbURL string) check.Item { + return check.Item{ + Name: "database", + Status: dbCheckStatus(err, dbURL), + Detail: err.Error(), + } +} + +func dbCheckStatus(err error, dbURL string) check.Status { + if err == nil { + return check.StatusOK + } + msg := strings.ToLower(err.Error()) + if isDockerInternalHost(dbURL) && (strings.Contains(msg, "no such host") || + strings.Contains(msg, "name or service not known") || + strings.Contains(msg, "hostname resolving")) { + return check.StatusWarn + } + return check.StatusError +} + +func isDockerInternalHost(dbURL string) bool { + u, err := url.Parse(dbURL) + if err != nil { + return false + } + host := u.Hostname() + return host == "postgres" || host == "db" || host == "shop-postgres" +} + func printSummary(r check.Report) { fmt.Printf("ShopNova %s | %s\n\n", r.AppVersion, r.GoVersion) for _, it := range r.Items { diff --git a/install.sh b/install.sh old mode 100644 new mode 100755 diff --git a/internal/setup/setup.go b/internal/setup/setup.go index 79b250b..749dee3 100644 --- a/internal/setup/setup.go +++ b/internal/setup/setup.go @@ -59,8 +59,9 @@ func RunInteractive(root string) (Config, error) { } fmt.Println("\n✓ Созданы файлы: .env, caddy/Caddyfile") - fmt.Println("\nДальше:") + fmt.Println("\nДальше (на сервере):") fmt.Println(" docker compose up --build -d") + fmt.Println(" ./check.sh --after-start") if !useLocalDomain(cfg.SiteDomain) { fmt.Printf(" Сайт: https://%s\n", cfg.SiteDomain) } else {