fix(sdk): close remaining unsigned audio upload paths from review #2048
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Web CI/CD | |
| on: | |
| push: | |
| branches: | |
| - main | |
| paths: | |
| - 'packages/web/**' | |
| - 'packages/common/**' | |
| - 'packages/harmony/**' | |
| - 'packages/libs/**' | |
| - 'packages/sdk/**' | |
| - 'package-lock.json' | |
| - '.github/workflows/web.yml' | |
| pull_request: | |
| paths: | |
| - 'packages/web/**' | |
| - 'packages/common/**' | |
| - 'packages/harmony/**' | |
| - 'packages/libs/**' | |
| - 'packages/sdk/**' | |
| - 'package-lock.json' | |
| - '.github/workflows/web.yml' | |
| workflow_dispatch: | |
| # Cancel superseded PR runs (new commits supersede in-flight CI). Keyed on the | |
| # PR branch for PRs; on main, head_ref is empty so we fall back to run_id, giving | |
| # every main run its own group. Main runs are therefore independent — a run parked | |
| # at the production/release approval gate never blocks (or is blocked by) the next | |
| # push, and an in-flight deploy is never interrupted. | |
| concurrency: | |
| group: web-${{ github.head_ref || github.run_id }} | |
| cancel-in-progress: ${{ github.event_name == 'pull_request' }} | |
| env: | |
| NODE_VERSION: '24.10.0' | |
| jobs: | |
| web-init: | |
| name: Web Init (Install & Cache) | |
| runs-on: ubuntu-latest | |
| 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: Upgrade npm to 11.10.0 | |
| run: npm install -g npm@11.10.0 | |
| - 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 | |
| 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 | |
| if [[ -d node_modules ]]; then | |
| echo "Using cached node_modules, running postinstall..." | |
| npm run postinstall | |
| else | |
| echo "No cache found, running fresh install..." | |
| # Clear npm cache to avoid EEXIST conflicts | |
| npm cache clean --force || true | |
| # Try npm ci first, fallback to npm install if lock file is out of sync | |
| npm ci --prefer-offline || npm install --prefer-offline | |
| fi | |
| web-lint: | |
| name: Web Lint & Stylelint | |
| runs-on: ubuntu-latest | |
| needs: web-init | |
| 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: Upgrade npm to 11.10.0 | |
| run: npm install -g npm@11.10.0 | |
| - 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 | |
| # Clear npm cache to avoid EEXIST conflicts | |
| npm cache clean --force || true | |
| # Try npm ci first, fallback to npm install if lock file is out of sync | |
| npm ci --prefer-offline || npm install --prefer-offline | |
| - name: Cache for Turbo | |
| uses: rharkor/caching-for-turbo@v2.2.1 | |
| - name: Lint | |
| run: npx turbo run lint --filter=@audius/web | |
| - name: Stylelint | |
| run: npm run stylelint -w @audius/web | |
| web-typecheck: | |
| name: Web Typecheck | |
| runs-on: ubuntu-latest | |
| needs: web-init | |
| 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: Upgrade npm to 11.10.0 | |
| run: npm install -g npm@11.10.0 | |
| - 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 | |
| # Clear npm cache to avoid EEXIST conflicts | |
| npm cache clean --force || true | |
| # Try npm ci first, fallback to npm install if lock file is out of sync | |
| npm ci --prefer-offline || npm install --prefer-offline | |
| - name: Cache for Turbo | |
| uses: rharkor/caching-for-turbo@v2.2.1 | |
| - name: Typecheck | |
| run: npx turbo run typecheck --filter=@audius/web | |
| web-test: | |
| name: Web Tests | |
| runs-on: ubuntu-latest | |
| needs: web-init | |
| 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: Upgrade npm to 11.10.0 | |
| run: npm install -g npm@11.10.0 | |
| - 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 | |
| # Clear npm cache to avoid EEXIST conflicts | |
| npm cache clean --force || true | |
| # Try npm ci first, fallback to npm install if lock file is out of sync | |
| npm ci --prefer-offline || npm install --prefer-offline | |
| - name: Cache for Turbo | |
| uses: rharkor/caching-for-turbo@v2.2.1 | |
| - name: Run tests | |
| timeout-minutes: 30 | |
| run: npm run web:test -- -- run --reporter=default --reporter=junit --outputFile=report.xml | |
| - name: Upload test results | |
| uses: actions/upload-artifact@v4 | |
| if: always() | |
| with: | |
| name: test-results | |
| path: packages/web/report.xml | |
| - name: Upload test output | |
| uses: actions/upload-artifact@v4 | |
| if: always() | |
| with: | |
| name: test-output | |
| path: packages/web/test-output | |
| web-build: | |
| name: Web Build | |
| runs-on: ubuntu-latest | |
| needs: [web-init, web-lint, web-typecheck] | |
| 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: Upgrade npm to 11.10.0 | |
| run: npm install -g npm@11.10.0 | |
| - 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 | |
| # Clear npm cache to avoid EEXIST conflicts | |
| npm cache clean --force || true | |
| # Try npm ci first, fallback to npm install if lock file is out of sync | |
| 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: Cache for Turbo | |
| uses: rharkor/caching-for-turbo@v2.2.1 | |
| - name: Build production | |
| timeout-minutes: 30 | |
| run: | | |
| cd packages/web | |
| npm run build:prod | |
| cp package.json build-production | |
| - name: Build SSR production | |
| timeout-minutes: 30 | |
| run: | | |
| cd packages/web | |
| npm run build:ssr:prod | |
| - name: Upload builds | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: builds | |
| path: | | |
| packages/web/build-production | |
| packages/web/build-ssr-production | |
| web-deploy-preview: | |
| name: Web Deploy Preview | |
| runs-on: ubuntu-latest | |
| needs: web-build | |
| # Opt-in: only deploy a live Cloudflare preview when the PR carries the | |
| # `preview` label. Most PRs don't need one, and each preview is a build | |
| # download + two wrangler deploys. Add the label to get a preview URL. | |
| if: github.event_name == 'pull_request' && contains(github.event.pull_request.labels.*.name, 'preview') | |
| 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: Upgrade npm to 11.10.0 | |
| run: npm install -g npm@11.10.0 | |
| - 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 | |
| # Source maps are uploaded to S3 in release/production deploys (see the | |
| # `Move sourcemaps` step in the release/prod jobs). For preview we don't | |
| # ship them anywhere, but they still need to be removed from the bundle — | |
| # individual chunk maps can exceed the Cloudflare 25 MiB per-asset limit | |
| # and break the deploy. Strip them from both bundles before wrangler. | |
| - name: Strip sourcemaps for preview | |
| run: | | |
| cd packages/web | |
| find build build-ssr -type f -name '*.map' -delete || 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 = '<!-- audius-web-preview -->'; | |
| 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 | |
| needs: web-build | |
| if: github.ref == 'refs/heads/main' | |
| 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: Upgrade npm to 11.10.0 | |
| run: npm install -g npm@11.10.0 | |
| - 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 | |
| # Clear npm cache to avoid EEXIST conflicts | |
| npm cache clean --force || true | |
| # Try npm ci first, fallback to npm install if lock file is out of sync | |
| 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: Check bundlesize | |
| run: | | |
| cd packages/web | |
| npm run bundlesize:prod | |
| web-deploy-release-candidate: | |
| name: Web Deploy Release Candidate | |
| runs-on: ubuntu-latest | |
| needs: [web-build, web-check-ssr-bundlesize] | |
| if: github.ref == 'refs/heads/main' | |
| environment: | |
| name: release | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: ${{ env.NODE_VERSION }} | |
| - name: Upgrade npm to 11.10.0 | |
| run: npm install -g npm@11.10.0 | |
| - 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 | |
| # Clear npm cache to avoid EEXIST conflicts | |
| npm cache clean --force || true | |
| # Try npm ci first, fallback to npm install if lock file is out of sync | |
| 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 sourcemaps | |
| run: | | |
| cd packages/web | |
| mkdir -p sourcemaps/assets | |
| mv build-production/assets/*.map sourcemaps/assets | |
| mv build-ssr-production/client/assets/chunks/*.map sourcemaps/assets | |
| mv build-ssr-production/client/assets/entries/*.map sourcemaps/assets | |
| mv build-ssr-production/server/chunks/*.map sourcemaps/assets | |
| mv build-ssr-production/server/entries/*.map sourcemaps/assets | |
| - 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 | |
| - name: Deploy to Cloudflare (Release) | |
| env: | |
| CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }} | |
| run: | | |
| cd packages/web | |
| npm_config_yes=true npx wrangler@4.54.0 deploy --config ./src/ssr/wrangler.toml --env release | |
| npm_config_yes=true npx wrangler@4.54.0 deploy --config ./wrangler.toml --env release | |
| - name: Configure AWS credentials | |
| uses: aws-actions/configure-aws-credentials@v4 | |
| with: | |
| aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} | |
| aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} | |
| aws-region: us-east-1 | |
| - name: Deploy sourcemaps to S3 | |
| run: | | |
| aws s3 sync packages/web/sourcemaps s3://sourcemaps.audius.co --cache-control max-age=604800 | |
| # Single approval gate for the whole production release. Approving this job | |
| # releases web *and* all three desktop builds, replacing the separate | |
| # per-platform approval gates the old CircleCI pipeline had. | |
| production-gate: | |
| name: Production Release Gate | |
| runs-on: ubuntu-latest | |
| needs: [web-build, web-check-ssr-bundlesize] | |
| if: github.ref == 'refs/heads/main' | |
| environment: | |
| name: production | |
| steps: | |
| - run: echo "Production release approved — deploying web and desktop" | |
| web-deploy: | |
| name: Web Deploy | |
| runs-on: ubuntu-latest | |
| needs: [production-gate] | |
| if: github.ref == 'refs/heads/main' | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: ${{ env.NODE_VERSION }} | |
| - name: Upgrade npm to 11.10.0 | |
| run: npm install -g npm@11.10.0 | |
| - 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 | |
| # Clear npm cache to avoid EEXIST conflicts | |
| npm cache clean --force || true | |
| # Try npm ci first, fallback to npm install if lock file is out of sync | |
| 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 sourcemaps | |
| run: | | |
| cd packages/web | |
| mkdir -p sourcemaps/assets | |
| mv build-production/assets/*.map sourcemaps/assets | |
| mv build-ssr-production/client/assets/chunks/*.map sourcemaps/assets | |
| mv build-ssr-production/client/assets/entries/*.map sourcemaps/assets | |
| mv build-ssr-production/server/chunks/*.map sourcemaps/assets | |
| mv build-ssr-production/server/entries/*.map sourcemaps/assets | |
| - 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 | |
| - name: Deploy to Cloudflare (Production) | |
| env: | |
| CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }} | |
| run: | | |
| cd packages/web | |
| npm_config_yes=true npx wrangler@4.54.0 deploy --config ./src/ssr/wrangler.toml --env production | |
| npm_config_yes=true npx wrangler@4.54.0 deploy --config ./wrangler.toml --env production | |
| - name: Slack notification | |
| if: success() | |
| env: | |
| SLACK_WEBHOOK: ${{ secrets.SLACK_DAILY_DEPLOY_WEBHOOK }} | |
| run: | | |
| cd packages/web | |
| deploying_version=$(jq -r '.version' package.json) | |
| job_url="${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" | |
| json_content="{ \"blocks\": [{ \"type\": \"section\", \"text\": { \"type\": \"mrkdwn\", \"text\": \"Deployed production <${job_url}|v${deploying_version}> to web \n\" } }]}" | |
| curl -f -X POST -H 'Content-type: application/json' --data "$json_content" $SLACK_WEBHOOK | |
| # Desktop (Electron) builds. electron-builder reads packages/web/build-production | |
| # directly (see packages/web/scripts/dist.js), so the `builds` artifact is | |
| # downloaded in place and not renamed. | |
| desktop-build-mac: | |
| name: Desktop Build (Mac) | |
| runs-on: macos-latest | |
| needs: [production-gate] | |
| if: github.ref == 'refs/heads/main' | |
| timeout-minutes: 90 | |
| 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 | |
| # node-gyp needs distutils, removed in Python 3.12+ | |
| - name: Setup Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: '3.11' | |
| - name: Upgrade npm to 11.10.0 | |
| run: npm install -g npm@11.10.0 | |
| - name: Install dependencies | |
| 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 ci --prefer-offline || npm install --prefer-offline | |
| # Required by electron-builder to build the .dmg on macOS | |
| - name: Add dmg-license | |
| run: npm run install-dmg-license -w @audius/web | |
| - name: Download builds | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: builds | |
| path: packages/web | |
| - name: Build & publish Mac desktop app | |
| env: | |
| APP_STORE_CONNECT_API_KEY_ISSUER_ID: ${{ secrets.APP_STORE_CONNECT_API_KEY_ISSUER_ID }} | |
| APP_STORE_CONNECT_API_KEY_KEY: ${{ secrets.APP_STORE_CONNECT_API_KEY_KEY }} | |
| APP_STORE_CONNECT_API_KEY_KEY_ID: ${{ secrets.APP_STORE_CONNECT_API_KEY_KEY_ID }} | |
| AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} | |
| AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} | |
| run: | | |
| cd packages/web | |
| npm run dist:mac-publish-production | |
| - name: Slack notification | |
| if: success() | |
| env: | |
| SLACK_WEBHOOK: ${{ secrets.SLACK_DAILY_DEPLOY_WEBHOOK }} | |
| run: | | |
| cd packages/web | |
| deploying_version=$(jq -r '.version' package.json) | |
| job_url="${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" | |
| json_content="{ \"blocks\": [{ \"type\": \"section\", \"text\": { \"type\": \"mrkdwn\", \"text\": \"Deployed production <${job_url}|v${deploying_version}> to desktop mac \n\" } }]}" | |
| curl -f -X POST -H 'Content-type: application/json' --data "$json_content" $SLACK_WEBHOOK | |
| desktop-build-win: | |
| name: Desktop Build (Windows) | |
| runs-on: ubuntu-latest | |
| needs: [production-gate] | |
| if: github.ref == 'refs/heads/main' | |
| timeout-minutes: 90 | |
| container: | |
| image: electronuserland/builder:18-wine | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| # The image ships Node 18; the repo sets engine-strict with node >=24.10.0 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: ${{ env.NODE_VERSION }} | |
| cache: 'npm' | |
| cache-dependency-path: package-lock.json | |
| - name: Upgrade npm to 11.10.0 | |
| run: npm install -g npm@11.10.0 | |
| - name: Install dependencies | |
| 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 ci --prefer-offline || npm install --prefer-offline | |
| - name: Download builds | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: builds | |
| path: packages/web | |
| - name: Build & publish Windows desktop app | |
| env: | |
| AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} | |
| AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} | |
| run: | | |
| cd packages/web | |
| npm run dist:win-publish-production | |
| - name: Slack notification | |
| if: success() | |
| env: | |
| SLACK_WEBHOOK: ${{ secrets.SLACK_DAILY_DEPLOY_WEBHOOK }} | |
| run: | | |
| cd packages/web | |
| deploying_version=$(jq -r '.version' package.json) | |
| job_url="${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" | |
| json_content="{ \"blocks\": [{ \"type\": \"section\", \"text\": { \"type\": \"mrkdwn\", \"text\": \"Deployed production <${job_url}|v${deploying_version}> to desktop win \n\" } }]}" | |
| curl -f -X POST -H 'Content-type: application/json' --data "$json_content" $SLACK_WEBHOOK | |
| desktop-build-linux: | |
| name: Desktop Build (Linux) | |
| runs-on: ubuntu-latest | |
| needs: [production-gate] | |
| if: github.ref == 'refs/heads/main' | |
| timeout-minutes: 90 | |
| container: | |
| image: electronuserland/builder | |
| 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: Upgrade npm to 11.10.0 | |
| run: npm install -g npm@11.10.0 | |
| - name: Install dependencies | |
| 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 ci --prefer-offline || npm install --prefer-offline | |
| - name: Download builds | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: builds | |
| path: packages/web | |
| - name: Build & publish Linux desktop app | |
| env: | |
| AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} | |
| AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} | |
| run: | | |
| cd packages/web | |
| npm run dist:linux-publish-production | |
| - name: Slack notification | |
| if: success() | |
| env: | |
| SLACK_WEBHOOK: ${{ secrets.SLACK_DAILY_DEPLOY_WEBHOOK }} | |
| run: | | |
| cd packages/web | |
| deploying_version=$(jq -r '.version' package.json) | |
| job_url="${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" | |
| json_content="{ \"blocks\": [{ \"type\": \"section\", \"text\": { \"type\": \"mrkdwn\", \"text\": \"Deployed production <${job_url}|v${deploying_version}> to desktop linux \n\" } }]}" | |
| curl -f -X POST -H 'Content-type: application/json' --data "$json_content" $SLACK_WEBHOOK |