From 6d8012c19cf766d9ef87871e430735c2aee6e99f Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 18 Aug 2026 13:32:24 +0000 Subject: [PATCH 1/3] Skip Lighthouse when no preview URL is available MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit deploy-app yields an empty deployment-url when Cloudflare returns no preview URL (Preview URLs disabled for the Worker); it warns and carries on. The Lighthouse job then ran `lhci autorun --collect.url=""`, which makes LHCI fall back to hunting for a static dist dir and fail with a misleading "Unable to automatically determine the location of static site files" error — observed on apps-management#1151. The shared lighthouserc.json sets every assertion to `off` (reports are informational), so a missing preview URL must never fail a PR. Skip with a clear warning instead, and stop the deploy-app warning from printing a broken `dash.cloudflare.com//workers-and-pages` link when the account-id input is empty. --- .github/workflows/app-build-deploy-dev.yml | 12 ++++++++++++ actions/deploy-app/action.yml | 11 ++++++++++- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/.github/workflows/app-build-deploy-dev.yml b/.github/workflows/app-build-deploy-dev.yml index 550c521..4003798 100644 --- a/.github/workflows/app-build-deploy-dev.yml +++ b/.github/workflows/app-build-deploy-dev.yml @@ -131,6 +131,18 @@ jobs: LHCI_CONFIG: ${{ inputs.lighthouse-config }} DEPLOYMENT_URL: ${{ needs.deploy.outputs.deployment-url }} run: | + # deploy-app yields an empty deployment-url when Cloudflare returns + # no preview URL (Preview URLs disabled for the Worker) — it warns + # and carries on. Passing that empty value to lhci is worse than + # skipping: with no --collect.url it falls back to hunting for a + # static dist dir and fails with a misleading "could not determine + # staticDistDir" error. Skip instead — this config's assertions are + # all `off` (reports are informational), so a missing preview URL + # must never fail a PR. + if [ -z "$DEPLOYMENT_URL" ]; then + echo "::warning::No preview URL from the deploy job — skipping Lighthouse. Enable Preview URLs for this Worker in Cloudflare to get performance reports on PRs." + exit 0 + fi CONFIG="$LHCI_CONFIG" [ -z "$CONFIG" ] && CONFIG=".lib/lighthouserc.json" npm install -g @lhci/cli diff --git a/actions/deploy-app/action.yml b/actions/deploy-app/action.yml index edd532f..5fbc20a 100644 --- a/actions/deploy-app/action.yml +++ b/actions/deploy-app/action.yml @@ -131,4 +131,13 @@ runs: WRANGLER_ENV: ${{ steps.wrangler-command.outputs.wrangler-env }} CF_ACCOUNT_ID: ${{ inputs.cloudflare-account-id }} run: | - echo "::warning::Preview URLs disabled for $WRANGLER_ENV. %0A Please enable from https://dash.cloudflare.com/$CF_ACCOUNT_ID/workers-and-pages" + # Downstream jobs (e.g. the Lighthouse check) must handle an empty + # deployment-url; this step only warns. Link to the account's Workers + # page when we know the account id — interpolating an empty one + # yields a broken `dash.cloudflare.com//workers-and-pages` URL. + if [ -n "$CF_ACCOUNT_ID" ]; then + WHERE="https://dash.cloudflare.com/$CF_ACCOUNT_ID/workers-and-pages" + else + WHERE="the Cloudflare dashboard (Workers & Pages -> your Worker -> Settings)" + fi + echo "::warning::No preview URL returned for $WRANGLER_ENV (Preview URLs likely disabled for this Worker). %0A Enable them from $WHERE" From 553d534618de98577f44430cb678902c62e85b37 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 18 Aug 2026 13:44:13 +0000 Subject: [PATCH 2/3] Stop the missing-preview-URL warning from blaming the wrong cause MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The warning asserted "Preview URLs disabled for ", which sent an investigation down the wrong path: apps-management's launchpad-demo has Preview URLs enabled (a run from the previous day printed a real https://-launchpad-demo.kf-dev.workers.dev), yet the URL went missing after its Cloudflare API token was rotated. wrangler resolves the preview URL with a follow-up API call after printing the Worker Version ID and stays silent when that call fails, so an absent URL can equally mean the token cannot read the account's workers.dev subdomain, or that no account id was supplied for wrangler to resolve one. Name all three causes in likelihood order, and warn separately when cloudflare-account-id arrives empty — it is a required input, and apps-management is currently passing nothing. --- actions/deploy-app/action.yml | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/actions/deploy-app/action.yml b/actions/deploy-app/action.yml index 5fbc20a..88a1503 100644 --- a/actions/deploy-app/action.yml +++ b/actions/deploy-app/action.yml @@ -132,12 +132,20 @@ runs: CF_ACCOUNT_ID: ${{ inputs.cloudflare-account-id }} run: | # Downstream jobs (e.g. the Lighthouse check) must handle an empty - # deployment-url; this step only warns. Link to the account's Workers - # page when we know the account id — interpolating an empty one - # yields a broken `dash.cloudflare.com//workers-and-pages` URL. + # deployment-url; this step only warns. + # + # Do NOT assume "Preview URLs are disabled" here. wrangler resolves the + # preview URL with a follow-up API call after printing the Worker + # Version ID, and it stays SILENT when that call fails — so an absent + # URL means any of: previews genuinely disabled, the API token cannot + # read the account's workers.dev subdomain, or no account id was + # supplied for the token to resolve one. Only the first is a Worker + # setting; list them all so the next reader does not chase the wrong + # one (we did). if [ -n "$CF_ACCOUNT_ID" ]; then WHERE="https://dash.cloudflare.com/$CF_ACCOUNT_ID/workers-and-pages" else WHERE="the Cloudflare dashboard (Workers & Pages -> your Worker -> Settings)" + echo "::warning::No cloudflare-account-id was supplied to deploy-app; wrangler must resolve the account from the token alone, which can silently break preview-URL lookup." fi - echo "::warning::No preview URL returned for $WRANGLER_ENV (Preview URLs likely disabled for this Worker). %0A Enable them from $WHERE" + echo "::warning::wrangler returned no preview URL for $WRANGLER_ENV. Check, in order: (1) the API token can read the account's workers.dev subdomain (Workers Scripts Read + Account Settings Read), (2) cloudflare-account-id is set, (3) Preview URLs are enabled for this Worker at $WHERE" From 266b98753a46cbcd16d945cdaaf9cc6164f62795 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 18 Aug 2026 14:15:29 +0000 Subject: [PATCH 3/3] Surface the Lighthouse report link on the run summary MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The hosted report URL was only discoverable by expanding the job log and finding lhci's "Open the report at " line. Lift it into GITHUB_STEP_SUMMARY alongside the tested URL, so it shows on the run's summary page. Reports are deliberately not uploaded as artifacts — the shared config already publishes to LHCI temporary public storage and nobody is expected to trawl old reports, so the summary notes that the link expires after a few days rather than promising durable access. lhci output is teed to lift the URL out; `set -o pipefail` keeps a real lhci failure from being masked by tee's exit status. If no hosted link is present (e.g. a caller overrides the upload target), the summary says so instead of rendering a broken link. --- .github/workflows/app-build-deploy-dev.yml | 27 +++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/.github/workflows/app-build-deploy-dev.yml b/.github/workflows/app-build-deploy-dev.yml index 4003798..2b80a32 100644 --- a/.github/workflows/app-build-deploy-dev.yml +++ b/.github/workflows/app-build-deploy-dev.yml @@ -146,4 +146,29 @@ jobs: CONFIG="$LHCI_CONFIG" [ -z "$CONFIG" ] && CONFIG=".lib/lighthouserc.json" npm install -g @lhci/cli - lhci autorun --config="$CONFIG" --collect.url="$DEPLOYMENT_URL" + + # Tee so the hosted report link can be lifted out of the output; + # pipefail keeps a genuine lhci failure from being masked by tee. + set -o pipefail + lhci autorun --config="$CONFIG" --collect.url="$DEPLOYMENT_URL" 2>&1 | tee /tmp/lhci.log + + # The shared config uploads to LHCI's temporary public storage and + # prints "Open the report at ". Surface that on the run summary + # so nobody has to expand job logs to find it. Reports are NOT kept + # as artifacts and that bucket expires them after a few days, so the + # link is only good for a short while. + REPORT_URL=$(grep -oE 'https://storage\.googleapis\.com/[^[:space:]]+\.report\.html' /tmp/lhci.log | head -1) + { + echo "### 📊 Lighthouse" + echo "" + echo "Tested: ${DEPLOYMENT_URL}" + if [ -n "$REPORT_URL" ]; then + echo "" + echo "[Open the report](${REPORT_URL}) — hosted on LHCI temporary public storage, expires after a few days." + else + echo "" + echo "No hosted report link found in the lhci output (upload target may not be temporary-public-storage)." + fi + echo "" + echo "_All assertions are \`off\` in the shared config, so this check is informational and cannot fail a PR._" + } >> "$GITHUB_STEP_SUMMARY"