Ctrl K
ComunidadGuías…

scripts/apply-site-url.py

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
#!/usr/bin/env python3
"""Propagate a new public site URL across every tracked surface that spells it.

The literal domain has to stay in the docs — a reader runs ``curl … | bash``
before cloning, so nothing can be resolved from ``flint.toml`` at read time.
That makes a domain move a rewrite problem, not an abstraction problem: this
script is the site-URL twin of ``scripts/apply-version.py``. It updates the
single authority (``flint.toml``'s ``[project] site_url``), rewrites every file
in ``scripts/check-site-url-consistency.py``'s ``SITE_URL_FILES``, reports what
changed, and self-verifies by running that checker.

The rewrite targets the *host*, so it catches both shapes in one pass: a full
``https://host/route`` URL, and the bare host some surfaces name on its own (an
allowlist key, a redirect host).

``flint.toml`` is written last, so an interrupted run leaves the authority still
naming the old host and re-running the same command finishes the job. That is a
convenience, not a transactional guarantee: files are rewritten one at a time
with no rollback, so a run interrupted midway leaves a mixed tree until it is
repeated. Run ``scripts/check-site-url-consistency.py`` afterwards — it names
every file that still disagrees.
``tests/test_site_url_single_source.py`` holds the same invariant in CI.

Regenerate the public site afterwards so the generated MDX picks up the doc
edits:

    npx --yes pnpm@10.34.5 --dir packages/apps/site run generate:content

Usage:
    python scripts/apply-site-url.py https://flinttrade.dev
"""

from __future__ import annotations

import importlib.util
import subprocess
import sys
from pathlib import Path

ROOT = Path(__file__).resolve().parents[1]

_spec = importlib.util.spec_from_file_location(
    "check_site_url_consistency", ROOT / "scripts" / "check-site-url-consistency.py"
)
assert _spec is not None and _spec.loader is not None
_checker = importlib.util.module_from_spec(_spec)
_spec.loader.exec_module(_checker)


def _rewrite(path: Path, old_url: str, new_url: str) -> int:
    """Rewrite every mention of *old_url* (and its bare host) in one file.

    Args:
        path: File to rewrite in place.
        old_url: The previous canonical origin, e.g. ``https://old.example``.
        new_url: The new canonical origin.

    Returns:
        The number of replacements made; ``0`` when the file was already current.
    """
    # newline="" on both ends: the repository is LF-only (.gitattributes says
    # `* text=auto eol=lf`), and Python's default newline translation would
    # rewrite every line of every touched file to CRLF on a Windows checkout.
    with path.open(encoding="utf-8", newline="") as handle:
        text = handle.read()
    # Rewriting the host alone covers both shapes in one pass — `https://host/x`
    # and a bare `host` — and cannot double-apply when the new host contains the
    # old one as a substring.
    old_host = _checker.site_host(old_url)
    new_host = _checker.site_host(new_url)
    replacements = text.count(old_host)
    updated = text.replace(old_host, new_host)
    if updated != text:
        with path.open("w", encoding="utf-8", newline="") as handle:
            handle.write(updated)
    return replacements


def main() -> int:
    """Rewrite the site URL everywhere and return a shell exit code."""
    if len(sys.argv) != 2 or not _checker.SITE_URL_PATTERN.match(sys.argv[1]):
        print(__doc__)
        return 2
    new_url = sys.argv[1]
    old_url = _checker.read_site_url(ROOT)

    if old_url == new_url:
        print(f"apply-site-url: flint.toml already declares {new_url}; re-checking every surface")
    else:
        total = 0
        for rel in _checker.SITE_URL_FILES:
            path = ROOT / rel
            if not path.is_file():
                raise SystemExit(f"apply-site-url: listed file is missing: {rel}")
            count = _rewrite(path, old_url, new_url)
            total += count
            print(f"  {rel}: {count} replacement(s)" if count else f"  {rel}: already current")

        # Last, so an interrupted run keeps the old URL and can simply be re-run.
        authority = ROOT / _checker.SITE_URL_AUTHORITY
        if _rewrite(authority, old_url, new_url) == 0:
            raise SystemExit(
                f"apply-site-url: no {old_url} to replace in {_checker.SITE_URL_AUTHORITY}"
            )
        print(f"\napply-site-url: {old_url} -> {new_url} ({total} replacement(s) across "
              f"{len(_checker.SITE_URL_FILES)} file(s), plus {_checker.SITE_URL_AUTHORITY})")
        print(
            "Regenerate the site content so the published docs follow: "
            "npx --yes pnpm@10.34.5 --dir packages/apps/site run generate:content"
        )

    result = subprocess.run(
        [sys.executable, str(ROOT / "scripts/check-site-url-consistency.py")], check=False
    )
    return result.returncode


if __name__ == "__main__":
    sys.exit(main())