rsync --exclude bez lomítka vyloučí i vnořené adresáře stejného jména
import { Aside } from ‘@astrojs/starlight/components’;
Symptom
Sekce “Symptom”Deploy „proběhl úspěšně”, build zelený, ale nová veřejná API route (/api/feeds/<neco>) vrací v produkci 404 / HTML app shell místo očekávaného obsahu. Soubor přitom lokálně existuje a v buildu lokálně funguje. Na serveru soubor route vůbec není — přestože rsync „nic nehlásil”.
Root cause
Sekce “Root cause”Deploy skript používá rsync --exclude='feeds/' (bez počátečního lomítka) — původně kvůli runtime adresáři s generovanými feed soubory v kořeni projektu.
rsync pattern bez počátečního lomítka matchuje na jakékoli úrovni stromu. feeds/ tedy nevyloučí jen /<projekt>/feeds/, ale i src/app/api/feeds/ — celý adresář s API routes. Nové routes se tak nikdy nepřenesly. --delete navíc nic nesmazal (vyloučené cesty se nemažou), takže staré routes na serveru přežily → iluze, že „to funguje”.
# ŠPATNĚ — vyloučí feeds/ na jakékoli úrovni, včetně src/app/api/feeds/rsync -az --delete --exclude='feeds/' --exclude='logs/' ./ server:/app/Fix
Sekce “Fix”Ukotvit exclude počátečním lomítkem — tím se pattern váže na kořen přenosu (./) a matchuje jen tam:
# SPRÁVNĚ — vyloučí jen kořenový /feeds/, ne vnořenérsync -az --delete --exclude='/feeds/' --exclude='/logs/' --exclude='/src/lib/data/' ./ server:/app/Po opravě se src/app/api/feeds/ normálně přenese a nová route vrací správný obsah.
Obecné pravidlo: exclude bez / = „kdekoli ve stromu”, exclude s / = „jen v kořeni přenosu”. Když myslíš jeden konkrétní adresář, vždy ho ukotvi. Stejná past hrozí u logs/, data/, tmp/, build/ apod.