Files
taxbaik/scripts/validate_seo.py
kjh2064 fb3ee4aad6
TaxBaik CI/CD / build-and-deploy (push) Successful in 1m22s
Use combined RSS feed items
2026-07-11 15:37:50 +09:00

55 lines
2.3 KiB
Python

#!/usr/bin/env python3
"""Static SEO guardrails run in CI before deployment."""
from pathlib import Path
import re
import sys
ROOT = Path(__file__).resolve().parents[1]
WEB = ROOT / "src" / "TaxBaik.Web"
errors: list[str] = []
def read(relative: str) -> str:
return (ROOT / relative).read_text(encoding="utf-8")
def require(condition: bool, message: str) -> None:
if not condition:
errors.append(message)
sitemap_view = read("src/TaxBaik.Web/Pages/Sitemap.cshtml")
rss_view = read("src/TaxBaik.Web/Pages/Rss.cshtml")
feed_view = read("src/TaxBaik.Web/Pages/Feed.cshtml")
sitemap_model = read("src/TaxBaik.Web/Pages/Sitemap.cshtml.cs")
layout = read("src/TaxBaik.Web/Pages/_Layout.cshtml")
robots = read("src/TaxBaik.Web/wwwroot/robots.txt")
require("Layout = null" in sitemap_view, "sitemap.xml must render without the HTML layout")
require("Layout = null" in rss_view, "rss.xml must render without the HTML layout")
require("Html.Raw(rssContent.ToString())" in rss_view, "RSS XML must not be HTML-encoded")
require("Model.Items" in rss_view, "RSS view must render from the combined feed items")
require("StatusCodes.Status308PermanentRedirect" in feed_view, "feed.xml must permanently redirect to rss.xml")
require("DateTime.UtcNow:yyyy-MM-dd" not in sitemap_view, "sitemap lastmod must not use the current request date")
require("GetAllPublishedPostsAsync" in sitemap_model, "sitemap must page through all published blog posts")
require("/faq" not in sitemap_model and "/announcement" not in sitemap_model and "/inquiry" not in sitemap_model,
"redirect-only URLs must not be included in the sitemap")
require("var canonicalUrl" in layout and "Context.Request.Path" in layout,
"default canonical URL must use the current path")
sitemap_directives = re.findall(r"^Sitemap:\s*(\S+)\s*$", robots, flags=re.MULTILINE)
require(sitemap_directives == ["https://www.taxbaik.com/sitemap.xml"],
"robots.txt must declare exactly one canonical sitemap URL")
require(not re.search(r"^Disallow:\s*.*\.xml", robots, flags=re.MULTILINE),
"robots.txt must not block XML feeds or the sitemap")
if errors:
print("SEO guardrail validation failed:", file=sys.stderr)
for error in errors:
print(f"- {error}", file=sys.stderr)
sys.exit(1)
print("SEO guardrail validation passed")