name: CI on: push: branches: - main pull_request: branches: - main jobs: smoke-test: runs-on: ubuntu-latest steps: - name: Checkout repository uses: actions/checkout@v4 with: github-server-url: http://gitea:3000 - name: Set up Python uses: actions/setup-python@v5 with: python-version: "3.12" - name: Run smoke tests run: python3 scripts/smoke_test.py - name: Install Docker CLI run: | apt-get update apt-get install -y docker.io - name: Login to Docker Hub if: github.event_name == 'push' && github.ref == 'refs/heads/main' env: DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }} DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }} run: | echo "$DOCKERHUB_TOKEN" | docker login \ -u "$DOCKERHUB_USERNAME" \ --password-stdin - name: Build Docker image if: github.event_name == 'push' && github.ref == 'refs/heads/main' run: | docker build \ -t mikhaillobanov/devops-platform:latest \ -t mikhaillobanov/devops-platform:${GITHUB_SHA} \ . - name: Scan Docker image with Trivy if: github.event_name == 'push' && github.ref == 'refs/heads/main' run: | docker run --rm \ -v /var/run/docker.sock:/var/run/docker.sock \ -v "$HOME/.cache/trivy:/root/.cache/" \ aquasec/trivy:0.76.0 image \ --scanners vuln \ --severity HIGH,CRITICAL \ --ignore-unfixed \ --exit-code 1 \ mikhaillobanov/devops-platform:${GITHUB_SHA} - name: Push Docker image if: github.event_name == 'push' && github.ref == 'refs/heads/main' run: | docker push mikhaillobanov/devops-platform:latest docker push mikhaillobanov/devops-platform:${GITHUB_SHA} - name: Deploy application if: github.event_name == 'push' && github.ref == 'refs/heads/main' env: IMAGE: mikhaillobanov/devops-platform:${{ github.sha }} run: | set -eu OLD_IMAGE=$(docker inspect --format='{{.Image}}' devops-platform) docker pull "$IMAGE" docker stop devops-platform docker rm devops-platform if IMAGE="$IMAGE" docker compose up -d --no-build app; then echo "New container started" else echo "Failed to start new container; restoring old image" docker run -d \ --name devops-platform \ --restart unless-stopped \ --read-only \ --cap-drop=ALL \ --security-opt=no-new-privileges:true \ --memory=256m \ --cpus=0.5 \ -p 127.0.0.1:8000:8000 \ "$OLD_IMAGE" exit 1 fi HEALTHY=false for attempt in $(seq 1 15); do if docker exec devops-platform python -c \ "import urllib.request; r=urllib.request.urlopen('http://127.0.0.1:8000/health', timeout=2); assert r.status == 200"; then HEALTHY=true break fi sleep 2 done if [ "$HEALTHY" = true ]; then echo "Deployment successful" else echo "Health check failed; rolling back" docker stop devops-platform || true docker rm devops-platform || true docker run -d \ --name devops-platform \ --restart unless-stopped \ --read-only \ --cap-drop=ALL \ --security-opt=no-new-privileges:true \ --memory=256m \ --cpus=0.5 \ -p 127.0.0.1:8000:8000 \ "$OLD_IMAGE" exit 1 fi