Skip to content
Open
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
59 changes: 2 additions & 57 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -167,41 +167,10 @@ jobs:
run: pnpm install --frozen-lockfile
working-directory: .

- name: Setup pscale
uses: planetscale/setup-pscale-action@v1

- name: Generate PlanetScale branch password
env:
PLANETSCALE_SERVICE_TOKEN_ID: ${{ secrets.PLANETSCALE_SERVICE_TOKEN_ID }}
PLANETSCALE_SERVICE_TOKEN: ${{ secrets.PLANETSCALE_SERVICE_TOKEN }}
run: |
branch="${STAGE}"
if [ "$branch" = "prod" ]; then
branch="main"
fi

response=$(pscale password create ${{ secrets.PLANETSCALE_DATABASE_NAME }} "$branch" "" -f json --org ${{ secrets.PLANETSCALE_ORGANIZATION }})

id=$(echo "$response" | jq -r '.id')
host=$(echo "$response" | jq -r '.access_host_url')
username=$(echo "$response" | jq -r '.username')
password=$(echo "$response" | jq -r '.plain_text')
echo "PASSWORD_ID=$id" >> $GITHUB_ENV
database_url="mysql://$username:$password@$host/${{ secrets.PLANETSCALE_DATABASE_NAME }}"
echo "DATABASE_URL=$database_url" >> $GITHUB_ENV
echo "::add-mask::$database_url"

- name: Push schema to PlanetScale branch
run: pnpm --filter wodsmith-start exec drizzle-kit push
working-directory: .
env:
DATABASE_URL: ${{ env.DATABASE_URL }}

- name: Deploy with Alchemy
run: pnpm run deploy
env:
STAGE: ${{ env.STAGE }}
DATABASE_URL: ${{ env.DATABASE_URL }}
CLOUDFLARE_ACCOUNT_ID: ${{ vars.CLOUDFLARE_ACCOUNT_ID }}
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
ALCHEMY_PASSWORD: ${{ secrets.ALCHEMY_PASSWORD }}
Expand All @@ -218,6 +187,7 @@ jobs:
# AI configuration (optional)
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
BRAINTRUST_API_KEY: ${{ secrets.BRAINTRUST_API_KEY }}
CF_AIG_TOKEN: ${{ secrets.CF_AIG_TOKEN }}
# Stripe secrets - prod and demo get their respective keys
STRIPE_API_KEY: ${{ env.STAGE == 'prod' && secrets.STRIPE_SECRET_KEY || (env.STAGE == 'demo' && secrets.STRIPE_SECRET_KEY_DEMO || '') }}
STRIPE_SECRET_KEY: ${{ env.STAGE == 'prod' && secrets.STRIPE_SECRET_KEY || (env.STAGE == 'demo' && secrets.STRIPE_SECRET_KEY_DEMO || '') }}
Expand Down Expand Up @@ -264,32 +234,6 @@ jobs:
run: pnpm install --frozen-lockfile
working-directory: .

- name: Setup pscale
uses: planetscale/setup-pscale-action@v1

- name: Generate PlanetScale demo branch password
env:
PLANETSCALE_SERVICE_TOKEN_ID: ${{ secrets.PLANETSCALE_SERVICE_TOKEN_ID }}
PLANETSCALE_SERVICE_TOKEN: ${{ secrets.PLANETSCALE_SERVICE_TOKEN }}
run: |
response=$(pscale password create ${{ secrets.PLANETSCALE_DATABASE_NAME }} demo "" -f json --org ${{ secrets.PLANETSCALE_ORGANIZATION }})

id=$(echo "$response" | jq -r '.id')
host=$(echo "$response" | jq -r '.access_host_url')
username=$(echo "$response" | jq -r '.username')
password=$(echo "$response" | jq -r '.plain_text')
echo "PASSWORD_ID=$id" >> $GITHUB_ENV
database_url="mysql://$username:$password@$host/${{ secrets.PLANETSCALE_DATABASE_NAME }}"
echo "DATABASE_URL=$database_url" >> $GITHUB_ENV
echo "::add-mask::$database_url"

- name: Push schema to PlanetScale demo branch
run: pnpm --filter wodsmith-start exec drizzle-kit push
working-directory: .
env:
DATABASE_URL: ${{ env.DATABASE_URL }}


- name: Deploy with Alchemy
run: pnpm run deploy
env:
Expand All @@ -310,6 +254,7 @@ jobs:
# AI configuration (optional)
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
BRAINTRUST_API_KEY: ${{ secrets.BRAINTRUST_API_KEY }}
CF_AIG_TOKEN: ${{ secrets.CF_AIG_TOKEN }}
# Both point to same secret - STRIPE_API_KEY is for Alchemy webhook creation,
# STRIPE_SECRET_KEY is for runtime API calls
STRIPE_API_KEY: ${{ secrets.STRIPE_SECRET_KEY_DEMO }}
Expand Down
47 changes: 22 additions & 25 deletions apps/wodsmith-start/alchemy.run.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ import {
Branch as PlanetScaleBranch,
Password as PlanetScalePassword,
} from "alchemy/planetscale"
import { Exec } from "alchemy/os"
import { CloudflareStateStore } from "alchemy/state"
import { WebhookEndpoint } from "alchemy/stripe"

Expand Down Expand Up @@ -247,33 +248,25 @@ const psBranch =
adopt: true,
})

const psPassword = await PlanetScalePassword(`ps-password-${stage}`, {
const psPassword = await PlanetScalePassword(`ps-deploy-password-${stage}`, {
organization: psOrg,
database: psDbName,
branch: psBranch ?? psBranchName,
role: "admin",
})

const ciDatabaseUrl = process.env.DATABASE_URL
? new URL(process.env.DATABASE_URL)
: undefined
const hyperdriveOrigin = ciDatabaseUrl
? {
host: ciDatabaseUrl.hostname,
database: ciDatabaseUrl.pathname.slice(1),
user: decodeURIComponent(ciDatabaseUrl.username),
password: decodeURIComponent(ciDatabaseUrl.password),
port: ciDatabaseUrl.port ? Number(ciDatabaseUrl.port) : 3306,
scheme: "mysql" as const,
}
: {
host: psPassword.host,
database: psDbName,
user: psPassword.username,
password: psPassword.password.unencrypted,
port: 3306,
scheme: "mysql" as const,
}
const databaseUrl = alchemy.secret(
`mysql://${encodeURIComponent(psPassword.username)}:${encodeURIComponent(
psPassword.password.unencrypted,
)}@${psPassword.host}/${psDbName}`,
)

await Exec(`push-schema-${stage}`, {
command: "pnpm exec drizzle-kit push",
env: {
DATABASE_URL: databaseUrl,
},
})

/**
* Cloudflare Hyperdrive for PlanetScale connection pooling and caching.
Expand All @@ -287,10 +280,14 @@ const hyperdriveOrigin = ciDatabaseUrl
* which exposes a `connectionString` for use with standard MySQL drivers (mysql2).
*/
const hyperdrive = await Hyperdrive(`hyperdrive-${stage}`, {
// CI creates a fresh PlanetScale branch password before deploy and verifies it
// with drizzle-kit. Prefer that URL so stale Alchemy password state cannot
// make Cloudflare reject Hyperdrive updates during credential validation.
origin: hyperdriveOrigin,
origin: {
host: psPassword.host,
database: psDbName,
user: psPassword.username,
password: psPassword.password.unencrypted,
port: 3306,
scheme: "mysql",
},
caching: {
disabled: true,
},
Expand Down
Loading