From 4ee762383757f36ab6763bac74a0b222d135c1c3 Mon Sep 17 00:00:00 2001 From: "Michael H." Date: Fri, 16 Jan 2026 02:40:10 +0100 Subject: [PATCH] build: deploy on both environments (#5129) * build: deploy on both environments * build: missing whitespace * build: add path filter * build: add sentry env * build: inherit secrets * remove if check * Revert "remove if check" This reverts commit b2ffe1d611269ddaf13bdbfacfdb89cd40316c29. * remove if check 2 * Fix Wrangler env * Fix Wrangler env but for real this time * Alternative method of getting URLs * Check for environment instead * Fix comment * Clickable commit * Set PREVIEW build var * Fix commit shown in comment * Fix linting errors * ) * add preview banner * prepr * prepr again * .. --------- Co-authored-by: Prospector <6166773+Prospector@users.noreply.github.com> --- .github/workflows/frontend-deploy.yml | 60 ++++++++----- .github/workflows/frontend-preview.yml | 72 ++++++++++++++++ apps/frontend/nuxt.config.ts | 3 + .../src/components/ui/ModrinthFooter.vue | 23 +++++ .../components/ui/banner/PreviewBanner.vue | 86 +++++++++++++++++++ apps/frontend/src/composables/featureFlags.ts | 17 +--- apps/frontend/src/layouts/default.vue | 2 + apps/frontend/src/locales/en-US/index.json | 6 ++ .../plugins/sentry-cloudflare-plugin.ts | 2 + packages/ui/src/components/base/AutoLink.vue | 4 +- turbo.jsonc | 6 +- 11 files changed, 241 insertions(+), 40 deletions(-) create mode 100644 .github/workflows/frontend-preview.yml create mode 100644 apps/frontend/src/components/ui/banner/PreviewBanner.vue diff --git a/.github/workflows/frontend-deploy.yml b/.github/workflows/frontend-deploy.yml index 26153ef9..cf6f8eff 100644 --- a/.github/workflows/frontend-deploy.yml +++ b/.github/workflows/frontend-deploy.yml @@ -13,12 +13,16 @@ on: - '**/wrangler.jsonc' - '**/pnpm-*.yaml' - '.github/workflows/frontend-deploy.yml' - pull_request: workflow_dispatch: + workflow_call: + inputs: + environment: + required: true + type: string + description: 'The environment to deploy to (staging-preview or production-preview)' jobs: deploy: - if: github.repository_owner == 'modrinth' runs-on: ubuntu-latest permissions: contents: read @@ -34,15 +38,28 @@ jobs: id: meta run: | echo "cmd=deploy" >> $GITHUB_OUTPUT - if [ "${{ github.ref }}" == "refs/heads/main" ]; then + + ENV_INPUT="${{ inputs.environment }}" + REF="${{ github.ref }}" + SHA_SHORT="${GITHUB_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 + 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 + + elif [ "$REF" = "refs/heads/main" ]; then echo "env=staging" >> $GITHUB_OUTPUT echo "url=https://staging.modrinth.com" >> $GITHUB_OUTPUT - elif [ "${{ github.ref }}" != "refs/heads/prod" ] && [ "${{ github.ref }}" != "refs/heads/main" ]; then - echo "env=staging" >> $GITHUB_OUTPUT - echo "url=https://git-${GITHUB_SHA::8}-frontend-staging.modrinth.workers.dev" >> $GITHUB_OUTPUT - echo "cmd=versions upload --preview-alias git-${GITHUB_SHA::8} --var PREVIEW:true" >> $GITHUB_OUTPUT + else - # Production env should be empty + # Production env (no preview) + echo "env=production" >> $GITHUB_OUTPUT echo "url=https://modrinth.com" >> $GITHUB_OUTPUT fi @@ -77,6 +94,8 @@ jobs: CF_PAGES_BRANCH: ${{ github.ref_name }} CF_PAGES_COMMIT_SHA: ${{ github.sha }} CF_PAGES_URL: ${{ steps.meta.outputs.url }} + BUILD_ENV: ${{ steps.meta.outputs.env }} + PREVIEW: ${{ inputs.environment != '' && 'true' || 'false' }} SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} - name: Create Sentry release and upload sourcemaps @@ -86,7 +105,7 @@ jobs: SENTRY_ORG: modrinth SENTRY_PROJECT: knossos-server with: - environment: ${{ steps.meta.outputs.env || 'production' }} + environment: ${{ steps.meta.outputs.env }} sourcemaps: ./apps/frontend/.output/server url_prefix: '~/' @@ -96,7 +115,7 @@ jobs: with: apiToken: ${{ secrets.CF_API_TOKEN }} accountId: ${{ secrets.CF_ACCOUNT_ID }} - environment: ${{ steps.meta.outputs.env }} + environment: ${{ steps.meta.outputs.env != 'production' && steps.meta.outputs.env || '' }} workingDirectory: ./apps/frontend packageManager: pnpm wranglerVersion: '4.54.0' @@ -111,15 +130,14 @@ jobs: --data '{"hosts": ["modrinth.com", "www.modrinth.com", "staging.modrinth.com"]}' \ https://api.cloudflare.com/client/v4/zones/e39df17b9c4ef44cbce2646346ee6d33/purge_cache - - name: Comment deploy URL on PR - if: github.event_name == 'pull_request' - uses: peter-evans/create-or-update-comment@v4 - with: - issue-number: ${{ github.event.pull_request.number }} - body: | - ## 🚀 Frontend Deploy + - name: Write deployment URL to file + if: ${{ inputs.environment != '' }} + run: | + echo "${{ steps.meta.outputs.url }}" > deployment-url-${{ inputs.environment }}.txt - | Commit | URL | - |--------|-----| - | ${{ github.event.pull_request.head.sha }} | ${{ steps.wrangler.outputs.deployment-url }} | - comment-tag: frontend-deploy + - name: Upload deployment URL + if: ${{ inputs.environment != '' }} + uses: actions/upload-artifact@v6 + with: + name: deployment-url-${{ inputs.environment }} + path: deployment-url-${{ inputs.environment }}.txt diff --git a/.github/workflows/frontend-preview.yml b/.github/workflows/frontend-preview.yml new file mode 100644 index 00000000..e75a7122 --- /dev/null +++ b/.github/workflows/frontend-preview.yml @@ -0,0 +1,72 @@ +name: Deploy frontend preview + +on: + pull_request: + paths: + - 'apps/frontend/**/*' + - 'packages/ui/**/*' + - 'packages/utils/**/*' + - 'packages/assets/**/*' + - '**/wrangler.jsonc' + - '**/pnpm-*.yaml' + - '.github/workflows/frontend-preview.yml' + +jobs: + deploy: + if: github.repository_owner == 'modrinth' && github.event.pull_request.head.repo.full_name == github.repository + uses: ./.github/workflows/frontend-deploy.yml + secrets: inherit + strategy: + matrix: + environment: [staging-preview, production-preview] + with: + environment: ${{ matrix.environment }} + + comment: + if: github.repository_owner == 'modrinth' && github.event.pull_request.head.repo.full_name == github.repository + runs-on: ubuntu-latest + needs: deploy + steps: + - name: Download deployment URLs + uses: actions/download-artifact@v7 + with: + pattern: deployment-url-* + merge-multiple: true + + - name: Read deployment URLs + id: urls + run: | + STAGING_PREVIEW_URL=$(cat deployment-url-staging-preview.txt) + PRODUCTION_PREVIEW_URL=$(cat deployment-url-production-preview.txt) + + echo "Production preview URL: $PRODUCTION_PREVIEW_URL" + echo "Staging preview URL: $STAGING_PREVIEW_URL" + + echo "staging-preview-url=$STAGING_PREVIEW_URL" >> $GITHUB_OUTPUT + echo "production-preview-url=$PRODUCTION_PREVIEW_URL" >> $GITHUB_OUTPUT + + - name: Find comment + if: github.event_name == 'pull_request' + uses: peter-evans/find-comment@v3 + id: fc + with: + issue-number: ${{ github.event.pull_request.number }} + comment-author: 'github-actions[bot]' + body-includes: Frontend previews + + - name: Comment deploy URL on PR + if: github.event_name == 'pull_request' + uses: peter-evans/create-or-update-comment@v5 + with: + issue-number: ${{ github.event.pull_request.number }} + comment-id: ${{ steps.fc.outputs.comment-id }} + body: | + ## Frontend previews + + Last deployed commit is [${{ github.sha }}](${{ github.event.pull_request.head.repo.html_url }}/commit/${{ github.sha }}) + + | Environment | URL | + |-------------|-----| + | staging | ${{ steps.urls.outputs.staging-preview-url }} | + | production | ${{ steps.urls.outputs.production-preview-url }} | + edit-mode: replace diff --git a/apps/frontend/nuxt.config.ts b/apps/frontend/nuxt.config.ts index 7a7e16c8..93afe78c 100644 --- a/apps/frontend/nuxt.config.ts +++ b/apps/frontend/nuxt.config.ts @@ -187,6 +187,8 @@ export default defineNuxtConfig({ pyroBaseUrl: process.env.PYRO_BASE_URL, siteUrl: getDomain(), production: isProduction(), + buildEnv: process.env.BUILD_ENV, + preview: process.env.PREVIEW === 'true', featureFlagOverrides: getFeatureFlagOverrides(), owner: process.env.VERCEL_GIT_REPO_OWNER || 'modrinth', @@ -253,6 +255,7 @@ export default defineNuxtConfig({ }, replace: { __SENTRY_RELEASE__: JSON.stringify(process.env.CF_PAGES_COMMIT_SHA || 'unknown'), + __SENTRY_ENVIRONMENT__: JSON.stringify(process.env.BUILD_ENV || 'development'), }, }, devtools: { diff --git a/apps/frontend/src/components/ui/ModrinthFooter.vue b/apps/frontend/src/components/ui/ModrinthFooter.vue index 39283653..a641d109 100644 --- a/apps/frontend/src/components/ui/ModrinthFooter.vue +++ b/apps/frontend/src/components/ui/ModrinthFooter.vue @@ -1,6 +1,7 @@ + + diff --git a/apps/frontend/src/composables/featureFlags.ts b/apps/frontend/src/composables/featureFlags.ts index 92798d9c..d7f5b721 100644 --- a/apps/frontend/src/composables/featureFlags.ts +++ b/apps/frontend/src/composables/featureFlags.ts @@ -42,22 +42,7 @@ export const DEFAULT_FEATURE_FLAGS = validateValues({ hideRussiaCensorshipBanner: false, serverDiscovery: false, disablePrettyProjectUrlRedirects: false, - // advancedRendering: true, - // externalLinksNewTab: true, - // notUsingBlockers: false, - // hideModrinthAppPromos: false, - // preferredDarkTheme: 'dark', - // hideStagingBanner: false, - - // Project display modes - // modSearchDisplayMode: 'list', - // pluginSearchDisplayMode: 'list', - // resourcePackSearchDisplayMode: 'gallery', - // modpackSearchDisplayMode: 'list', - // shaderSearchDisplayMode: 'gallery', - // dataPackSearchDisplayMode: 'list', - // userProjectDisplayMode: 'list', - // collectionProjectDisplayMode: 'list', + hidePreviewBanner: false, } as const) export type FeatureFlag = keyof typeof DEFAULT_FEATURE_FLAGS diff --git a/apps/frontend/src/layouts/default.vue b/apps/frontend/src/layouts/default.vue index 10456d75..b156ddbd 100644 --- a/apps/frontend/src/layouts/default.vue +++ b/apps/frontend/src/layouts/default.vue @@ -47,6 +47,7 @@ route.path !== '/settings/billing' " /> + https://modrinth.com. This preview deploy is used by Modrinth staff for testing purposes. It was built using {owner}/{branch} @ {commit}." + }, + "layout.banner.preview.title": { + "message": "This is a preview deploy of the Modrinth website." + }, "layout.banner.staging.description": { "message": "The staging environment is completely separate from the production Modrinth database. This is used for testing and debugging purposes, and may be running in-development versions of the Modrinth backend or frontend newer than the production instance." }, diff --git a/apps/frontend/src/server/plugins/sentry-cloudflare-plugin.ts b/apps/frontend/src/server/plugins/sentry-cloudflare-plugin.ts index 1bcb0ab1..4f103424 100644 --- a/apps/frontend/src/server/plugins/sentry-cloudflare-plugin.ts +++ b/apps/frontend/src/server/plugins/sentry-cloudflare-plugin.ts @@ -1,11 +1,13 @@ import { sentryCloudflareNitroPlugin } from '@sentry/nuxt/module/plugins' declare const __SENTRY_RELEASE__: string +declare const __SENTRY_ENVIRONMENT__: string export default defineNitroPlugin( sentryCloudflareNitroPlugin({ dsn: 'https://9cf8f56ab7055ab6b1042fad535f2a44@o485889.ingest.us.sentry.io/4510709722185728', tracesSampleRate: 0.0001, // match with wrangler.jsonc release: __SENTRY_RELEASE__, + environment: __SENTRY_ENVIRONMENT__, }), ) diff --git a/packages/ui/src/components/base/AutoLink.vue b/packages/ui/src/components/base/AutoLink.vue index 36fd26a7..192c9aa8 100644 --- a/packages/ui/src/components/base/AutoLink.vue +++ b/packages/ui/src/components/base/AutoLink.vue @@ -1,8 +1,8 @@