name: Build and Deploy Demo App on: push: branches: - main jobs: test: runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v4 - name: Set up Python uses: actions/setup-python@v5 with: python-version: '3.12' - name: Install deps run: pip install -r requirements.txt - name: Run tests env: DB_USER: '' # Empty to force SQLite fallback DB_PASS: '' DB_NAME: '' run: pytest build: needs: test runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v4 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - name: Cache Docker layers uses: actions/cache@v4 with: path: /tmp/.buildx-cache key: ${{ runner.os }}-buildx-${{ hashFiles('Dockerfile', 'requirements.txt') }} restore-keys: ${{ runner.os }}-buildx- - name: Build Docker image uses: docker/build-push-action@v6 with: load: true tags: demo-app:latest cache-from: type=local,src=/tmp/.buildx-cache cache-to: type=local,dest=/tmp/.buildx-cache-new,mode=max - name: Save Docker image to tar run: docker save demo-app:latest > demo-app.tar - name: Upload image tar uses: actions/upload-artifact@v4 with: name: demo-app-image path: demo-app.tar retention-days: 1 scan: needs: build runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v4 - name: Scan Image uses: aquasecurity/trivy-action@master with: image-ref: demo-app:latest format: table exit-code: 1 severity: CRITICAL,HIGH deploy: needs: [build, scan] runs-on: ubuntu-latest steps: - name: Set up SSH run: | apt update && apt install -y openssh-client mkdir -p ~/.ssh echo "${{ secrets.SSH_PRIVATE_KEY }}" > ~/.ssh/id_ed25519 chmod 600 ~/.ssh/id_ed25519 eval "$(ssh-agent -s)" ssh-add ~/.ssh/id_ed25519 ssh-keyscan -p ${{ secrets.SERVER_PORT }} ${{ secrets.SERVER_HOST }} >> ~/.ssh/known_hosts - name: Copy tar to server run: scp -o StrictHostKeyChecking=no -P ${{ secrets.SERVER_PORT }} demo-app.tar ${{ secrets.SERVER_USER }}@${{ secrets.SERVER_HOST }}:${{ secrets.DEPLOY_PATH }}demo-app.tar - name: Deploy on server run: | ssh -o StrictHostKeyChecking=no -p ${{ secrets.SERVER_PORT }} ${{ secrets.SERVER_USER }}@${{ secrets.SERVER_HOST }} << EOF cd ${{ secrets.DEPLOY_PATH }} # Create/update .env with secrets echo "DB_USER=${{ secrets.DB_USER }}" > .env echo "DB_PASS=${{ secrets.DB_PASS }}" >> .env echo "DB_NAME=${{ secrets.DB_NAME }}" >> .env # Load and deploy docker load -i demo-app.tar docker compose down docker compose --env-file .env up -d --remove-orphans rm demo-app.tar EOF