diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml new file mode 100644 index 0000000..3a3e9be --- /dev/null +++ b/.github/workflows/ci-cd.yml @@ -0,0 +1,168 @@ +name: CI/CD Pipeline + +on: + push: + branches: [ main, develop ] + pull_request: + branches: [ main ] + workflow_dispatch: + +jobs: + test: + runs-on: ubuntu-latest + strategy: + matrix: + python-version: [3.9, 3.10, 3.11] + + steps: + - uses: actions/checkout@v4 + + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v4 + with: + python-version: ${{ matrix.python-version }} + + - name: Cache pip packages + uses: actions/cache@v3 + with: + path: ~/.cache/pip + key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }} + restore-keys: | + ${{ runner.os }}-pip- + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install pytest pytest-cov flake8 black isort + pip install -r requirements.txt + + - name: Lint with flake8 + run: | + # Stop the build if there are Python syntax errors or undefined names + flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics + # Exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide + flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics + + - name: Check code formatting with black + run: | + black --check --diff . + + - name: Check import sorting with isort + run: | + isort --check-only --diff . + + - name: Run tests with pytest + run: | + pytest --cov=. --cov-report=xml --cov-report=html + + - name: Upload coverage to Codecov + uses: codecov/codecov-action@v3 + with: + file: ./coverage.xml + flags: unittests + name: codecov-umbrella + + security-scan: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: 3.11 + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install safety bandit + + - name: Run safety check + run: | + safety check + + - name: Run bandit security scan + run: | + bandit -r . -f json -o bandit-report.json + bandit -r . -f txt + + build-and-deploy: + needs: [test, security-scan] + runs-on: ubuntu-latest + if: github.ref == 'refs/heads/main' + + steps: + - uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: 3.11 + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install -r requirements.txt + + - name: Build application + run: | + # Add your build steps here + echo "Building application..." + # python setup.py build + + - name: Create deployment package + run: | + # Create a deployment package + tar -czf gogo2-deployment.tar.gz . --exclude='.git' --exclude='__pycache__' --exclude='*.pyc' + + - name: Upload deployment artifact + uses: actions/upload-artifact@v3 + with: + name: deployment-package + path: gogo2-deployment.tar.gz + + docker-build: + needs: [test, security-scan] + runs-on: ubuntu-latest + if: github.ref == 'refs/heads/main' + + steps: + - uses: actions/checkout@v4 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Login to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_PASSWORD }} + + - name: Build and push Docker image + uses: docker/build-push-action@v5 + with: + context: . + push: true + tags: | + ${{ secrets.DOCKER_USERNAME }}/gogo2:latest + ${{ secrets.DOCKER_USERNAME }}/gogo2:${{ github.sha }} + cache-from: type=gha + cache-to: type=gha,mode=max + + notify: + needs: [build-and-deploy, docker-build] + runs-on: ubuntu-latest + if: always() + + steps: + - name: Notify on success + if: ${{ needs.build-and-deploy.result == 'success' && needs.docker-build.result == 'success' }} + run: | + echo "🎉 Deployment successful!" + # Add notification logic here (Slack, email, etc.) + + - name: Notify on failure + if: ${{ needs.build-and-deploy.result == 'failure' || needs.docker-build.result == 'failure' }} + run: | + echo "❌ Deployment failed!" + # Add notification logic here (Slack, email, etc.)