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
4 changes: 2 additions & 2 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
BETTER_AUTH_SECRET=""
BETTER_AUTH_URL="http://localhost:3000"
GITHUB_CLIENT_ID=""
GITHUB_CLIENT_SECRET=""
OAUTH_GITHUB_CLIENT_ID=""
OAUTH_GITHUB_CLIENT_SECRET=""
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: "Run Code Quality Checks"
description: "Install dependencies and run formatting, linting, type checking, and tests"
name: "Setup Bun and Dependencies"
description: "Setup Bun and install dependencies"

runs:
using: "composite"
Expand All @@ -12,7 +12,3 @@ runs:
- name: Install dependencies
shell: bash
run: bun install --frozen-lockfile --prefer-offline

- name: Run checks
shell: bash
run: bun run check
16 changes: 0 additions & 16 deletions .github/workflows/check.yml

This file was deleted.

221 changes: 60 additions & 161 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
@@ -1,187 +1,86 @@
name: Deploy to Cloudflare Workers
name: Production Deploy

# Requires repository secrets:
# - CLOUDFLARE_ACCOUNT_ID: Cloudflare account ID for the worker.
# - CLOUDFLARE_API_TOKEN: Token with Workers Scripts Edit permissions.
#
# Requires production environment variables:
# - BETTER_AUTH_URL: Production domain URL (e.g., https://startkit.dev)
# - OAUTH_GITHUB_CLIENT_ID: GitHub OAuth app client ID
#
# Requires production environment secrets:
# - BETTER_AUTH_SECRET: Better Auth secret key
# - OAUTH_GITHUB_CLIENT_SECRET: GitHub OAuth app client secret

on:
pull_request:
types: [opened, synchronize, reopened, closed]
push:
branches: [main]
branches:
- main
workflow_dispatch:

jobs:
# Check code quality on PRs and main pushes
check:
if: github.event.action != 'closed'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: ./.github/actions/check
permissions:
contents: read
deployments: write

# Prevent multiple production deployments from running simultaneously
# Ensures deployments complete in order without race conditions
concurrency:
group: production-deploy
cancel-in-progress: false

# Deploy preview environment on PRs
preview:
if: github.event_name == 'pull_request' && github.event.action != 'closed'
needs: check
jobs:
deploy:
runs-on: ubuntu-latest
environment:
name: preview
url: https://startkit-preview-pr-${{ github.event.number }}.startkit-dev.workers.dev
outputs:
preview-url: ${{ steps.deploy.outputs.deployment-url }}
db-name: ${{ steps.setup-db.outputs.db-name }}
environment: production
steps:
- uses: actions/checkout@v4

- name: Setup Bun
uses: oven-sh/setup-bun@v2
with:
bun-version: latest
- name: Checkout
uses: actions/checkout@v5

- name: Install dependencies
run: bun install --frozen-lockfile
uses: ./.github/actions/setup

- name: Setup preview database and run migrations
id: setup-db
run: |
DB_NAME="startkit-preview-pr-${{ github.event.number }}"
echo "db-name=$DB_NAME" >> $GITHUB_OUTPUT

# Create preview database and capture the database ID
bunx wrangler d1 create "$DB_NAME" --output json > db-output.json
DB_ID=$(cat db-output.json | jq -r '.result.uuid')
echo "DB_ID=$DB_ID" >> $GITHUB_ENV

# Run migrations on preview database
bunx wrangler d1 migrations apply "$DB_NAME" --remote
env:
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
- name: Run code quality checks
run: bun run check

- name: Build application
- name: Build project
run: bun run build
env:
BETTER_AUTH_URL: ${{ vars.BETTER_AUTH_URL || format('https://startkit-preview-pr-{0}.startkit-dev.workers.dev', github.event.number) }}
BETTER_AUTH_SECRET: ${{ secrets.BETTER_AUTH_SECRET }}
GITHUB_CLIENT_ID: ${{ secrets.OAUTH_GITHUB_CLIENT_ID }}
GITHUB_CLIENT_SECRET: ${{ secrets.OAUTH_GITHUB_CLIENT_SECRET }}

- name: Create temporary wrangler config for preview
run: |
cat > wrangler.preview.jsonc << EOF
{
"name": "startkit-preview-pr-${{ github.event.number }}",
"main": "@tanstack/react-start/server-entry",
"compatibility_date": "2025-09-24",
"compatibility_flags": ["nodejs_compat"],
"observability": {
"enabled": true
},
"vars": {
"BETTER_AUTH_URL": "${{ vars.BETTER_AUTH_URL || format('https://startkit-preview-pr-{0}.startkit-dev.workers.dev', github.event.number) }}",
"GITHUB_CLIENT_ID": "${{ secrets.OAUTH_GITHUB_CLIENT_ID }}"
},
"d1_databases": [
{
"binding": "DB",
"database_name": "startkit-preview-pr-${{ github.event.number }}",
"database_id": "${{ env.DB_ID }}"
}
]
}
EOF

- name: Deploy to Cloudflare Workers
id: deploy
uses: cloudflare/wrangler-action@v3
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
command: deploy --config wrangler.preview.jsonc

- name: Comment PR
uses: actions/github-script@v7
with:
script: |
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: `🚀 **Preview deployment is ready!**

**Preview URL:** ${{ steps.deploy.outputs.deployment-url }}
**Database:** startkit-preview-pr-${{ github.event.number }}

This preview will be automatically deleted when the PR is closed.`
})

# Clean up preview environment when PR is closed
cleanup:
if: github.event_name == 'pull_request' && github.event.action == 'closed'
runs-on: ubuntu-latest
steps:
- name: Delete preview deployment
uses: cloudflare/wrangler-action@v3
continue-on-error: true
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
command: delete startkit-preview-pr-${{ github.event.number }} --force

- name: Delete preview database
- name: Run database migrations
uses: cloudflare/wrangler-action@v3
continue-on-error: true
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
command: d1 delete startkit-preview-pr-${{ github.event.number }} --force

- name: Comment PR
uses: actions/github-script@v7
with:
script: |
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: `🧹 **Preview environment cleaned up**

The preview deployment and database for this PR have been deleted.`
})

# Deploy to production on main branch
production:
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
needs: check
runs-on: ubuntu-latest
environment:
name: production
url: ${{ vars.BETTER_AUTH_URL }}
steps:
- uses: actions/checkout@v4

- name: Setup Bun
uses: oven-sh/setup-bun@v2
with:
bun-version: latest

- name: Install dependencies
run: bun install --frozen-lockfile
command: d1 migrations apply DB --remote
packageManager: bun

- name: Run database migrations
- name: Deploy Worker
uses: cloudflare/wrangler-action@v3
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
command: d1 migrations apply DB --remote

- name: Build application
run: bun run build
command: deploy
packageManager: bun
vars: |
BETTER_AUTH_URL
OAUTH_GITHUB_CLIENT_ID
secrets: |
BETTER_AUTH_SECRET
OAUTH_GITHUB_CLIENT_SECRET
env:
BETTER_AUTH_URL: ${{ vars.BETTER_AUTH_URL }}
BETTER_AUTH_SECRET: ${{ secrets.BETTER_AUTH_SECRET }}
GITHUB_CLIENT_ID: ${{ secrets.OAUTH_GITHUB_CLIENT_ID }}
GITHUB_CLIENT_SECRET: ${{ secrets.OAUTH_GITHUB_CLIENT_SECRET }}
OAUTH_GITHUB_CLIENT_ID: ${{ vars.OAUTH_GITHUB_CLIENT_ID }}
OAUTH_GITHUB_CLIENT_SECRET: ${{ secrets.OAUTH_GITHUB_CLIENT_SECRET }}

- name: Deploy to production
uses: cloudflare/wrangler-action@v3
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
command: deploy
- name: Summarize deployment
if: success()
run: |
{
echo "### Deployed"
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
echo "Triggered manually via workflow_dispatch"
else
echo "Triggered by push to main"
fi
echo "Commit: ${{ github.sha }}"
} >>"$GITHUB_STEP_SUMMARY"
96 changes: 96 additions & 0 deletions .github/workflows/preview.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
name: Preview Deploy

# Requires repository secrets:
# - CLOUDFLARE_ACCOUNT_ID: Cloudflare account ID for the worker.
# - CLOUDFLARE_API_TOKEN: Token with Workers Scripts Edit permissions.
#
# Requires preview environment variables:
# - OAUTH_GITHUB_CLIENT_ID: GitHub OAuth app client ID
#
# Requires preview environment secrets:
# - BETTER_AUTH_SECRET: Better Auth secret key
# - OAUTH_GITHUB_CLIENT_SECRET: GitHub OAuth app client secret

on:
pull_request:
types: [opened, reopened, synchronize]

permissions:
contents: read
pull-requests: write

jobs:
upload-preview:
name: Upload Worker Preview
runs-on: ubuntu-latest
environment: preview
env:
PR_ALIAS: pr-${{ github.event.number }}
WORKER_NAME: startkit-preview
WORKER_SUBDOMAIN: blendist
steps:
- name: Checkout
uses: actions/checkout@v5

- name: Install dependencies
uses: ./.github/actions/setup

- name: Run code quality checks
run: bun run check

- name: Build project
run: bun run build
env:
CLOUDFLARE_ENV: preview
BETTER_AUTH_URL: ${{ format('https://{0}-{1}.{2}.workers.dev', env.PR_ALIAS, env.WORKER_NAME, env.WORKER_SUBDOMAIN) }}
OAUTH_GITHUB_CLIENT_ID: ${{ vars.OAUTH_GITHUB_CLIENT_ID }}

- name: Run database migrations
uses: cloudflare/wrangler-action@v3
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
command: d1 migrations apply DB --remote --env preview
packageManager: bun

- name: Upload preview Worker
id: wrangler
uses: cloudflare/wrangler-action@v3
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
command: versions upload --preview-alias ${{ env.PR_ALIAS }}
packageManager: bun
vars: |
BETTER_AUTH_URL
OAUTH_GITHUB_CLIENT_ID
env:
CLOUDFLARE_ENV: preview
BETTER_AUTH_SECRET: ${{ secrets.BETTER_AUTH_SECRET }}
BETTER_AUTH_URL: ${{ format('https://{0}-{1}.{2}.workers.dev', env.PR_ALIAS, env.WORKER_NAME, env.WORKER_SUBDOMAIN) }}
OAUTH_GITHUB_CLIENT_ID: ${{ vars.OAUTH_GITHUB_CLIENT_ID }}
OAUTH_GITHUB_CLIENT_SECRET: ${{ secrets.OAUTH_GITHUB_CLIENT_SECRET }}

- name: Find existing comment
uses: peter-evans/find-comment@v3
id: find-comment
with:
token: ${{ secrets.GITHUB_TOKEN }}
issue-number: ${{ github.event.number }}
comment-author: "github-actions[bot]"
body-includes: "<!-- ${{ env.WORKER_NAME }} -->"

- name: Comment preview link
if: success()
uses: peter-evans/create-or-update-comment@v4
with:
token: ${{ secrets.GITHUB_TOKEN }}
issue-number: ${{ github.event.number }}
comment-id: ${{ steps.find-comment.outputs.comment-id }}
body: |
<!-- ${{ env.WORKER_NAME }} -->
**Preview Deployment**

- Version Preview URL: ${{ steps.wrangler.outputs.deployment-url }}
- Version Preview Alias URL: ${{ format('[https://{0}-{1}.{2}.workers.dev](https://{0}-{1}.{2}.workers.dev)', env.PR_ALIAS, env.WORKER_NAME, env.WORKER_SUBDOMAIN) }}
edit-mode: replace
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,6 @@ dist

# Cloudflare
.wrangler

# Local settings
*.local.json
Loading