mirror of
https://github.com/grafana/loki.git
synced 2025-08-02 03:06:14 +08:00

**What this PR does / why we need it**: Supports Ubuntu Snap based Docker installations by using TMPDIR instead of an explicit tempfile. Because Ubuntu Snap packages have access to only the user's home directory, users must specify something like `TMPDIR="$(mktemp -d -q ~/.make-docs.XXXXX)"` in order to be able to run `make docs`. Signed-off-by: Jack Baldry <jack.baldry@grafana.com>
362 lines
9.7 KiB
Bash
Executable File
362 lines
9.7 KiB
Bash
Executable File
#!/bin/sh
|
|
# The source of this file is https://raw.githubusercontent.com/grafana/writers-toolkit/main/docs/make-docs.
|
|
|
|
set -ef
|
|
|
|
readonly DOCS_CONTAINER="${DOCS_CONTAINER:-make-docs}"
|
|
readonly DOCS_HOST_PORT="${DOCS_HOST_PORT:-3002}"
|
|
readonly DOCS_IMAGE="${DOCS_IMAGE:-grafana/docs-base:latest}"
|
|
|
|
readonly DOC_VALIDATOR_INCLUDE="${DOC_VALIDATOR_INCLUDE:-.+\.md$}"
|
|
|
|
readonly HUGO_REFLINKSERRORLEVEL="${HUGO_REFLINKSERRORLEVEL:-WARNING}"
|
|
readonly WEBSITE_EXEC="${WEBSITE_EXEC:-make server}"
|
|
# If set, the docs-base image will run a prebuild script that sets up Hugo mounts.
|
|
readonly WEBSITE_MOUNTS="${WEBSITE_MOUNTS:-}"
|
|
|
|
PODMAN="$(if command -v podman >/dev/null 2>&1; then echo podman; else echo docker; fi)"
|
|
|
|
about() {
|
|
cat <<EOF
|
|
Test documentation locally with multiple source repositories.
|
|
|
|
The REPOS_PATH environment variable is a colon (:) separated list of paths in which to look for project repositories.
|
|
EOF
|
|
}
|
|
|
|
usage() {
|
|
cat <<EOF
|
|
Usage:
|
|
REPOS_PATH=<PATH[:<PATH>...]> $0 [<PROJECT>[:<VERSION>[:<REPO>[:<DIR>]]]...]
|
|
|
|
Examples:
|
|
REPOS_PATH=~/ext/grafana/ $0 writers-toolkit tempo:latest helm-charts/mimir-distributed:latest:mimir:docs/sources/mimir-distributed
|
|
EOF
|
|
}
|
|
|
|
if [ $# -lt 1 ]; then
|
|
cat <<EOF >&2
|
|
ERRR: arguments required but not supplied.
|
|
|
|
$(about)
|
|
|
|
$(usage)
|
|
EOF
|
|
exit 1
|
|
fi
|
|
|
|
readonly REPOS_PATH="${REPOS_PATH:-$(realpath "$(git rev-parse --show-toplevel)/..")}"
|
|
|
|
if [ -z "${REPOS_PATH}" ]; then
|
|
cat <<EOF >&2
|
|
ERRR: REPOS_PATH environment variable is required but has not been provided.
|
|
|
|
$(usage)
|
|
EOF
|
|
exit 1
|
|
fi
|
|
|
|
SOURCES_as_code='as-code-docs'
|
|
SOURCES_enterprise_metrics='backend-enterprise'
|
|
SOURCES_enterprise_metrics_='backend-enterprise'
|
|
SOURCES_grafana_cloud='cloud-docs'
|
|
SOURCES_grafana_cloud_k6='k6-docs'
|
|
SOURCES_helm_charts_mimir_distributed='mimir'
|
|
SOURCES_helm_charts_tempo_distributed='tempo'
|
|
SOURCES_opentelemetry='opentelemetry-docs'
|
|
|
|
VERSIONS_as_code='UNVERSIONED'
|
|
VERSIONS_grafana_cloud='UNVERSIONED'
|
|
VERSIONS_grafana_cloud_k6='UNVERSIONED'
|
|
VERSIONS_opentelemetry='UNVERSIONED'
|
|
VERSIONS_technical_documentation='UNVERSIONED'
|
|
VERSIONS_writers_toolkit='UNVERSIONED'
|
|
|
|
PATHS_helm_charts_mimir_distributed='docs/sources/helm-charts/mimir-distributed'
|
|
PATHS_helm_charts_tempo_distributed='docs/sources/helm-charts/tempo-distributed'
|
|
PATHS_mimir='docs/sources/mimir'
|
|
PATHS_tempo='docs/sources/tempo'
|
|
|
|
# identifier STR
|
|
# Replace characters that are not valid in an identifier with underscores.
|
|
identifier() {
|
|
echo "$1" | tr -C '[:alnum:]_\n' '_'
|
|
}
|
|
|
|
# aget ARRAY KEY
|
|
# Get the value of KEY from associative array ARRAY.
|
|
# Characters that are not valid in an identifier are replaced with underscores.
|
|
aget() {
|
|
eval echo '$'"$(identifier "$1")_$(identifier "$2")"
|
|
}
|
|
|
|
# new_proj populates a new project structure.
|
|
new_proj() {
|
|
_project="$1"
|
|
_version="$2"
|
|
_repo="$3"
|
|
_path="$4"
|
|
|
|
# If version is not set, use the script mapping of project to default versions if it exists.
|
|
# Fallback to 'latest'.
|
|
if [ -z "${_version}" ]; then
|
|
if [ -z "$(aget VERSIONS "${_project}")" ]; then
|
|
_version=latest
|
|
else
|
|
_version="$(aget VERSIONS "${_project}")"
|
|
fi
|
|
fi
|
|
|
|
# If repo is not set, use the script mapping of project to repo name if it exists.
|
|
# Fallback to using the project name.
|
|
if [ -z "${_repo}" ]; then
|
|
if [ -z "$(aget SOURCES "${_project}")" ]; then
|
|
_repo="${_project}"
|
|
else
|
|
_repo="$(aget SOURCES "${_project}")"
|
|
fi
|
|
fi
|
|
|
|
# If path is not set, use the script mapping of project to docs sources path if it exists.
|
|
# Fallback to using 'docs/sources'.
|
|
if [ -z "${_path}" ]; then
|
|
if [ -z "$(aget PATHS "${_project}")" ]; then
|
|
_path="docs/sources"
|
|
else
|
|
_path="$(aget PATHS "${_project}")"
|
|
fi
|
|
fi
|
|
|
|
echo "${_project}:${_version}:${_repo}:${_path}"
|
|
unset _project _version _repo _path
|
|
}
|
|
|
|
# proj_url returns the webserver URL for a project.
|
|
# It expects a complete project structure as input.
|
|
proj_url() {
|
|
IFS=: read -r _project _version _ _ <<POSIX_HERESTRING
|
|
$1
|
|
POSIX_HERESTRING
|
|
|
|
if [ -z "${_version}" ] || [ "${_version}" = 'UNVERSIONED' ]; then
|
|
echo "http://localhost:${DOCS_HOST_PORT}/docs/${_project}/"
|
|
else
|
|
echo "http://localhost:${DOCS_HOST_PORT}/docs/${_project}/${_version}/"
|
|
fi
|
|
|
|
unset _project _version
|
|
}
|
|
|
|
# proj_ver returns the version for a project.
|
|
# It expects a complete project structure as input.
|
|
proj_ver() {
|
|
IFS=: read -r _ _ver _ _ <<POSIX_HERESTRING
|
|
$1
|
|
POSIX_HERESTRING
|
|
|
|
echo "${_ver}"
|
|
unset _ver
|
|
}
|
|
|
|
# proj_dst returns the container path to content source for a project.
|
|
# It expects a complete project structure as input.
|
|
proj_dst() {
|
|
IFS=: read -r _project _version _ _ <<POSIX_HERESTRING
|
|
$1
|
|
POSIX_HERESTRING
|
|
|
|
if [ -z "${_version}" ] || [ "${_version}" = 'UNVERSIONED' ]; then
|
|
echo "/hugo/content/docs/${_project}"
|
|
else
|
|
echo "/hugo/content/docs/${_project}/${_version}"
|
|
fi
|
|
unset _project _version
|
|
}
|
|
|
|
# proj_src returns the host path to content source for a project.
|
|
# It expects a complete project structure as input.
|
|
# It looks for the provided repository name in each of the paths specified in the REPOS_PATH environment variable.
|
|
proj_src() {
|
|
IFS=: read -r _ _ _repo _path <<POSIX_HERESTRING
|
|
$1
|
|
POSIX_HERESTRING
|
|
|
|
IFS=:
|
|
for lookup in ${REPOS_PATH}; do
|
|
if [ -d "${lookup}/${_repo}" ]; then
|
|
echo "${lookup}/${_repo}/${_path}"
|
|
unset _path _repo
|
|
return
|
|
fi
|
|
done
|
|
unset IFS
|
|
|
|
echo "ERRR: could not find project '${_repo}' in any of the paths in REPOS_PATH '${REPOS_PATH}'." >&2
|
|
echo "NOTE: you must have a checkout of the project '${_repo}' at '${REPOS_PATH##:*}/${_repo}'." >&2
|
|
echo "NOTE: if you have cloned the repository into a directory with a different name, consider changing it to ${_repo}." >&2
|
|
unset _path _repo
|
|
exit 1
|
|
}
|
|
|
|
# proj_canonical returns the canonical absolute path partial URI for a project.
|
|
# It expects a complete project structure as input.
|
|
proj_canonical() {
|
|
IFS=: read -r _project _version _ _ <<POSIX_HERESTRING
|
|
$1
|
|
POSIX_HERESTRING
|
|
|
|
if [ -z "${_version}" ] || [ "${_version}" = 'UNVERSIONED' ]; then
|
|
echo "/docs/${_project}"
|
|
else
|
|
echo "/docs/${_project}/${_version}"
|
|
fi
|
|
unset _project _version
|
|
}
|
|
|
|
proj_to_url_src_dst_ver() {
|
|
_url="$(proj_url "$1")"
|
|
_src="$(proj_src "$1")"
|
|
_dst="$(proj_dst "$1")"
|
|
_ver="$(proj_ver "$1")"
|
|
|
|
echo "${_url}^${_src}^${_dst}^${_ver}"
|
|
unset _url _src _dst _ver
|
|
}
|
|
|
|
url_src_dst_vers() {
|
|
for arg in "$@"; do
|
|
IFS=: read -r _project _version _repo _path <<POSIX_HERESTRING
|
|
$arg
|
|
POSIX_HERESTRING
|
|
|
|
case "${_project}" in
|
|
# Workaround for arbitrary mounts where the version field is expected to be the local directory
|
|
# and the repo field is expected to be the container directory.
|
|
arbitrary)
|
|
echo "${_project}^${_version}^${_repo}^" # TODO
|
|
;;
|
|
logs)
|
|
proj_to_url_src_dst_ver "$(new_proj loki "${_version}")"
|
|
proj_to_url_src_dst_ver "$(new_proj enterprise-logs "${_version}")"
|
|
;;
|
|
metrics)
|
|
proj_to_url_src_dst_ver "$(new_proj mimir "${_version}")"
|
|
proj_to_url_src_dst_ver "$(new_proj helm-charts/mimir-distributed "${_version}")"
|
|
proj_to_url_src_dst_ver "$(new_proj enterprise-metrics "${_version}")"
|
|
;;
|
|
traces)
|
|
proj_to_url_src_dst_ver "$(new_proj tempo "${_version}")"
|
|
proj_to_url_src_dst_ver "$(new_proj enterprise-traces "${_version}")"
|
|
;;
|
|
*)
|
|
proj_to_url_src_dst_ver "$(new_proj "${_project}" "${_version}" "${_repo}" "${_path}")"
|
|
;;
|
|
esac
|
|
done
|
|
|
|
unset _project _version _repo _path
|
|
}
|
|
|
|
url_src_dst_vers="$(url_src_dst_vers "$@")"
|
|
|
|
volumes=""
|
|
redirects=""
|
|
|
|
for x in ${url_src_dst_vers}; do
|
|
IFS='^' read -r _url _src _dst _ver <<POSIX_HERESTRING
|
|
$x
|
|
POSIX_HERESTRING
|
|
|
|
if [ "${_url}" != "arbitrary" ]; then
|
|
if [ ! -f "${_src}/_index.md" ]; then
|
|
echo "ERRR: Index file '${_src}/_index.md' does not exist." >&2
|
|
echo "Is '${_src}' the correct source directory?" >&2
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
echo "DEBG: Mounting '${_src}' at container path '${_dst}'" >&2
|
|
if [ -z "${volumes}" ]; then
|
|
volumes="--volume=${_src}:${_dst}"
|
|
else
|
|
volumes="${volumes} --volume=${_src}:${_dst}"
|
|
fi
|
|
|
|
if [ -n "${_ver}" ] && [ "${_ver}" != 'UNVERSIONED' ]; then
|
|
if [ -z "${redirects}" ]; then
|
|
redirects="${_dst}^${_ver}"
|
|
else
|
|
redirects="${redirects} ${_dst}^${_ver}"
|
|
fi
|
|
fi
|
|
unset _url _src _dst _ver
|
|
done
|
|
|
|
IFS=':' read -r image _ <<POSIX_HERESTRING
|
|
${DOCS_IMAGE}
|
|
POSIX_HERESTRING
|
|
|
|
if [ "${image}" = "grafana/doc-validator" ]; then
|
|
echo
|
|
"${PODMAN}" run \
|
|
--init \
|
|
--interactive \
|
|
--name "${DOCS_CONTAINER}" \
|
|
--platform linux/amd64 \
|
|
--rm \
|
|
--tty \
|
|
${volumes} \
|
|
"${DOCS_IMAGE}" \
|
|
--skip-image-validation \
|
|
--include="${DOC_VALIDATOR_INCLUDE}" \
|
|
/hugo/content/docs \
|
|
"$(proj_canonical "$(new_proj "$1")")"
|
|
else
|
|
|
|
tempfile="$(mktemp -t make-docs.XXX)"
|
|
cat <<EOF >"${tempfile}"
|
|
#!/usr/bin/env bash
|
|
for redirect in ${redirects}; do
|
|
IFS='^' read -r path ver <<<"\${redirect}"
|
|
echo -e "---\\nredirectURL: \"\${path/\/hugo\/content/}\"\\ntype: redirect\\n---\\n" > "\${path/\${ver}/_index.md}"
|
|
|
|
done
|
|
|
|
if [[ -n "${WEBSITE_MOUNTS}" ]]; then
|
|
unset WEBSITE_SKIP_MOUNTS
|
|
fi
|
|
|
|
${WEBSITE_EXEC}
|
|
EOF
|
|
chmod +x "${tempfile}"
|
|
volumes="${volumes} --volume=$(realpath "${tempfile}"):/entrypoint"
|
|
readonly volumes
|
|
|
|
echo
|
|
echo "Documentation will be served at the following URLs:"
|
|
for x in ${url_src_dst_vers}; do
|
|
IFS='^' read -r url _ _ <<POSIX_HERESTRING
|
|
$x
|
|
POSIX_HERESTRING
|
|
|
|
if [ -n "${url}" ]; then
|
|
echo " ${url}"
|
|
fi
|
|
done
|
|
|
|
echo
|
|
"${PODMAN}" run \
|
|
--env "HUGO_REFLINKSERRORLEVEL=${HUGO_REFLINKSERRORLEVEL}" \
|
|
--init \
|
|
--interactive \
|
|
--name "${DOCS_CONTAINER}" \
|
|
--platform linux/amd64 \
|
|
--publish "${DOCS_HOST_PORT}:3002" \
|
|
--publish "3003:3003" \
|
|
--rm \
|
|
--tty \
|
|
${volumes} \
|
|
"${DOCS_IMAGE}" \
|
|
/entrypoint
|
|
fi
|