Skip to content

Fix localStorage vulnerability #300

Fix localStorage vulnerability

Fix localStorage vulnerability #300

Workflow file for this run

name: Preview Deployment
on:
pull_request:
types: [opened, synchronize, reopened]
jobs:
deploy-preview:
name: Deploy Convex Preview
runs-on: ubuntu-latest
# Only run for PRs from the same repo (not forks)
if: github.event.pull_request.head.repo.full_name == github.repository
permissions:
pull-requests: write
contents: read
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Bun
uses: oven-sh/setup-bun@v1
with:
bun-version: "1.3.8"
- name: Install dependencies
run: bun install --frozen-lockfile
- name: Deploy Convex Preview
id: convex-deploy
working-directory: apps/server
env:
CONVEX_DEPLOY_KEY: ${{ secrets.CONVEX_PREVIEW_DEPLOY_KEY }}
run: |
PR_NUM=${{ github.event.pull_request.number }}
echo "🚀 Deploying Convex preview for PR #${PR_NUM}..."
# First deploy creates the preview (social providers are optional,
# so this succeeds even without env vars set yet)
OUTPUT_FILE=$(mktemp)
bunx convex deploy --preview-create "pr-${PR_NUM}" 2>&1 | tee "$OUTPUT_FILE"
CONVEX_URL=$(grep -o 'https://[a-z0-9-]*\.convex\.cloud' "$OUTPUT_FILE" | head -1)
if [ -z "$CONVEX_URL" ]; then
echo "❌ Failed to extract Convex URL"
exit 1
fi
CONVEX_SITE_URL=$(echo "$CONVEX_URL" | sed 's/\.convex\.cloud/.convex.site/')
echo "✅ Convex Preview deployed!"
echo " Cloud URL: $CONVEX_URL"
echo " Site URL: $CONVEX_SITE_URL"
echo "convex_url=$CONVEX_URL" >> $GITHUB_OUTPUT
echo "convex_site_url=$CONVEX_SITE_URL" >> $GITHUB_OUTPUT
- name: Set Convex Environment Variables
working-directory: apps/server
env:
CONVEX_DEPLOY_KEY: ${{ secrets.CONVEX_PREVIEW_DEPLOY_KEY }}
BETTER_AUTH_SECRET: ${{ secrets.BETTER_AUTH_SECRET }}
GITHUB_CLIENT_ID: ${{ secrets.AUTH_GITHUB_CLIENT_ID }}
GITHUB_CLIENT_SECRET: ${{ secrets.AUTH_GITHUB_CLIENT_SECRET }}
VERCEL_CLIENT_ID: ${{ secrets.VERCEL_CLIENT_ID }}
VERCEL_CLIENT_SECRET: ${{ secrets.VERCEL_CLIENT_SECRET }}
run: |
PR_NUM=${{ github.event.pull_request.number }}
RAILWAY_URL="https://web-openchat-pr-${PR_NUM}.up.railway.app"
bunx convex env set SITE_URL "$RAILWAY_URL" --preview-name "pr-${PR_NUM}"
bunx convex env set BETTER_AUTH_SECRET "$BETTER_AUTH_SECRET" --preview-name "pr-${PR_NUM}"
bunx convex env set GITHUB_CLIENT_ID "$GITHUB_CLIENT_ID" --preview-name "pr-${PR_NUM}"
bunx convex env set GITHUB_CLIENT_SECRET "$GITHUB_CLIENT_SECRET" --preview-name "pr-${PR_NUM}"
bunx convex env set VERCEL_CLIENT_ID "$VERCEL_CLIENT_ID" --preview-name "pr-${PR_NUM}"
bunx convex env set VERCEL_CLIENT_SECRET "$VERCEL_CLIENT_SECRET" --preview-name "pr-${PR_NUM}"
bunx convex env set PRODUCTION_CONVEX_SITE_URL "https://outgoing-setter-201.convex.site" --preview-name "pr-${PR_NUM}"
echo "✅ Convex env vars set for pr-${PR_NUM}"
- name: Configure Railway Environment
env:
RAILWAY_TOKEN: ${{ secrets.RAILWAY_TOKEN }}
REDIS_RAILWAY_REF: ${{ '${{Redis.REDIS_URL}}' }}
run: |
echo "🚂 Configuring Railway environment via GraphQL API..."
PR_NUM=${{ github.event.pull_request.number }}
CONVEX_URL="${{ steps.convex-deploy.outputs.convex_url }}"
CONVEX_SITE_URL="${{ steps.convex-deploy.outputs.convex_site_url }}"
ENV_NAME="openchat-pr-${PR_NUM}"
PROJECT_ID="e3803b5c-22bf-4cbe-a8b3-2e4c8a5fbe8a"
SERVICE_ID="f12f449e-b9d8-471b-94ea-7107b7c5da47"
# Wait for Railway to create the PR environment
echo "Waiting for Railway PR environment..."
sleep 20
# Get the environment ID
echo "Looking up environment ID for ${ENV_NAME}..."
ENV_RESPONSE=$(curl -s -X POST \
-H "Authorization: Bearer ${RAILWAY_TOKEN}" \
-H "Content-Type: application/json" \
-d "{\"query\": \"query { project(id: \\\"${PROJECT_ID}\\\") { environments { edges { node { id name } } } } }\"}" \
https://backboard.railway.app/graphql/v2)
echo "Environment response: ${ENV_RESPONSE}"
ENV_ID=$(echo "$ENV_RESPONSE" | jq -r ".data.project.environments.edges[] | select(.node.name == \"${ENV_NAME}\") | .node.id")
if [ -z "$ENV_ID" ] || [ "$ENV_ID" == "null" ]; then
echo "⚠️ Could not find environment ${ENV_NAME}, skipping Railway config"
exit 0
fi
echo "Found environment ID: ${ENV_ID}"
# Set VITE_CONVEX_URL
echo "Setting VITE_CONVEX_URL..."
curl -s -X POST \
-H "Authorization: Bearer ${RAILWAY_TOKEN}" \
-H "Content-Type: application/json" \
-d "{\"query\": \"mutation { variableUpsert(input: { projectId: \\\"${PROJECT_ID}\\\", environmentId: \\\"${ENV_ID}\\\", serviceId: \\\"${SERVICE_ID}\\\", name: \\\"VITE_CONVEX_URL\\\", value: \\\"${CONVEX_URL}\\\" }) }\"}" \
https://backboard.railway.app/graphql/v2
# Set VITE_CONVEX_SITE_URL
echo "Setting VITE_CONVEX_SITE_URL..."
curl -s -X POST \
-H "Authorization: Bearer ${RAILWAY_TOKEN}" \
-H "Content-Type: application/json" \
-d "{\"query\": \"mutation { variableUpsert(input: { projectId: \\\"${PROJECT_ID}\\\", environmentId: \\\"${ENV_ID}\\\", serviceId: \\\"${SERVICE_ID}\\\", name: \\\"VITE_CONVEX_SITE_URL\\\", value: \\\"${CONVEX_SITE_URL}\\\" }) }\"}" \
https://backboard.railway.app/graphql/v2
# Set REDIS_URL (Railway service reference)
echo "Setting REDIS_URL..."
curl -s -X POST \
-H "Authorization: Bearer ${RAILWAY_TOKEN}" \
-H "Content-Type: application/json" \
-d "{\"query\": \"mutation { variableUpsert(input: { projectId: \\\"${PROJECT_ID}\\\", environmentId: \\\"${ENV_ID}\\\", serviceId: \\\"${SERVICE_ID}\\\", name: \\\"REDIS_URL\\\", value: \\\"${REDIS_RAILWAY_REF}\\\" }) }\"}" \
https://backboard.railway.app/graphql/v2
echo "✅ Railway environment variables updated"
- name: Comment on PR
uses: actions/github-script@v7
with:
script: |
const prNumber = context.payload.pull_request.number;
const convexUrl = '${{ steps.convex-deploy.outputs.convex_url }}';
const convexSiteUrl = '${{ steps.convex-deploy.outputs.convex_site_url }}';
const railwayUrl = `https://web-openchat-pr-${prNumber}.up.railway.app`;
const body = `## 🚀 Preview Deployment Ready
| Environment | URL |
|------------|-----|
| **Frontend** | [${railwayUrl}](${railwayUrl}) |
| **Convex Dashboard** | [Dashboard](https://dashboard.convex.dev) |
### Convex Preview Backend
- Cloud URL: \`${convexUrl}\`
- Site URL: \`${convexSiteUrl}\`
---
<sub>🤖 Deployed automatically by GitHub Actions</sub>`;
// Find existing comment
const { data: comments } = await github.rest.issues.listComments({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: prNumber,
});
const botComment = comments.find(comment =>
comment.user.type === 'Bot' &&
comment.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: prNumber,
body: body
});
}
- name: Summary
if: always()
run: |
PR_NUM=${{ github.event.pull_request.number }}
echo "## Preview Deployment Summary" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "| Component | Status |" >> $GITHUB_STEP_SUMMARY
echo "|-----------|--------|" >> $GITHUB_STEP_SUMMARY
echo "| Convex Preview | ✅ Deployed |" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "### URLs" >> $GITHUB_STEP_SUMMARY
echo "- Frontend: https://web-openchat-pr-${PR_NUM}.up.railway.app" >> $GITHUB_STEP_SUMMARY
echo "- Convex: ${{ steps.convex-deploy.outputs.convex_url }}" >> $GITHUB_STEP_SUMMARY