diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..13b1f3b --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,43 @@ +version: 2 +updates: + # npm dependencies + - package-ecosystem: "npm" + directory: "/" + schedule: + interval: "weekly" + day: "monday" + open-pull-requests-limit: 10 + reviewers: + - "blackboxprogramming" + labels: + - "dependencies" + - "automated" + commit-message: + prefix: "chore" + include: "scope" + + # GitHub Actions + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" + day: "monday" + open-pull-requests-limit: 5 + labels: + - "dependencies" + - "github-actions" + commit-message: + prefix: "ci" + + # pip dependencies + - package-ecosystem: "pip" + directory: "/" + schedule: + interval: "weekly" + day: "monday" + open-pull-requests-limit: 10 + labels: + - "dependencies" + - "python" + commit-message: + prefix: "chore" diff --git a/.github/workflows/auto-deploy.yml b/.github/workflows/auto-deploy.yml new file mode 100644 index 0000000..00958fa --- /dev/null +++ b/.github/workflows/auto-deploy.yml @@ -0,0 +1,115 @@ +name: 🚀 Auto Deploy + +on: + push: + branches: [main, master] + workflow_dispatch: + +env: + NODE_VERSION: '20' + +jobs: + detect-service: + name: Detect Service Type + runs-on: ubuntu-latest + outputs: + service_type: ${{ steps.detect.outputs.service_type }} + deploy_target: ${{ steps.detect.outputs.deploy_target }} + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Detect Service Type + id: detect + run: | + if [ -f "next.config.mjs" ] || [ -f "next.config.js" ]; then + echo "service_type=nextjs" >> $GITHUB_OUTPUT + echo "deploy_target=cloudflare" >> $GITHUB_OUTPUT + elif [ -f "Dockerfile" ]; then + echo "service_type=docker" >> $GITHUB_OUTPUT + echo "deploy_target=railway" >> $GITHUB_OUTPUT + elif [ -f "package.json" ]; then + echo "service_type=node" >> $GITHUB_OUTPUT + echo "deploy_target=railway" >> $GITHUB_OUTPUT + elif [ -f "requirements.txt" ]; then + echo "service_type=python" >> $GITHUB_OUTPUT + echo "deploy_target=railway" >> $GITHUB_OUTPUT + else + echo "service_type=static" >> $GITHUB_OUTPUT + echo "deploy_target=cloudflare" >> $GITHUB_OUTPUT + fi + + deploy-cloudflare: + name: Deploy to Cloudflare Pages + needs: detect-service + if: needs.detect-service.outputs.deploy_target == 'cloudflare' + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Node + uses: actions/setup-node@v4 + with: + node-version: ${{ env.NODE_VERSION }} + cache: 'npm' + + - name: Install Dependencies + run: npm ci + + - name: Build + run: npm run build + env: + NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY: ${{ secrets.NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY }} + + - name: Deploy to Cloudflare Pages + uses: cloudflare/wrangler-action@v3 + with: + apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }} + accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} + command: pages deploy .next --project-name=${{ github.event.repository.name }} + + deploy-railway: + name: Deploy to Railway + needs: detect-service + if: needs.detect-service.outputs.deploy_target == 'railway' + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Install Railway CLI + run: npm i -g @railway/cli + + - name: Deploy to Railway + run: railway up --service ${{ github.event.repository.name }} + env: + RAILWAY_TOKEN: ${{ secrets.RAILWAY_TOKEN }} + + health-check: + name: Health Check + needs: [deploy-cloudflare, deploy-railway] + if: always() && (needs.deploy-cloudflare.result == 'success' || needs.deploy-railway.result == 'success') + runs-on: ubuntu-latest + + steps: + - name: Wait for Deployment + run: sleep 30 + + - name: Check Health Endpoint + run: | + URL="${{ secrets.DEPLOY_URL }}/api/health" + curl -f $URL || exit 1 + + - name: Notify Success + if: success() + run: echo "✅ Deployment successful and healthy!" + + - name: Notify Failure + if: failure() + run: | + echo "❌ Deployment health check failed!" + exit 1 diff --git a/.github/workflows/security-scan.yml b/.github/workflows/security-scan.yml new file mode 100644 index 0000000..bcb270c --- /dev/null +++ b/.github/workflows/security-scan.yml @@ -0,0 +1,55 @@ +name: 🔒 Security Scan + +on: + push: + branches: [main, master, dev] + pull_request: + branches: [main, master] + schedule: + - cron: '0 0 * * 0' + workflow_dispatch: + +permissions: + contents: read + security-events: write + actions: read + +jobs: + codeql: + name: CodeQL Analysis + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + language: ['javascript', 'typescript', 'python'] + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Initialize CodeQL + uses: github/codeql-action/init@v3 + with: + languages: ${{ matrix.language }} + + - name: Autobuild + uses: github/codeql-action/autobuild@v3 + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v3 + + dependency-scan: + name: Dependency Scan + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Run npm audit + if: hashFiles('package.json') != '' + run: npm audit --audit-level=moderate || true + + - name: Dependency Review + uses: actions/dependency-review-action@v4 + if: github.event_name == 'pull_request' diff --git a/.github/workflows/self-healing.yml b/.github/workflows/self-healing.yml new file mode 100644 index 0000000..e4f6652 --- /dev/null +++ b/.github/workflows/self-healing.yml @@ -0,0 +1,86 @@ +name: 🔧 Self-Healing + +on: + schedule: + - cron: '*/30 * * * *' # Every 30 minutes + workflow_dispatch: + workflow_run: + workflows: ["🚀 Auto Deploy"] + types: [completed] + +jobs: + monitor: + name: Monitor Deployments + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Check Health + id: health + run: | + if [ ! -z "${{ secrets.DEPLOY_URL }}" ]; then + STATUS=$(curl -s -o /dev/null -w "%{http_code}" ${{ secrets.DEPLOY_URL }}/api/health || echo "000") + echo "status=$STATUS" >> $GITHUB_OUTPUT + else + echo "status=skip" >> $GITHUB_OUTPUT + fi + + - name: Auto-Rollback + if: steps.health.outputs.status != '200' && steps.health.outputs.status != 'skip' + run: | + echo "🚨 Health check failed (Status: ${{ steps.health.outputs.status }})" + echo "Triggering rollback..." + gh workflow run auto-deploy.yml --ref $(git rev-parse HEAD~1) + env: + GH_TOKEN: ${{ github.token }} + + - name: Attempt Auto-Fix + if: steps.health.outputs.status != '200' && steps.health.outputs.status != 'skip' + run: | + echo "🔧 Attempting automatic fixes..." + # Check for common issues + if [ -f "package.json" ]; then + npm ci || true + npm run build || true + fi + + - name: Create Issue on Failure + if: failure() + uses: actions/github-script@v7 + with: + script: | + github.rest.issues.create({ + owner: context.repo.owner, + repo: context.repo.repo, + title: '🚨 Self-Healing: Deployment Health Check Failed', + body: `Deployment health check failed.\n\nStatus: ${{ steps.health.outputs.status }}\nWorkflow: ${context.workflow}\nRun: ${context.runId}`, + labels: ['bug', 'deployment', 'auto-generated'] + }) + + dependency-updates: + name: Auto Update Dependencies + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Node + if: hashFiles('package.json') != '' + uses: actions/setup-node@v4 + with: + node-version: '20' + + - name: Update npm dependencies + if: hashFiles('package.json') != '' + run: | + npm update + if [ -n "$(git status --porcelain)" ]; then + git config user.name "BlackRoad Bot" + git config user.email "bot@blackroad.io" + git add package*.json + git commit -m "chore: auto-update dependencies" + git push + fi