mirror of
https://github.com/hanzoai/datastore.git
synced 2026-09-26 13:55:07 +00:00
176 lines
7.2 KiB
Python
176 lines
7.2 KiB
Python
import argparse
|
|
import shlex
|
|
|
|
from ci.jobs.scripts.docs.check_autogenerated_regions import (
|
|
check_autogenerated_regions,
|
|
)
|
|
from ci.jobs.scripts.docs.check_readonly_copies import check_readonly_copies
|
|
from ci.jobs.scripts.docs.mintlify_docs_check import (
|
|
DEFAULT_CHECKS,
|
|
LOCALE_CHECKS,
|
|
QUICKSTARTS_CHECK,
|
|
)
|
|
from ci.praktika.info import Info
|
|
from ci.praktika.result import Result
|
|
from ci.praktika.utils import Shell, Utils
|
|
|
|
# The translated trees that docs.json ships (via `languages` + `$ref`s): both the
|
|
# top-level locale pages and the localized snippet components they render. The
|
|
# locale checks run only when a PR touches one of these folders -- or the
|
|
# checkers themselves -- so ordinary English-only edits don't pay for them.
|
|
LOCALE_DIRS = ["ar", "es", "fr", "ja", "ko", "pt-BR", "ru", "zh"]
|
|
LOCALE_CHECK_TRIGGERS = tuple(f"docs/{d}/" for d in LOCALE_DIRS) + (
|
|
"ci/jobs/scripts/docs/lychee_check.py",
|
|
"ci/jobs/scripts/docs/locale_components_check.py",
|
|
"docs/lychee.toml",
|
|
# Shared inputs the locale resolvers depend on, so a PR that touches them can
|
|
# break localized navigation and must re-run the locale checks even when no
|
|
# docs/<locale>/ page changed:
|
|
# - all of snippets/ (locale pages import/link both localized snippets and
|
|
# shared English snippets, e.g. /snippets/delete);
|
|
# - redirect sources, which count as valid locale link targets (e.g.
|
|
# /<locale>/integrations resolves only via a redirect).
|
|
"docs/snippets/",
|
|
"docs/_site/redirects.json",
|
|
)
|
|
|
|
# The quickstarts check (frontmatter tags + generated explorer data freshness)
|
|
# runs only when a PR touches a quickstarts tree, the generated data modules,
|
|
# the generator, or the checker itself.
|
|
QUICKSTARTS_CHECK_TRIGGERS = (
|
|
("docs/get-started/quickstarts/",)
|
|
+ tuple(f"docs/{d}/get-started/quickstarts/" for d in LOCALE_DIRS)
|
|
+ ("docs/snippets/components/QuickStartsGrid/",)
|
|
+ tuple(f"docs/snippets/{d}/components/QuickStartsGrid/" for d in LOCALE_DIRS)
|
|
+ (
|
|
"docs/_site/scripts/update_quickstarts.py",
|
|
"ci/jobs/scripts/docs/quickstarts_check.py",
|
|
)
|
|
)
|
|
|
|
|
|
def parse_args():
|
|
parser = argparse.ArgumentParser(description="Mintlify Docs Check Job")
|
|
parser.add_argument("--test", help="Sub check name", default="")
|
|
return parser.parse_args()
|
|
|
|
|
|
def _locale_check_should_run():
|
|
# Run the locale link-check only when the PR changes a locale tree or the
|
|
# checker. If the changed-file list is unavailable, run it (fail open toward
|
|
# coverage: a missed run would let broken locale links merge).
|
|
changed_files = Info().get_changed_files()
|
|
if changed_files is None:
|
|
return True
|
|
return any(f.startswith(LOCALE_CHECK_TRIGGERS) for f in changed_files)
|
|
|
|
|
|
def _quickstarts_check_should_run():
|
|
# Same gating idea as the locale checks: run only when the PR touches the
|
|
# quickstarts content or its tooling; fail open toward coverage when the
|
|
# changed-file list is unavailable.
|
|
changed_files = Info().get_changed_files()
|
|
if changed_files is None:
|
|
return True
|
|
return any(f.startswith(QUICKSTARTS_CHECK_TRIGGERS) for f in changed_files)
|
|
|
|
|
|
def _protected_docs_guard():
|
|
# Fail direct edits both to generated regions and to docs folders whose
|
|
# canonical source lives in another repo. This is aggregator-only, so it is
|
|
# deliberately not part of the shared DEFAULT_CHECKS.
|
|
info = Info()
|
|
changed_files = info.get_changed_files()
|
|
if changed_files is None:
|
|
# Fail close: without the changed-file list we cannot prove the PR does
|
|
# not touch read-only copies, so do not report success.
|
|
print("Error: the changed-file list is unavailable, cannot run the check.")
|
|
return False
|
|
|
|
# Generated output may intentionally update protected marker regions, but
|
|
# it must never modify one-way copies owned by another repository.
|
|
readonly_copies_ok = check_readonly_copies(changed_files)
|
|
if "pr-autogenerated-docs" in info.pr_labels:
|
|
print("OK: skipping the generated-region guard for autogenerated docs.")
|
|
return readonly_copies_ok
|
|
|
|
merge_base = info.get_kv_data("merge_base_commit_sha")
|
|
if not merge_base or info.pr_number <= 0 or not info.sha:
|
|
print("Error: the PR revisions are unavailable, cannot run the check.")
|
|
return False
|
|
|
|
# The checkout can be shallow and contain neither the merge base nor the
|
|
# actual PR head when GitHub checked out its synthetic merge commit. Fetch
|
|
# both revisions explicitly so the comparison does not depend on checkout
|
|
# depth or on whether merge-commit checkout is enabled.
|
|
pull_ref = f"refs/pull/{info.pr_number}/head"
|
|
if not Shell.check(
|
|
"git fetch --no-tags --filter=blob:none origin "
|
|
f"{shlex.quote(merge_base)} {shlex.quote(pull_ref)}",
|
|
verbose=True,
|
|
):
|
|
print("Error: could not fetch the PR revisions, cannot run the check.")
|
|
return False
|
|
|
|
autogenerated_regions_ok = check_autogenerated_regions(merge_base, info.sha)
|
|
return readonly_copies_ok and autogenerated_regions_ok
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
args = parse_args()
|
|
testpattern = args.test
|
|
|
|
docs_dir = f"{Utils.cwd()}/docs"
|
|
|
|
def selected(name):
|
|
# Case-insensitive substring match; an empty pattern runs every check.
|
|
return testpattern.lower() in name.lower()
|
|
|
|
# The mint check definitions are shared with the standalone driver
|
|
# (ci/jobs/scripts/docs/mintlify_docs_check.py). This job already runs inside
|
|
# the docs-builder image with the docs present natively, so it runs them
|
|
# directly; add new checks to DEFAULT_CHECKS, not here. --test selects a
|
|
# subset by sub-check name.
|
|
results = [
|
|
Result.from_commands_run(name=name, command=command, workdir=docs_dir)
|
|
for name, command in DEFAULT_CHECKS
|
|
if selected(name)
|
|
]
|
|
|
|
# Locale checks: blocking, but only when the PR touches a locale tree,
|
|
# a localized snippet, or a checker. This is how a GT translation PR that
|
|
# reintroduces broken/unlocalized locale links gets caught before merge.
|
|
if _locale_check_should_run():
|
|
for locale_name, locale_command in LOCALE_CHECKS:
|
|
if selected(locale_name):
|
|
results.append(
|
|
Result.from_commands_run(
|
|
name=locale_name, command=locale_command, workdir=docs_dir
|
|
)
|
|
)
|
|
|
|
# Quickstarts check: blocking, but only when the PR touches the quickstarts
|
|
# trees or their tooling. Validates frontmatter tags and fails when the
|
|
# generated explorer data was not regenerated and committed.
|
|
if _quickstarts_check_should_run():
|
|
qs_name, qs_command = QUICKSTARTS_CHECK
|
|
if selected(qs_name):
|
|
results.append(
|
|
Result.from_commands_run(
|
|
name=qs_name, command=qs_command, workdir=docs_dir
|
|
)
|
|
)
|
|
|
|
# These guards run from the repo root (not the docs root), so keep them out
|
|
# of the docs_dir loop above.
|
|
if selected("No direct edits to generated or read-only docs"):
|
|
results.append(
|
|
Result.from_commands_run(
|
|
name="No direct edits to generated or read-only docs",
|
|
command=_protected_docs_guard,
|
|
)
|
|
)
|
|
|
|
Result.create_from(results=results).complete_job()
|