# Gitea Actions CI/CD Pipeline for Datacenter Documentation System name: CI/CD Pipeline on: push: branches: [ main, develop ] pull_request: branches: [ main, develop ] schedule: - cron: '0 */6 * * *' # Every 6 hours for docs generation env: POETRY_VERSION: 1.8.0 PYTHON_VERSION: "3.12" REGISTRY: ${{ vars.PACKAGES_REGISTRY }} IMAGE_NAME: ${{ gitea.repository }} jobs: lint: name: Lint Code runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v4 - name: Set up Python uses: actions/setup-python@v5 with: python-version: ${{ env.PYTHON_VERSION }} cache: 'pip' - name: Install Poetry run: | curl -sSL https://install.python-poetry.org | python3 - echo "$HOME/.local/bin" >> $GITHUB_PATH - name: Install dependencies run: | poetry config virtualenvs.in-project true poetry install --no-root - name: Run Black run: poetry run black --check src/ tests/ continue-on-error: true - name: Run Ruff run: poetry run ruff check src/ tests/ continue-on-error: true - name: Run MyPy run: poetry run mypy src/ continue-on-error: true test: name: Run Tests runs-on: ubuntu-latest needs: lint services: mongodb: image: mongo:7-jammy ports: - 27017:27017 options: >- --health-cmd "mongosh --eval 'db.adminCommand(\"ping\")'" --health-interval 10s --health-timeout 5s --health-retries 5 steps: - name: Checkout code uses: actions/checkout@v4 - name: Set up Python uses: actions/setup-python@v5 with: python-version: ${{ env.PYTHON_VERSION }} cache: 'pip' - name: Install Poetry run: | curl -sSL https://install.python-poetry.org | python3 - echo "$HOME/.local/bin" >> $GITHUB_PATH - name: Install dependencies run: | poetry config virtualenvs.in-project true poetry install - name: Run unit tests env: MONGODB_URL: mongodb://localhost:27017 MONGODB_DATABASE: testdb run: | poetry run pytest tests/unit -v --cov --cov-report=xml --cov-report=html continue-on-error: true - name: Upload coverage uses: codecov/codecov-action@v3 with: files: ./coverage.xml flags: unittests name: codecov-umbrella continue-on-error: true - name: Archive coverage results uses: actions/upload-artifact@v4 with: name: coverage-report path: htmlcov/ continue-on-error: true security: name: Security Scanning runs-on: ubuntu-latest needs: lint steps: - name: Checkout code uses: actions/checkout@v4 - name: Set up Python uses: actions/setup-python@v5 with: python-version: ${{ env.PYTHON_VERSION }} - name: Install Poetry run: | curl -sSL https://install.python-poetry.org | python3 - echo "$HOME/.local/bin" >> $GITHUB_PATH - name: Install dependencies run: | poetry config virtualenvs.in-project true poetry install - name: Run Bandit run: | poetry add --group dev bandit poetry run bandit -r src/ -f json -o bandit-report.json continue-on-error: true - name: Run Safety run: | poetry export -f requirements.txt --output requirements.txt --without-hashes poetry add --group dev safety poetry run safety check --file requirements.txt continue-on-error: true build-and-push: name: Build and Push Docker Images runs-on: ubuntu-latest needs: [test, security] if: github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/') strategy: matrix: component: [api, chat, worker, frontend] steps: - name: Checkout code uses: actions/checkout@v4 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - name: Log in to Container Registry uses: docker/login-action@v3 with: registry: ${{ vars.PACKAGES_REGISTRY }} username: ${{ secrets.USERNAME }} password: ${{ secrets.TOKEN }} - name: Extract metadata id: meta uses: docker/metadata-action@v5 with: images: ${{ vars.PACKAGES_REGISTRY }}/${{ env.IMAGE_NAME }}/${{ matrix.component }} tags: | type=ref,event=branch type=ref,event=pr type=semver,pattern={{version}} type=semver,pattern={{major}}.{{minor}} type=sha,prefix={{branch}}- type=raw,value=latest,enable={{is_default_branch}} - name: Build and push Docker image uses: docker/build-push-action@v5 with: context: . file: deploy/docker/Dockerfile.${{ matrix.component }} push: true tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} cache-from: type=registry,ref=${{ vars.PACKAGES_REGISTRY }}/${{ env.IMAGE_NAME }}/${{ matrix.component }}:buildcache cache-to: type=registry,ref=${{ vars.PACKAGES_REGISTRY }}/${{ env.IMAGE_NAME }}/${{ matrix.component }}:buildcache,mode=max deploy-staging: name: Deploy to Staging runs-on: ubuntu-latest needs: build-and-push if: github.ref == 'refs/heads/main' environment: name: staging url: https://staging-docs.company.local steps: - name: Checkout code uses: actions/checkout@v4 - name: Set up kubectl uses: azure/setup-kubectl@v3 with: version: 'latest' - name: Configure kubectl run: | echo "${{ secrets.KUBE_CONFIG_STAGING }}" > kubeconfig export KUBECONFIG=kubeconfig - name: Deploy to Kubernetes run: | export KUBECONFIG=kubeconfig kubectl set image deployment/api api=${{ vars.PACKAGES_REGISTRY }}/${{ env.IMAGE_NAME }}/api:${{ github.sha }} -n datacenter-docs kubectl set image deployment/chat chat=${{ vars.PACKAGES_REGISTRY }}/${{ env.IMAGE_NAME }}/chat:${{ github.sha }} -n datacenter-docs kubectl set image deployment/worker worker=${{ vars.PACKAGES_REGISTRY }}/${{ env.IMAGE_NAME }}/worker:${{ github.sha }} -n datacenter-docs kubectl rollout status deployment/api -n datacenter-docs --timeout=5m kubectl rollout status deployment/chat -n datacenter-docs --timeout=5m kubectl rollout status deployment/worker -n datacenter-docs --timeout=5m continue-on-error: true deploy-production: name: Deploy to Production runs-on: ubuntu-latest needs: build-and-push if: startsWith(github.ref, 'refs/tags/') environment: name: production url: https://docs.company.local steps: - name: Checkout code uses: actions/checkout@v4 - name: Set up kubectl uses: azure/setup-kubectl@v3 with: version: 'latest' - name: Configure kubectl run: | echo "${{ secrets.KUBE_CONFIG_PRODUCTION }}" > kubeconfig export KUBECONFIG=kubeconfig - name: Deploy to Kubernetes run: | export KUBECONFIG=kubeconfig kubectl set image deployment/api api=${{ vars.PACKAGES_REGISTRY }}/${{ env.IMAGE_NAME }}/api:${{ github.ref_name }} -n datacenter-docs kubectl set image deployment/chat chat=${{ vars.PACKAGES_REGISTRY }}/${{ env.IMAGE_NAME }}/chat:${{ github.ref_name }} -n datacenter-docs kubectl set image deployment/worker worker=${{ vars.PACKAGES_REGISTRY }}/${{ env.IMAGE_NAME }}/worker:${{ github.ref_name }} -n datacenter-docs kubectl rollout status deployment/api -n datacenter-docs --timeout=5m kubectl rollout status deployment/chat -n datacenter-docs --timeout=5m kubectl rollout status deployment/worker -n datacenter-docs --timeout=5m - name: Smoke test run: | sleep 30 curl -f https://docs.company.local/health || exit 1 continue-on-error: true generate-docs: name: Generate Documentation runs-on: ubuntu-latest if: github.event.schedule == '0 */6 * * *' || github.ref == 'refs/heads/main' steps: - name: Checkout code uses: actions/checkout@v4 - name: Set up Python uses: actions/setup-python@v5 with: python-version: ${{ env.PYTHON_VERSION }} - name: Install Poetry run: | curl -sSL https://install.python-poetry.org | python3 - echo "$HOME/.local/bin" >> $GITHUB_PATH - name: Install dependencies run: | poetry config virtualenvs.in-project true poetry install - name: Generate documentation env: MCP_SERVER_URL: ${{ secrets.MCP_SERVER_URL }} ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} run: | poetry run datacenter-docs generate-all continue-on-error: true - name: Upload documentation artifacts uses: actions/upload-artifact@v4 with: name: documentation path: output/ retention-days: 30 - name: Commit and push if changed run: | git config --global user.name "Docs Bot" git config --global user.email "bot@company.local" git add output/ git diff --quiet && git diff --staged --quiet || (git commit -m "docs: Auto-generated documentation update [skip ci]" && git push) continue-on-error: true