/
githubmirror
/
tldraw
Обзор
Документация
Войти
/
githubmirror
/
tldraw
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
.github/workflows/deploy-dotcom.yml
203 строки
9 KB
Niall D
perf(dotcom): stop the OG render consumer resolving the same file twice (#9913)
07 авг 2026, 18:25
Не верифицирован
07 авг 2026, 18:25
d04e492
Код
Авторство
О чём код?
name: Deploy .com on: pull_request: types: [opened, synchronize, labeled, unlabeled] push: branches: - main - production permissions: write-all env: CI: 1 PRINT_GITHUB_ANNOTATIONS: 1 TLDRAW_ENV: ${{ (github.ref == 'refs/heads/production' && 'production') || (github.ref == 'refs/heads/main' && 'staging') || 'preview' }} defaults: run: shell: bash jobs: deploy: name: Deploy dotcom to ${{ (github.ref == 'refs/heads/production' && 'production') || (github.ref == 'refs/heads/main' && 'staging') || 'preview' }} timeout-minutes: 15 runs-on: ubuntu-latest-16-cores-arm-open environment: ${{ github.ref == 'refs/heads/production' && 'deploy-production' || 'deploy-staging' }} concurrency: dotcom-${{ github.ref == 'refs/heads/production' && 'deploy-production' || github.ref }} if: | github.event_name == 'push' || (github.event_name == 'pull_request' && contains(github.event.pull_request.labels.*.name, 'dotcom-preview-please')) steps: # - name: Notify initial start # uses: MineBartekSA/discord-webhook@v2 # if: github.ref == 'refs/heads/production' # with: # webhook: ${{ secrets.DISCORD_DEPLOY_WEBHOOK_URL }} # content: 'Preparing ${{ env.TLDRAW_ENV }} dotcom deploy: ${{ github.event.head_commit.message }} by ${{ github.event.head_commit.author.name }}' - name: Check out code uses: actions/checkout@v6 with: submodules: true fetch-depth: 0 - uses: ./.github/actions/setup - name: Determine zero deploy target id: deploy_target env: GH_TOKEN: ${{ github.token }} run: | if [[ "${GITHUB_REF}" == "refs/heads/production" ]]; then echo "DEPLOY_ZERO=flyio-multinode" >> $GITHUB_ENV elif [[ "${GITHUB_REF}" == "refs/heads/main" ]]; then echo "DEPLOY_ZERO=flyio-multinode" >> $GITHUB_ENV else echo "DEPLOY_ZERO=flyio" >> $GITHUB_ENV fi - name: Install Supabase CLI if: github.event_name == 'pull_request' uses: supabase/setup-cli@v1 with: # Pinned: v2.112.0 rejects the Management API's own timestamps, which # breaks `branches get` and `branches delete`. See supabase/cli#6115. version: 2.111.0 - name: Delete Supabase branch if: contains(github.event.pull_request.labels.*.name, 'reset-preview-db') env: SUPABASE_ACCESS_TOKEN: ${{ secrets.SUPABASE_ACCESS_TOKEN }} run: | supabase branches delete "pr-${{ github.event.number }}" \ --project-ref "${{ vars.SUPABASE_PREVIEW_PROJECT_ID }}" || echo "::warning::Failed to delete Supabase branch (may not exist yet)" - name: Create Supabase preview branch if: github.event_name == 'pull_request' env: SUPABASE_ACCESS_TOKEN: ${{ secrets.SUPABASE_ACCESS_TOKEN }} run: | BRANCH_NAME="pr-${{ github.event.number }}" PROJECT_REF="${{ vars.SUPABASE_PREVIEW_PROJECT_ID }}" # Create branch if it doesn't already exist. if supabase branches get "$BRANCH_NAME" \ --project-ref "$PROJECT_REF" > /dev/null 2>&1; then echo "Branch $BRANCH_NAME already exists." else supabase branches create "$BRANCH_NAME" --project-ref "$PROJECT_REF" > /dev/null echo "Branch $BRANCH_NAME created." fi # Wait for branch to be ready, then extract connection strings. # Write to a temp file to avoid secrets leaking into CI step output. BRANCH_JSON=$(mktemp) for i in $(seq 1 24); do # While the branch is still provisioning, `branches get` may exit # non-zero and/or write a non-JSON line to stdout (the newer CLI # renders an error there). Tolerate both: `|| true` keeps `set -e` # from aborting on a non-zero get, and the guarded jq below treats # any non-JSON / missing field as "not ready yet" so the loop retries. supabase branches get "$BRANCH_NAME" \ --project-ref "$PROJECT_REF" \ -o json > "$BRANCH_JSON" 2>/dev/null || true POSTGRES_URL_TRANSACTION=$(jq -r '.POSTGRES_URL // empty' "$BRANCH_JSON" 2>/dev/null || true) if [ -n "$POSTGRES_URL_TRANSACTION" ]; then echo "Branch $BRANCH_NAME is ready." break fi echo "Waiting for branch to be ready ($i/24)..." sleep 5 done POSTGRES_URL_NON_POOLING=$(jq -r '.POSTGRES_URL_NON_POOLING // empty' "$BRANCH_JSON" 2>/dev/null || true) rm "$BRANCH_JSON" if [ -z "$POSTGRES_URL_TRANSACTION" ]; then echo "::error::Branch not ready after 2 minutes — POSTGRES_URL still empty" exit 1 fi if [ -z "$POSTGRES_URL_NON_POOLING" ] || [ "$POSTGRES_URL_NON_POOLING" = "null" ]; then echo "::error::Failed to get POSTGRES_URL_NON_POOLING from branch" exit 1 fi # Rewrite transaction pooler (port 6543, IPv6-only) to session pooler # (port 5432, IPv4-compatible) since GitHub Actions runners are IPv4-only. POSTGRES_URL="${POSTGRES_URL_TRANSACTION/:6543/:5432}" echo "::add-mask::$POSTGRES_URL" echo "::add-mask::$POSTGRES_URL_TRANSACTION" echo "::add-mask::$POSTGRES_URL_NON_POOLING" echo "POSTGRES_URL=$POSTGRES_URL" >> "$GITHUB_ENV" echo "POSTGRES_URL_NON_POOLING=$POSTGRES_URL_NON_POOLING" >> "$GITHUB_ENV" - name: Build types run: yarn build-types - name: Setup Fly cli if: env.DEPLOY_ZERO == 'flyio' || env.DEPLOY_ZERO == 'flyio-multinode' uses: superfly/flyctl-actions/setup-flyctl@ed8efb33836e8b2096c7fd3ba1c8afe303ebbff1 # 1.6 - name: Deploy run: yarn tsx internal/scripts/deploy-dotcom.ts env: RELEASE_COMMIT_HASH: ${{ github.sha }} GH_TOKEN: ${{ github.token }} APP_ORIGIN: ${{ vars.APP_ORIGIN }} ASSET_UPLOAD: ${{ vars.ASSET_UPLOAD }} IMAGE_WORKER: ${{ vars.IMAGE_WORKER }} MULTIPLAYER_SERVER: ${{ vars.MULTIPLAYER_SERVER }} USER_CONTENT_SENTRY_DSN: ${{ secrets.USER_CONTENT_SENTRY_DSN }} USER_CONTENT_URL: ${{ vars.USER_CONTENT_URL }} NEXT_PUBLIC_GOOGLE_CLOUD_PROJECT_NUMBER: ${{ vars.NEXT_PUBLIC_GOOGLE_CLOUD_PROJECT_NUMBER }} SUPABASE_LITE_URL: ${{ vars.SUPABASE_LITE_URL }} VERCEL_ORG_ID: ${{ vars.VERCEL_ORG_ID }} VERCEL_PROJECT_ID: ${{ vars.VERCEL_DOTCOM_PROJECT_ID }} ANALYTICS_API_URL: ${{ secrets.ANALYTICS_API_URL }} ANALYTICS_API_TOKEN: ${{ secrets.ANALYTICS_API_TOKEN }} ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} ASSET_UPLOAD_SENTRY_DSN: ${{ secrets.ASSET_UPLOAD_SENTRY_DSN }} BOTCOM_POSTGRES_CONNECTION_STRING: ${{ env.POSTGRES_URL_NON_POOLING || secrets.BOTCOM_POSTGRES_CONNECTION_STRING }} BOTCOM_POSTGRES_POOLED_CONNECTION_STRING: ${{ env.POSTGRES_URL || secrets.BOTCOM_POSTGRES_POOLED_CONNECTION_STRING }} CLERK_SECRET_KEY: ${{ secrets.CLERK_SECRET_KEY }} CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }} MCP_SCREENSHOT_TOKEN_SECRET: ${{ secrets.MCP_SCREENSHOT_TOKEN_SECRET }} DISCORD_DEPLOY_WEBHOOK_URL: ${{ secrets.DISCORD_DEPLOY_WEBHOOK_URL }} DISCORD_FEEDBACK_WEBHOOK_URL: ${{ secrets.DISCORD_FEEDBACK_WEBHOOK_URL }} PLAIN_API_KEY: ${{ secrets.PLAIN_API_KEY }} PLAIN_LABEL_TYPE_ID: ${{ secrets.PLAIN_LABEL_TYPE_ID }} PLAIN_WORKSPACE_ID: ${{ secrets.PLAIN_WORKSPACE_ID }} DISCORD_HEALTH_WEBHOOK_URL: ${{ secrets.DISCORD_HEALTH_WEBHOOK_URL }} GC_MAPS_API_KEY: ${{ secrets.GC_MAPS_API_KEY }} GOOGLE_API_KEY: ${{ secrets.GOOGLE_API_KEY }} HEALTH_CHECK_BEARER_TOKEN: ${{ secrets.HEALTH_CHECK_BEARER_TOKEN }} HEALTH_WORKER_UPDOWN_WEBHOOK_PATH: ${{ secrets.HEALTH_WORKER_UPDOWN_WEBHOOK_PATH }} OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} R2_ACCESS_KEY_ID: ${{ secrets.R2_ACCESS_KEY_ID }} R2_ACCESS_KEY_SECRET: ${{ secrets.R2_ACCESS_KEY_SECRET }} SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} SENTRY_CSP_REPORT_URI: ${{ secrets.SENTRY_CSP_REPORT_URI }} SENTRY_DSN: ${{ secrets.SENTRY_DSN }} SUPABASE_LITE_ANON_KEY: ${{ secrets.SUPABASE_LITE_ANON_KEY }} TLDRAW_LICENSE: ${{ secrets.TLDRAW_LICENSE }} VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }} VITE_CLERK_PUBLISHABLE_KEY: ${{ secrets.VITE_CLERK_PUBLISHABLE_KEY }} VITE_POSTHOG_KEY: ${{ secrets.VITE_POSTHOG_KEY }} VITE_GA4_MEASUREMENT_ID: ${{ secrets.VITE_GA4_MEASUREMENT_ID }} WORKER_SENTRY_DSN: ${{ secrets.WORKER_SENTRY_DSN }} FLY_API_TOKEN: ${{ secrets.FLY_API_TOKEN }} PIERRE_KEY: ${{ secrets.PIERRE_KEY }} ZERO_ADMIN_PASSWORD: ${{ secrets.ZERO_ADMIN_PASSWORD }} ZERO_R2_ENDPOINT: ${{ secrets.ZERO_R2_ENDPOINT }} ZERO_R2_BUCKET_NAME: ${{ secrets.ZERO_R2_BUCKET_NAME }} ZERO_R2_ACCESS_KEY_ID: ${{ secrets.ZERO_R2_ACCESS_KEY_ID }} ZERO_R2_SECRET_ACCESS_KEY: ${{ secrets.ZERO_R2_SECRET_ACCESS_KEY }} ZERO_OTEL_EXPORTER_OTLP_ENDPOINT: ${{ secrets.ZERO_OTEL_EXPORTER_OTLP_ENDPOINT }} ZERO_OTEL_EXPORTER_OTLP_HEADERS: ${{ secrets.ZERO_OTEL_EXPORTER_OTLP_HEADERS }}