refactor: restructure project — separate tools, config, generated, provider
TOOLS/ — generators + scripts + config + ARCHITECTURE.md ├── yaml-generator/ (code) ├── resource-generator/ (code) ├── docs-generator/ (code) ├── scripts/ (← devops/*.sh) ├── config/ (← devops/profiles/ + devops/config/) │ ├── test/ profile.env, services_list.txt, operation_timeouts.json │ ├── prod/ │ └── dev/ └── ARCHITECTURE.md (← devops/ARCHITECTURE.md) generated/ — pipeline output only (gitignored) ├── test/resources_yaml/, go/, docs/, provider_build/ ├── prod/ └── dev/ provider/ — code only, no generated files resources_yaml/ — DELETED (generated) internal/resources_gen/ — DELETED (generated) devops/ — removed (replaced by TOOLS/scripts + TOOLS/config + generated/) Generators now fail if NUBES_*_DIR not set (no defaults to provider/). Provider requires pipeline to populate resources_gen/ before build.
This commit is contained in:
Executable
+248
@@ -0,0 +1,248 @@
|
||||
#!/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%/}"
|
||||
if [[ -z "$endpoint" ]]; then
|
||||
echo "https://deck-api.ngcloud.ru/api/v1/index.cfm"
|
||||
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="${DOCS_VERSION:-${RELEASE_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:-terra.k8c.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
|
||||
|
||||
DOCS_API_ENDPOINT="${NUBES_API_ENDPOINT:-https://deck-api.ngcloud.ru/api/v1/index.cfm}"
|
||||
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
|
||||
python3 - <<'PY'
|
||||
import os
|
||||
import re
|
||||
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}/docs/{namespace}/{name}/{version}/",
|
||||
text,
|
||||
flags=re.M,
|
||||
)
|
||||
|
||||
docs_dir = os.environ.get("MKDOCS_DOCS_DIR", "").strip()
|
||||
if docs_dir:
|
||||
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"
|
||||
|
||||
(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}"
|
||||
Reference in New Issue
Block a user