diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml deleted file mode 100644 index 60670feb..00000000 --- a/.github/workflows/ci.yml +++ /dev/null @@ -1,256 +0,0 @@ -name: GoChat CI/CD Pipeline -# Reference: Chatwoot uses CircleCI for CI/CD; this is the Go equivalent using GitHub Actions -# Multi-stage pipeline: test → build → security → deploy - -on: - push: - branches: [main, develop, 'release/**'] - pull_request: - branches: [main] - -env: - REGISTRY: ghcr.io - IMAGE_NAME: gochat/gochat - SHANGWUTONG_IMAGE_NAME: gochat/shangwutong - GOPROXY: https://goproxy.cn,direct - -jobs: - # ---- Stage 1: Lint + Test ---- - test: - name: Test & Lint - runs-on: ubuntu-latest - strategy: - matrix: - db-mode: [postgres, sqlite] - services: - postgres: - image: pgvector/pgvector:pg16 - env: - POSTGRES_DB: gochat_test - POSTGRES_USER: postgres - POSTGRES_PASSWORD: postgres - ports: - - 5432:5432 - options: >- - --health-cmd pg_isready - --health-interval 10s - --health-timeout 5s - --health-retries 5 - redis: - image: redis:7-alpine - ports: - - 6379:6379 - options: >- - --health-cmd "redis-cli ping" - --health-interval 10s - --health-timeout 5s - --health-retries 5 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-go@v5 - with: - go-version: '1.25.13' - cache-dependency-path: backend/go.sum - - - name: Download Go modules - working-directory: backend - run: go mod download - - # Lint - - name: Run golangci-lint - uses: golangci/golangci-lint-action@v6 - with: - version: v1.64 - install-mode: goinstall - args: --timeout=5m - working-directory: backend - - # Vet - - name: Run go vet - working-directory: backend - run: go vet ./... - - # Unit + Integration Tests - - name: Run unit & integration tests - working-directory: backend - env: - GOCHAT_ENV: test - GOCHAT_TEST_DB: ${{ matrix.db-mode }} - GOCHAT_DATABASE_DSN: postgres://postgres:postgres@localhost:5432/gochat_test?sslmode=disable - GOCHAT_REDIS_DSN: redis://localhost:6379 - GOPROXY: https://goproxy.cn,direct - run: go test -v -race -coverprofile=coverage.out -timeout 180s ./internal/... ./pkg/... ./cmd/... - - # E2E Tests (only on postgres matrix) - - name: Run e2e tests - if: matrix.db-mode == 'postgres' - working-directory: backend - env: - GOCHAT_ENV: test - GOCHAT_DATABASE_DSN: postgres://postgres:postgres@localhost:5432/gochat_test?sslmode=disable - GOCHAT_REDIS_DSN: redis://localhost:6379 - run: go test -v -timeout 120s ./tests/e2e/... - - # Benchmark (quick sanity check, not full bench) - - name: Run benchmarks - working-directory: backend - env: - GOCHAT_ENV: test - GOCHAT_TEST_DB: ${{ matrix.db-mode }} - GOCHAT_DATABASE_DSN: postgres://postgres:postgres@localhost:5432/gochat_test?sslmode=disable - run: go test -bench=. -benchtime=1s -run=^$ -timeout 60s ./internal/service/... ./pkg/crypto/... - - # Coverage report - - name: Upload coverage - if: matrix.db-mode == 'postgres' - uses: codecov/codecov-action@v4 - with: - files: backend/coverage.out - - shangwutong: - name: Shangwutong Connector - runs-on: ubuntu-latest - defaults: - run: - working-directory: channels/shangwutong - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-go@v5 - with: - go-version: '1.26.6' - cache-dependency-path: channels/shangwutong/go.sum - - name: Verify sqlc generation - run: go tool sqlc generate && git diff --exit-code -- db/generated - - name: Test with race detector - run: go test -race ./... - - name: Vet and build - run: go vet ./... && go build -o /tmp/shangwutong-build-check ./cmd/shangwutong - - # ---- Stage 2: Security Scan ---- - security: - name: Security Scan - needs: [test, shangwutong] - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-go@v5 - with: - go-version: '1.25.13' - - # Gosec — Go security scanner - - name: Run gosec - working-directory: backend - run: go run github.com/securego/gosec/v2/cmd/gosec@v2.28.0 -no-fail ./... - - # Dependency vulnerability scan - - name: Run govulncheck - working-directory: backend - run: go install golang.org/x/vuln/cmd/govulncheck@latest && govulncheck ./... - - # Trivy filesystem scan - - name: Run Trivy vulnerability scanner - uses: aquasecurity/trivy-action@master - with: - scan-type: 'fs' - scan-ref: '.' - format: 'table' - exit-code: '1' - severity: 'CRITICAL,HIGH' - - # ---- Stage 3: Build Docker Image ---- - build: - name: Build Docker Image - needs: [test, shangwutong, security] - runs-on: ubuntu-latest - if: github.event_name == 'push' # Only build on push, not PRs - permissions: - contents: read - packages: write - outputs: - image_tag: ${{ steps.meta.outputs.tags }} - image_digest: ${{ steps.build.outputs.digest }} - steps: - - uses: actions/checkout@v4 - - # Set up Docker Buildx for multi-platform builds - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - # Login to GHCR - - name: Login to GHCR - uses: docker/login-action@v3 - with: - registry: ${{ env.REGISTRY }} - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - # Extract metadata (tags, labels) - - name: Extract metadata - id: meta - uses: docker/metadata-action@v5 - with: - images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} - tags: | - type=ref,event=branch - type=ref,event=pr - type=semver,pattern={{version}} - type=semver,pattern={{major}}.{{minor}} - type=sha - - # Build and push main GoChat image - - name: Build and push GoChat image - id: build - uses: docker/build-push-action@v5 - with: - context: . - file: ./deploy/docker/Dockerfile - push: true - tags: ${{ steps.meta.outputs.tags }} - labels: ${{ steps.meta.outputs.labels }} - build-args: | - VERSION=${{ github.ref_name }} - COMMIT_SHA=${{ github.sha }} - BUILD_DATE=${{ github.event.head_commit.timestamp }} - cache-from: type=gha,scope=gochat - cache-to: type=gha,mode=max,scope=gochat - - - name: Extract Shangwutong connector metadata - id: shangwutong_meta - uses: docker/metadata-action@v5 - with: - images: ${{ env.REGISTRY }}/${{ env.SHANGWUTONG_IMAGE_NAME }} - tags: | - type=ref,event=branch - type=ref,event=pr - type=semver,pattern={{version}} - type=semver,pattern={{major}}.{{minor}} - type=sha - - - name: Build and push Shangwutong connector image - id: shangwutong_build - uses: docker/build-push-action@v5 - with: - context: . - file: ./channels/shangwutong/Dockerfile - push: true - tags: ${{ steps.shangwutong_meta.outputs.tags }} - labels: ${{ steps.shangwutong_meta.outputs.labels }} - cache-from: type=gha,scope=shangwutong - cache-to: type=gha,mode=max,scope=shangwutong - - # Scan Docker images with Trivy - - name: Scan GoChat image - uses: aquasecurity/trivy-action@master - with: - image-ref: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@${{ steps.build.outputs.digest }} - format: 'table' - exit-code: '1' - severity: 'CRITICAL,HIGH' - - - name: Scan Shangwutong connector image - uses: aquasecurity/trivy-action@master - with: - image-ref: ${{ env.REGISTRY }}/${{ env.SHANGWUTONG_IMAGE_NAME }}@${{ steps.shangwutong_build.outputs.digest }} - format: 'table' - exit-code: '1' - severity: 'CRITICAL,HIGH' diff --git a/AGENTS.md b/AGENTS.md index 319e1b81..9fdb3d92 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -71,8 +71,7 @@ GOCHAT_TEST_DB=sqlite go test ./internal/... ./pkg/... ./cmd/... # no PG needed go test -v -race ./... # with race detector go test -v ./tests/e2e/... # e2e -# Lint -golangci-lint run ./... +# Static analysis go vet ./... ``` @@ -88,7 +87,7 @@ make docker ## Go Version & Tooling -- **Go**: 1.24+ (go.mod declares 1.24.0; CI uses 1.25). Toolchain: go1.24.4. +- **Go**: 1.24+ (go.mod declares 1.24.0). Toolchain: go1.24.4. - **HTTP**: Gin v1.10 - **ORM**: GORM v2 - **DB**: PostgreSQL 16 + pgvector (SQLite supported for tests via `GOCHAT_TEST_DB=sqlite`) @@ -114,7 +113,6 @@ make docker - The production `Dockerfile` (in `deploy/docker/`) uses repo root as build context and `COPY backend/` for sources. When adding files the image needs, place them under `backend/` or update the COPY directives. - `docker-compose*.yml` files in `deploy/docker/` use `context: ../..` (repo root) and `dockerfile: deploy/docker/Dockerfile`. -- CI (`.github/workflows/ci.yml`) runs Go commands with `working-directory: backend` and builds the Docker image with `file: ./deploy/docker/Dockerfile`. ## Frontend (Chatwoot Vue 3 — decoupled) diff --git a/README.md b/README.md index 7d05d3fd..3592785b 100644 --- a/README.md +++ b/README.md @@ -165,7 +165,6 @@ GoChat 使用 **Viper 多环境叠加**机制: | 单元测试 | Go test + testify | Service/Repository/Model/Auth/Config | | 集成测试 | Go test + GORM | Service↔Repository↔DB | | E2E测试 | httptest + Gin | Handler↔Service↔DB 全链路 | -| 安全测试 | golangci-lint + gosec + govulncheck | 代码安全扫描 | | 性能测试 | Go benchmark | Service/crypto基准 | | DB双模式 | PG + SQLite | `GOCHAT_TEST_DB` 自动切换 | @@ -183,16 +182,6 @@ PG-only功能(vector搜索等)使用 `skipIfSQLite` 自动跳过。 详见 [SECURITY_AUDIT_REPORT.md](docs/SECURITY_AUDIT_REPORT.md) -## CI/CD - -GitHub Actions 3阶段流水线: - -1. **Test & Lint**: lint + vet + 单元/集成/e2e/benchmark(PG+SQLite矩阵) -2. **Security Scan**: gosec + govulncheck + Trivy -3. **Build**: Docker多平台镜像 + GHCR推送 - -详见 [.github/workflows/ci.yml](.github/workflows/ci.yml) - ## 技术栈 | 组件 | 技术 | diff --git a/backend/Makefile b/backend/Makefile index f3eec021..ae0e5c81 100644 --- a/backend/Makefile +++ b/backend/Makefile @@ -9,7 +9,7 @@ LDFLAGS := -s -w BUILD_DIR := ./bin # Targets -.PHONY: all setup build run dev test lint clean docker db_create db_migrate db_seed db_reset migrate help +.PHONY: all setup build run dev test clean docker db_create db_migrate db_seed db_reset migrate help all: build @@ -39,10 +39,6 @@ test-cover: go test -v -race -coverprofile=coverage.out ./... go tool cover -html=coverage.out -o coverage.html -## lint: Run golangci-lint -lint: - golangci-lint run ./... - ## clean: Remove build artifacts clean: rm -rf $(BUILD_DIR)