diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml new file mode 100644 index 000000000..de4001017 --- /dev/null +++ b/.github/workflows/ci-cd.yml @@ -0,0 +1,132 @@ +name: CI/CD Pipeline + +on: + push: + branches: [ main, develop ] + pull_request: + branches: [ main ] + +jobs: + test: + name: Test + runs-on: ubuntu-latest + + strategy: + matrix: + python-version: ['3.11', '3.12'] + + steps: + - name: Checkout code + 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 -r requirements.txt + pip install pytest pytest-cov pytest-asyncio + + - name: Run tests + env: + USE_IN_MEMORY_DB: true + run: | + pytest tests/ -v --cov=packages --cov-report=xml --cov-report=term + + - name: Upload coverage to Codecov + uses: codecov/codecov-action@v3 + with: + file: ./coverage.xml + flags: unittests + name: codecov-umbrella + + lint: + name: Lint + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: '3.12' + + - name: Install linting tools + run: | + python -m pip install --upgrade pip + pip install black isort flake8 mypy + + - name: Check code formatting with black + run: black --check packages/ apps/ tests/ + + - name: Check import sorting with isort + run: isort --check-only packages/ apps/ tests/ + + - name: Lint with flake8 + run: flake8 packages/ apps/ tests/ --max-line-length=100 --ignore=E203,W503 + + build: + name: Build Docker Image + runs-on: ubuntu-latest + needs: [test, lint] + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Build Docker image + uses: docker/build-push-action@v5 + with: + context: . + push: false + tags: xiaoxia-saas:${{ github.sha }} + cache-from: type=gha + cache-to: type=gha,mode=max + + deploy-staging: + name: Deploy to Staging + runs-on: ubuntu-latest + needs: [build] + if: github.ref == 'refs/heads/develop' + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Deploy to staging + run: | + echo "Deploying to staging environment..." + # Add your staging deployment commands here + # Example: ssh deploy@staging-server 'cd /app && docker-compose pull && docker-compose up -d' + + deploy-production: + name: Deploy to Production + runs-on: ubuntu-latest + needs: [build] + if: github.ref == 'refs/heads/main' && github.event_name == 'push' + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Deploy to production + run: | + echo "Deploying to production environment..." + # Add your production deployment commands here + # Example: ssh deploy@prod-server 'cd /app && docker-compose pull && docker-compose up -d' diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 000000000..11e9ccc85 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,74 @@ +name: Release + +on: + push: + tags: + - 'v*' + +jobs: + create-release: + name: Create Release + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Generate changelog + id: changelog + run: | + # Extract changelog for this version + VERSION=${GITHUB_REF#refs/tags/} + echo "version=$VERSION" >> $GITHUB_OUTPUT + + - name: Create Release + uses: actions/create-release@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + tag_name: ${{ github.ref }} + release_name: Release ${{ steps.changelog.outputs.version }} + body: | + See [CHANGELOG.md](https://github.com/${{ github.repository }}/blob/main/CHANGELOG.md) for details. + draft: false + prerelease: false + + build-and-push: + name: Build and Push Docker Image + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Log in to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_PASSWORD }} + + - name: Extract metadata + id: meta + uses: docker/metadata-action@v5 + with: + images: xiaoxia/saas + tags: | + type=semver,pattern={{version}} + type=semver,pattern={{major}}.{{minor}} + type=semver,pattern={{major}} + type=raw,value=latest + + - name: Build and push + uses: docker/build-push-action@v5 + with: + context: . + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + cache-from: type=gha + cache-to: type=gha,mode=max diff --git a/.github/workflows/security.yml b/.github/workflows/security.yml new file mode 100644 index 000000000..e9b94eb3b --- /dev/null +++ b/.github/workflows/security.yml @@ -0,0 +1,59 @@ +name: Security Scan + +on: + push: + branches: [ main, develop ] + pull_request: + branches: [ main ] + schedule: + # Run every Monday at 00:00 UTC + - cron: '0 0 * * 1' + +jobs: + security-scan: + name: Security Scan + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: '3.12' + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install safety bandit + + - name: Check for known security vulnerabilities + run: | + pip install -r requirements.txt + safety check --json + + - name: Run Bandit security linter + run: | + bandit -r packages/ apps/ -f json -o bandit-report.json || true + cat bandit-report.json + + - name: Upload security reports + uses: actions/upload-artifact@v3 + if: always() + with: + name: security-reports + path: | + bandit-report.json + + dependency-review: + name: Dependency Review + runs-on: ubuntu-latest + if: github.event_name == 'pull_request' + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Dependency Review + uses: actions/dependency-review-action@v3