Skip to content

Complete the galaxyproject.eu → hub redirect map#2198

Open
itisAliRH wants to merge 7 commits into
masterfrom
eu/hub-redirect-map
Open

Complete the galaxyproject.eu → hub redirect map#2198
itisAliRH wants to merge 7 commits into
masterfrom
eu/hub-redirect-map

Conversation

@itisAliRH

Copy link
Copy Markdown
Member

Replaces the blanket galaxyproject.euusegalaxy-eu.github.io shim with a per-URL 301 map onto galaxyproject.org, derived from the migration audit manifest and verified URL-by-URL against the live hub.

⚠️ Deployment ordering — read this first

master's config currently ends with:

# The rest should continue to be served by the European website, but under the github.io domain.
return 301 https://usegalaxy-eu.github.io$request_uri;

So today the entire legacy long tail is served by the GitHub Pages build of usegalaxy-eu/website — the very repo that is slated for archival. This branch removes both github.io references (0 remain).

Deploying this map is therefore a precondition for archiving usegalaxy-eu/website, not a follow-up to it. Archiving that repo first would break every legacy URL, including the ~222 tool-update posts and every asset. This ordering constraint was not previously recorded anywhere in the migration work.

Rule counts

rule kind before after
exact location = 842 969
regex location ~ 38 64
prefix location ^~ 0 1
server-level rewrite 2 4
total 882 1038

Exact blocks: 663 news posts + 302 events + 4 structural.

Coverage

Posts and events (1187 published legacy URLs)

verdict before after
full (specific rule + hub content + live 200) 832 965
redirect-only (blanket index) 355 222
broken-target 0 0
no-rule 0 0

The remaining 222 are exactly the auto-generated tool-update posts, collapsed to /news/ by design (galaxyproject/galaxy-hub/issues/1480). Every other post and event now resolves to its own article.

Pages, subdomains, subsites, feeds, assets (615 legacy URLs)

verdict before after
full 75 265
redirect-only 45 29
no-rule 492 31
broken-target 3 0
honest-404 (asset absent from hub, deliberate) 290

Slashless URL normalisation — the largest defect fixed here

Every exact block is keyed on a trailing-slash URL, but the legacy host also answers the slashless form (GitHub Pages 301s
/posts/2018/10/08/gxadmin/posts/2018/10/08/gxadmin/), so slashless URLs are real, linked and working in the wild. Without normalisation they matched no exact block and fell through to the blanket index — silently bypassing the
entire rule table.

Measured by replaying all 1187 post/event URLs in slashless and .html form against a real nginx running each config:

slashless/.html variant requests (2374) before after
reach their specific article 0 1930
fall through to the blanket index 2374 444
disagree with the canonical form's target 1666 0

The 444 remaining are exactly 2 × the 222 tool-update posts.

What changed

  1. 133 missing post/event rules (89 posts, 44 events). The audit manifest marks these migrated and the hub content exists and serves 200, but no rule was ever generated, so they landed on the index. Three manifest targets were mis-cased and 404 as recorded (/events/2022-11-BH2022/, /events/2022-10-PSU-Workshop/); the hub lower-cases published slugs, so all targets are written lower-cased and were re-verified live.
  2. Slashless / .html normalisation — two server-level rewrites folding both forms onto the canonical key, following the existing plain/ICS folding pattern. [^/]+? cannot match a trailing slash, so no rewrite loop is possible.
  3. index-* bare forms. /index-microbiome, /index-ssh and /index-test were keyed only on .html and trailing slash, so the canonical bare form hit the generic rule and 404ed — all three were broken-target. ** Six exact blocks (two of them dead) are replaced by three regex blocks covering all forms. index-microbiome.md is a symlink to index-metagenomics.md in the legacy repo, and content/redirects.yaml in the hub independently declares the same target, so it now points at /bare/eu/usegalaxy/metagenomics/.
  4. /assets/ pass-through. All 467 legacy asset URLs previously hit the catch-all and 301ed to /eu/, answering an image request with a 52 KB HTML page at HTTP 200 — strictly worse than a 404, because nothing can detect the breakage. 163 exist on the hub at the identical path and are now recovered; the rest 404 honestly.
  5. Feeds, people and subsite pages — see below.

The asset decision

location ^~ /assets/ { return 301 https://galaxyproject.org$request_uri; }

css/, fonts/ and js/ are deliberately included rather than carved out. None of them exist on the hub (it ships its own theme chrome), so they will 404 — but a 301 that ends in a 404 is a truthful answer, whereas the catch-all returns 200 text/html for a stylesheet request. A carve-out would add rules to produce a strictly worse outcome.

Feeds

These are live subscriber endpoints, so a 301 to an HTML page breaks every reader silently.

legacy target note
/feed.xml /eu/feed.atom jekyll-feed's site-wide posts feed. RSS → Atom is a format change; mainstream readers follow the 301 and parse Atom.
/events-ical /eu/events/calendar.ics legacy served this as text/html, so strict clients never worked; the hub serves real text/calendar. Matches content/redirects.yaml.

/event/<slug>/event.ics keeps folding to its event page rather than to the EU calendar: that calendar contains only the 12 upcoming events, so a request for a 2022 event would import unrelated ones.

Known gaps

These are deliberate and verified, not oversights.

  • 222 tool-update posts/news/. Auto-generated changelog posts, collapsed by design (Hub unification: Initial launch checklist galaxyproject/galaxy-hub#1480).
  • ~290 assets not on the hub (267 media/ images + 10 css/, 9 fonts/, 4 js/). These now 404 honestly instead of returning an HTML page at 200. Recovering them requires migrating the files, not a redirect change.
  • /index-ssh and /index-test have no hub counterpart/eu/. index-ssh is stranger than it looks: it returns 200 on the deployed legacy site but does not exist in the source tree at all — the deployed GitHub Pages branch carries files absent from master. Worth a separate look, since other deployed-only files may exist that neither a source derivation nor a crawl can see.
  • 19 subsite embed pages (/<sub>/galaxy/, /<sub>/galaxy/gxnews, /<sub>/galaxy/gxevents for 6 subsites, plus /freiburg/maintenance/) → the subsite home. /bare/<sub>/news/ and /bare/<sub>/events/ were probed and 404 on the hub; there is nothing to point at.
  • /livestream, /livestream-plain, /wall/, /wall/social_template/eu/. No hub equivalent. Given explicit rules anyway so a future reader can see they were considered rather than missed.
  • 8 /error_pages/* stay on the catch-all — infrastructure, not user-facing.
  • 9 /_bibliography/*.bib need no rule: an underscore directory Jekyll never published (404 on legacy today). The source data was migrated to content/*/citations/*.bib.
  • 3 audit-manifest disagreements remain by design — the three mis-cased targets above. The manifest is wrong (its values 404); the map is right.

Validation

  • nginx -t passes on the rendered config.
  • All 1023 distinct redirect targets in the file probed live: zero non-200. No rule points at a 404.
  • 37 end-to-end assertions against a real nginx (subdomain forms, asset pass-through including query strings, feeds, subsite pages, fallbacks, regressions).
  • 2374 slashless/.html variants replayed through a real nginx: 0 disagreements with the canonical form.
  • Both verification scripts re-run; distributions above.

Note for reviewing on macOS

nginx -t fails locally on macOS with duplicate location "/event/2022-07-05-community-call/". This is a platform artifact, not a config defect: nginx defines NGX_HAVE_CASELESS_FILESYSTEM on Darwin and Win32, so ngx_filename_cmp compares location keys case-insensitively there. Linux — the deploy target — is case-sensitive.

_events/2022-07-05-Community-Call.md and _events/2022-07-05-community-call.md are two distinct source files with distinct content, both live 200 on the legacy site, mapping to two different hub events. Both rules are required. Verified: 0 duplicates under case-sensitive (Linux) semantics.

Extend the galaxyproject.eu server block with the full legacy URL to
galaxyproject.org redirect table derived from the EU website migration
audit manifest, completing the work started in #421.

All 1308 routable legacy records are covered: 574 news posts and 258
events get exact `location =` rules pointing at their verified hub page,
subdomain landing pages, core EU pages and member subsites are handled by
deterministic regex rules, and un-migrated content (chiefly the ~222
autogenerated tool-update posts) collapses to the news index per the
redirect table in galaxyproject/galaxy-hub#1480.

Exact blocks rather than a single regex transform are required because the
hub does not normalise slugs -- uppercase, camelCase, underscore and
re-dated event URLs all 404 -- and stock nginx cannot lower-case in a
rewrite. Regexes that interpolate a capture into their target are
therefore case-sensitive; the rest are case-insensitive and tolerant of a
trailing slash and of the legacy .html suffix, following #2108.

Two rewrites fold the plain.html, -plain and event.ics variants onto the
canonical path so one rule per item suffices. Unmatched paths now land on
/eu/ instead of being proxied to usegalaxy-eu.github.io.

Verified with nginx -t and by replaying all 5613 legacy URLs against a
local nginx: every one returns 301, and all 906 distinct targets resolve
on galaxyproject.org (zero 404s).
The audit manifest marks these 89 posts and 44 events as `migrated` and the
hub content exists and serves 200, but no exact `location =` rule was
generated for them, so they fell through to the blanket index redirect
(/news/ or /eu/events/) instead of reaching their article.

Targets are lower-cased: the hub lower-cases published slugs. Three manifest
entries were mis-cased and 404 as recorded --
/events/2022-11-BH2022/ and /events/2022-10-PSU-Workshop/ -- their lower-cased
forms are 200. All 133 targets were verified live before being written.

Exact rules: 832 -> 965 (posts 574 -> 663, events 258 -> 302).
Every exact `location =` block is keyed on a trailing-slash URL, but the
legacy host also answers the slashless form: GitHub Pages 301s
/posts/2018/10/08/gxadmin -> /posts/2018/10/08/gxadmin/, so slashless URLs are
real, linked and working in the wild. A slashless request matched no exact
block and fell through to the blanket index redirect, silently bypassing the
entire 965-rule table.

Two server-level rewrites fold the slashless and .html forms onto the
canonical key, following the existing plain/ics folding pattern. `[^/]+?`
cannot match a trailing slash, so a rewritten URI cannot re-enter these rules
and no rewrite loop is possible.

The .html form 404s on the legacy host today (posts and events are directory
-style URLs); folding it is defensive and can only upgrade a dead URL.

Verified against a live nginx: slashless, trailing-slash, .html, -plain,
/plain.html and /event.ics variants all resolve to the article, dotted slugs
(Galaxy-17.09) survive normalisation, and unmigrated tool-update posts still
reach the blanket rule.
The overrides for index-microbiome, index-ssh and index-test were keyed only
on the .html and trailing-slash forms, so the BARE form -- which is the
canonical published URL (/index-ssh 200, /index-ssh/ 404 on the legacy host)
-- fell through to the generic index- rule and was sent to
/bare/eu/usegalaxy/<name>/, which 404s on the hub. All three were
broken-target.

Replaces the six exact blocks (two of which were dead: the trailing-slash
URLs were never published) with three regex blocks covering the bare, .html
and trailing-slash forms in one place, ordered ahead of the generic rule.

index-microbiome.md is a symlink to index-metagenomics.md in the legacy repo,
so it is the metagenomics page; content/redirects.yaml in the hub
independently declares the same target. Verified 200.

index-ssh and index-test have no hub counterpart -- index-ssh does not even
exist in the legacy source tree, only in the deployed branch -- so they point
at the EU landing page and are recorded as content gaps.
All 467 legacy asset URLs hit the catch-all and 301 to /eu/, so an image
request is answered with a 52 KB HTML page at HTTP 200. That is strictly
worse than a 404: no client or crawler can detect the breakage, and every
legacy hotlink -- in third-party pages, archived posts and Galaxy tool help
text -- renders as a broken image.

163 of them exist on the hub at the identical path, so a single prefix rule
recovers them (/assets/media/tk_besoek.jpg -> 200 image/jpeg, verified). The
remaining ~290 now 404 honestly.

css/, fonts/ and js/ are deliberately included rather than carved out: none
exist on the hub, but a 301 that ends in a 404 is a truthful answer whereas
the catch-all returns 200 text/html for a stylesheet.
Feeds first -- these are subscription endpoints, and a 301 to an HTML page
breaks every reader silently:
  /feed.xml    -> /eu/feed.atom            (jekyll-feed site-wide posts feed;
                                            RSS -> Atom, readers follow the 301)
  /events-ical -> /eu/events/calendar.ics  (legacy served this as text/html, so
                                            strict clients never worked; the hub
                                            serves real text/calendar)
Per-event /event/<slug>/event.ics keeps folding to the event page rather than
to the EU calendar: that calendar holds only the 12 upcoming events, so a
request for a 2022 event would import unrelated ones.

Pages that already have hub content but were being swallowed by a fallback:
  /galaxy/data-policy -> /eu/storage/   (content/eu/common/data-policy.md is an
                                         include fragment; the hub publishes it
                                         under /eu/storage/)
  /people             -> /eu/people/
  {7 subsites}/people       -> /<sub>/people/
  {7 subsites}/publications -> /<sub>/citations/   (renamed on the hub)
  /freiburg/{projects,services}
  /freiburg/jobs[/*]  -> /careers/

/freiburg/jobs is the one URL where this map was worse than the status quo:
it 301s to a working page today, but the subsite fallback would have sent the
three job ads to the Freiburg home page.

/livestream, /livestream-plain and /wall/* have no hub equivalent and are
recorded explicitly so a later reader can see they were considered.

All 30 targets verified 200 live.
The SSH (Social Sciences and Humanities) front page has been ported to
the hub at /bare/eu/usegalaxy/ssh/, so /index-ssh no longer needs the
/eu/ fallback. All three forms (bare, .html, trailing slash) follow.

/index-test keeps the /eu/ fallback and is now commented as an
intentional retirement: it was a throwaway test-server page and has no
hub counterpart by decision, so the fallback is permanent rather than a
gap awaiting a migration.

Refs usegalaxy-eu/issues#943.
# /feed.xml was jekyll-feed's site-wide posts feed; /eu/feed.atom is the hub
# equivalent. RSS -> Atom is a format change, but every mainstream reader
# follows the 301 and parses Atom.
location ~* "^/feed\.xml$" {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does that really exist? https://usegalaxy-eu.github.io/feed.xml ?


# The rest should continue to be served by the European website, but under the github.io domain.
return 301 https://usegalaxy-eu.github.io$request_uri;
# No hub equivalent exists for these; recorded explicitly so that a future

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove those please

location ~* "^/livestream(?:-plain)?(?:\.html|/)?$" {
return 301 https://galaxyproject.org/eu/;
}
location ~* "^/wall(?:/.*)?$" {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

drop for now and ask @wm75 we should have a mastodon wall on the Hub already.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, there is https://galaxyproject.org/wall/ already - we just have to decide how much of this we want to host ourselves. Currently, https://gxy.io/fediwall points to fediwall.social passing it the config file at https://raw.githubusercontent.com/bgruening/fediwall-config/refs/heads/main/fediwall-config.json as a param.
I guess we could decide to:

If this takes some time to decide, we could just put a redirect to https://gxy.io/fediwall here for now.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @wm75

@itisAliRH please redirect this one then to https://galaxyproject.org/wall/ for the time being.

return 301 https://galaxyproject.org/eu/;
}

# ---------------------------------------------------------------------------

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should remove that and keep the config small.

We made sure that the posts / events are redirected on the Hub website. And if we add as a last resort fallback to the old jekyll website a info page (this website has migrated, please visit ...) that should be fine.

location = /event/2022-10-28-analysis-data-Galaxy/ { return 301 https://galaxyproject.org/events/2022-10-psu-workshop/; }
location = /event/2022-10-28-community-call/ { return 301 https://galaxyproject.org/events/2022-11-17-community-call/; }
location = /event/2022-10-28-single-cell-RNA-seq/ { return 301 https://galaxyproject.org/events/2023-02-ebi-single-cell/; }
location = /event/2022-10-31-Galaxy-biohackaton-Europe/ { return 301 https://galaxyproject.org/events/2022-11-bh2022/; }

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

drop everything until here, all posts and events

location = /event/2022-10-28-single-cell-RNA-seq/ { return 301 https://galaxyproject.org/events/2023-02-ebi-single-cell/; }
location = /event/2022-10-31-Galaxy-biohackaton-Europe/ { return 301 https://galaxyproject.org/events/2022-11-bh2022/; }

# Static assets keep their path on the hub, so map the prefix straight across.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do we need this?

return 301 https://galaxyproject.org$request_uri;
}

# Blanket rules for content that was never migrated individually -- chiefly the

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

drop

location ~* "^/posts/\d{4}/\d{2}/\d{2}/" { return 301 https://galaxyproject.org/news/; }
location ~* "^/event/" { return 301 https://galaxyproject.org/eu/events/; }

# Anything not matched above is legacy content with no hub equivalent.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would drop this as well, or redirect to a speical site that is:

  • nice looking
  • Apologize that the link is not working
  • redirecting users to news, events, storage etc ....

@bgruening

Copy link
Copy Markdown
Member

@itisAliRH this now needs a rebase.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants