name: CI/CD Pipeline on: push: branches: [ main, develop ] pull_request: branches: [ main ] env: REGISTRY: ${{ secrets.CI_HOST }}:5000 IMAGE_NAME: ${{ secrets.APP_NAME || 'sharenet' }} jobs: test-backend: name: Test Backend runs-on: ubuntu-latest services: postgres: image: postgres:15 env: POSTGRES_PASSWORD: postgres POSTGRES_DB: ${{ secrets.APP_NAME || 'sharenet' }}_test options: >- --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5 ports: - 5432:5432 steps: - name: Checkout code uses: actions/checkout@v4 - name: Install Rust toolchain uses: actions-rs/toolchain@v1 with: toolchain: stable override: true - name: Cache Rust dependencies uses: actions/cache@v3 with: path: | ~/.cargo/registry ~/.cargo/git backend/target key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} restore-keys: | ${{ runner.os }}-cargo- - name: Run backend tests working-directory: ./backend run: | cargo test --all cargo clippy --all -- -D warnings cargo fmt --all -- --check test-frontend: name: Test Frontend runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v4 - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: '20' cache: 'npm' cache-dependency-path: frontend/package-lock.json - name: Install frontend dependencies working-directory: ./frontend run: npm ci - name: Run frontend tests working-directory: ./frontend run: | npm run lint npm run type-check npm run build build-and-push: name: Build and Push Docker Images needs: [test-backend, test-frontend] runs-on: ubuntu-latest if: github.ref == 'refs/heads/main' steps: - name: Checkout code uses: actions/checkout@v4 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - name: Configure Docker for local registry run: | echo '{"insecure-registries": ["${{ secrets.CI_HOST }}:5000"]}' | sudo tee /etc/docker/daemon.json sudo systemctl restart docker - name: Build and push backend image uses: docker/build-push-action@v5 with: context: ./backend file: ./backend/Dockerfile push: true tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}/backend:${{ github.sha }} cache-from: type=gha cache-to: type=gha,mode=max - name: Build and push frontend image uses: docker/build-push-action@v5 with: context: ./frontend file: ./frontend/Dockerfile push: true tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}/frontend:${{ github.sha }} cache-from: type=gha cache-to: type=gha,mode=max deploy: name: Deploy to Production needs: build-and-push runs-on: ubuntu-latest if: github.ref == 'refs/heads/main' steps: - name: Deploy to production server uses: appleboy/ssh-action@v1.0.3 with: host: ${{ secrets.PROD_HOST }} username: ${{ secrets.PROD_USER }} key: ${{ secrets.PROD_SSH_KEY }} script: | cd /opt/${{ secrets.APP_NAME || 'sharenet' }} # Pull latest code from repository (includes docker-compose.yml and nginx config) git pull origin main # Create environment file for this deployment echo "IMAGE_TAG=${{ github.sha }}" > .env echo "REGISTRY=${{ secrets.CI_HOST }}:5000" >> .env echo "IMAGE_NAME=${{ secrets.APP_NAME || 'sharenet' }}" >> .env echo "POSTGRES_PASSWORD=${{ secrets.POSTGRES_PASSWORD || 'your_secure_password_here' }}" >> .env echo "DATABASE_URL=postgresql://${{ secrets.POSTGRES_USER || 'sharenet' }}:${{ secrets.POSTGRES_PASSWORD || 'your_secure_password_here' }}@postgres:5432/${{ secrets.POSTGRES_DB || 'sharenet' }}" >> .env echo "NODE_ENV=production" >> .env echo "RUST_LOG=info" >> .env # Run deployment using the repository's docker-compose.yml sudo ./deploy.sh