diff --git a/.github/workflows/frontend-deploy.yml b/.github/workflows/frontend-deploy.yml index 4912cd6121..f53b985cff 100644 --- a/.github/workflows/frontend-deploy.yml +++ b/.github/workflows/frontend-deploy.yml @@ -16,10 +16,10 @@ on: workflow_dispatch: workflow_call: inputs: - environment: - required: true - type: string - description: 'The environment to deploy to (staging-preview or production-preview)' + preview: + required: false + type: boolean + description: 'Whether this is a preview deployment' head_sha: required: false type: string @@ -28,9 +28,13 @@ on: required: false type: string description: 'The branch name to deploy (defaults to github.ref_name)' + branch_alias: + required: false + type: string + description: 'The persistent preview alias for the branch' concurrency: - group: ${{ github.workflow }}-${{ github.ref }}-${{ inputs.environment || 'push' }} + group: ${{ github.workflow }}-${{ github.ref }}-${{ inputs.preview && 'preview' || 'push' }} cancel-in-progress: ${{ github.ref != 'refs/heads/main' && github.ref != 'refs/heads/prod' }} jobs: @@ -49,23 +53,31 @@ jobs: - name: Configure environment id: meta env: - ENV_INPUT: ${{ inputs.environment }} + PREVIEW_INPUT: ${{ inputs.preview }} REF: ${{ github.ref }} DEPLOY_SHA: ${{ inputs.head_sha || github.sha }} + BRANCH_ALIAS: ${{ inputs.branch_alias }} run: | echo "cmd=deploy" >> $GITHUB_OUTPUT SHA_SHORT="${DEPLOY_SHA::8}" - if [ "$ENV_INPUT" = "staging-preview" ]; then - echo "env=staging" >> $GITHUB_OUTPUT - echo "url=https://git-$SHA_SHORT-frontend-staging.modrinth.workers.dev" >> $GITHUB_OUTPUT - echo "cmd=versions upload --preview-alias git-$SHA_SHORT --var PREVIEW:true" >> $GITHUB_OUTPUT - - elif [ "$ENV_INPUT" = "production-preview" ]; then + if [ "$PREVIEW_INPUT" = "true" ]; then + URL="https://git-$SHA_SHORT-frontend.modrinth.workers.dev" + STAGING_URL="https://git-$SHA_SHORT-staging-frontend.modrinth.workers.dev" echo "env=production" >> $GITHUB_OUTPUT - echo "url=https://git-$SHA_SHORT-frontend.modrinth.workers.dev" >> $GITHUB_OUTPUT - echo "cmd=versions upload --preview-alias git-$SHA_SHORT --var PREVIEW:true" >> $GITHUB_OUTPUT + echo "url=$URL" >> $GITHUB_OUTPUT + echo "staging_url=$STAGING_URL" >> $GITHUB_OUTPUT + echo "cmd=versions upload --preview-alias git-$SHA_SHORT --var PREVIEW:true --var CF_PAGES_URL:$URL" >> $GITHUB_OUTPUT + + STAGING_VARS=$(jq -r '.env.staging.vars | to_entries[] | "--var \(.key):\(.value)"' ./apps/frontend/wrangler.jsonc | tr '\n' ' ') + echo "staging_cmd=versions upload --preview-alias git-$SHA_SHORT-staging ${STAGING_VARS}--var PREVIEW:true --var CF_PAGES_URL:$STAGING_URL" >> $GITHUB_OUTPUT + + if [ -n "$BRANCH_ALIAS" ]; then + echo "branch_alias_url=https://$BRANCH_ALIAS-frontend.modrinth.workers.dev" >> $GITHUB_OUTPUT + echo "staging_branch_alias_url=https://$BRANCH_ALIAS-staging-frontend.modrinth.workers.dev" >> $GITHUB_OUTPUT + echo "staging_branch_alias_cmd=versions upload --preview-alias $BRANCH_ALIAS-staging ${STAGING_VARS}--var PREVIEW:true --var CF_PAGES_URL:https://$BRANCH_ALIAS-staging-frontend.modrinth.workers.dev" >> $GITHUB_OUTPUT + fi elif [ "$REF" = "refs/heads/main" ]; then echo "env=staging" >> $GITHUB_OUTPUT @@ -120,7 +132,7 @@ jobs: CF_PAGES_COMMIT_SHA: ${{ inputs.head_sha || github.sha }} CF_PAGES_URL: ${{ steps.meta.outputs.url }} BUILD_ENV: ${{ steps.meta.outputs.env }} - PREVIEW: ${{ inputs.environment != '' && 'true' || 'false' }} + PREVIEW: ${{ inputs.preview && 'true' || 'false' }} SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} - name: Create Sentry release and upload sourcemaps @@ -146,6 +158,39 @@ jobs: wranglerVersion: '4.54.0' command: ${{ steps.meta.outputs.cmd }} + - name: Deploy staging Cloudflare Worker preview + if: ${{ inputs.preview }} + uses: cloudflare/wrangler-action@9acf94ace14e7dc412b076f2c5c20b8ce93c79cd # v3.15.0 + with: + apiToken: ${{ secrets.CF_API_TOKEN }} + accountId: ${{ secrets.CF_ACCOUNT_ID }} + workingDirectory: ./apps/frontend + packageManager: pnpm + wranglerVersion: '4.54.0' + command: ${{ steps.meta.outputs.staging_cmd }} + + - name: Deploy persistent Cloudflare Worker preview + if: ${{ inputs.preview && inputs.branch_alias != '' }} + uses: cloudflare/wrangler-action@9acf94ace14e7dc412b076f2c5c20b8ce93c79cd # v3.15.0 + with: + apiToken: ${{ secrets.CF_API_TOKEN }} + accountId: ${{ secrets.CF_ACCOUNT_ID }} + workingDirectory: ./apps/frontend + packageManager: pnpm + wranglerVersion: '4.54.0' + command: versions upload --preview-alias ${{ inputs.branch_alias }} --var PREVIEW:true --var CF_PAGES_URL:${{ steps.meta.outputs.branch_alias_url }} + + - name: Deploy persistent staging Cloudflare Worker preview + if: ${{ inputs.preview && inputs.branch_alias != '' }} + uses: cloudflare/wrangler-action@9acf94ace14e7dc412b076f2c5c20b8ce93c79cd # v3.15.0 + with: + apiToken: ${{ secrets.CF_API_TOKEN }} + accountId: ${{ secrets.CF_ACCOUNT_ID }} + workingDirectory: ./apps/frontend + packageManager: pnpm + wranglerVersion: '4.54.0' + command: ${{ steps.meta.outputs.staging_branch_alias_cmd }} + - name: Purge cache if: github.ref == 'refs/heads/prod' run: | @@ -155,14 +200,22 @@ jobs: --data '{"hosts": ["modrinth.com", "www.modrinth.com", "staging.modrinth.com"]}' \ https://api.cloudflare.com/client/v4/zones/e39df17b9c4ef44cbce2646346ee6d33/purge_cache - - name: Write deployment URL to file - if: ${{ inputs.environment != '' }} + - name: Write deployment URLs to files + if: ${{ inputs.preview }} run: | - echo "${{ steps.meta.outputs.url }}" > deployment-url-${{ inputs.environment }}.txt + echo "${{ steps.meta.outputs.url }}" > deployment-url-production.txt + echo "${{ steps.meta.outputs.staging_url }}" > deployment-url-staging.txt - - name: Upload deployment URL - if: ${{ inputs.environment != '' }} + - name: Upload production deployment URL + if: ${{ inputs.preview }} uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: - name: deployment-url-${{ inputs.environment }} - path: deployment-url-${{ inputs.environment }}.txt + name: deployment-url-production + path: deployment-url-production.txt + + - name: Upload staging deployment URL + if: ${{ inputs.preview }} + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: deployment-url-staging + path: deployment-url-staging.txt diff --git a/.github/workflows/frontend-preview.yml b/.github/workflows/frontend-preview.yml index b406d5bec4..8b0d7c6f34 100644 --- a/.github/workflows/frontend-preview.yml +++ b/.github/workflows/frontend-preview.yml @@ -12,23 +12,33 @@ on: - '.github/workflows/frontend-preview.yml' jobs: + metadata: + if: github.repository_owner == 'modrinth' && github.event.pull_request.head.repo.full_name == github.repository + runs-on: ubuntu-latest + outputs: + branch-alias: ${{ steps.meta.outputs.branch_alias }} + steps: + - name: Configure branch alias + id: meta + run: echo "branch_alias=pr-${{ github.event.pull_request.number }}" >> $GITHUB_OUTPUT + deploy: if: github.repository_owner == 'modrinth' && github.event.pull_request.head.repo.full_name == github.repository + needs: metadata uses: ./.github/workflows/frontend-deploy.yml secrets: inherit concurrency: - group: ${{ github.workflow }}-${{ github.ref }}-${{ matrix.environment }} + group: ${{ github.workflow }}-${{ github.ref }}-deploy cancel-in-progress: true - strategy: - matrix: - environment: [staging-preview, production-preview] with: - environment: ${{ matrix.environment }} + preview: true head_sha: ${{ github.event.pull_request.head.sha }} head_ref: ${{ github.event.pull_request.head.ref }} + branch_alias: ${{ needs.metadata.outputs.branch-alias }} deploy-storybook: if: github.repository_owner == 'modrinth' && github.event.pull_request.head.repo.full_name == github.repository + needs: metadata runs-on: blacksmith-2vcpu-ubuntu-2404 concurrency: group: ${{ github.workflow }}-${{ github.ref }}-storybook @@ -86,6 +96,18 @@ jobs: wranglerVersion: '4.54.0' command: versions upload --preview-alias git-${{ steps.meta.outputs.sha_short }} + - name: Deploy persistent Storybook preview + uses: cloudflare/wrangler-action@9acf94ace14e7dc412b076f2c5c20b8ce93c79cd # v3.15.0 + env: + NODE_OPTIONS: --max-old-space-size=6144 + with: + apiToken: ${{ secrets.CF_API_TOKEN }} + accountId: ${{ secrets.CF_ACCOUNT_ID }} + workingDirectory: ./packages/ui + packageManager: pnpm + wranglerVersion: '4.54.0' + command: versions upload --preview-alias ${{ needs.metadata.outputs.branch-alias }} + comment: if: | !cancelled() @@ -93,7 +115,7 @@ jobs: && github.event.pull_request.head.repo.full_name == github.repository && needs.deploy.result == 'success' runs-on: ubuntu-latest - needs: [deploy, deploy-storybook] + needs: [metadata, deploy, deploy-storybook] steps: - name: Download deployment URLs uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 @@ -105,25 +127,29 @@ jobs: id: urls env: HEAD_SHA: ${{ github.event.pull_request.head.sha }} + BRANCH_ALIAS: ${{ needs.metadata.outputs.branch-alias }} STORYBOOK_RESULT: ${{ needs.deploy-storybook.result }} RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} run: | - STAGING_PREVIEW_URL=$(cat deployment-url-staging-preview.txt) - PRODUCTION_PREVIEW_URL=$(cat deployment-url-production-preview.txt) + STAGING_SHA_URL=$(cat deployment-url-staging.txt) + PRODUCTION_SHA_URL=$(cat deployment-url-production.txt) + STAGING_BRANCH_URL="https://$BRANCH_ALIAS-staging-frontend.modrinth.workers.dev" + PRODUCTION_BRANCH_URL="https://$BRANCH_ALIAS-frontend.modrinth.workers.dev" if [ "$STORYBOOK_RESULT" = "success" ]; then - STORYBOOK_PREVIEW_URL="https://git-${HEAD_SHA::8}-storybook.modrinth.workers.dev" + STORYBOOK_SHA_URL="https://git-${HEAD_SHA::8}-storybook.modrinth.workers.dev" + STORYBOOK_BRANCH_URL="https://$BRANCH_ALIAS-storybook.modrinth.workers.dev" else - STORYBOOK_PREVIEW_URL="⚠️ Deployment $STORYBOOK_RESULT ([logs]($RUN_URL))" + STORYBOOK_SHA_URL="⚠️ Deployment $STORYBOOK_RESULT ([logs]($RUN_URL))" + STORYBOOK_BRANCH_URL="⚠️ Deployment $STORYBOOK_RESULT ([logs]($RUN_URL))" fi - echo "Production preview URL: $PRODUCTION_PREVIEW_URL" - echo "Staging preview URL: $STAGING_PREVIEW_URL" - echo "Storybook preview URL: $STORYBOOK_PREVIEW_URL" - - echo "staging-preview-url=$STAGING_PREVIEW_URL" >> $GITHUB_OUTPUT - echo "production-preview-url=$PRODUCTION_PREVIEW_URL" >> $GITHUB_OUTPUT - echo "storybook-preview-url=$STORYBOOK_PREVIEW_URL" >> $GITHUB_OUTPUT + echo "staging-sha-url=$STAGING_SHA_URL" >> $GITHUB_OUTPUT + echo "production-sha-url=$PRODUCTION_SHA_URL" >> $GITHUB_OUTPUT + echo "storybook-sha-url=$STORYBOOK_SHA_URL" >> $GITHUB_OUTPUT + echo "staging-branch-url=$STAGING_BRANCH_URL" >> $GITHUB_OUTPUT + echo "production-branch-url=$PRODUCTION_BRANCH_URL" >> $GITHUB_OUTPUT + echo "storybook-branch-url=$STORYBOOK_BRANCH_URL" >> $GITHUB_OUTPUT - name: Find comment if: github.event_name == 'pull_request' @@ -146,9 +172,19 @@ jobs: Last deployed commit is [${{ github.event.pull_request.head.sha }}](${{ github.event.pull_request.head.repo.html_url }}/commit/${{ github.event.pull_request.head.sha }}) + ### Persistent + | Environment | URL | |-------------|-----| - | staging | ${{ steps.urls.outputs.staging-preview-url }} | - | production | ${{ steps.urls.outputs.production-preview-url }} | - | storybook | ${{ steps.urls.outputs.storybook-preview-url }} | + | staging | ${{ steps.urls.outputs.staging-branch-url }} | + | production | ${{ steps.urls.outputs.production-branch-url }} | + | storybook | ${{ steps.urls.outputs.storybook-branch-url }} | + + ### Latest commit + + | Environment | URL | + |-------------|-----| + | staging | ${{ steps.urls.outputs.staging-sha-url }} | + | production | ${{ steps.urls.outputs.production-sha-url }} | + | storybook | ${{ steps.urls.outputs.storybook-sha-url }} | edit-mode: replace diff --git a/apps/frontend/nuxt.config.ts b/apps/frontend/nuxt.config.ts index f7f8a5296b..0d14d0c54c 100644 --- a/apps/frontend/nuxt.config.ts +++ b/apps/frontend/nuxt.config.ts @@ -364,11 +364,7 @@ function getFeatureFlagOverrides() { function getDomain() { if (process.env.NODE_ENV === 'production') { - // @ts-ignore - if (process.env.CF_PAGES_URL || globalThis.CF_PAGES_URL) { - // @ts-ignore - return process.env.CF_PAGES_URL ?? globalThis.CF_PAGES_URL - } else if (process.env.HEROKU_APP_NAME) { + if (process.env.HEROKU_APP_NAME) { return `https://${process.env.HEROKU_APP_NAME}.herokuapp.com` } else if (process.env.VERCEL_URL) { return `https://${process.env.VERCEL_URL}` diff --git a/apps/frontend/src/server/middleware/site-url.ts b/apps/frontend/src/server/middleware/site-url.ts new file mode 100644 index 0000000000..967bef2234 --- /dev/null +++ b/apps/frontend/src/server/middleware/site-url.ts @@ -0,0 +1,20 @@ +export default defineEventHandler(async (event) => { + try { + const mod = 'cloudflare:workers' + const { env } = await import(/* @vite-ignore */ mod) + const cfEnv = env as any + const config = useRuntimeConfig(event) + + if (cfEnv.CF_PAGES_URL) config.public.siteUrl = cfEnv.CF_PAGES_URL + if (cfEnv.BROWSER_BASE_URL) config.public.apiBaseUrl = cfEnv.BROWSER_BASE_URL + if (cfEnv.BASE_URL) config.apiBaseUrl = cfEnv.BASE_URL + if (cfEnv.PYRO_BASE_URL) { + config.public.pyroBaseUrl = cfEnv.PYRO_BASE_URL + config.pyroBaseUrl = cfEnv.PYRO_BASE_URL + } + if (cfEnv.STRIPE_PUBLISHABLE_KEY) + config.public.stripePublishableKey = cfEnv.STRIPE_PUBLISHABLE_KEY + } catch { + /* empty */ + } +})