Files
tf_provider/TOOLS/scripts/04_build_and_publish_docs.sh
T

289 lines
9.1 KiB
Bash
Executable File

#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
ROOT_DIR="${ROOT_DIR:-$(cd "${SCRIPT_DIR}/../.." && pwd)}"
PROVIDER_MAIN="${ROOT_DIR}/provider/main.go"
PROFILE_DIR="${PROFILE_DIR:-}"
normalize_api_endpoint() {
local endpoint="$1"
endpoint="${endpoint%/}"
# ⛔ LEGACY: deck-api.ngcloud.ru ЗАКРЫВАЕТСЯ.
if [[ -z "$endpoint" ]]; then
echo "https://lk-api-gateway.ngcloud.ru/api/v1/svc"
return
fi
# Keep as-is: both legacy proxy (index.cfm) and new REST gateway are valid.
# No forced /index.cfm normalization — the downstream tools auto-detect.
echo "$endpoint"
}
if [[ "${1:-}" == "--profile" ]]; then
PROFILE_DIR="${2:-}"
shift 2
fi
if [[ -n "$PROFILE_DIR" ]]; then
if [[ ! -d "$PROFILE_DIR" ]]; then
echo "Error: profile directory not found: $PROFILE_DIR" >&2
exit 2
fi
PROFILE_ENV_FILE="${PROFILE_DIR}/profile.env"
if [[ -f "$PROFILE_ENV_FILE" ]]; then
set -a
# shellcheck disable=SC1090
source "$PROFILE_ENV_FILE"
set +a
fi
fi
resolve_root_path() {
local path_value="$1"
if [[ -z "$path_value" ]]; then
echo ""
return
fi
if [[ "$path_value" = /* ]]; then
echo "$path_value"
return
fi
echo "${ROOT_DIR}/${path_value}"
}
VERSION="${1:-}"
if [[ -z "$VERSION" ]]; then
VERSION="${VERSION:-}"
fi
if [[ -z "$VERSION" ]]; then
VERSION=$(grep -E 'version string' "$PROVIDER_MAIN" | sed -E 's/.*"([0-9.]+)".*/\1/')
fi
if [[ -z "$VERSION" ]]; then
echo "Error: unable to detect version from $PROVIDER_MAIN" >&2
exit 2
fi
REGISTRY_HOST="${REGISTRY_HOST:-tf-docs.nodejsk8s.dev.nubes.ru}"
NAMESPACE="${NAMESPACE:-nubes}"
PROVIDER_NAME="${PROVIDER_NAME:-nubes}"
export REGISTRY_HOST NAMESPACE PROVIDER_NAME VERSION
S3CFG_REGISTRY="${S3CFG_REGISTRY:-${ROOT_DIR}/secrets/.s3cfg_registry}"
S3CFG_REGISTRY="$(resolve_root_path "$S3CFG_REGISTRY")"
TMP_DOCS_DIR=""
if [[ -n "$PROFILE_DIR" ]]; then
# ⛔ NEVER merge with docs/ — ONLY generated docs from docs_gen/<stand>/
DOCS_GEN_DIR="${DOCS_GEN_DIR:-generated/test}"
DOCS_GEN_DIR="$(resolve_root_path "$DOCS_GEN_DIR")"
if [[ -d "$DOCS_GEN_DIR" ]]; then
export MKDOCS_DOCS_DIR="$DOCS_GEN_DIR"
else
echo "Error: DOCS_GEN_DIR not found: $DOCS_GEN_DIR" >&2
exit 2
fi
fi
# ⛔ LEGACY: deck-api.ngcloud.ru ЗАКРЫВАЕТСЯ. Default = Gateway.
DOCS_API_ENDPOINT="${NUBES_API_ENDPOINT:-https://lk-api-gateway.ngcloud.ru/api/v1/svc}"
DOCS_API_ENDPOINT="$(normalize_api_endpoint "$DOCS_API_ENDPOINT")"
if [[ -n "${MKDOCS_DOCS_DIR:-}" ]]; then
export DOCS_GUIDE_VERSION="$VERSION"
export DOCS_GUIDE_API_ENDPOINT="$DOCS_API_ENDPOINT"
export DOCS_GUIDE_FILE="${MKDOCS_DOCS_DIR}/guides/getting-started.md"
python3 - <<'PY'
import os
import re
from pathlib import Path
guide_path = Path(os.environ["DOCS_GUIDE_FILE"])
if guide_path.exists():
text = guide_path.read_text(encoding="utf-8")
text = re.sub(
r'(version\s*=\s*")([0-9.]+)("\s*#\s*Поставьте нужную вам версию провайдера)',
lambda m: f'{m.group(1)}{os.environ["DOCS_GUIDE_VERSION"]}{m.group(3)}',
text,
count=1,
)
text = re.sub(
r'(api_endpoint\s*=\s*")([^"]+)(")',
lambda m: f'{m.group(1)}{os.environ["DOCS_GUIDE_API_ENDPOINT"]}{m.group(3)}',
text,
count=1,
)
guide_path.write_text(text, encoding="utf-8")
PY
fi
load_s3cfg_registry() {
local cfg="$1"
if [[ ! -f "$cfg" ]]; then
echo "Error: S3 config not found: $cfg" >&2
exit 2
fi
local access_key secret_key host_base use_https endpoint
access_key=$(awk -F '=' '/^\s*access_key\s*=/ {gsub(/^[ \t]+|[ \t]+$/, "", $2); print $2; exit}' "$cfg")
secret_key=$(awk -F '=' '/^\s*secret_key\s*=/ {gsub(/^[ \t]+|[ \t]+$/, "", $2); print $2; exit}' "$cfg")
host_base=$(awk -F '=' '/^\s*host_base\s*=/ {gsub(/^[ \t]+|[ \t]+$/, "", $2); print $2; exit}' "$cfg")
use_https=$(awk -F '=' '/^\s*use_https\s*=/ {gsub(/^[ \t]+|[ \t]+$/, "", $2); print tolower($2); exit}' "$cfg")
if [[ -z "${S3_ACCESS_KEY:-}" && -n "$access_key" ]]; then
export S3_ACCESS_KEY="$access_key"
fi
if [[ -z "${S3_SECRET_KEY:-}" && -n "$secret_key" ]]; then
export S3_SECRET_KEY="$secret_key"
fi
if [[ -z "${S3_ENDPOINT:-}" && -n "$host_base" ]]; then
if [[ "$host_base" == http* ]]; then
endpoint="$host_base"
else
if [[ "$use_https" == "false" || "$use_https" == "0" || "$use_https" == "no" ]]; then
endpoint="http://${host_base}"
else
endpoint="https://${host_base}"
fi
fi
export S3_ENDPOINT="$endpoint"
fi
if [[ -z "${S3_ENDPOINT:-}" || -z "${S3_ACCESS_KEY:-}" || -z "${S3_SECRET_KEY:-}" ]]; then
echo "Error: S3 credentials are not set (S3_ENDPOINT/S3_ACCESS_KEY/S3_SECRET_KEY)" >&2
exit 2
fi
}
TMP_CFG="${ROOT_DIR}/.mkdocs.tmp.yml"
export ROOT_DIR
# Copy 30_registry assets and curated content into docs dir
if [[ -n "${MKDOCS_DOCS_DIR:-}" ]]; then
if [[ -d "${ROOT_DIR}/docs/30_registry" ]]; then
mkdir -p "${MKDOCS_DOCS_DIR}/30_registry"
cp -r "${ROOT_DIR}/docs/30_registry/"* "${MKDOCS_DOCS_DIR}/30_registry/" 2>/dev/null || true
fi
if [[ -d "${ROOT_DIR}/docs/curated" ]]; then
mkdir -p "${MKDOCS_DOCS_DIR}/curated"
cp -r "${ROOT_DIR}/docs/curated/"* "${MKDOCS_DOCS_DIR}/curated/" 2>/dev/null || true
fi
fi
python3 - <<'PY'
import os
import re
import yaml
from pathlib import Path
registry_host = os.environ["REGISTRY_HOST"]
namespace = os.environ["NAMESPACE"]
name = os.environ["PROVIDER_NAME"]
version = os.environ["VERSION"]
root_dir = Path(os.environ["ROOT_DIR"])
cfg_path = root_dir / "mkdocs.yml"
text = cfg_path.read_text(encoding="utf-8")
text = re.sub(
r"^site_url:\s*.*$",
f"site_url: https://{registry_host}/{namespace}/",
text,
flags=re.M,
)
docs_dir = os.environ.get("MKDOCS_DOCS_DIR", "").strip()
if docs_dir:
# Относительный docs_dir: работает и на хосте (сборка из ROOT_DIR), и в docker (/docs).
if os.path.isabs(docs_dir):
try:
rel = os.path.relpath(docs_dir, os.environ.get("ROOT_DIR", os.path.sep))
if not rel.startswith(".."):
docs_dir = rel
except ValueError:
pass
if re.search(r"^docs_dir:\s*.*$", text, flags=re.M):
text = re.sub(r"^docs_dir:\s*.*$", f"docs_dir: {docs_dir}", text, flags=re.M)
else:
text += f"\ndocs_dir: {docs_dir}\n"
# Inject resources_nav from _nav_fragment.yml into nav section
docs_dir_path = Path(docs_dir) if docs_dir else None
nav_fragment_path = docs_dir_path / "_nav_fragment.yml" if docs_dir_path else None
if nav_fragment_path and nav_fragment_path.exists():
config = yaml.safe_load(text)
fragment = yaml.safe_load(nav_fragment_path.read_text(encoding="utf-8"))
resources_nav = fragment.get("resources_nav", [])
if resources_nav:
nav = config.get("nav", [])
for i, item in enumerate(nav):
if isinstance(item, dict) and "Ресурсы" in item:
# Replace "Ресурсы" children with generated categories
item["Ресурсы"] = resources_nav
break
config["nav"] = nav
text = yaml.dump(config, allow_unicode=True, default_flow_style=False, sort_keys=False)
(root_dir / ".mkdocs.tmp.yml").write_text(text, encoding="utf-8")
PY
build_docs() {
local docs_build_mode
docs_build_mode="${DOCS_BUILD_MODE:-auto}"
if [[ -n "${MKDOCS_DOCS_DIR:-}" && "$docs_build_mode" == "auto" ]]; then
docs_build_mode="local"
fi
if [[ "$docs_build_mode" != "local" ]] && command -v docker >/dev/null 2>&1; then
local docker_err
docker_err="$(mktemp)"
if docker run --rm -v "${ROOT_DIR}:/docs" squidfunk/mkdocs-material build -f "/docs/.mkdocs.tmp.yml" -d site 2>"$docker_err"; then
rm -f "$docker_err"
return 0
fi
if grep -q "error while creating mount source path" "$docker_err"; then
echo "Warning: docker mount issue detected, using local mkdocs" >&2
else
cat "$docker_err" >&2
echo "Warning: docker build failed, trying local mkdocs" >&2
fi
rm -f "$docker_err"
fi
local venv_python
venv_python="${ROOT_DIR}/.venv/bin/python"
if [[ -x "$venv_python" ]]; then
if "$venv_python" -m mkdocs --version >/dev/null 2>&1; then
(cd "$ROOT_DIR" && "$venv_python" -m mkdocs build -f "$TMP_CFG" -d site)
return 0
fi
echo "Warning: mkdocs module is missing in .venv, installing pinned versions" >&2
"$venv_python" -m pip install --disable-pip-version-check -q "mkdocs==1.6.1" "mkdocs-material==9.7.3"
(cd "$ROOT_DIR" && "$venv_python" -m mkdocs build -f "$TMP_CFG" -d site)
return 0
fi
if command -v mkdocs >/dev/null 2>&1 && mkdocs --version >/dev/null 2>&1; then
(cd "$ROOT_DIR" && mkdocs build -f "$TMP_CFG" -d site)
return 0
fi
echo "Error: mkdocs is not installed or not runnable." >&2
echo "Install once: python3 -m venv .venv && .venv/bin/python -m pip install mkdocs==1.6.1 mkdocs-material==9.7.3" >&2
exit 2
}
trap 'rm -f "$TMP_CFG"' EXIT
build_docs
:
:
load_s3cfg_registry "$S3CFG_REGISTRY"
(cd "$ROOT_DIR" && ./scripts/publish-docs.sh site "$REGISTRY_HOST" "$NAMESPACE" "$PROVIDER_NAME" "$VERSION")
echo "Docs published for ${VERSION}"