Repository navigation
[quality] Production deploy bakes the pre-transfer castrojo.github.io origin into every canonical URL, og:url and sitemap entry #348
Description
Finding
Every page on the live production site declares a canonical URL, an og:url,
and 44 sitemap entries pointing at https://castrojo.github.io/endusers/ — a
personal fork origin, not the origin the content is served from.
The site is served from https://cncf.github.io/endusers/ (HTTP 200, verified
below). .github/workflows/deploy-gh-pages.yml:58 overrides SITE_URL with
the pre-transfer personal origin, so docusaurus.config.js:28 (url: siteUrl)
bakes that origin into every absolute URL Docusaurus emits.
This is stale state left over from the castrojo/endusers -> cncf/endusers
transfer. .github/workflows/ci.yml:31 was already updated and uses
SITE_URL: https://cncf.github.io; the deploy workflow was not.
Evidence (live production site, fetched 2026-09-20)
$ curl -sI https://cncf.github.io/endusers/ | head -1
HTTP/2 200
$ curl -s https://cncf.github.io/endusers/ | grep -oE '(canonical|og:url)[^>]{0,80}'
og:url content=https://castrojo.github.io/endusers/
canonical href=https://castrojo.github.io/endusers/
$ curl -s https://cncf.github.io/endusers/sitemap.xml | grep -c 'castrojo.github.io'
1 # single-line XML: all 44 <loc> entries use the castrojo origin, zero use cncf
At rev 00b44df the only remaining castrojo reference in .github/workflows/
is this one:
$ grep -rn 'castrojo' .github/workflows/
.github/workflows/deploy-gh-pages.yml:58: SITE_URL: https://castrojo.github.io
Impact
- Search engines are told the canonical copy of every page lives on another
origin. Arel=canonicalpointing off-origin is the strongest possible
de-indexing signal for the origin actually serving the content. - Social previews resolve to the wrong origin —
og:urlis what Slack,
LinkedIn and X follow when a link is unfurled. - The sitemap submitted for the site lists 44 URLs on an origin the project
does not control. static/CNAMEdoes not exist, soendusers.cncf.iois not yet active and
https://cncf.github.iois the correct value today. The comment already in
the workflow (lines 54-57) covers the later flip to the custom domain.
Why existing gates miss it
onBrokenLinks: 'throw'validates internal routes, not the absolute origin
they are rendered against.npm run test:unit(55 tests at00b44df) contains no assertion over
.github/workflows/**env values.ci.ymlbuilds with the correctSITE_URL, so the defect is invisible on
every pull request and appears only in the deploy job.- The
docusaurus.config.jsdefault (https://endusers.cncf.io) is correct;
only the workflow override is wrong, so reading the config suggests nothing
is amiss. Open PR fix(config): point editUrl at cncf/endusers, not castrojo #245 fixeseditUrlin that config — a different key in a
different file, and it does not touch this.
Recommendation
One-line change. Exact replacement for .github/workflows/deploy-gh-pages.yml
lines 53-59 — replace this:
# Build for the GitHub Pages project URL. When the custom domain in
# static/CNAME is verified and active, update these values to
# SITE_URL=https://endusers.cncf.io and BASE_URL=/ so canonical and
# Open Graph URLs point to the production domain.
- name: Build website
env:
SITE_URL: https://castrojo.github.io
BASE_URL: /endusers/
run: npm run build:productionwith this:
# Build for the GitHub Pages project URL. When the custom domain in
# static/CNAME is verified and active, update these values to
# SITE_URL=https://endusers.cncf.io and BASE_URL=/ so canonical and
# Open Graph URLs point to the production domain.
- name: Build website
env:
SITE_URL: https://cncf.github.io
BASE_URL: /endusers/
run: npm run build:productionNothing else changes: BASE_URL is already correct, and the value now matches
ci.yml, so pull-request builds and deploy builds agree.
Verification after merge
curl -s https://cncf.github.io/endusers/ | grep -o 'canonical[^>]*'
# expect: canonical href=https://cncf.github.io/endusers/
curl -s https://cncf.github.io/endusers/sitemap.xml | grep -c 'castrojo.github.io'
# expect: 0
No PR is attached, and that is not a judgement call
The entire fix is inside .github/workflows/. This agent's GitHub App token is
minted at the contributor tier, which does not carry the Workflows
permission, so GitHub rejects any push whose diff touches that directory. There
is nothing this agent can push that would contain the change. It needs a
human maintainer or an agent running at a tier that holds the Workflows
permission to land it. The replacement text above is complete and mechanical
so applying it requires no re-derivation.
A regression-guard test asserting that the deploy workflow's SITE_URL matches
the origin the site is served from is deliberately not proposed here: it
would be red against main until this change lands, and splitting it out would
mean shipping a failing test. It is worth filing separately once this is green.
Priority
- Impact: high — affects the canonical URL, Open Graph URL and sitemap of every page on the live production site
- Effort: low — one line, no new dependency, no behaviour change beyond the emitted origin
Filed by quality agent (hold-gated mode)
— hive: agent=quality backend=copilot model=claude-opus-5
Activity
mrbobbytables commentedon Sep 21, 2026
Confirmed and reproduced: this fix requires pushing a change to
.github/workflows/deploy-gh-pages.yml, and bothgit pushand the Contents API reject the write:The Contents API confirms the same restriction is scoped specifically to the workflow path (a parallel PUT to
README.mdon the same branch succeeds; the identical PUT to.github/workflows/deploy-gh-pages.ymlreturns 404). This is a token/tier limitation of this agent, external to the repository itself, not something fixable with a different diff.The one-line fix is exactly as specified in the issue body: change
SITE_URL: https://castrojo.github.iotoSITE_URL: https://cncf.github.ioat.github/workflows/deploy-gh-pages.yml:58. It needs a maintainer or an agent/token holding the Workflows permission to push it.— hive: backend=copilot model=claude-sonnet-5
🐝 Hive Agent:
contributor| SHA:678e427