Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions .github/workflows/cleanup-preview.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
name: Cleanup Preview

on:
pull_request:
types: [closed]

jobs:
cleanup:
name: Delete Preview Deployment
runs-on: ubuntu-latest
permissions:
pull-requests: write

steps:
- name: Delete Preview Deployment
uses: cloudflare/wrangler-action@v3
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
command: delete --name aicodingstack-pr-${{ github.event.pull_request.number }} --force
continue-on-error: true

- name: Comment Cleanup Status
uses: actions/github-script@v7
with:
script: |
const prNumber = context.payload.pull_request.number;

await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: prNumber,
body: `### Preview deployment cleaned up\n\nThe preview deployment for PR #${prNumber} has been removed.`
});
159 changes: 102 additions & 57 deletions .github/workflows/deploy-preview.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,57 @@ name: Deploy Preview

on:
pull_request:
branches: [main]
push:
branches-ignore: [main, develop]

concurrency:
group: preview-${{ github.ref }}
group: preview-${{ github.event.pull_request.number || github.ref_name }}
cancel-in-progress: true

jobs:
deploy-preview:
name: Deploy Preview to Cloudflare Pages
deploy:
name: Deploy Preview to Cloudflare Workers
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write
deployments: write

steps:
- name: Checkout code
uses: actions/checkout@v6

- name: Compute preview identifiers
id: preview_meta
run: |
if [[ "${{ github.event_name }}" == "pull_request" ]]; then
CF_BRANCH="pr-${{ github.event.pull_request.number }}"
CONTEXT_LABEL="PR #${{ github.event.pull_request.number }}"
else
RAW_BRANCH="${{ github.ref_name }}"
SLUG="$(echo "$RAW_BRANCH" | tr '[:upper:]' '[:lower:]' | sed -E 's#[^a-z0-9]+#-#g; s#(^-+|-+$)##g' | cut -c1-40)"
if [[ -z "$SLUG" ]]; then
SLUG="branch"
fi
CF_BRANCH="br-$SLUG"
CONTEXT_LABEL="Branch $RAW_BRANCH"
fi

# Cloudflare Preview URLs (aliased) format:
# <ALIAS>-<WORKER_NAME>.<SUBDOMAIN>.workers.dev
# See: https://developers.cloudflare.com/workers/configuration/previews/
PREVIEW_ALIAS="$CF_BRANCH"
WORKER_NAME="aicodingstack"
PREVIEW_URL="https://${PREVIEW_ALIAS}-${WORKER_NAME}.pr-preview.workers.dev"

{
echo "cf_branch=$CF_BRANCH"
echo "worker_name=$WORKER_NAME"
echo "preview_alias=$PREVIEW_ALIAS"
echo "preview_url=$PREVIEW_URL"
echo "context_label=$CONTEXT_LABEL"
} >> "$GITHUB_OUTPUT"

- name: Setup Node.js
uses: actions/setup-node@v6
with:
Expand All @@ -28,61 +62,72 @@ jobs:
- name: Install dependencies
run: npm ci

- name: Run validation tests
run: npm run test:validate

- name: Generate manifests and metadata
run: |
npm run generate:manifests
npm run generate:metadata
- name: Run CI tests
run: npm run test:ci

- name: Build with OpenNext
run: npm run build
env:
BUILD_TIME: ${{ github.event.pull_request.updated_at }}

# TODO: Configure Cloudflare Pages deployment
# You'll need to add these secrets to your repository:
# - CLOUDFLARE_API_TOKEN
# - CLOUDFLARE_ACCOUNT_ID
#
# Uncomment the steps below after adding the secrets:
#
# - name: Deploy to Cloudflare Pages (Preview)
# id: deploy
# uses: cloudflare/wrangler-action@v3
# with:
# apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
# accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
# command: pages deploy .open-next --project-name=aicodingstack --branch=preview-${{ github.event.pull_request.number }}
#
# - name: Comment preview URL
# uses: actions/github-script@v7
# with:
# script: |
# const previewUrl = '${{ steps.deploy.outputs.deployment-url }}';
# const comment = `## πŸš€ Preview Deployment
#
# Preview is ready!
#
# **Preview URL:** ${previewUrl}
#
# ### Build Details
# - **Commit:** ${context.sha.substring(0, 7)}
# - **Build Time:** ${{ github.event.pull_request.updated_at }}
#
# The preview will be automatically deleted when this PR is merged or closed.`;
#
# github.rest.issues.createComment({
# issue_number: context.issue.number,
# owner: context.repo.owner,
# repo: context.repo.repo,
# body: comment
# });

- name: Preview deployment placeholder
BUILD_TIME: ${{ github.event.pull_request.updated_at || github.event.head_commit.timestamp }}

- name: Deploy Preview
uses: cloudflare/wrangler-action@v3
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
command: versions upload --preview-alias ${{ steps.preview_meta.outputs.preview_alias }}

- name: Comment Preview URL
if: github.event_name == 'pull_request'
uses: actions/github-script@v7
env:
PREVIEW_URL: ${{ steps.preview_meta.outputs.preview_url }}
with:
script: |
const prNumber = context.payload.pull_request.number;
const previewUrl = process.env.PREVIEW_URL;
const commitSha = context.sha.substring(0, 7);

// Find existing bot comment
const { data: comments } = await github.rest.issues.listComments({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: prNumber,
});

const botComment = comments.find(c =>
c.user.type === 'Bot' && c.body.includes('Preview deployment')
);

const body = `### Preview deployment

| Status | URL |
|--------|-----|
| Ready | [${previewUrl}](${previewUrl}) |

**Commit:** \`${commitSha}\`
**Updated:** ${new Date().toISOString()}`;

if (botComment) {
await github.rest.issues.updateComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: botComment.id,
body
});
} else {
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: prNumber,
body
});
}

- name: Deployment summary
run: |
echo "⚠️ Preview deployment not yet configured"
echo "To enable preview deployments:"
echo "1. Add CLOUDFLARE_API_TOKEN and CLOUDFLARE_ACCOUNT_ID to repository secrets"
echo "2. Uncomment the deployment steps in .github/workflows/deploy-preview.yml"
echo "### Preview Deployment" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "- **Context:** ${{ steps.preview_meta.outputs.context_label }}" >> $GITHUB_STEP_SUMMARY
echo "- **URL:** ${{ steps.preview_meta.outputs.preview_url }}" >> $GITHUB_STEP_SUMMARY
echo "- **Commit:** ${{ github.sha }}" >> $GITHUB_STEP_SUMMARY
56 changes: 20 additions & 36 deletions .github/workflows/deploy-production.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,20 @@ on:
branches: [main]

concurrency:
group: production
group: production-deploy
cancel-in-progress: false

jobs:
deploy-production:
name: Deploy to Cloudflare Pages
name: Deploy to Cloudflare Workers
runs-on: ubuntu-latest
permissions:
contents: read
deployments: write
environment:
name: production
url: https://aicodingstack.io

steps:
- name: Checkout code
uses: actions/checkout@v6
Expand All @@ -28,45 +32,25 @@ jobs:
- name: Install dependencies
run: npm ci

- name: Run validation tests
run: npm run test:validate

- name: Generate manifests and metadata
run: |
npm run generate:manifests
npm run generate:metadata
- name: Run CI tests
run: npm run test:ci

- name: Build with OpenNext
run: npm run build
env:
BUILD_TIME: ${{ github.event.head_commit.timestamp }}

# TODO: Configure Cloudflare Pages deployment
# You'll need to add these secrets to your repository:
# - CLOUDFLARE_API_TOKEN
# - CLOUDFLARE_ACCOUNT_ID
#
# Uncomment the steps below after adding the secrets:
#
# - name: Deploy to Cloudflare Pages (Production)
# uses: cloudflare/wrangler-action@v3
# with:
# apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
# accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
# command: pages deploy .open-next --project-name=aicodingstack --branch=main
#
# - name: Notify deployment success
# run: |
# echo "βœ… Production deployment successful!"
# echo "🌐 Site: https://aicodingstack.io"
# echo "πŸ“ Commit: ${{ github.sha }}"
- name: Deploy to Production
uses: cloudflare/wrangler-action@v3
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
command: deploy --env production

- name: Production deployment placeholder
- name: Deployment summary
run: |
echo "⚠️ Production deployment not yet configured"
echo "To enable production deployments:"
echo "1. Add CLOUDFLARE_API_TOKEN and CLOUDFLARE_ACCOUNT_ID to repository secrets"
echo "2. Uncomment the deployment steps in .github/workflows/deploy-production.yml"
echo ""
echo "Manual deployment command:"
echo "npm run deploy"
echo "### Production Deployment" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "- **URL:** https://aicodingstack.io" >> $GITHUB_STEP_SUMMARY
echo "- **Commit:** ${{ github.sha }}" >> $GITHUB_STEP_SUMMARY
echo "- **Time:** $(date -u '+%Y-%m-%d %H:%M:%S UTC')" >> $GITHUB_STEP_SUMMARY
56 changes: 56 additions & 0 deletions .github/workflows/deploy-staging.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
name: Deploy Staging

on:
push:
branches: [develop]

concurrency:
group: staging-deploy
cancel-in-progress: true

jobs:
deploy-staging:
name: Deploy to Cloudflare Workers (Staging)
runs-on: ubuntu-latest
permissions:
contents: read
deployments: write
environment:
name: staging
url: https://staging.aicodingstack.io

steps:
- name: Checkout code
uses: actions/checkout@v6

- name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version: '22'
cache: 'npm'

- name: Install dependencies
run: npm ci

- name: Run CI tests
run: npm run test:ci

- name: Build with OpenNext
run: npm run build
env:
BUILD_TIME: ${{ github.event.head_commit.timestamp }}

- name: Deploy to Staging
uses: cloudflare/wrangler-action@v3
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
command: deploy --env staging

- name: Deployment summary
run: |
echo "### Staging Deployment" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "- **URL:** https://staging.aicodingstack.io" >> $GITHUB_STEP_SUMMARY
echo "- **Commit:** ${{ github.sha }}" >> $GITHUB_STEP_SUMMARY
echo "- **Time:** $(date -u '+%Y-%m-%d %H:%M:%S UTC')" >> $GITHUB_STEP_SUMMARY
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ next-env.d.ts
!.env.example

# claude settings
.claude/settings.local.json
.claude/settings.local*.json

# python cache
__pycache__/
Expand Down
Loading
Loading