github.com/grafana/pyroscope@v1.18.0/docs/make-docs (about) 1 #!/bin/sh 2 # shellcheck disable=SC2034 3 # 4 # The source of this file is https://raw.githubusercontent.com/grafana/writers-toolkit/main/docs/make-docs. 5 # # `make-docs` procedure changelog 6 # 7 # Updates should conform to the guidelines in https://keepachangelog.com/en/1.1.0/. 8 # [Semantic versioning](https://semver.org/) is used to help the reader identify the significance of changes. 9 # Changes are relevant to this script and the support docs.mk GNU Make interface. 10 # 11 # ## 10.1.0 (2025-11-11) 12 # 13 # ### Fixed 14 # 15 # - Extend readiness probes to prevent confusing output. 16 # 17 # Before, the probes could fail too soon and long an error message which contradicted the service starting up. 18 # 19 # ## 10.0.0 (2025-10-13) 20 # 21 # ### Changed 22 # 23 # - Hugo no longer supports the `--debug` option, use `--logLevel debug` instead. 24 # 25 # Thank you to @karlskewes for their contribution! 26 # 27 # ## 9.0.0 (2025-04-05) 28 # 29 # ### Removed 30 # 31 # - doc-validator target and associated scripts. 32 # 33 # Most useful rules have been migrated to Vale and the others are often false positives. 34 # 35 # ## 8.5.2 (2025-02-28) 36 # 37 # ### Fixed 38 # 39 # - topic/<KIND> targets are no longer no-ops as a result of 8.5.1. 40 # 41 # ## 8.5.1 (2025-02-18) 42 # 43 # ### Fixed 44 # 45 # - PHONY declaration for topic/<KIND> targets. 46 # 47 # ## 8.5.0 (2025-02-13) 48 # 49 # ### Added 50 # 51 # - make topic/<KIND> TOPIC_PATH=<PATH> target to create a new topic from the Writers' Toolkit templates. 52 # 53 # ## 8.4.0 (2025-01-27) 54 # 55 # ### Fixed 56 # 57 # - Correct mount for the /docs/grafana-cloud/send-data/fleet-management/ project. 58 # 59 # ## 8.3.0 (2024-12-27) 60 # 61 # ### Added 62 # 63 # - Debug output of the final command when DEBUG=true. 64 # 65 # Useful to inspect if the script is correctly constructing the final command. 66 # 67 # ## 8.2.0 (2024-12-22) 68 # 69 # ### Removed 70 # 71 # - Special cases for Oracle and Datadog plugins now that they exist in the plugins monorepo. 72 # 73 # ## 8.1.0 (2024-08-22) 74 # 75 # ### Added 76 # 77 # - Additional website mounts for projects that use the website repository. 78 # 79 # Mounts are required for `make docs` to work in the website repository or with the website project. 80 # The Makefile is also mounted for convenient development of the procedure in that repository. 81 # 82 # ## 8.0.1 (2024-07-01) 83 # 84 # ### Fixed 85 # 86 # - Update log suppression to catch new format of website /docs/ homepage REF_NOT_FOUND warnings. 87 # 88 # These warnings are related to missing some pages during the build that are required for the /docs/ homepage. 89 # They were previously suppressed but the log format changed and without this change they reappear in the latest builds. 90 # 91 # ## 8.0.0 (2024-05-28) 92 # 93 # ### Changed 94 # 95 # - Add environment variable `OUTPUT_FORMAT` to control the output of commands. 96 # 97 # The default value is `human` and means the output format is human readable. 98 # The value `json` is also supported and outputs JSON. 99 # 100 # Note that the `json` format isn't supported by `make docs`, only `make doc-validator` and `make vale`. 101 # 102 # ## 7.0.0 (2024-05-03) 103 # 104 # ### Changed 105 # 106 # - Pull images for all recipes that use containers by default. 107 # 108 # Use the `PULL=false` variable to disable this behavior. 109 # 110 # ### Removed 111 # 112 # - The `docs-no-pull` target as it's redundant with the new `PULL=false` variable. 113 # 114 # ## 6.1.0 (2024-04-22) 115 # 116 # ### Changed 117 # 118 # - Mount volumes with SELinux labels. 119 # 120 # https://docs.docker.com/storage/bind-mounts/#configure-the-selinux-label 121 # 122 # ### Added 123 # 124 # - Pseudo project for including only website resources and no website content. 125 # 126 # Facilitates testing shortcodes and layout changes with a small documentation set instead of Grafana Cloud or the entire website. 127 # 128 # ## 6.0.1 (2024-02-28) 129 # 130 # ### Added 131 # 132 # - Suppress new errors relating to absent content introduced in https://github.com/grafana/website/pull/17561. 133 # 134 # ## 6.0.0 (2024-02-16) 135 # 136 # ### Changed 137 # 138 # - Require `jq` for human readable `make doc-validator` output. 139 # 140 # ## 5.4.0 (2024-02-12) 141 # 142 # ### Changed 143 # 144 # - Set `WEBSITE_MOUNTS=true` when a user includes the `website` project. 145 # 146 # Ensures consistent behavior across repositories. 147 # To disable website mounts, add `export WEBSITE_MOUNTS := false` to your `variables.mk` or `variables.mk.local` file. 148 # - Use website mounts and container volumes also when a user includes the `grafana-cloud` project. 149 # 150 # ## 5.3.0 (2024-02-08) 151 # 152 # ### Changed 153 # 154 # - Updated support for plugins monorepo now that multiple projects have been moved into it. 155 # - Use `printf` instead of `echo` for better portability of output. 156 # 157 # https://www.in-ulm.de/~mascheck/various/echo+printf/ 158 # 159 # ## 5.2.0 (2024-01-18) 160 # 161 # ### Changed 162 # 163 # - Updated `make vale` to use latest Vale style and configuration. 164 # - Updated `make vale` to use platform appropriate image. 165 # 166 # ## 5.1.2 (2023-11-08) 167 # 168 # ### Added 169 # 170 # - Hide manual_mount warning messages from non-debug output. 171 # Set the DEBUG environment variable to see all hidden messages. 172 # 173 # ## 5.1.1 (2023-10-30) 174 # 175 # ### Added 176 # 177 # - Support for Datadog and Oracle data source plugins repositories. 178 # 179 # ## 5.1.0 (2023-10-20) 180 # 181 # ### Added 182 # 183 # - Support for the plugins monorepo. 184 # 185 # ## 5.0.0 (2023-10-18) 186 # 187 # ### Added 188 # 189 # - Improved support for website repository. 190 # 191 # Mount more content and provide some feedback to users that the build can take time. 192 # 193 # - Ability to enter the `grafana/docs-base` container with a shell using the `ENTER` environment variable. 194 # 195 # ### Fixed 196 # 197 # - Correct key combination for interrupting the process. 198 # 199 # Keyboards use capital letters so this more accurately reflects the exact key combination users are expected to press. 200 # 201 # ### Removed 202 # 203 # - Imperfect implementation of container name. 204 # 205 # Facilitates running `make vale` and `make docs` at once. 206 # Container names are convenient for recognition in `docker ps` but the current implementation has more downsides than upsides. 207 # 208 # - Forced platform specification now that multiple architecture images exist. 209 # 210 # Significantly speeds up build times on larger repositories. 211 # 212 # ## 4.2.2 (2023-10-05) 213 214 # - Added support for Jira data source and MongoDB data source plugins repositories. 215 # 216 # ## 4.2.1 (2023-09-13) 217 218 # ## Fixed 219 # 220 # - Improved consistency of the webserver request loop by polling the Hugo port rather than the proxy port. 221 # 222 # ## 4.2.0 (2023-09-01) 223 # 224 # ### Added 225 # 226 # - Retry the initial webserver request up to ten times to allow for the process to start. 227 # If it is still failing after ten seconds, an error message is logged. 228 # 229 # ## 4.1.1 (2023-07-20) 230 # 231 # ### Fixed 232 # 233 # - Replaced use of `realpath` with POSIX compatible alternative to determine default value for REPOS_PATH. 234 # 235 # ## 4.1.0 (2023-06-16) 236 # 237 # ### Added 238 # 239 # - Mounts of `layouts` and `config` directories for the `website` project. 240 # Ensures that local changes to mounts or shortcodes are reflected in the development server. 241 # 242 # ### Fixed 243 # 244 # - Version inference for versioned docs pages. 245 # Pages in versioned projects now have the `versioned: true` front matter set to ensure that "version" in $.Page.Scratch is set on builds. 246 # 247 # ## 4.0.0 (2023-06-06) 248 # 249 # ### Removed 250 # 251 # - `doc-validator/%` target. 252 # The behavior of the target was not as described. 253 # Instead, to limit `doc-validator` to only specific files, refer to https://grafana.com/docs/writers-toolkit/writing-guide/tooling-and-workflows/validate-technical-documentation/#run-on-specific-files. 254 # 255 # ## 3.0.0 (2023-05-18) 256 # 257 # ### Fixed 258 # 259 # - Compatibility with the updated Make targets in the `website` repository. 260 # `docs` now runs this script itself, `server-docs` builds the site with the `docs` Hugo environment. 261 # 262 # ## 2.0.0 (2023-05-18) 263 # 264 # ### Added 265 # 266 # - Support for the grafana-cloud/frontend-observability/faro-web-sdk project. 267 # - Use of `doc-validator` v2.0.x which includes breaking changes to command line options. 268 # 269 # ### Fixed 270 # 271 # - Source grafana-cloud project from website repository. 272 # 273 # ### Added 274 # 275 # - Support for running the Vale linter with `make vale`. 276 # 277 # ## 1.2.1 (2023-05-05) 278 # 279 # ### Fixed 280 # 281 # - Use `latest` tag of `grafana/vale` image by default instead of hardcoded older version. 282 # - Fix mounting multiple projects broken by the changes in 1.0.1 283 # 284 # ## 1.2.0 (2023-05-05) 285 # 286 # ### Added 287 # 288 # - Support for running the Vale linter with `make vale`. 289 # 290 # ### Fixed 291 # 292 # ## 1.1.0 (2023-05-05) 293 # 294 # ### Added 295 # 296 # - Rewrite error output so it can be followed by text editors. 297 # 298 # ### Fixed 299 # 300 # - Fix `docs-debug` container process port. 301 # 302 # ## 1.0.1 (2023-05-04) 303 # 304 # ### Fixed 305 # 306 # - Ensure complete section hierarchy so that all projects have a visible menu. 307 # 308 # ## 1.0.0 (2023-05-04) 309 # 310 # ### Added 311 # 312 # - Build multiple projects simultaneously if all projects are checked out locally. 313 # - Run [`doc-validator`](https://github.com/grafana/technical-documentation/tree/main/tools/cmd/doc-validator) over projects. 314 # - Redirect project root to mounted version. 315 # For example redirect `/docs/grafana/` to `/docs/grafana/latest/`. 316 # - Support for Podman or Docker containers with `PODMAN` environment variable. 317 # - Support for projects: 318 # - agent 319 # - enterprise-logs 320 # - enterprise-metrics 321 # - enterprise-traces 322 # - grafana 323 # - grafana-cloud 324 # - grafana-cloud/machine-learning 325 # - helm-charts/mimir-distributed 326 # - helm-charts/tempo-distributed 327 # - incident 328 # - loki 329 # - mimir 330 # - oncall 331 # - opentelemetry 332 # - phlare 333 # - plugins 334 # - slo 335 # - tempo 336 # - writers-toolkit 337 338 339 set -ef 340 341 readonly DOCS_HOST_PORT="${DOCS_HOST_PORT:-3002}" 342 readonly DOCS_IMAGE="${DOCS_IMAGE:-grafana/docs-base:latest}" 343 344 readonly DOC_VALIDATOR_INCLUDE="${DOC_VALIDATOR_INCLUDE:-.+\.md$}" 345 readonly DOC_VALIDATOR_SKIP_CHECKS="${DOC_VALIDATOR_SKIP_CHECKS:-^image-}" 346 347 readonly HUGO_REFLINKSERRORLEVEL="${HUGO_REFLINKSERRORLEVEL:-WARNING}" 348 readonly VALE_MINALERTLEVEL="${VALE_MINALERTLEVEL:-error}" 349 readonly WEBSITE_EXEC="${WEBSITE_EXEC:-make server-docs}" 350 351 readonly OUTPUT_FORMAT="${OUTPUT_FORMAT:-human}" 352 353 PODMAN="$(if command -v podman >/dev/null 2>&1; then echo podman; else echo docker; fi)" 354 355 if ! command -v curl >/dev/null 2>&1; then 356 if ! command -v wget >/dev/null 2>&1; then 357 # shellcheck disable=SC2016 358 errr 'either `curl` or `wget` must be installed for this script to work.' 359 360 exit 1 361 fi 362 fi 363 364 if ! command -v "${PODMAN}" >/dev/null 2>&1; then 365 # shellcheck disable=SC2016 366 errr 'either `podman` or `docker` must be installed for this script to work.' 367 368 exit 1 369 fi 370 371 372 about() { 373 cat <<EOF 374 Test documentation locally with multiple source repositories. 375 376 The REPOS_PATH environment variable is a colon (:) separated list of paths in which to look for project repositories. 377 EOF 378 } 379 380 usage() { 381 cat <<EOF 382 Usage: 383 REPOS_PATH=<PATH[:<PATH>...]> $0 [<PROJECT>[:<VERSION>[:<REPO>[:<DIR>]]]...] 384 385 Examples: 386 REPOS_PATH=~/ext/grafana/ $0 writers-toolkit tempo:latest helm-charts/mimir-distributed:latest:mimir:docs/sources/mimir-distributed 387 EOF 388 } 389 390 if [ $# -lt 1 ]; then 391 cat <<EOF >&2 392 ERRR: arguments required but not supplied. 393 394 $(about) 395 396 $(usage) 397 EOF 398 exit 1 399 fi 400 401 readonly REPOS_PATH="${REPOS_PATH:-$(cd "$(git rev-parse --show-toplevel)/.." && echo "${PWD}")}" 402 403 if [ -z "${REPOS_PATH}" ]; then 404 cat <<EOF >&2 405 ERRR: REPOS_PATH environment variable is required but has not been provided. 406 407 $(usage) 408 EOF 409 exit 1 410 fi 411 412 # The following variables comprise a pseudo associative array of project names to source repositories. 413 # You only need to set a SOURCES variable if the project name does not match the source repository name. 414 # You can get a key identifier using the `identifier` function. 415 # To look up the value of any pseudo associative array, use the `aget` function. 416 SOURCES_as_code='as-code-docs' 417 SOURCES_enterprise_metrics='backend-enterprise' 418 SOURCES_enterprise_metrics_='backend-enterprise' 419 SOURCES_grafana_cloud='website' 420 SOURCES_grafana_cloud_alerting_and_irm_machine_learning='machine-learning' 421 SOURCES_grafana_cloud_alerting_and_irm_slo='slo' 422 SOURCES_grafana_cloud_k6='k6-docs' 423 SOURCES_grafana_cloud_data_configuration_integrations='cloud-onboarding' 424 SOURCES_grafana_cloud_frontend_observability_faro_web_sdk='faro-web-sdk' 425 SOURCES_grafana_cloud_send_data_fleet_management='fleet-management' 426 SOURCES_helm_charts_mimir_distributed='mimir' 427 SOURCES_helm_charts_tempo_distributed='tempo' 428 SOURCES_opentelemetry='opentelemetry-docs' 429 SOURCES_resources='website' 430 431 # The following variables comprise a pseudo associative array of project names to versions. 432 # You only need to set a VERSIONS variable if it is not the default of 'latest'. 433 # You can get a key identifier using the `identifier` function. 434 # To look up the value of any pseudo associative array, use the `aget` function. 435 VERSIONS_as_code='UNVERSIONED' 436 VERSIONS_grafana_cloud='UNVERSIONED' 437 VERSIONS_grafana_cloud_alerting_and_irm_machine_learning='UNVERSIONED' 438 VERSIONS_grafana_cloud_alerting_and_irm_slo='UNVERSIONED' 439 VERSIONS_grafana_cloud_k6='UNVERSIONED' 440 VERSIONS_grafana_cloud_data_configuration_integrations='UNVERSIONED' 441 VERSIONS_grafana_cloud_frontend_observability_faro_web_sdk='UNVERSIONED' 442 VERSIONS_grafana_cloud_send_data_fleet_management='UNVERSIONED' 443 VERSIONS_opentelemetry='UNVERSIONED' 444 VERSIONS_resources='UNVERSIONED' 445 VERSIONS_technical_documentation='UNVERSIONED' 446 VERSIONS_website='UNVERSIONED' 447 VERSIONS_writers_toolkit='UNVERSIONED' 448 449 # The following variables comprise a pseudo associative array of project names to source repository paths. 450 # You only need to set a PATHS variable if it is not the default of 'docs/sources'. 451 # You can get a key identifier using the `identifier` function. 452 # To look up the value of any pseudo associative array, use the `aget` function. 453 PATHS_grafana_cloud='content/docs/grafana-cloud' 454 PATHS_helm_charts_mimir_distributed='docs/sources/helm-charts/mimir-distributed' 455 PATHS_helm_charts_tempo_distributed='docs/sources/helm-charts/tempo-distributed' 456 PATHS_mimir='docs/sources/mimir' 457 PATHS_resources='content' 458 PATHS_tempo='docs/sources/tempo' 459 PATHS_website='content' 460 461 # identifier STR 462 # Replace characters that are not valid in an identifier with underscores. 463 identifier() { 464 echo "$1" | tr -C '[:alnum:]_\n' '_' 465 } 466 467 # aget ARRAY KEY 468 # Get the value of KEY from associative array ARRAY. 469 # Characters that are not valid in an identifier are replaced with underscores. 470 aget() { 471 eval echo '$'"$(identifier "$1")_$(identifier "$2")" 472 } 473 474 # src returns the project source repository name for a project. 475 src() { 476 _project="$1" 477 478 case "${_project}" in 479 plugins/*) 480 if [ -z "$(aget SOURCES "${_project}")" ]; then 481 echo plugins-private 482 else 483 aget SOURCES "${_project}" 484 fi 485 ;; 486 *) 487 if [ -z "$(aget SOURCES "${_project}")" ]; then 488 echo "${_project}" 489 else 490 aget SOURCES "${_project}" 491 fi 492 ;; 493 esac 494 495 unset _project 496 } 497 498 # path returns the relative path within the repository that contain the docs for a project. 499 path() { 500 _project="$1" 501 502 case "${_project}" in 503 plugins/*) 504 if [ -z "$(aget PATHS "${_project}")" ]; then 505 echo "${_project}/docs/sources" 506 else 507 aget PATHS "${_project}" 508 fi 509 ;; 510 *) 511 if [ -z "$(aget PATHS "${_project}")" ]; then 512 echo "docs/sources" 513 else 514 aget PATHS "${_project}" 515 fi 516 esac 517 518 unset _project 519 } 520 521 # version returns the version for a project. Unversioned projects return the special value 'UNVERSIONED'. 522 version() { 523 _project="$1" 524 525 case "${_project}" in 526 plugins/*) 527 if [ -z "$(aget VERSIONS "${_project}")" ]; then 528 echo "UNVERSIONED" 529 else 530 aget VERSIONS "${_project}" 531 fi 532 ;; 533 *) 534 if [ -z "$(aget VERSIONS "${_project}")" ]; then 535 echo latest 536 else 537 aget VERSIONS "${_project}" 538 fi 539 esac 540 541 unset _project 542 } 543 544 545 # new_proj populates a new project structure. 546 new_proj() { 547 _project="$1" 548 _version="$2" 549 _repo="$3" 550 _path="$4" 551 552 # If version is not set, use the script mapping of project to default versions if it exists. 553 # Fallback to 'latest'. 554 if [ -z "${_version}" ]; then 555 _version="$(version "${_project}")" 556 fi 557 558 # If repo is not set, use the script mapping of project to repo name if it exists. 559 # Fallback to using the project name. 560 if [ -z "${_repo}" ]; then 561 _repo="$(src "${_project}")" 562 fi 563 564 # If path is not set, use the script mapping of project to docs sources path if it exists. 565 # Fallback to using 'docs/sources'. 566 if [ -z "${_path}" ]; then 567 _path="$(path "${_project}")" 568 fi 569 570 echo "${_project}:${_version}:${_repo}:${_path}" 571 unset _project _version _repo _path 572 } 573 574 # proj_url returns the webserver URL for a project. 575 # It expects a complete project structure as input. 576 proj_url() { 577 IFS=: read -r _project _version _ _ <<POSIX_HERESTRING 578 $1 579 POSIX_HERESTRING 580 581 if [ "${_project}" = website ]; then 582 echo "http://localhost:${DOCS_HOST_PORT}/docs/" 583 584 unset _project _version 585 return 586 fi 587 588 if [ -z "${_version}" ] || [ "${_version}" = 'UNVERSIONED' ]; then 589 echo "http://localhost:${DOCS_HOST_PORT}/docs/${_project}/" 590 else 591 echo "http://localhost:${DOCS_HOST_PORT}/docs/${_project}/${_version}/" 592 fi 593 594 unset _project _version 595 } 596 597 # proj_ver returns the version for a project. 598 # It expects a complete project structure as input. 599 proj_ver() { 600 IFS=: read -r _ _ver _ _ <<POSIX_HERESTRING 601 $1 602 POSIX_HERESTRING 603 604 echo "${_ver}" 605 unset _ver 606 } 607 608 # proj_dst returns the container path to content source for a project. 609 # It expects a complete project structure as input. 610 proj_dst() { 611 IFS=: read -r _project _version _ _ <<POSIX_HERESTRING 612 $1 613 POSIX_HERESTRING 614 615 if [ "${_project}" = website ]; then 616 echo '/hugo/content' 617 618 unset _project _version 619 return 620 fi 621 622 if [ -z "${_version}" ] || [ "${_version}" = 'UNVERSIONED' ]; then 623 echo "/hugo/content/docs/${_project}" 624 else 625 echo "/hugo/content/docs/${_project}/${_version}" 626 fi 627 628 unset _project _version 629 } 630 631 # repo_path returns the host path to the project repository. 632 # It looks for the provided repository name in each of the paths specified in the REPOS_PATH environment variable. 633 repo_path() { 634 _repo="$1" 635 IFS=: 636 for lookup in ${REPOS_PATH}; do 637 if [ -d "${lookup}/${_repo}" ]; then 638 echo "${lookup}/${_repo}" 639 unset _path _repo 640 return 641 fi 642 done 643 unset IFS 644 645 errr "could not find project '${_repo}' in any of the paths in REPOS_PATH '${REPOS_PATH}'." 646 note "you must have a checkout of the project '${_repo}' at '${REPOS_PATH##:*}/${_repo}'." 647 note "if you have cloned the repository into a directory with a different name, consider changing it to ${_repo}." 648 649 unset _repo 650 exit 1 651 } 652 653 # proj_src returns the host path to content source for a project. 654 # It expects a complete project structure as input. 655 # It looks for the provided repository name in each of the paths specified in the REPOS_PATH environment variable. 656 proj_src() { 657 IFS=: read -r _ _ _repo _path <<POSIX_HERESTRING 658 $1 659 POSIX_HERESTRING 660 661 _repo="$(repo_path "${_repo}")" 662 echo "${_repo}/${_path}" 663 664 unset _path _repo 665 } 666 667 # proj_canonical returns the canonical absolute path partial URI for a project. 668 # It expects a complete project structure as input. 669 proj_canonical() { 670 IFS=: read -r _project _version _ _ <<POSIX_HERESTRING 671 $1 672 POSIX_HERESTRING 673 674 if [ "${_project}" = website ]; then 675 echo '/docs' 676 677 unset _project _version 678 return 679 fi 680 681 if [ -z "${_version}" ] || [ "${_version}" = 'UNVERSIONED' ]; then 682 echo "/docs/${_project}" 683 else 684 echo "/docs/${_project}/${_version}" 685 fi 686 687 unset _project _version 688 } 689 690 proj_to_url_src_dst_ver() { 691 _url="$(proj_url "$1")" 692 _src="$(proj_src "$1")" 693 _dst="$(proj_dst "$1")" 694 _ver="$(proj_ver "$1")" 695 696 echo "${_url}^${_src}^${_dst}^${_ver}" 697 unset _url _src _dst _ver 698 } 699 700 url_src_dst_vers() { 701 for arg in "$@"; do 702 IFS=: read -r _project _version _repo _path <<POSIX_HERESTRING 703 $arg 704 POSIX_HERESTRING 705 706 case "${_project}" in 707 # Workaround for arbitrary mounts where the version field is expected to be the local directory 708 # and the repo field is expected to be the container directory. 709 arbitrary) 710 echo "${_project}^${_version}^${_repo}^" # TODO 711 ;; 712 logs) 713 proj_to_url_src_dst_ver "$(new_proj loki "${_version}")" 714 proj_to_url_src_dst_ver "$(new_proj enterprise-logs "${_version}")" 715 ;; 716 metrics) 717 proj_to_url_src_dst_ver "$(new_proj mimir "${_version}")" 718 proj_to_url_src_dst_ver "$(new_proj helm-charts/mimir-distributed "${_version}")" 719 proj_to_url_src_dst_ver "$(new_proj enterprise-metrics "${_version}")" 720 ;; 721 resources) 722 _repo="$(repo_path website)" 723 echo "arbitrary^${_repo}/config^/hugo/config" "arbitrary^${_repo}/layouts^/hugo/layouts" "arbitrary^${_repo}/scripts^/hugo/scripts" 724 unset _repo 725 ;; 726 traces) 727 proj_to_url_src_dst_ver "$(new_proj tempo "${_version}")" 728 proj_to_url_src_dst_ver "$(new_proj enterprise-traces "${_version}")" 729 ;; 730 *) 731 proj_to_url_src_dst_ver "$(new_proj "${_project}" "${_version}" "${_repo}" "${_path}")" 732 ;; 733 esac 734 done 735 736 unset _project _version _repo _path 737 } 738 739 await_build() { 740 url="$1" 741 req="$(if command -v curl >/dev/null 2>&1; then echo 'curl -s -o /dev/null'; else echo 'wget -q'; fi)" 742 743 # Initial delay to allow container to start before beginning healthchecks 744 sleep 3 745 746 # Fast retries for initial startup (10 attempts, 1 second apart) 747 i=1 748 max=10 749 while [ "${i}" -ne "${max}" ] 750 do 751 sleep 1 752 debg "Retrying request to web server assuming the process is still starting up." 753 i=$((i + 1)) 754 755 if ${req} "${url}"; then 756 printf '\r\nView documentation locally:\r\n' 757 for x in ${url_src_dst_vers}; do 758 IFS='^' read -r url _ _ <<POSIX_HERESTRING 759 $x 760 POSIX_HERESTRING 761 762 if [ -n "${url}" ]; then 763 if [ "${url}" != arbitrary ]; then 764 printf '\r %s\r\n' "${url}" 765 fi 766 fi 767 done 768 printf '\r\nPress Ctrl+C to stop the server\r\n' 769 770 unset i max req url 771 return 772 fi 773 done 774 775 # Continue checking with longer intervals for slower builds 776 # This prevents false positives for large builds that take longer to start 777 i=1 778 max=20 779 while [ "${i}" -ne "${max}" ] 780 do 781 sleep 2 782 debg "Continuing to check web server (build may be taking longer than expected)." 783 i=$((i + 1)) 784 785 if ${req} "${url}"; then 786 printf '\r\nView documentation locally:\r\n' 787 for x in ${url_src_dst_vers}; do 788 IFS='^' read -r url _ _ <<POSIX_HERESTRING 789 $x 790 POSIX_HERESTRING 791 792 if [ -n "${url}" ]; then 793 if [ "${url}" != arbitrary ]; then 794 printf '\r %s\r\n' "${url}" 795 fi 796 fi 797 done 798 printf '\r\nPress Ctrl+C to stop the server\r\n' 799 800 unset i max req url 801 return 802 fi 803 done 804 805 # Only log error after extended checking period (total ~60 seconds) 806 printf '\r\n' 807 errr 'The build was interrupted or a build error occurred, check the previous logs for possible causes.' 808 note 'You might need to use Ctrl+C to end the process.' 809 810 unset i max req url 811 } 812 813 debg() { 814 if [ -n "${DEBUG}" ]; then 815 printf 'DEBG: %s\r\n' "$1" >&2 816 fi 817 } 818 819 errr() { 820 printf 'ERRR: %s\r\n' "$1" >&2 821 } 822 823 note() { 824 printf 'NOTE: %s\r\n' "$1" >&2 825 } 826 827 url_src_dst_vers="$(url_src_dst_vers "$@")" 828 829 volumes="" 830 redirects="" 831 832 for arg in "$@"; do 833 IFS=: read -r _project _ _repo _ <<POSIX_HERESTRING 834 ${arg} 835 POSIX_HERESTRING 836 if [ "${_project}" = website ] || [ "${_project}" = grafana-cloud ]; then 837 note "Please be patient, building the website can take some time." 838 839 # If set, the docs-base image will run a prebuild script that sets up Hugo mounts. 840 if [ "${WEBSITE_MOUNTS}" = false ]; then 841 unset WEBSITE_MOUNTS 842 else 843 readonly WEBSITE_MOUNTS=true 844 fi 845 846 _repo="$(repo_path website)" 847 volumes="--volume=${_repo}/config:/hugo/config:z" 848 volumes="${volumes} --volume=${_repo}/content/guides:/hugo/content/guides:z" 849 volumes="${volumes} --volume=${_repo}/content/whats-new:/hugo/content/whats-new:z" 850 volumes="${volumes} --volume=${_repo}/Makefile:/hugo/Makefile:z" 851 volumes="${volumes} --volume=${_repo}/layouts:/hugo/layouts:z" 852 volumes="${volumes} --volume=${_repo}/scripts:/hugo/scripts:z" 853 fi 854 unset _project _repo 855 done 856 857 for x in ${url_src_dst_vers}; do 858 IFS='^' read -r _url _src _dst _ver <<POSIX_HERESTRING 859 $x 860 POSIX_HERESTRING 861 862 if [ "${_url}" != arbitrary ]; then 863 if [ ! -f "${_src}/_index.md" ]; then 864 errr "Index file '${_src}/_index.md' does not exist." 865 note "Is '${_src}' the correct source directory?" 866 exit 1 867 fi 868 fi 869 870 debg "Mounting '${_src}' at container path '${_dst}'" 871 872 if [ -z "${volumes}" ]; then 873 volumes="--volume=${_src}:${_dst}:z" 874 else 875 volumes="${volumes} --volume=${_src}:${_dst}:z" 876 fi 877 878 if [ -n "${_ver}" ] && [ "${_ver}" != 'UNVERSIONED' ]; then 879 if [ -z "${redirects}" ]; then 880 redirects="${_dst}^${_ver}" 881 else 882 redirects="${redirects} ${_dst}^${_ver}" 883 fi 884 fi 885 unset _url _src _dst _ver 886 done 887 888 IFS=':' read -r image _ <<POSIX_HERESTRING 889 ${DOCS_IMAGE} 890 POSIX_HERESTRING 891 892 case "${image}" in 893 'grafana/vale') 894 proj="$(new_proj "$1")" 895 printf '\r\n' 896 IFS='' read -r cmd <<EOF 897 ${PODMAN} run \ 898 --init \ 899 --interactive \ 900 --rm \ 901 --workdir /etc/vale \ 902 --tty \ 903 ${volumes} \ 904 ${DOCS_IMAGE} \ 905 --minAlertLevel=${VALE_MINALERTLEVEL} \ 906 --glob=*.md \ 907 /hugo/content/docs 908 EOF 909 910 if [ -n "${DEBUG}" ]; then 911 debg "${cmd}" 912 fi 913 914 case "${OUTPUT_FORMAT}" in 915 human) 916 ${cmd} --output=line \ 917 | sed "s#$(proj_dst "${proj}")#sources#" 918 ;; 919 json) 920 ${cmd} --output=/etc/vale/rdjsonl.tmpl \ 921 | sed "s#$(proj_dst "${proj}")#sources#" 922 ;; 923 *) 924 errr "Invalid output format '${OUTPUT_FORMAT}'" 925 esac 926 927 ;; 928 *) 929 tempfile="$(mktemp -t make-docs.XXX)" 930 cat <<EOF >"${tempfile}" 931 #!/usr/bin/env bash 932 933 tc() { 934 set \${*,,} 935 echo \${*^} 936 } 937 938 for redirect in ${redirects}; do 939 IFS='^' read -r path ver <<<"\${redirect}" 940 echo -e "---\\nredirectURL: \"\${path/\/hugo\/content/}\"\\ntype: redirect\\nversioned: true\\n---\\n" > "\${path/\${ver}/_index.md}" 941 done 942 943 for x in "${url_src_dst_vers}"; do 944 IFS='^' read -r _ _ dst _ <<<"\${x}" 945 946 title="\${dst%/*}" 947 title="\$(tc \${title##*/})" 948 while [[ -n "\${dst}" ]]; do 949 if [[ ! -f "\${dst}/_index.md" ]]; then 950 echo -e "---title: \${title}\\n---\\n\\n# \${title}\\n\\n{{< section >}}" > "\${dst}/_index.md" 951 fi 952 dst="\${dst%/*}" 953 done 954 done 955 956 if [[ -n "${WEBSITE_MOUNTS}" ]]; then 957 unset WEBSITE_SKIP_MOUNTS 958 fi 959 960 ${WEBSITE_EXEC} 961 EOF 962 chmod +x "${tempfile}" 963 volumes="${volumes} --volume=${tempfile}:/entrypoint:z" 964 readonly volumes 965 966 IFS='' read -r cmd <<EOF 967 ${PODMAN} run \ 968 --env=HUGO_REFLINKSERRORLEVEL=${HUGO_REFLINKSERRORLEVEL} \ 969 --init \ 970 --interactive \ 971 --publish=${DOCS_HOST_PORT}:3002 \ 972 --publish=3003:3003 \ 973 --rm \ 974 --tty \ 975 ${volumes} \ 976 ${DOCS_IMAGE} 977 EOF 978 979 if [ -n "${ENTER}" ]; then 980 ${cmd} /bin/bash 981 elif [ -n "${DEBUG}" ]; then 982 await_build http://localhost:3003 & 983 984 debg "${cmd} /entrypoint" 985 ${cmd} /entrypoint 986 else 987 await_build http://localhost:3003 & 988 989 ${cmd} /entrypoint 2>&1\ 990 | sed -u \ 991 -e '/Web Server is available at http:\/\/localhost:3003\/ (bind address 0.0.0.0)/ d' \ 992 -e '/^hugo server/ d' \ 993 -e '/fatal: not a git repository (or any parent up to mount point \/)/ d' \ 994 -e '/Stopping at filesystem boundary (GIT_DISCOVERY_ACROSS_FILESYSTEM not set)./ d' \ 995 -e "/Makefile:[0-9]*: warning: overriding recipe for target 'docs'/ d" \ 996 -e "/docs.mk:[0-9]*: warning: ignoring old recipe for target 'docs'/ d" \ 997 -e '/\/usr\/bin\/make -j 2 proxy hserver-docs HUGO_PORT=3003/ d' \ 998 -e '/website-proxy/ d' \ 999 -e '/rm -rf dist*/ d' \ 1000 -e '/Press Ctrl+C to stop/ d' \ 1001 -e '/make/ d' \ 1002 -e '/WARNING: The manual_mount source directory/ d' \ 1003 -e '/"docs\/_index.md" not found/d' 1004 fi 1005 ;; 1006 esac