diff --git a/.gitea/workflows/ci.yml b/.gitea/workflows/ci.yml index 13e683b..bef2171 100644 --- a/.gitea/workflows/ci.yml +++ b/.gitea/workflows/ci.yml @@ -1,136 +1,53 @@ name: CI/CD on: - pull_request: push: branches: - main - master concurrency: - group: ci-${{ gitea.workflow }}-${{ gitea.ref }} + group: deploy-${{ gitea.ref }} cancel-in-progress: true jobs: - backend: - name: Backend - runs-on: ubuntu-latest - defaults: - run: - working-directory: backend + deploy: + name: Deploy + runs-on: aliyun steps: - name: Checkout uses: actions/checkout@v4 - - name: Setup Go - uses: actions/setup-go@v5 - with: - go-version: "1.24.x" - cache-dependency-path: backend/go.sum - - - name: Download dependencies - run: go mod download + # -- Backend: vet + test -- + - name: Install Go + run: | + sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories + apk add --no-cache go - name: Vet + working-directory: backend run: go vet ./... - name: Test + working-directory: backend run: go test -race -count=1 ./... - frontend: - name: Frontend - runs-on: ubuntu-latest - defaults: - run: + # -- Frontend: install + build -- + - name: Install Node + run: apk add --no-cache nodejs npm + + - name: Build Frontend working-directory: frontend - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Setup Node - uses: actions/setup-node@v4 - with: - node-version: "22" - cache: npm - cache-dependency-path: frontend/package-lock.json - - - name: Install dependencies - run: npm ci - - - name: Build - run: npm run build - - build-and-push: - name: Build & Push - runs-on: ubuntu-latest - needs: [backend, frontend] - if: ${{ gitea.ref == 'refs/heads/main' || gitea.ref == 'refs/heads/master' }} - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Login to Gitea Container Registry run: | - REGISTRY_HOST=$(echo "${{ gitea.server_url }}" | sed 's|https\?://||') - echo "${{ secrets.REGISTRY_PASSWORD }}" | docker login "$REGISTRY_HOST" -u "${{ secrets.REGISTRY_USER }}" --password-stdin + npm ci + npm run build - - name: Build & Push Backend API + # -- Deploy -- + - name: Deploy run: | - REGISTRY_HOST=$(echo "${{ gitea.server_url }}" | sed 's|https\?://||') - REPO="${{ gitea.repository }}" - docker build -f backend/Dockerfile --target api \ - -t "$REGISTRY_HOST/$REPO/backend-api:${{ gitea.sha }}" \ - -t "$REGISTRY_HOST/$REPO/backend-api:latest" \ - . - docker push "$REGISTRY_HOST/$REPO/backend-api" --all-tags - - - name: Build & Push Backend Worker - run: | - REGISTRY_HOST=$(echo "${{ gitea.server_url }}" | sed 's|https\?://||') - REPO="${{ gitea.repository }}" - docker build -f backend/Dockerfile --target worker \ - -t "$REGISTRY_HOST/$REPO/backend-worker:${{ gitea.sha }}" \ - -t "$REGISTRY_HOST/$REPO/backend-worker:latest" \ - . - docker push "$REGISTRY_HOST/$REPO/backend-worker" --all-tags - - - name: Build & Push Frontend - run: | - REGISTRY_HOST=$(echo "${{ gitea.server_url }}" | sed 's|https\?://||') - REPO="${{ gitea.repository }}" - docker build -f frontend/Dockerfile \ - -t "$REGISTRY_HOST/$REPO/frontend:${{ gitea.sha }}" \ - -t "$REGISTRY_HOST/$REPO/frontend:latest" \ - . - docker push "$REGISTRY_HOST/$REPO/frontend" --all-tags - - deploy: - name: Deploy - runs-on: ubuntu-latest - needs: [build-and-push] - if: ${{ gitea.ref == 'refs/heads/main' || gitea.ref == 'refs/heads/master' }} - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Setup SSH - run: | - mkdir -p ~/.ssh - echo "${{ secrets.SSH_PRIVATE_KEY }}" > ~/.ssh/vloop-deploy - chmod 600 ~/.ssh/vloop-deploy - - - name: Copy nginx.prod.conf to server - run: | - scp -o StrictHostKeyChecking=no -i ~/.ssh/vloop-deploy \ - frontend/nginx.prod.conf \ - ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }}:/opt/vloop/nginx.prod.conf - - - name: Pull images & restart services - run: | - ssh -o StrictHostKeyChecking=no -i ~/.ssh/vloop-deploy \ - ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }} \ - "cd /opt/vloop && \ - sed -i 's/^TAG=.*/TAG=${{ gitea.sha }}/' .env && \ - docker compose -f docker-compose.prod.yml pull && \ - docker compose -f docker-compose.prod.yml up -d --remove-orphans && \ - docker image prune -f" + cp docker-compose.prod.yml /opt/vloop/ + cp -r backend /opt/vloop/ + cp -r frontend /opt/vloop/ + cd /opt/vloop + docker compose -f docker-compose.prod.yml up -d --build --remove-orphans + docker image prune -f diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml index 7d44596..f330b23 100644 --- a/docker-compose.prod.yml +++ b/docker-compose.prod.yml @@ -45,15 +45,17 @@ services: retries: 20 backend: - image: ${REGISTRY}/${OWNER}/${REPO}/backend-api:${TAG} + build: + context: . + dockerfile: backend/Dockerfile + target: api + image: vloop-backend-api:latest restart: always environment: CONFIG_PATH: /app/configs/config.yaml - # Docker 内部服务发现 —— 覆盖 baked-in config.yaml 中的 localhost MYSQL_HOST: mysql REDIS_HOST: redis RABBITMQ_HOST: rabbitmq - # 密码和密钥 —— 从 .env 注入 MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD} MYSQL_DATABASE: ${MYSQL_DATABASE} REDIS_PASSWORD: ${REDIS_PASSWORD} @@ -76,7 +78,11 @@ services: retries: 3 worker: - image: ${REGISTRY}/${OWNER}/${REPO}/backend-worker:${TAG} + build: + context: . + dockerfile: backend/Dockerfile + target: worker + image: vloop-backend-worker:latest restart: always environment: CONFIG_PATH: /app/configs/config.yaml @@ -103,12 +109,15 @@ services: retries: 3 frontend: - image: ${REGISTRY}/${OWNER}/${REPO}/frontend:${TAG} + build: + context: . + dockerfile: frontend/Dockerfile + args: + NGINX_CONFIG: nginx.prod.conf + image: vloop-frontend:latest restart: always ports: - "127.0.0.1:9001:80" - volumes: - - ./nginx.prod.conf:/etc/nginx/conf.d/default.conf:ro depends_on: - backend healthcheck: diff --git a/frontend/Dockerfile b/frontend/Dockerfile index a9b1526..e983c82 100644 --- a/frontend/Dockerfile +++ b/frontend/Dockerfile @@ -5,6 +5,8 @@ # docker build -f frontend/Dockerfile -t feedsystem-frontend . # +ARG NGINX_CONFIG=nginx.conf + FROM node:24-alpine AS build WORKDIR /src @@ -15,7 +17,8 @@ COPY frontend/ ./ RUN npm run build FROM nginx:1.27-alpine -COPY frontend/nginx.conf /etc/nginx/conf.d/default.conf +ARG NGINX_CONFIG +COPY frontend/${NGINX_CONFIG} /etc/nginx/conf.d/default.conf COPY --from=build /src/dist /usr/share/nginx/html EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]