From 188ebf853c2fb9ce36e2ccecae4cd179076a6fb7 Mon Sep 17 00:00:00 2001 From: ulflow_phattt2901 Date: Fri, 6 Jun 2025 12:49:18 +0700 Subject: [PATCH 1/4] fix:update feature-flag - enable database --- Makefile | 2 +- cmd/app/main.go | 56 ++++++++++----- configs/config.yaml | 4 +- docker-compose.yml | 48 +++---------- internal/helper/config/load.go | 1 + internal/transport/http/router.go | 109 +++++++++++++++++------------- 6 files changed, 114 insertions(+), 106 deletions(-) diff --git a/Makefile b/Makefile index 7d76af8..8ec1216 100644 --- a/Makefile +++ b/Makefile @@ -106,7 +106,7 @@ docker-compose-up: # Stop Docker Compose services for local development docker-compose-down: @echo "Stopping all development services..." - docker-compose down + docker-compose down -v # Run Docker Compose for production docker-compose-prod-up: diff --git a/cmd/app/main.go b/cmd/app/main.go index 25ce7a1..99dbc1b 100644 --- a/cmd/app/main.go +++ b/cmd/app/main.go @@ -24,10 +24,14 @@ type HTTPService struct { } func NewHTTPService(cfg *config.Config, db *database.Database) *HTTPService { + var gormDB *gorm.DB + if db != nil { + gormDB = db.DB + } return &HTTPService{ - server: http.NewServer(cfg, db.DB), + server: http.NewServer(cfg, gormDB), // gormDB can be nil here cfg: cfg, - db: db, + db: db, // db itself (the *database.Database wrapper) can also be nil } } @@ -108,26 +112,44 @@ func main() { } lifecycleMgr := lifecycle.New(shutdownTimeout) - // Initialize database connection - db, err := database.NewConnection(&cfg.Database) - if err != nil { - logger.WithError(err).Fatal("Failed to connect to database") + var gormDB *gorm.DB // Declare gormDB for database connection + var dbInstance *database.Database // Declare dbInstance for HTTPService and other potential users + + if feature.IsEnabled(feature.EnableDatabase) { + logger.Info("Feature flag 'enable_database' is true. Initializing database connection...") + // Initialize database connection + var dbErr error + gormDB, dbErr = database.NewConnection(&cfg.Database) + if dbErr != nil { + logger.WithError(dbErr).Fatal("Failed to connect to database") + } + + // Run database migrations + if err := database.Migrate(cfg.Database); err != nil { // Migrate still needs cfg.Database for path etc. + logger.WithError(err).Fatal("Failed to migrate database") + } + + // Register database cleanup on shutdown + lifecycleMgr.Register(&databaseService{db: gormDB}) + + // Prepare dbInstance for HTTPService + dbInstance = &database.Database{DB: gormDB, Config: &cfg.Database} + } else { + logger.Info("Feature flag 'enable_database' is false. Skipping database initialization.") + // gormDB remains nil + // dbInstance remains nil + // No databaseService is registered with lifecycleMgr if DB is disabled. } - // Run database migrations - if err := database.Migrate(cfg.Database); err != nil { - logger.WithError(err).Fatal("Failed to migrate database") - } - - // Register database cleanup on shutdown - lifecycleMgr.Register(&databaseService{db: db}) - - // Initialize HTTP service with database - httpService := NewHTTPService(cfg, &database.Database{DB: db}) + // Initialize HTTP service + // NewHTTPService and its chain (http.NewServer, http.SetupRouter) + // must be able to handle a nil dbInstance or a dbInstance with a nil DB. + // The NewHTTPService function already checks if its db argument (or db.DB) is nil. + httpService := NewHTTPService(cfg, dbInstance) // dbInstance can be nil here if httpService == nil { logger.Fatal("Failed to create HTTP service") } - lifecycleMgr.Register(httpService) + lifecycleMgr.Register(httpService) // HTTP service is always registered // Start all services logger.Info("Đang khởi động các dịch vụ...") diff --git a/configs/config.yaml b/configs/config.yaml index 1fca4c2..5143571 100644 --- a/configs/config.yaml +++ b/configs/config.yaml @@ -19,11 +19,11 @@ server: database: driver: "postgres" - host: "localhost" + host: "postgres" port: 5432 username: "postgres" password: "postgres" - database: "ulflow" + database: "ulflow_zee" ssl_mode: "disable" max_open_conns: 25 max_idle_conns: 5 diff --git a/docker-compose.yml b/docker-compose.yml index 071fbef..b180a2c 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -26,58 +26,30 @@ services: container_name: ulflow-postgres restart: unless-stopped environment: - POSTGRES_USER: ${DB_USER:-user} - POSTGRES_PASSWORD: ${DB_PASSWORD:-password} - POSTGRES_DB: ${DB_NAME:-ulflow_db} + POSTGRES_USER: postgres + POSTGRES_PASSWORD: Minhtuyen0605 + POSTGRES_DB: ulflow_zee ports: - "5432:5432" volumes: - postgres-data:/var/lib/postgresql/data networks: - ulflow-network - - # Gitea (Git Server, CI/CD, Registry) - gitea: - image: gitea/gitea:1.21 - container_name: ulflow-gitea + adminer: + image: adminer:latest # Hoặc adminer:4.8.1 (chọn phiên bản cụ thể nếu muốn) + container_name: ulflow-adminer restart: unless-stopped - environment: - - USER_UID=1000 - - USER_GID=1000 - - GITEA__database__DB_TYPE=postgres - - GITEA__database__HOST=postgres:5432 - - GITEA__database__NAME=gitea - - GITEA__database__USER=${DB_USER:-user} - - GITEA__database__PASSWD=${DB_PASSWORD:-password} ports: - - "3001:3000" - - "2222:22" - volumes: - - gitea-data:/data - - /etc/timezone:/etc/timezone:ro - - /etc/localtime:/etc/localtime:ro + - "8080:8080" # Ánh xạ cổng 8080 của container ra cổng 8080 của host + environment: + ADMINER_DEFAULT_SERVER: postgres # Tên service của PostgreSQL trong Docker Compose depends_on: - - postgres - networks: - - ulflow-network - - # Gitea Runner for CI/CD - gitea-runner: - image: gitea/act_runner:latest - container_name: ulflow-gitea-runner - restart: unless-stopped - volumes: - - /var/run/docker.sock:/var/run/docker.sock - - gitea-runner-data:/data - depends_on: - - gitea + - postgres # Đảm bảo postgres khởi động trước adminer networks: - ulflow-network volumes: postgres-data: - gitea-data: - gitea-runner-data: go-modules: networks: diff --git a/internal/helper/config/load.go b/internal/helper/config/load.go index 64eed47..bd352f5 100644 --- a/internal/helper/config/load.go +++ b/internal/helper/config/load.go @@ -107,6 +107,7 @@ func (l *ViperConfigLoader) loadEnvFile(v *viper.Viper) error { if err := os.Setenv(key, val); err != nil { return fmt.Errorf("failed to set environment variable %s: %w", key, err) } + fmt.Println("Loaded environment variable:", key, "=", val) } return nil diff --git a/internal/transport/http/router.go b/internal/transport/http/router.go index 64b1bf4..9faa30d 100644 --- a/internal/transport/http/router.go +++ b/internal/transport/http/router.go @@ -4,6 +4,7 @@ import ( "time" "zee/internal/adapter/postgres" "zee/internal/helper/config" + "zee/internal/helper/logger" // Added logger import "zee/internal/service" "zee/internal/transport/http/handler" "zee/internal/transport/http/middleware" @@ -31,60 +32,72 @@ func SetupRouter(cfg *config.Config, db *gorm.DB) *gin.Engine { securityCfg := middleware.DefaultSecurityConfig() securityCfg.Apply(router) - // Khởi tạo repositories - userRepo := postgres.NewUserRepository(db) - roleRepo := postgres.NewRoleRepository(db) - - // Get JWT configuration from config - jwtSecret := "your-secret-key" // Default fallback - accessTokenExpire := 24 * time.Hour - - // Override with config values if available - if cfg.JWT.Secret != "" { - jwtSecret = cfg.JWT.Secret - } - if cfg.JWT.AccessTokenExpire > 0 { - accessTokenExpire = time.Duration(cfg.JWT.AccessTokenExpire) * time.Minute - } - - // Khởi tạo services - authSvc := service.NewAuthService( - userRepo, - roleRepo, - jwtSecret, - accessTokenExpire, - ) - - // Khởi tạo middleware - authMiddleware := middleware.NewAuthMiddleware(authSvc) - _ = authMiddleware // TODO: Use authMiddleware when needed - - // Khởi tạo các handlers + // Khởi tạo các handlers không phụ thuộc DB healthHandler := handler.NewHealthHandler(cfg) - authHandler := handler.NewAuthHandler(authSvc) - // Đăng ký các routes - - // Health check routes (public) + // Đăng ký các routes không phụ thuộc DB router.GET("/ping", healthHandler.Ping) router.GET("/health", healthHandler.HealthCheck) - // Auth routes (public) - authGroup := router.Group("/api/v1/auth") - { - authGroup.POST("/register", authHandler.Register) - authGroup.POST("/login", authHandler.Login) - authGroup.POST("/refresh", authHandler.RefreshToken) - authGroup.POST("/logout", authMiddleware.Authenticate(), authHandler.Logout) - } + // Các thành phần và routes phụ thuộc vào DB + if db != nil { + logger.Info("Database connection is available. Initializing DB-dependent services and routes...") + // Khởi tạo repositories + userRepo := postgres.NewUserRepository(db) + roleRepo := postgres.NewRoleRepository(db) - // Protected API routes - api := router.Group("/api/v1") - api.Use(authMiddleware.Authenticate()) - { - // Ví dụ về protected endpoints - // api.GET("/profile", userHandler.GetProfile) - // api.PUT("/profile", userHandler.UpdateProfile) + // Get JWT configuration from config + jwtSecret := "your-secret-key" // Default fallback + accessTokenExpire := 24 * time.Hour + + // Override with config values if available + if cfg.JWT.Secret != "" { + jwtSecret = cfg.JWT.Secret + } + if cfg.JWT.AccessTokenExpire > 0 { + accessTokenExpire = time.Duration(cfg.JWT.AccessTokenExpire) * time.Minute + } + + // Khởi tạo services + authSvc := service.NewAuthService( + userRepo, + roleRepo, + jwtSecret, + accessTokenExpire, + ) + + // Khởi tạo middleware + authMiddleware := middleware.NewAuthMiddleware(authSvc) + + // Khởi tạo các handlers phụ thuộc DB + authHandler := handler.NewAuthHandler(authSvc) + + // Auth routes (public) + authGroup := router.Group("/api/v1/auth") + { + authGroup.POST("/register", authHandler.Register) + authGroup.POST("/login", authHandler.Login) + authGroup.POST("/refresh", authHandler.RefreshToken) + authGroup.POST("/logout", authMiddleware.Authenticate(), authHandler.Logout) + } + + // Protected API routes + api := router.Group("/api/v1") + api.Use(authMiddleware.Authenticate()) + { + // Ví dụ về protected endpoints + // api.GET("/profile", userHandler.GetProfile) + // api.PUT("/profile", userHandler.UpdateProfile) + } + } else { + logger.Info("Database is disabled via feature flag or connection failed. DB-dependent routes (e.g., /api/v1/auth, /api/v1/*) will not be available.") + // Optionally, register placeholder routes that return 503 Service Unavailable + // router.Any("/api/v1/auth/*any", func(c *gin.Context) { + // c.JSON(http.StatusServiceUnavailable, gin.H{"error": "Authentication service is currently disabled"}) + // }) + // router.Any("/api/v1/*any", func(c *gin.Context) { + // c.JSON(http.StatusServiceUnavailable, gin.H{"error": "API service is currently disabled due to database unavailability"}) + // }) } return router From 02c6a15607c8d1a7bc3d7243c61c586bd6c53ce5 Mon Sep 17 00:00:00 2001 From: ulflow_phattt2901 Date: Fri, 6 Jun 2025 12:50:35 +0700 Subject: [PATCH 2/4] fix: Makefile - setup-git-hooks --- .gitea/hooks/pre-commit | 5 ++++- Makefile | 2 -- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.gitea/hooks/pre-commit b/.gitea/hooks/pre-commit index f76814b..7b80874 100644 --- a/.gitea/hooks/pre-commit +++ b/.gitea/hooks/pre-commit @@ -3,7 +3,10 @@ # This hook runs linters and checks before allowing a commit echo "Running pre-commit checks..." - +echo "Current working directory: $(pwd)" +echo "Which golangci-lint: $(which golangci-lint)" +echo "golangci-lint version: $(golangci-lint version)" +cd "$PROJECT_ROOT" || exit 1 # Exit if cd fails # Check for staged Go files STAGED_GO_FILES=$(git diff --cached --name-only --diff-filter=ACM | grep "\.go$") diff --git a/Makefile b/Makefile index 8ec1216..1585fbe 100644 --- a/Makefile +++ b/Makefile @@ -133,9 +133,7 @@ setup-git-hooks: @echo Copying prepare-commit-msg hook... @copy /Y .gitea\hooks\prepare-commit-msg .git\hooks\prepare-commit-msg >nul || (echo Warning: Could not copy prepare-commit-msg hook & exit /b 1) - git config --local core.hooksPath .git/hooks @echo "Git setup complete!" - # Create git message template setup-git-message: @echo "Creating Git commit message template..." From f8957e0d957d28e4244ed28adb831c4fd61ce428 Mon Sep 17 00:00:00 2001 From: ulflow_phattt2901 Date: Fri, 6 Jun 2025 19:11:07 +0700 Subject: [PATCH 3/4] chore:update docker --- Dockerfile | 32 +++++------- Dockerfile.local => Dockerfile.dev | 0 Makefile | 12 ++++- cmd/app/main.go | 3 +- docker-compose.dev.yml | 59 +++++++++++++++++++++ docker-compose.prod.yml | 83 ------------------------------ docker-compose.yml | 52 +++++++------------ 7 files changed, 106 insertions(+), 135 deletions(-) rename Dockerfile.local => Dockerfile.dev (100%) create mode 100644 docker-compose.dev.yml delete mode 100644 docker-compose.prod.yml diff --git a/Dockerfile b/Dockerfile index eb4b5f0..7a5cd4f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,4 @@ -# syntax=docker/dockerfile:1.4 -# Production-ready multi-stage build for server deployment - +# Dockerfile # Build arguments ARG GO_VERSION=1.24.3 ARG ALPINE_VERSION=3.19 @@ -16,7 +14,7 @@ RUN apk add --no-cache git make gcc libc-dev # Set working directory WORKDIR /build -# Enable Go modules +# Enable Go modules and set build environment variables ENV GO111MODULE=on \ CGO_ENABLED=0 \ GOOS=linux \ @@ -25,37 +23,35 @@ ENV GO111MODULE=on \ # Copy dependency files first for better layer caching COPY go.mod go.sum ./ - -# Download dependencies +# Download dependencies using cache mount for efficiency RUN --mount=type=cache,target=/go/pkg/mod \ go mod download # Copy source code COPY . . +# Create the configs directory in the build context (if it exists) +RUN if test -d "configs"; then mkdir -p /build/configs && cp -r configs/* /build/configs/; fi -# Create the configs directory in the build context -RUN mkdir -p /build/configs && \ - cp -r configs/* /build/configs/ 2>/dev/null || : - -# Build the application with optimizations +# Build the application with optimizations and version info RUN --mount=type=cache,target=/root/.cache/go-build \ go build -ldflags="-w -s -X 'main.Version=$(git describe --tags --always 2>/dev/null || echo 'dev')'" \ - -o /build/bin/app ./cmd/app + -o /build/bin/app ./src/cmd/api # Update path to your main package # --- Final Stage --- FROM alpine:${ALPINE_VERSION} # Re-declare ARG to use in this stage -ARG APP_USER=appuser -ARG APP_GROUP=appgroup +ARG APP_USER +ARG APP_GROUP ARG APP_HOME=/app -# Set environment variables +# Set runtime environment variables ENV TZ=Asia/Ho_Chi_Minh \ APP_USER=${APP_USER} \ APP_GROUP=${APP_GROUP} \ - APP_HOME=${APP_HOME} + APP_HOME=${APP_HOME} \ + APP_ENV=production # Install runtime dependencies RUN apk add --no-cache \ @@ -68,7 +64,7 @@ RUN apk add --no-cache \ RUN addgroup -S ${APP_GROUP} && \ adduser -S -G ${APP_GROUP} -h ${APP_HOME} -D ${APP_USER} -# Create necessary directories +# Create necessary application directories RUN mkdir -p ${APP_HOME}/configs ${APP_HOME}/logs ${APP_HOME}/storage # Switch to app directory @@ -99,4 +95,4 @@ EXPOSE 3000 ENV APP_ENV=production # Command to run the application -ENTRYPOINT ["/sbin/tini", "--"] +ENTRYPOINT ["/sbin/tini", "--"] \ No newline at end of file diff --git a/Dockerfile.local b/Dockerfile.dev similarity index 100% rename from Dockerfile.local rename to Dockerfile.dev diff --git a/Makefile b/Makefile index 1585fbe..00934c4 100644 --- a/Makefile +++ b/Makefile @@ -86,7 +86,10 @@ clean: docker-build: @echo "Building Docker image..." docker build -t ulflow-zee:latest . - +# Build Docker image for development +docker-build-dev: + @echo "Building Docker image for development..." + docker-compose -f docker-compose.dev.yml up --build # Run application in Docker container docker-run: @echo "Running application in Docker container..." @@ -97,6 +100,13 @@ docker-run: docker run -p 3000:3000 --env-file .env ulflow-zee:latest ) +docker-up-dev: + @echo "Starting all services with Docker Compose for local development..." + docker-compose -f docker-compose.dev.yml up + +docker-down-dev: + @echo "Stopping all development services..." + docker-compose -f docker-compose.dev.yml down -v # Run Docker Compose for local development docker-compose-up: @echo "Starting all services with Docker Compose for local development..." diff --git a/cmd/app/main.go b/cmd/app/main.go index 99dbc1b..faca0a6 100644 --- a/cmd/app/main.go +++ b/cmd/app/main.go @@ -70,6 +70,7 @@ func (s *HTTPService) Shutdown(ctx context.Context) error { } func main() { + fmt.Println("Starting application 222...") // Initialize config loader configLoader := config.NewConfigLoader() @@ -112,7 +113,7 @@ func main() { } lifecycleMgr := lifecycle.New(shutdownTimeout) - var gormDB *gorm.DB // Declare gormDB for database connection + var gormDB *gorm.DB // Declare gormDB for database connection var dbInstance *database.Database // Declare dbInstance for HTTPService and other potential users if feature.IsEnabled(feature.EnableDatabase) { diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml new file mode 100644 index 0000000..5391f72 --- /dev/null +++ b/docker-compose.dev.yml @@ -0,0 +1,59 @@ +# docker-compose.dev.yml (Cho Local Development) +version: '3.8' + +services: + api: + build: + context: . + dockerfile: Dockerfile.dev # Sử dụng Dockerfile.dev + container_name: ulflow-api-dev + ports: + - "3000:3000" + volumes: + - .:/app # Bind mount code cho hot reload + - go-modules:/go/pkg/mod + command: air # Chạy công cụ hot reload + env_file: + - ./.env # Load biến môi trường từ file .env + depends_on: + - postgres + networks: + - ulflow-network + restart: "no" # Không tự động restart trong dev + + postgres: + image: postgres:15-alpine + container_name: ulflow-postgres-dev + restart: unless-stopped + environment: + # Lấy biến từ file .env + POSTGRES_USER: ${DATABASE_USERNAME} + POSTGRES_PASSWORD: ${DATABASE_PASSWORD} + POSTGRES_DB: ${DATABASE_NAME} + ports: + - "5432:5432" # Để truy cập từ host nếu muốn + volumes: + - postgres-dev-data:/var/lib/postgresql/data # Volume riêng cho dev DB + networks: + - ulflow-network + + adminer: # Adminer cũng nên có trong dev để quản lý DB dễ dàng + image: adminer:latest + container_name: ulflow-adminer-dev + restart: unless-stopped + ports: + - "8080:8080" + environment: + ADMINER_DEFAULT_SERVER: postgres # Tên service của postgres trong compose này + depends_on: + - postgres + networks: + - ulflow-network + +volumes: + postgres-dev-data: # Volume riêng cho dev DB + go-modules: # Volume để cache Go modules cho dev + +networks: + ulflow-network: + driver: bridge \ No newline at end of file diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml deleted file mode 100644 index 0364810..0000000 --- a/docker-compose.prod.yml +++ /dev/null @@ -1,83 +0,0 @@ -version: '3.8' - -services: - # API Service - Production Configuration - api: - build: - context: . - dockerfile: Dockerfile - container_name: ulflow-api - restart: always - ports: - - "3000:3000" - env_file: - - .env - environment: - - APP_ENV=production - depends_on: - - postgres - networks: - - ulflow-network - deploy: - resources: - limits: - cpus: '1' - memory: 1G - restart_policy: - condition: on-failure - max_attempts: 3 - healthcheck: - test: ["CMD", "wget", "--spider", "-q", "http://localhost:3000/health"] - interval: 30s - timeout: 10s - retries: 3 - start_period: 40s - - # PostgreSQL Database - Production Configuration - postgres: - image: postgres:15-alpine - container_name: ulflow-postgres - restart: always - environment: - POSTGRES_USER: ${DB_USER:-user} - POSTGRES_PASSWORD: ${DB_PASSWORD:-password} - POSTGRES_DB: ${DB_NAME:-ulflow_db} - volumes: - - postgres-data:/var/lib/postgresql/data - networks: - - ulflow-network - deploy: - resources: - limits: - cpus: '1' - memory: 1G - healthcheck: - test: ["CMD-SHELL", "pg_isready -U ${DB_USER:-user} -d ${DB_NAME:-ulflow_db}"] - interval: 30s - timeout: 5s - retries: 3 - start_period: 10s - - # Nginx Reverse Proxy - nginx: - image: nginx:alpine - container_name: ulflow-nginx - restart: always - ports: - - "80:80" - - "443:443" - volumes: - - ./nginx/conf.d:/etc/nginx/conf.d - - ./nginx/ssl:/etc/nginx/ssl - - ./nginx/logs:/var/log/nginx - depends_on: - - api - networks: - - ulflow-network - -volumes: - postgres-data: - -networks: - ulflow-network: - driver: bridge diff --git a/docker-compose.yml b/docker-compose.yml index b180a2c..73660b5 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,57 +1,45 @@ +# docker-compose.prod.yml (Cho Production / CI/CD) version: '3.8' services: - # API Service api: build: context: . - dockerfile: Dockerfile.local - container_name: ulflow-api - restart: unless-stopped + dockerfile: Dockerfile # Sử dụng Dockerfile production + container_name: ulflow-api-prod ports: - "3000:3000" - volumes: - - .:/app - - go-modules:/go/pkg/mod - env_file: - - .env + # KHÔNG CÓ VOLUMES: - .:/app ở đây! + command: /app/app # Chạy binary đã build + # KHÔNG CÓ ENV_FILE Ở ĐÂY, BIẾN MÔI TRƯỜNG SẼ ĐƯỢC CUNG CẤP TỪ BÊN NGOÀI + restart: always + deploy: + resources: + limits: + cpus: '0.50' + memory: 256M depends_on: - postgres networks: - ulflow-network - # PostgreSQL Database postgres: image: postgres:15-alpine - container_name: ulflow-postgres + container_name: ulflow-postgres-prod restart: unless-stopped environment: - POSTGRES_USER: postgres - POSTGRES_PASSWORD: Minhtuyen0605 - POSTGRES_DB: ulflow_zee + POSTGRES_USER: ${DATABASE_USERNAME} + POSTGRES_PASSWORD: ${DATABASE_PASSWORD} + POSTGRES_DB: ${DATABASE_NAME} ports: - - "5432:5432" + - "5433:5432" volumes: - - postgres-data:/var/lib/postgresql/data + - postgres-prod-data:/var/lib/postgresql/data # Volume riêng cho prod DB networks: - ulflow-network - adminer: - image: adminer:latest # Hoặc adminer:4.8.1 (chọn phiên bản cụ thể nếu muốn) - container_name: ulflow-adminer - restart: unless-stopped - ports: - - "8080:8080" # Ánh xạ cổng 8080 của container ra cổng 8080 của host - environment: - ADMINER_DEFAULT_SERVER: postgres # Tên service của PostgreSQL trong Docker Compose - depends_on: - - postgres # Đảm bảo postgres khởi động trước adminer - networks: - - ulflow-network - volumes: - postgres-data: - go-modules: + postgres-prod-data: networks: ulflow-network: - driver: bridge + driver: bridge \ No newline at end of file From c272b9844f64f042b719f2ffc30187a048040cdf Mon Sep 17 00:00:00 2001 From: ulflow_phattt2901 Date: Fri, 6 Jun 2025 19:46:04 +0700 Subject: [PATCH 4/4] chore: update ci.yml --- .gitea/workflows/ci.yml | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/.gitea/workflows/ci.yml b/.gitea/workflows/ci.yml index 5a893f1..64ec39b 100644 --- a/.gitea/workflows/ci.yml +++ b/.gitea/workflows/ci.yml @@ -18,12 +18,18 @@ jobs: with: go-version: '1.24.3' cache-dependency-path: go.sum - + - name: Cache golangci-lint + uses: actions/cache@v4 + with: + path: ~/.cache/golangci-lint + key: ${{ runner.os }}-golangci-lint-${{ hashFiles('**/go.sum') }} + restore-keys: | + ${{ runner.os }}-golangci-lint- - name: Lint uses: golangci/golangci-lint-action@v6 with: version: latest - args: --timeout=5m + args: --timeout=15m - name: Notify on failure if: failure()