diff --git a/.github/workflows/web.yml b/.github/workflows/web.yml index 1b1a171576b..cd0d68b00a2 100644 --- a/.github/workflows/web.yml +++ b/.github/workflows/web.yml @@ -277,7 +277,6 @@ jobs: name: Web Build runs-on: ubuntu-latest needs: [web-init, web-lint, web-typecheck] - if: github.ref == 'refs/heads/main' steps: - name: Checkout code uses: actions/checkout@v4 @@ -361,6 +360,167 @@ jobs: packages/web/build-production packages/web/build-ssr-production + web-deploy-preview: + name: Web Deploy Preview + runs-on: ubuntu-latest + needs: web-build + if: github.event_name == 'pull_request' + permissions: + contents: read + pull-requests: write + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: ${{ env.NODE_VERSION }} + cache: 'npm' + cache-dependency-path: package-lock.json + + - name: Create concatenated patch file + id: patch-file + run: | + ls -d -- packages/*/patches/*.patch 2>/dev/null | xargs cat > combined-patch-file.txt || touch combined-patch-file.txt + echo "patch_checksum=$(sha256sum combined-patch-file.txt | cut -d' ' -f1)" >> $GITHUB_OUTPUT + + - name: Cache node modules + id: cache-node-modules + uses: actions/cache@v4 + with: + path: | + node_modules + packages/web/node_modules + packages/harmony/node_modules + packages/common/node_modules + packages/libs/node_modules + packages/sdk/node_modules + key: npm-cache-${{ runner.os }}-node-${{ env.NODE_VERSION }}-${{ hashFiles('package-lock.json') }}-${{ steps.patch-file.outputs.patch_checksum }} + restore-keys: | + npm-cache-${{ runner.os }}-node-${{ env.NODE_VERSION }}-${{ hashFiles('package-lock.json') }}- + + - name: Install dependencies (if cache miss) + if: steps.cache-node-modules.outputs.cache-hit != 'true' + env: + CI: true + SKIP_POD_INSTALL: true + SKIP_ANDROID_INSTALL: true + ANDROID_HOME: /tmp/android-sdk-dummy + NODE_OPTIONS: --max-old-space-size=8192 + run: | + mkdir -p /tmp/android-sdk-dummy + npm cache clean --force || true + npm ci --prefer-offline || npm install --prefer-offline + + - name: Run postinstall (if cache hit) + if: steps.cache-node-modules.outputs.cache-hit == 'true' + env: + CI: true + SKIP_POD_INSTALL: true + SKIP_ANDROID_INSTALL: true + ANDROID_HOME: /tmp/android-sdk-dummy + NODE_OPTIONS: --max-old-space-size=8192 + run: | + mkdir -p /tmp/android-sdk-dummy + npm run postinstall + + - name: Download builds + uses: actions/download-artifact@v4 + with: + name: builds + path: packages/web + + - name: Move build + run: | + cd packages/web + mv build-production build + mv build-ssr-production build-ssr + + - name: Copy robots.txt + run: | + cd packages/web + cp ./robots.txt build + cp ./robots.txt build-ssr/client + + - name: Copy .well-known files + run: | + cd packages/web + cp -r ./public/.well-known build 2>/dev/null || true + + - name: Deploy to Cloudflare (Preview) + id: deploy + env: + CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }} + PR_NUM: ${{ github.event.pull_request.number }} + run: | + cd packages/web + SSR_NAME="audius-web-ssr-preview-pr-${PR_NUM}" + MAIN_NAME="audius-web-preview-pr-${PR_NUM}" + npm_config_yes=true npx wrangler@4.54.0 deploy --config ./src/ssr/wrangler.toml --env preview --name "$SSR_NAME" + cp wrangler.toml wrangler.preview.pr.toml + sed -i "s/audius-web-ssr-preview/audius-web-ssr-preview-pr-${PR_NUM}/g; s/audius-web-preview/audius-web-preview-pr-${PR_NUM}/g" wrangler.preview.pr.toml + npm_config_yes=true npx wrangler@4.54.0 deploy --config ./wrangler.preview.pr.toml --env preview 2>&1 | tee deploy.log + echo "url=https://${MAIN_NAME}.audius.workers.dev" >> $GITHUB_OUTPUT + + - name: Comment on PR with preview URL + uses: actions/github-script@v7 + if: steps.deploy.outcome == 'success' && github.event_name == 'pull_request' + with: + script: | + const previewUrl = '${{ steps.deploy.outputs.url }}' || 'https://audius-web-preview.audius.workers.dev'; + const body = `## 🌐 Web preview ready + + **Preview URL:** ${previewUrl} + + Unique preview for this PR (deployed from this branch). + _[Workflow run](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})_`; + const marker = ''; + const bodyWithMarker = body + '\n' + marker; + const { data: comments } = await github.rest.issues.listComments({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.issue.number + }); + const existing = comments.find(c => c.body && c.body.includes(marker) && c.user.type === 'Bot'); + if (existing) { + await github.rest.issues.updateComment({ + owner: context.repo.owner, + repo: context.repo.repo, + comment_id: existing.id, + body: bodyWithMarker + }); + } else { + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.issue.number, + body: bodyWithMarker + }); + } + env: + GH_TOKEN: ${{ github.token }} + + web-cleanup-preview: + name: Cleanup PR preview workers + runs-on: ubuntu-latest + if: github.event_name == 'pull_request' && github.event.action == 'closed' + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Delete PR preview workers + env: + CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }} + PR_NUM: ${{ github.event.pull_request.number }} + run: | + cd packages/web + MAIN_NAME="audius-web-preview-pr-${PR_NUM}" + SSR_NAME="audius-web-ssr-preview-pr-${PR_NUM}" + npx wrangler@4.54.0 delete --name "$MAIN_NAME" --config ./wrangler.toml --force 2>/dev/null || true + npx wrangler@4.54.0 delete --name "$SSR_NAME" --config ./src/ssr/wrangler.toml --force 2>/dev/null || true + continue-on-error: true + web-check-ssr-bundlesize: name: Web Check SSR Bundlesize runs-on: ubuntu-latest diff --git a/packages/web/src/ssr/wrangler.toml b/packages/web/src/ssr/wrangler.toml index c33f2e87a0c..12caf9205f1 100644 --- a/packages/web/src/ssr/wrangler.toml +++ b/packages/web/src/ssr/wrangler.toml @@ -18,6 +18,13 @@ vars = { SENTRY_DSN = "https://4db9c77b0bd7ae6a935f8bd58c06dad3@o260428.ingest.s "https://api.audius.co" ] } +# Preview environment for PR deployments (GitHub Actions) +[env.preview] +name = "audius-web-ssr-preview" +vars = { DISCOVERY_NODE_ALLOWLIST = [ + "https://api.audius.co" +] } + # Test environment, replace `test` with subdomain # Invoke with npx wrangler dev --env test [env.test] diff --git a/packages/web/wrangler.toml b/packages/web/wrangler.toml index c20c571ca7e..59dc1856795 100644 --- a/packages/web/wrangler.toml +++ b/packages/web/wrangler.toml @@ -20,6 +20,15 @@ services = [ ] vars = { ENVIRONMENT = "production", EMBED = "https://embed.audius.workers.dev", API_URL = "https://api.audius.co", DISCOVERY_NODES = "https://api.audius.co" } +# Preview environment for PR deployments (GitHub Actions) +# Deployed on every PR; single preview URL overwritten per build +[env.preview] +name = "audius-web-preview" +services = [ + { binding = "SSR", service = "audius-web-ssr-preview" } +] +vars = { ENVIRONMENT = "production", EMBED = "https://embed.audius.workers.dev", API_URL = "https://api.audius.co", DISCOVERY_NODES = "https://api.audius.co" } + # Test environment, replace `test` with subdomain # Invoke with npx wrangler dev --env test [env.test]