Repository navigation
chore: release new version 🚀 #43
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: Deploy Website Preview | |
| # Per-PR preview of the marketing site at https://ema.tnsor.network/preview/<n>/ | |
| # (the production router worker proxies /preview/<n> to this PR's worker, | |
| # nostream-web-pr-<n>, served from its workers.dev URL). The preview is deleted | |
| # when the PR closes (merged or not). | |
| # | |
| # Requires the `website-preview` GitHub environment to exist with | |
| # CLOUDFLARE_API_TOKEN (Workers Scripts edit) and CLOUDFLARE_ACCOUNT_ID — | |
| # one-time setup. While the environment or its secrets are absent, this | |
| # workflow skips with a notice instead of failing the PR. | |
| on: | |
| pull_request: | |
| types: | |
| - opened | |
| - synchronize | |
| - reopened | |
| - closed | |
| paths: | |
| - "website/site/**" | |
| - "website/hero-animation/**" | |
| - ".github/workflows/deploy-website-preview.yml" | |
| concurrency: | |
| group: website-preview-${{ github.event.pull_request.number }} | |
| cancel-in-progress: true | |
| permissions: | |
| contents: read | |
| pull-requests: write | |
| jobs: | |
| preview: | |
| runs-on: ubuntu-latest | |
| # Deploy credentials live in this GitHub environment: CLOUDFLARE_API_TOKEN | |
| # secret (Workers Scripts scope) and CLOUDFLARE_ACCOUNT_ID variable. | |
| environment: website-preview | |
| # Guard the environment reference so a missing setup skips rather than fails: | |
| # the job targets the environment only when it exists. | |
| steps: | |
| - name: Check preview environment is configured | |
| id: guard | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| run: | | |
| set -eu | |
| # Existence is the only check the runner's token can make: listing | |
| # environment secrets needs permissions github.token does not carry, | |
| # and probing them here once made every run skip with "lacks | |
| # CLOUDFLARE_API_TOKEN" even after the secrets were set. | |
| if gh api repos/${{ github.repository }}/environments/website-preview >/dev/null 2>&1; then | |
| echo "skip=false" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "skip=true" >> "$GITHUB_OUTPUT" | |
| echo "::notice::website-preview environment does not exist yet — PR preview skipped. Create it with CLOUDFLARE_API_TOKEN + CLOUDFLARE_ACCOUNT_ID to enable previews." | |
| fi | |
| - name: Checkout (for cleanup metadata) | |
| if: steps.guard.outputs.skip == 'false' | |
| uses: actions/checkout@v3 | |
| - uses: pnpm/action-setup@v4 | |
| if: steps.guard.outputs.skip == 'false' && github.event.action != 'closed' | |
| - uses: actions/setup-node@v3 | |
| if: steps.guard.outputs.skip == 'false' && github.event.action != 'closed' | |
| with: | |
| node-version-file: .nvmrc | |
| cache: pnpm | |
| - name: Install workspace dependencies | |
| if: steps.guard.outputs.skip == 'false' && github.event.action != 'closed' | |
| run: pnpm install --frozen-lockfile | |
| - name: Build the site under the preview base | |
| if: steps.guard.outputs.skip == 'false' && github.event.action != 'closed' | |
| working-directory: website/site | |
| env: | |
| SITE_URL: https://ema.tnsor.network | |
| SITE_BASE: /preview/${{ github.event.pull_request.number }}/ | |
| run: | | |
| pnpm run build | |
| node scripts/apply-base.mjs | |
| # The assets manifest is keyed by file path: the worker serves dist/ | |
| # at the root of its URL, but the preview is requested under | |
| # /preview/<n>/... — so the built tree must also EXIST at that path | |
| # or every asset request falls through to the SPA-fallback | |
| # index.html (text/html for .css/.mp4 requests — the broken preview). | |
| # Copy the build into dist/preview/<n>/ (excluding the copy itself). | |
| n="${{ github.event.pull_request.number }}" | |
| mkdir -p "dist/preview/$n" | |
| find dist -mindepth 1 -maxdepth 1 ! -name preview -exec cp -r {} "dist/preview/$n/" \; | |
| - name: Mark the preview comment as rendering | |
| if: steps.guard.outputs.skip == 'false' && github.event.action != 'closed' | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| URL: https://ema.tnsor.network/preview/${{ github.event.pull_request.number }}/ | |
| WORKER_URL: https://nostream-web-pr-${{ github.event.pull_request.number }}.cameri.workers.dev/preview/${{ github.event.pull_request.number }}/ | |
| MARKER: <!-- site-preview-comment --> | |
| run: | | |
| # Flip the single preview comment to a "rendering" state before the | |
| # deploy starts, so the link always exists but signals staleness. | |
| COMMENT_ID=$(gh api "repos/${{ github.repository }}/issues/${{ github.event.pull_request.number }}/comments?per_page=100" \ | |
| --jq '.[] | select(.body | startswith(env.MARKER)) | .id' | tail -1) | |
| BODY="${MARKER} | |
| ⏳ Preview is rendering for the latest push — ${WORKER_URL} will serve the new build in about a minute." | |
| if [ -n "$COMMENT_ID" ]; then | |
| gh api -X PATCH "repos/${{ github.repository }}/issues/comments/$COMMENT_ID" -f body="$BODY" >/dev/null | |
| echo "marked comment $COMMENT_ID as rendering" | |
| else | |
| gh pr comment ${{ github.event.pull_request.number }} --repo ${{ github.repository }} --body "$BODY" >/dev/null | |
| echo "created new preview comment (rendering)" | |
| fi | |
| - name: Deploy the preview worker | |
| if: steps.guard.outputs.skip == 'false' && github.event.action != 'closed' | |
| working-directory: website/site | |
| env: | |
| CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }} | |
| CLOUDFLARE_ACCOUNT_ID: ${{ vars.CLOUDFLARE_ACCOUNT_ID }} | |
| run: | | |
| npx wrangler deploy \ | |
| --config wrangler.preview.jsonc \ | |
| --name nostream-web-pr-${{ github.event.pull_request.number }} | |
| - name: Link the preview on the PR | |
| if: steps.guard.outputs.skip == 'false' && github.event.action != 'closed' | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| URL: https://ema.tnsor.network/preview/${{ github.event.pull_request.number }}/ | |
| WORKER_URL: https://nostream-web-pr-${{ github.event.pull_request.number }}.cameri.workers.dev/preview/${{ github.event.pull_request.number }}/ | |
| MARKER: <!-- site-preview-comment --> | |
| run: | | |
| # One comment per PR, updated in place on every push: find the | |
| # existing one by marker, edit it, or create it if absent. The | |
| # direct workers.dev URL works as soon as this deploy lands; the | |
| # ema.tnsor.network form starts working once the router ships | |
| # (it deploys with this PR's merge). | |
| COMMENT_ID=$(gh api "repos/${{ github.repository }}/issues/${{ github.event.pull_request.number }}/comments?per_page=100" \ | |
| --jq '.[] | select(.body | startswith(env.MARKER)) | .id' | tail -1) | |
| BODY="${MARKER} | |
| 🔍 Site preview for this PR (includes all changes on this branch): ${WORKER_URL} | |
| The ${URL} form serves the same build once this PR merges — the production router that proxies /preview/* ships with it. | |
| Updates with every push to this PR; deleted when the PR closes." | |
| if [ -n "$COMMENT_ID" ]; then | |
| gh api -X PATCH "repos/${{ github.repository }}/issues/comments/$COMMENT_ID" -f body="$BODY" >/dev/null | |
| echo "updated comment $COMMENT_ID" | |
| else | |
| gh pr comment ${{ github.event.pull_request.number }} --repo ${{ github.repository }} --body "$BODY" >/dev/null | |
| echo "created new preview comment" | |
| fi | |
| - name: Delete the preview worker | |
| if: steps.guard.outputs.skip == 'false' && github.event.action == 'closed' | |
| working-directory: website/site | |
| env: | |
| CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }} | |
| CLOUDFLARE_ACCOUNT_ID: ${{ vars.CLOUDFLARE_ACCOUNT_ID }} | |
| run: | | |
| # --force skips the "would this break dependents" probe, which calls | |
| # KV namespaces listing the deploy token's scope (Workers Scripts | |
| # only) cannot read — the probe errors with auth 10000 AFTER the | |
| # delete has already succeeded. Preview workers are assets-only | |
| # (no bindings), so the check is pure overhead. A missing worker | |
| # still errors and is caught below. | |
| npx wrangler delete --config wrangler.preview.jsonc --force \ | |
| --name nostream-web-pr-${{ github.event.pull_request.number }} \ | |
| || echo "preview worker already absent" | |
| - name: Note the cleanup on the PR | |
| if: steps.guard.outputs.skip == 'false' && github.event.action == 'closed' | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| MARKER: <!-- site-preview-comment --> | |
| run: | | |
| # Update the SAME single preview comment instead of adding one. | |
| COMMENT_ID=$(gh api "repos/${{ github.repository }}/issues/${{ github.event.pull_request.number }}/comments?per_page=100" \ | |
| --jq '.[] | select(.body | startswith(env.MARKER)) | .id' | tail -1) | |
| BODY="${MARKER} | |
| 🧹 Site preview for this PR was deleted (PR closed)." | |
| if [ -n "$COMMENT_ID" ]; then | |
| gh api -X PATCH "repos/${{ github.repository }}/issues/comments/$COMMENT_ID" -f body="$BODY" >/dev/null | |
| else | |
| gh pr comment ${{ github.event.pull_request.number }} --repo ${{ github.repository }} --body "$BODY" >/dev/null || true | |
| fi |