fix: harden surface reset cascades #2203
Workflow file for this run
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: Cloudflare Worker Preview Deploy | |
| on: | |
| pull_request: | |
| paths: | |
| - 'src/**' | |
| - 'worker/**' | |
| - 'public/**' | |
| - 'config.json' | |
| - 'index.html' | |
| - 'package.json' | |
| - 'package-lock.json' | |
| - 'scripts/inject-client-config.js' | |
| - 'vite.config.ts' | |
| - 'tsconfig.json' | |
| - '.github/workflows/cloudflare-web-preview.yml' | |
| - '.github/actions/setup/**' | |
| concurrency: | |
| group: cloudflare-worker-preview-${{ github.event.pull_request.number || github.ref_name }} | |
| cancel-in-progress: true | |
| jobs: | |
| deploy: | |
| if: github.event.pull_request.head.repo.full_name == github.repository && github.actor != 'dependabot[bot]' | |
| runs-on: ubuntu-latest | |
| environment: preview | |
| permissions: | |
| contents: read | |
| pull-requests: write | |
| env: | |
| CLIENT_CONFIG_OVERRIDES_JSON: ${{ vars.CLIENT_CONFIG_OVERRIDES_JSON }} | |
| CLIENT_CONFIG_OVERRIDES_STRICT: ${{ vars.CLIENT_CONFIG_OVERRIDES_STRICT || 'false' }} | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 | |
| with: | |
| persist-credentials: false | |
| - name: Prepare preview metadata | |
| id: metadata | |
| shell: bash | |
| run: | | |
| short_sha="$(git rev-parse --short=7 HEAD)" | |
| { | |
| echo "short_sha=$short_sha" | |
| } >> "$GITHUB_OUTPUT" | |
| - name: Set Sentry build environment for PR preview | |
| if: github.event_name == 'pull_request' | |
| env: | |
| VITE_SENTRY_DSN: ${{ secrets.VITE_SENTRY_DSN }} | |
| VITE_SENTRY_TOOLBAR: 'true' | |
| VITE_SENTRY_ORGANIZATION: ${{ secrets.SENTRY_ORG }} | |
| VITE_SENTRY_PROJECT: ${{ secrets.SENTRY_PROJECT }} | |
| SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} | |
| SENTRY_ORG: ${{ secrets.SENTRY_ORG }} | |
| SENTRY_PROJECT: ${{ secrets.SENTRY_PROJECT }} | |
| shell: bash | |
| run: | | |
| echo "VITE_SENTRY_DSN=$VITE_SENTRY_DSN" >> "$GITHUB_ENV" | |
| echo "VITE_SENTRY_ENVIRONMENT=preview" >> "$GITHUB_ENV" | |
| echo "VITE_SENTRY_PR=${{ github.event.pull_request.number }}" >> "$GITHUB_ENV" | |
| echo "VITE_SENTRY_TOOLBAR=$VITE_SENTRY_TOOLBAR" >> "$GITHUB_ENV" | |
| echo "VITE_SENTRY_ORGANIZATION=$VITE_SENTRY_ORGANIZATION" >> "$GITHUB_ENV" | |
| echo "VITE_SENTRY_PROJECT=$VITE_SENTRY_PROJECT" >> "$GITHUB_ENV" | |
| echo "SENTRY_AUTH_TOKEN=$SENTRY_AUTH_TOKEN" >> "$GITHUB_ENV" | |
| echo "SENTRY_ORG=$SENTRY_ORG" >> "$GITHUB_ENV" | |
| echo "SENTRY_PROJECT=$SENTRY_PROJECT" >> "$GITHUB_ENV" | |
| - name: Set build hash | |
| shell: bash | |
| run: | | |
| echo "VITE_BUILD_HASH=${{ steps.metadata.outputs.short_sha }}" >> "$GITHUB_ENV" | |
| - name: Setup app and build | |
| uses: ./.github/actions/setup | |
| with: | |
| build: 'true' | |
| - name: Set deploy alias | |
| id: alias | |
| shell: bash | |
| run: | | |
| if [ "${{ github.event_name }}" = "pull_request" ]; then | |
| echo "alias=pr-${{ github.event.pull_request.number }}" >> "$GITHUB_OUTPUT" | |
| else | |
| branch="${GITHUB_REF_NAME}" | |
| alias="$(echo "$branch" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9]/-/g' | sed 's/-\+/-/g' | sed 's/^-\|-$//g')" | |
| echo "alias=${alias}" >> "$GITHUB_OUTPUT" | |
| fi | |
| - name: Upload Worker preview | |
| id: deploy | |
| uses: cloudflare/wrangler-action@ebbaa1584979971c8614a24965b4405ff95890e0 # v4.0.0 | |
| with: | |
| apiToken: ${{ secrets.TF_CLOUDFLARE_API_TOKEN }} | |
| accountId: ${{ secrets.TF_VAR_ACCOUNT_ID }} | |
| command: > | |
| versions upload | |
| -c dist/charm/wrangler.json | |
| --preview-alias ${{ steps.alias.outputs.alias }} | |
| --tag ${{ steps.metadata.outputs.short_sha }} | |
| --message ${{ steps.metadata.outputs.short_sha }} | |
| - name: Resolve preview URL | |
| id: preview | |
| env: | |
| DEPLOYMENT_URL: ${{ steps.deploy.outputs.deployment-url }} | |
| COMMAND_OUTPUT: ${{ steps.deploy.outputs.command-output }} | |
| ALIAS: ${{ steps.alias.outputs.alias }} | |
| shell: bash | |
| run: | | |
| alias_url_pattern="^https?://${ALIAS}-[^[:space:]]+$" | |
| preview_url="" | |
| if printf '%s\n' "$DEPLOYMENT_URL" | grep -Eq "$alias_url_pattern"; then | |
| preview_url="$DEPLOYMENT_URL" | |
| else | |
| preview_url="$(printf '%s\n' "$COMMAND_OUTPUT" | grep -Eo "https?://${ALIAS}-[^[:space:]\"'<>)]+" | head -n 1 || true)" | |
| fi | |
| if ! printf '%s\n' "$preview_url" | grep -Eq "$alias_url_pattern"; then | |
| echo "::warning::Failed to resolve aliased Worker preview URL from Wrangler output." | |
| preview_url="" | |
| fi | |
| echo "preview_url=${preview_url}" >> "$GITHUB_OUTPUT" | |
| - name: Publish summary and PR comment | |
| uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 | |
| env: | |
| MARKER: '<!-- cloudflare-worker-preview -->' | |
| PREVIEW_URL: ${{ steps.preview.outputs.preview_url }} | |
| PREVIEW_ALIAS: ${{ steps.alias.outputs.alias }} | |
| SHORT_SHA: ${{ steps.metadata.outputs.short_sha }} | |
| with: | |
| github-token: ${{ secrets.GITHUB_TOKEN }} | |
| script: | | |
| const marker = process.env.MARKER; | |
| const previewUrl = process.env.PREVIEW_URL; | |
| const previewAlias = process.env.PREVIEW_ALIAS; | |
| const shortSha = process.env.SHORT_SHA?.slice(0, 7); | |
| const now = new Date().toUTCString().replace(':00 GMT', ' UTC'); | |
| async function publishPrComment(body) { | |
| if (context.eventName !== 'pull_request') return; | |
| try { | |
| const { owner, repo } = context.repo; | |
| const issue_number = context.issue.number; | |
| const comments = await github.paginate(github.rest.issues.listComments, { | |
| owner, repo, issue_number, | |
| }); | |
| const existing = comments.find( | |
| (c) => c.user.type === "Bot" && c.body.includes(marker), | |
| ); | |
| if (existing) { | |
| await github.rest.issues.deleteComment({ | |
| owner, repo, comment_id: existing.id, | |
| }); | |
| } | |
| await github.rest.issues.createComment({ owner, repo, issue_number, body }); | |
| } catch (error) { | |
| core.warning(`Worker preview uploaded, but the PR comment could not be updated: ${error.message}`); | |
| } | |
| } | |
| if (!previewUrl) { | |
| const message = [ | |
| marker, | |
| `## Deploying with <a href="https://workers.dev"><img alt="Cloudflare Workers" src="https://workers.cloudflare.com/logo.svg" width="16"></a> Cloudflare Workers`, | |
| ``, | |
| `✅ Worker preview upload completed, but Wrangler did not return a resolvable aliased preview URL.`, | |
| ``, | |
| `Alias: \`${previewAlias}\``, | |
| `Commit: \`${shortSha}\``, | |
| `Updated: ${now}`, | |
| ].join("\n"); | |
| await core.summary.addRaw(message.replace(marker + "\n", "")).write(); | |
| await publishPrComment(message); | |
| return; | |
| } | |
| const tableRow = "| ✅ Deployment successful! | <a href='" + previewUrl + "'>" + previewUrl + "</a> | " + shortSha + " | `" + previewAlias + "` | " + now + " |"; | |
| const comment = [ | |
| marker, | |
| `## Deploying with <a href="https://workers.dev"><img alt="Cloudflare Workers" src="https://workers.cloudflare.com/logo.svg" width="16"></a> Cloudflare Workers`, | |
| ``, | |
| `| Status | Preview URL | Commit | Alias | Updated (UTC) |`, | |
| `| - | - | - | - | - |`, | |
| tableRow, | |
| ].join("\n"); | |
| await core.summary.addRaw(comment.replace(marker + "\n", "")).write(); | |
| await publishPrComment(comment); |