Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/bot-serving-check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Comment on lines 108 to 112
fail=1 ;;
*) echo "OK: trailing slash -> $slash_target" ;;
Expand Down
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
39 changes: 37 additions & 2 deletions agentic/docs/project-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 <build-id> --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

Expand Down
9 changes: 9 additions & 0 deletions app/nginx.conf
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading