From 8ed1d6c80ad5a8904810d615e93afedc176ac4a3 Mon Sep 17 00:00:00 2001 From: Remco Veldkamp Date: Wed, 2 Sep 2026 21:40:45 +0200 Subject: [PATCH 1/3] Run workflow on merge --- .github/workflows/firebase-hosting-pull-request.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/firebase-hosting-pull-request.yml b/.github/workflows/firebase-hosting-pull-request.yml index c9e8534d..76578391 100644 --- a/.github/workflows/firebase-hosting-pull-request.yml +++ b/.github/workflows/firebase-hosting-pull-request.yml @@ -5,6 +5,7 @@ name: Deploy to Firebase Hosting on PR on: pull_request: + types: [opened, synchronize, reopened, closed] branches: - develop - v3.x From a0ba67e1fb699ffea3f291b02564359a58e09425 Mon Sep 17 00:00:00 2001 From: Remco Veldkamp Date: Wed, 2 Sep 2026 21:42:41 +0200 Subject: [PATCH 2/3] Skip npm when closing --- .github/workflows/firebase-hosting-pull-request.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/firebase-hosting-pull-request.yml b/.github/workflows/firebase-hosting-pull-request.yml index 76578391..b93610b0 100644 --- a/.github/workflows/firebase-hosting-pull-request.yml +++ b/.github/workflows/firebase-hosting-pull-request.yml @@ -24,7 +24,8 @@ jobs: steps: - uses: actions/checkout@v4 - - run: npm ci && npm run predeploy && npm run typedoc + - if: github.event.action != 'closed' + run: npm ci && npm run predeploy && npm run typedoc - uses: FirebaseExtended/action-hosting-deploy@v0 with: repoToken: '${{ secrets.GITHUB_TOKEN }}' From e51ceb93533fb0ed2bc904c9bdac7c07d450304f Mon Sep 17 00:00:00 2001 From: Remco Veldkamp Date: Thu, 10 Sep 2026 23:05:45 +0200 Subject: [PATCH 3/3] Review: actually tear down preview channels, skip non-deployable PRs The deploy action has no teardown, so running it on 'closed' did nothing. A separate cleanup_preview job now deletes the PR's channel with the firebase CLI, and a paths filter skips the build+deploy entirely for PRs that cannot change the deployed output. --- .../firebase-hosting-pull-request.yml | 59 ++++++++++++++++++- 1 file changed, 56 insertions(+), 3 deletions(-) diff --git a/.github/workflows/firebase-hosting-pull-request.yml b/.github/workflows/firebase-hosting-pull-request.yml index b93610b0..6dd2d761 100644 --- a/.github/workflows/firebase-hosting-pull-request.yml +++ b/.github/workflows/firebase-hosting-pull-request.yml @@ -18,17 +18,70 @@ permissions: jobs: build_and_preview: - if: '${{ github.event.pull_request.head.repo.full_name == github.repository }}' + if: >- + github.event.action != 'closed' && + github.event.pull_request.head.repo.full_name == github.repository runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - if: github.event.action != 'closed' + # A preview is only worth building when the deployed output can actually + # differ: the library, the demo it loads, or the deploy/docs config. + # Doc- and test-only PRs skip the whole build and deploy. + - uses: dorny/paths-filter@v3 + id: filter + with: + filters: | + deployable: + - 'src/**' + - '!src/__tests__/**' + - 'demo/**' + - 'package.json' + - 'package-lock.json' + - 'rollup.config.mjs' + - 'firebase.json' + - 'typedoc.json' + - 'typedoc.css' + - '.github/workflows/firebase-hosting-pull-request.yml' + - if: steps.filter.outputs.deployable == 'true' run: npm ci && npm run predeploy && npm run typedoc - - uses: FirebaseExtended/action-hosting-deploy@v0 + - if: steps.filter.outputs.deployable == 'true' + uses: FirebaseExtended/action-hosting-deploy@v0 with: repoToken: '${{ secrets.GITHUB_TOKEN }}' expires: 30d firebaseServiceAccount: '${{ secrets.FIREBASE_SERVICE_ACCOUNT_GCODE_PREVIEW }}' projectId: gcode-preview + + cleanup_preview: + if: >- + github.event.action == 'closed' && + github.event.pull_request.head.repo.full_name == github.repository + + runs-on: ubuntu-latest + + steps: + # The deploy action has no teardown of its own + # (FirebaseExtended/action-hosting-deploy#60), so the channel is removed + # with the CLI. The action names its channel `pr-` with + # the branch sanitized and truncated, so we match on the `pr-` + # prefix rather than reproducing that truncation here. + - name: Delete the PR's preview channel + env: + PR_NUMBER: ${{ github.event.pull_request.number }} + FIREBASE_SERVICE_ACCOUNT: ${{ secrets.FIREBASE_SERVICE_ACCOUNT_GCODE_PREVIEW }} + run: | + set -euo pipefail + echo "$FIREBASE_SERVICE_ACCOUNT" > "$RUNNER_TEMP/service-account.json" + export GOOGLE_APPLICATION_CREDENTIALS="$RUNNER_TEMP/service-account.json" + firebase() { npx --yes firebase-tools@14 "$@" --project gcode-preview; } + channel=$(firebase hosting:channel:list --json | + jq -r --arg prefix "pr${PR_NUMBER}-" \ + '.result.channels[].name | split("/") | last | select(startswith($prefix))') + if [ -z "$channel" ]; then + echo "No preview channel for PR ${PR_NUMBER}; nothing to delete." + exit 0 + fi + echo "Deleting preview channel $channel" + firebase hosting:channel:delete "$channel" --force