diff --git a/.github/workflows/bot-serving-check.yml b/.github/workflows/bot-serving-check.yml index e955dafbe6..6b3e3e23a1 100644 --- a/.github/workflows/bot-serving-check.yml +++ b/.github/workflows/bot-serving-check.yml @@ -108,7 +108,7 @@ jobs: slash_target=$(curl -sS --max-time 30 -o /dev/null -A "$GOOGLEBOT" \ -w '%{redirect_url}' "$ORIGIN/scatter-basic/") case "$slash_target" in - *"/seo-proxy"*|http://*) + *"/seo-proxy"*|http://*|*:8080/*) echo "::error::trailing-slash redirect leaks or downgrades: $slash_target" fail=1 ;; *) echo "OK: trailing slash -> $slash_target" ;; diff --git a/CHANGELOG.md b/CHANGELOG.md index b1d7c37945..83c2fc8df5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -232,6 +232,19 @@ aggregate instead: an italic *Catalog* line at the end of the version section an ### Fixed +- **The trailing-slash redirect leaked the internal port** — #10473 removed a redirect to + `http://api.anyplot.ai/seo-proxy/…` and replaced it with `http://anyplot.ai:8080/…`: a smaller + version of the same defect, since nginx builds a `permanent` rewrite's Location from + `$scheme://$host:$server_port`, and behind Cloud Run that is plain http on port 8080. + `absolute_redirect off` makes the Location relative, which the client resolves against the URL it + actually requested — the only value here guaranteed to be right. The daily `bot-serving-check` + would have caught this on its next run, since it already rejects an `http://` target; it now + rejects an internal port explicitly too. `agentic/docs/project-guide.md` also gains the step that + makes this checkable at all: the deploy triggers are **regional** (`europe-west4`), so a + `gcloud builds list` without `--region` returns builds from early 2026 and reads as "nothing has + deployed for months" — a wrong conclusion drawn in this session and corrected by the repo owner + (#10476). + - **Preview images were forbidden to every crawler that follows the rules** — `api.anyplot.ai` served a blanket `Disallow: /`, while every prerendered page references its preview image at `api.anyplot.ai/og/…png`. The image answered HTTP 200 and the host forbade fetching it, so an diff --git a/agentic/docs/project-guide.md b/agentic/docs/project-guide.md index dcaa0b3760..114a0cb699 100644 --- a/agentic/docs/project-guide.md +++ b/agentic/docs/project-guide.md @@ -890,8 +890,43 @@ The project runs on **Google Cloud Platform**: ### Automatic Deployment Push to `main` branch triggers Cloud Build: -- Changes in `api/`, `core/`, `pyproject.toml` -> Backend redeploy -- Changes in `app/` -> Frontend redeploy +- Changes in `api/`, `core/`, `pyproject.toml` -> Backend redeploy (`deploy-api`) +- Changes in `app/` -> Frontend redeploy (`deploy-app`) + +Roughly five minutes from merge to live, per build. + +#### Checking whether something actually deployed + +The triggers are **regional, in `europe-west4`**, and regional builds do not +appear in the global build list. Always pass `--region`: + +```bash +gcloud builds list --region=europe-west4 --project=anyplot --limit=10 \ + --format="table(id.slice(0,8),status,createTime.date('%H:%M'),substitutions.TRIGGER_NAME,substitutions.SHORT_SHA)" +gcloud builds describe --region=europe-west4 --project=anyplot +``` + +Omitting `--region` returns a handful of builds from early 2026 and nothing +since — which reads as "nothing has deployed for months" and is simply the +wrong list. That mistake has been made and had to be corrected by the repo +owner. + +`.github/workflows/notify-deployment.yml` only **records** a GitHub deployment; +it does not deploy anything. A green run there says nothing about whether the +code is live. + +The most trustworthy check is neither of the above: probe production and +compare against the expected behaviour, which is the only method that survives +a build succeeding while shipping the wrong thing. + +```bash +curl -A "Mozilla/5.0 (compatible; Googlebot/2.1)" -sSI https://anyplot.ai/box-basic/ | head -3 +curl -s https://anyplot.ai/robots.txt | head -5 +``` + +This matters most for `app/nginx.conf`: nginx behaviour has no local +verification loop in this repo, so production is the first place a change is +observable at all. ### Manual Deployment diff --git a/app/nginx.conf b/app/nginx.conf index 8233ddb18c..d64e572806 100644 --- a/app/nginx.conf +++ b/app/nginx.conf @@ -175,6 +175,15 @@ server { # 48 "Redirect error" URLs in Search Console got there. # # `/` itself cannot match: after `^/` there is nothing left for `/$`. + # + # absolute_redirect off is load-bearing, not tidiness. nginx builds the + # Location of a `permanent` rewrite from $scheme://$host:$server_port, and + # behind Cloud Run that is http and port 8080 — so the first version of + # this fix emitted `http://anyplot.ai:8080/box-basic`, trading the + # api-host leak it removed for an internal-port one. A relative Location + # is resolved by the client against the URL it actually requested, which + # is the only value here that is guaranteed correct. + absolute_redirect off; rewrite ^/(.*)/$ /$1 permanent; # Disable caching for index.html