Some checks are pending
CI/CD Pipeline (Fully Isolated DinD) / Run Tests (DinD) (push) Waiting to run
CI/CD Pipeline (Fully Isolated DinD) / Build and Push Docker Images (DinD) (push) Blocked by required conditions
CI/CD Pipeline (Fully Isolated DinD) / Deploy to Production (push) Blocked by required conditions
210 lines
No EOL
7.6 KiB
YAML
210 lines
No EOL
7.6 KiB
YAML
name: CI/CD Pipeline (Fully Isolated DinD)
|
|
|
|
on:
|
|
push:
|
|
branches: [ main, develop ]
|
|
pull_request:
|
|
branches: [ main ]
|
|
|
|
env:
|
|
REGISTRY: ${{ secrets.CI_HOST }}:5000
|
|
IMAGE_NAME: ${{ secrets.APP_NAME || 'sharenet' }}
|
|
|
|
jobs:
|
|
# Job 1: Testing - Uses DinD with multiple containers for comprehensive testing
|
|
test:
|
|
name: Run Tests (DinD)
|
|
runs-on: [self-hosted, dind]
|
|
if: github.ref == 'refs/heads/main'
|
|
|
|
steps:
|
|
- name: Checkout code
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Setup Containerized Testing Environment
|
|
run: |
|
|
# Start testing environment using dedicated compose file
|
|
docker compose -f docker-compose.test.yml up -d
|
|
|
|
# Wait for all services to be ready
|
|
echo "Waiting for testing environment to be ready..."
|
|
timeout 120 bash -c 'until docker compose -f docker-compose.test.yml ps | grep -q "healthy" && docker compose -f docker-compose.test.yml ps | grep -q "Up"; do sleep 2; done'
|
|
|
|
# Verify all containers are running
|
|
docker compose -f docker-compose.test.yml ps
|
|
|
|
- name: Install SQLx CLI in Rust container
|
|
run: |
|
|
docker exec ci-cd-test-rust cargo install sqlx-cli --no-default-features --features postgres
|
|
|
|
- name: Validate migration files
|
|
env:
|
|
DATABASE_URL: postgres://postgres:postgres@localhost:5432/sharenet_test
|
|
run: |
|
|
# Wait for PostgreSQL to be ready
|
|
echo "Waiting for PostgreSQL to be ready..."
|
|
timeout 60 bash -c 'until pg_isready -h localhost -p 5432 -U postgres; do sleep 1; done'
|
|
|
|
# Create test database if it doesn't exist
|
|
docker exec ci-cd-test-rust sqlx database create --database-url "$DATABASE_URL" || true
|
|
|
|
# Run initial migrations to set up the database
|
|
docker exec ci-cd-test-rust sqlx migrate run --database-url "$DATABASE_URL" || true
|
|
|
|
# Validate migration files
|
|
docker exec ci-cd-test-rust ./scripts/validate_migrations.sh --verbose
|
|
|
|
- name: Run backend tests
|
|
working-directory: ./backend
|
|
env:
|
|
DATABASE_URL: postgres://postgres:postgres@localhost:5432/sharenet_test
|
|
run: |
|
|
# Run tests with increased parallelism for Rust
|
|
docker exec ci-cd-test-rust cargo test --all --jobs 4
|
|
docker exec ci-cd-test-rust cargo clippy --all -- -D warnings
|
|
docker exec ci-cd-test-rust cargo fmt --all -- --check
|
|
|
|
- name: Install frontend dependencies
|
|
run: |
|
|
docker exec ci-cd-test-node npm ci
|
|
|
|
- name: Run frontend tests
|
|
run: |
|
|
docker exec ci-cd-test-node npm run lint
|
|
docker exec ci-cd-test-node npm run type-check
|
|
docker exec ci-cd-test-node npm run build
|
|
|
|
- name: Cleanup Containerized Environment
|
|
if: always()
|
|
run: |
|
|
# Stop and remove all testing containers
|
|
docker compose -f docker-compose.test.yml down
|
|
|
|
# Job 2: Building - Uses DinD for isolated image building and pushing
|
|
build-and-push:
|
|
name: Build and Push Docker Images (DinD)
|
|
needs: [test]
|
|
runs-on: [self-hosted, dind]
|
|
if: github.ref == 'refs/heads/main'
|
|
|
|
steps:
|
|
- name: Checkout code
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Setup DinD environment
|
|
run: |
|
|
# Start DinD container for isolated Docker operations
|
|
docker run -d \
|
|
--name ci-cd-build-dind \
|
|
--privileged \
|
|
-p 2375:2375 \
|
|
-e DOCKER_TLS_CERTDIR="" \
|
|
docker:dind
|
|
|
|
# Wait for DinD to be ready
|
|
echo "Waiting for DinD container to be ready..."
|
|
timeout 60 bash -c 'until docker exec ci-cd-build-dind docker version; do sleep 2; done'
|
|
|
|
# Configure Docker for Harbor registry (needed for pushing images)
|
|
docker exec ci-cd-build-dind sh -c 'echo "{\"insecure-registries\": [\"${{ secrets.CI_HOST }}:5000\"]}" > /etc/docker/daemon.json'
|
|
docker exec ci-cd-build-dind sh -c 'kill -HUP 1'
|
|
|
|
# Wait for Docker daemon to reload
|
|
sleep 5
|
|
|
|
# Verify DinD is working
|
|
docker exec ci-cd-build-dind docker version
|
|
|
|
- name: Set up Docker Buildx
|
|
uses: docker/setup-buildx-action@v3
|
|
|
|
- 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
|
|
platforms: linux/amd64
|
|
|
|
- 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
|
|
platforms: linux/amd64
|
|
|
|
- name: Cleanup DinD environment
|
|
if: always()
|
|
run: |
|
|
# Stop and remove DinD container
|
|
docker stop ci-cd-build-dind || true
|
|
docker rm ci-cd-build-dind || true
|
|
|
|
# Job 3: Deployment - Runs directly on production runner (no DinD needed)
|
|
deploy:
|
|
name: Deploy to Production
|
|
needs: build-and-push
|
|
runs-on: [self-hosted, production]
|
|
if: github.ref == 'refs/heads/main'
|
|
|
|
steps:
|
|
- name: Checkout code
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Create environment file for deployment
|
|
run: |
|
|
# 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 "POSTGRES_USER=${{ secrets.POSTGRES_USER || 'sharenet' }}" >> .env
|
|
echo "POSTGRES_DB=${{ secrets.POSTGRES_DB || 'sharenet' }}" >> .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
|
|
|
|
- name: Make scripts executable
|
|
run: chmod +x scripts/*.sh
|
|
|
|
- name: Configure Docker for Harbor access
|
|
run: |
|
|
# Configure Docker to access Harbor registry on CI Linode
|
|
echo '{"insecure-registries": ["${{ secrets.CI_HOST }}:5000"]}' | sudo tee /etc/docker/daemon.json
|
|
sudo systemctl restart docker
|
|
|
|
# Wait for Docker to be ready
|
|
timeout 30 bash -c 'until docker info; do sleep 1; done'
|
|
|
|
- name: Validate migration files
|
|
run: |
|
|
echo "Validating migration files before deployment..."
|
|
./scripts/validate_migrations.sh --verbose || {
|
|
echo "ERROR: Migration validation failed. Deployment aborted."
|
|
exit 1
|
|
}
|
|
|
|
- name: Pull and deploy application
|
|
run: |
|
|
# Pull latest images from Harbor registry
|
|
echo "Pulling latest images from Harbor registry..."
|
|
docker compose -f docker-compose.prod.yml pull
|
|
|
|
# Deploy the application stack
|
|
echo "Deploying application stack..."
|
|
docker compose -f docker-compose.prod.yml up -d
|
|
|
|
# Wait for all services to be healthy
|
|
echo "Waiting for all services to be healthy..."
|
|
timeout 120 bash -c 'until docker compose -f docker-compose.prod.yml ps | grep -q "healthy" && docker compose -f docker-compose.prod.yml ps | grep -q "Up"; do sleep 2; done'
|
|
|
|
# Verify deployment
|
|
echo "Verifying deployment..."
|
|
docker compose -f docker-compose.prod.yml ps |