- Auto Deploy: Deploys to Railway/Cloudflare on PR and push
- Auto Merge: Approves and merges PRs when CI passes
- CI: Runs lint, tests, and builds
🤖 Generated by BlackRoad OS Automation
189 lines
7.7 KiB
YAML
189 lines
7.7 KiB
YAML
name: Auto Deploy
|
|
|
|
on:
|
|
pull_request:
|
|
types: [opened, synchronize, reopened]
|
|
push:
|
|
branches: [main, master]
|
|
|
|
env:
|
|
RAILWAY_TOKEN: ${{ secrets.RAILWAY_TOKEN }}
|
|
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
|
|
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
|
|
|
|
jobs:
|
|
detect-and-deploy:
|
|
runs-on: ubuntu-latest
|
|
permissions:
|
|
contents: read
|
|
pull-requests: write
|
|
deployments: write
|
|
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Setup Node.js
|
|
uses: actions/setup-node@v4
|
|
with:
|
|
node-version: '20'
|
|
|
|
- name: Detect Project Type
|
|
id: detect
|
|
run: |
|
|
# Detect what kind of project this is
|
|
if [ -f "railway.toml" ] || [ -f "railway.json" ]; then
|
|
echo "platform=railway" >> $GITHUB_OUTPUT
|
|
elif [ -f "wrangler.toml" ] || [ -f "wrangler.json" ]; then
|
|
echo "platform=cloudflare-workers" >> $GITHUB_OUTPUT
|
|
elif [ -f "next.config.js" ] || [ -f "next.config.mjs" ] || [ -f "next.config.ts" ]; then
|
|
echo "platform=cloudflare-pages" >> $GITHUB_OUTPUT
|
|
echo "framework=next" >> $GITHUB_OUTPUT
|
|
elif [ -f "vite.config.ts" ] || [ -f "vite.config.js" ]; then
|
|
echo "platform=cloudflare-pages" >> $GITHUB_OUTPUT
|
|
echo "framework=vite" >> $GITHUB_OUTPUT
|
|
elif [ -f "Dockerfile" ]; then
|
|
echo "platform=railway" >> $GITHUB_OUTPUT
|
|
elif [ -f "requirements.txt" ] || [ -f "pyproject.toml" ]; then
|
|
echo "platform=railway" >> $GITHUB_OUTPUT
|
|
echo "framework=python" >> $GITHUB_OUTPUT
|
|
elif [ -f "package.json" ]; then
|
|
echo "platform=cloudflare-pages" >> $GITHUB_OUTPUT
|
|
echo "framework=static" >> $GITHUB_OUTPUT
|
|
else
|
|
echo "platform=railway" >> $GITHUB_OUTPUT
|
|
fi
|
|
|
|
# Get repo name for service naming
|
|
echo "repo_name=${GITHUB_REPOSITORY#*/}" >> $GITHUB_OUTPUT
|
|
|
|
# Set environment based on event
|
|
if [ "${{ github.event_name }}" == "pull_request" ]; then
|
|
echo "environment=preview" >> $GITHUB_OUTPUT
|
|
echo "pr_number=${{ github.event.pull_request.number }}" >> $GITHUB_OUTPUT
|
|
else
|
|
echo "environment=production" >> $GITHUB_OUTPUT
|
|
fi
|
|
|
|
- name: Install Dependencies
|
|
if: steps.detect.outputs.platform == 'cloudflare-pages' || steps.detect.outputs.platform == 'cloudflare-workers'
|
|
run: |
|
|
if [ -f "package.json" ]; then
|
|
npm ci || npm install
|
|
fi
|
|
|
|
- name: Build (if needed)
|
|
if: steps.detect.outputs.platform == 'cloudflare-pages'
|
|
run: |
|
|
if [ -f "package.json" ]; then
|
|
npm run build || true
|
|
fi
|
|
|
|
# ============ RAILWAY DEPLOYMENT ============
|
|
- name: Install Railway CLI
|
|
if: steps.detect.outputs.platform == 'railway' && env.RAILWAY_TOKEN != ''
|
|
run: npm install -g @railway/cli
|
|
|
|
- name: Deploy to Railway
|
|
if: steps.detect.outputs.platform == 'railway' && env.RAILWAY_TOKEN != ''
|
|
id: railway
|
|
run: |
|
|
railway link --environment ${{ steps.detect.outputs.environment }} 2>/dev/null || true
|
|
DEPLOY_URL=$(railway up --detach 2>&1 | grep -oP 'https://[^\s]+' | head -1 || echo "")
|
|
if [ -n "$DEPLOY_URL" ]; then
|
|
echo "url=$DEPLOY_URL" >> $GITHUB_OUTPUT
|
|
echo "success=true" >> $GITHUB_OUTPUT
|
|
else
|
|
DEPLOY_URL=$(railway status --json 2>/dev/null | jq -r '.deployments[0].url // empty' || echo "")
|
|
echo "url=$DEPLOY_URL" >> $GITHUB_OUTPUT
|
|
echo "success=true" >> $GITHUB_OUTPUT
|
|
fi
|
|
|
|
# ============ CLOUDFLARE PAGES DEPLOYMENT ============
|
|
- name: Deploy to Cloudflare Pages
|
|
if: steps.detect.outputs.platform == 'cloudflare-pages' && env.CLOUDFLARE_API_TOKEN != ''
|
|
id: cloudflare-pages
|
|
run: |
|
|
npm install -g wrangler
|
|
if [ -d "dist" ]; then OUTPUT_DIR="dist"
|
|
elif [ -d "build" ]; then OUTPUT_DIR="build"
|
|
elif [ -d "out" ]; then OUTPUT_DIR="out"
|
|
elif [ -d ".next" ]; then OUTPUT_DIR=".next"
|
|
elif [ -d "public" ]; then OUTPUT_DIR="public"
|
|
else OUTPUT_DIR="."; fi
|
|
|
|
PROJECT_NAME="${{ steps.detect.outputs.repo_name }}"
|
|
wrangler pages project create "$PROJECT_NAME" --production-branch main 2>/dev/null || true
|
|
|
|
if [ "${{ steps.detect.outputs.environment }}" == "preview" ]; then
|
|
RESULT=$(wrangler pages deploy "$OUTPUT_DIR" --project-name="$PROJECT_NAME" --branch="pr-${{ steps.detect.outputs.pr_number }}" 2>&1)
|
|
else
|
|
RESULT=$(wrangler pages deploy "$OUTPUT_DIR" --project-name="$PROJECT_NAME" --branch=main 2>&1)
|
|
fi
|
|
|
|
DEPLOY_URL=$(echo "$RESULT" | grep -oP 'https://[^\s]+\.pages\.dev' | head -1 || echo "")
|
|
echo "url=$DEPLOY_URL" >> $GITHUB_OUTPUT
|
|
echo "success=true" >> $GITHUB_OUTPUT
|
|
|
|
# ============ CLOUDFLARE WORKERS DEPLOYMENT ============
|
|
- name: Deploy to Cloudflare Workers
|
|
if: steps.detect.outputs.platform == 'cloudflare-workers' && env.CLOUDFLARE_API_TOKEN != ''
|
|
id: cloudflare-workers
|
|
run: |
|
|
npm install -g wrangler
|
|
if [ "${{ steps.detect.outputs.environment }}" == "preview" ]; then
|
|
RESULT=$(wrangler deploy --env preview 2>&1 || wrangler deploy 2>&1)
|
|
else
|
|
RESULT=$(wrangler deploy 2>&1)
|
|
fi
|
|
DEPLOY_URL=$(echo "$RESULT" | grep -oP 'https://[^\s]+\.workers\.dev' | head -1 || echo "")
|
|
echo "url=$DEPLOY_URL" >> $GITHUB_OUTPUT
|
|
echo "success=true" >> $GITHUB_OUTPUT
|
|
|
|
# ============ COMMENT ON PR ============
|
|
- name: Comment Deployment URL on PR
|
|
if: github.event_name == 'pull_request' && (steps.railway.outputs.success == 'true' || steps.cloudflare-pages.outputs.success == 'true' || steps.cloudflare-workers.outputs.success == 'true')
|
|
uses: actions/github-script@v7
|
|
with:
|
|
script: |
|
|
const railwayUrl = '${{ steps.railway.outputs.url }}';
|
|
const pagesUrl = '${{ steps.cloudflare-pages.outputs.url }}';
|
|
const workersUrl = '${{ steps.cloudflare-workers.outputs.url }}';
|
|
const platform = '${{ steps.detect.outputs.platform }}';
|
|
const deployUrl = railwayUrl || pagesUrl || workersUrl || 'Deployment in progress...';
|
|
|
|
const platformEmoji = { 'railway': '🚂', 'cloudflare-pages': '📄', 'cloudflare-workers': '⚡' };
|
|
|
|
const body = `## ${platformEmoji[platform] || '🚀'} Preview Deployment Ready!
|
|
|
|
| Platform | URL |
|
|
|----------|-----|
|
|
| **${platform}** | ${deployUrl ? `[${deployUrl}](${deployUrl})` : 'Deploying...'} |
|
|
|
|
---
|
|
🤖 *Auto-deployed by BlackRoad OS*`;
|
|
|
|
const { data: comments } = await github.rest.issues.listComments({
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
issue_number: context.issue.number,
|
|
});
|
|
|
|
const botComment = comments.find(c => c.body.includes('Preview Deployment Ready'));
|
|
|
|
if (botComment) {
|
|
await github.rest.issues.updateComment({
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
comment_id: botComment.id,
|
|
body: body
|
|
});
|
|
} else {
|
|
await github.rest.issues.createComment({
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
issue_number: context.issue.number,
|
|
body: body
|
|
});
|
|
}
|