| #!/usr/bin/env bash | |
| # SPDX-License-Identifier: Apache-2.0 | |
| # SPDX-FileCopyrightText: See the NOTICE file distributed with this work for additional information regarding copyright ownership | |
| # SPDX-FileContributor: Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements | |
| # Build the documentation for releases in | |
| # 1. docs/source/_static/versions.json (shown in the version picker) | |
| # 2. docs/source/_static/old_versions.json (older releases to keep links working) | |
| # | |
| # The release is checked out into a temporary worktree, writing the result | |
| # to <output>/<version>/. | |
| set -euo pipefail | |
| SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" | |
| DOCS_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)" | |
| REPO_DIR="$(cd "${DOCS_DIR}/.." && pwd)" | |
| OVERLAY_DIR="${SCRIPT_DIR}/release" | |
| MANIFEST="${DOCS_DIR}/source/_static/versions.json" | |
| OLD_MANIFEST="${DOCS_DIR}/source/_static/old_versions.json" | |
| # Where to fetch release tags from (forks usually do not contain release tags) | |
| UPSTREAM_URL="${DATAFUSION_UPSTREAM_URL:-https://github.com/apache/datafusion.git}" | |
| OUTPUT_DIR="${DOCS_DIR}/build/html/versions" | |
| WORK_DIR="" | |
| VERSIONS=() | |
| usage() { | |
| cat <<USAGE | |
| Build the documentation for released DataFusion versions. | |
| Usage: $(basename "$0") [options] [VERSION ...] | |
| Builds the documentation for each VERSION from its git tag. With no VERSION, | |
| builds every release listed in ${MANIFEST#"${REPO_DIR}/"} | |
| or ${OLD_MANIFEST#"${REPO_DIR}/"}. | |
| Options: | |
| -o, --output DIR Write the documentation to DIR/<version>/ | |
| (default: docs/build/html/versions, so that the versions | |
| appear under a site built with docs/build.sh) | |
| -w, --work DIR Check the tags out under DIR/<version> instead of a | |
| temporary directory | |
| -h, --help Show this help message | |
| Environment: | |
| DATAFUSION_UPSTREAM_URL Repository to fetch missing release tags from | |
| (default: ${UPSTREAM_URL}) | |
| Example: preview the site with the 55.0.0 docs under versions/55.0.0/ | |
| cd docs | |
| uv run --package datafusion-docs ./build.sh | |
| scripts/build_versions.sh 55.0.0 | |
| python3 -m http.server --directory build/html 8000 | |
| USAGE | |
| } | |
| while [[ $# -gt 0 ]]; do | |
| case "$1" in | |
| -o|--output) | |
| OUTPUT_DIR="$2" | |
| shift 2 | |
| ;; | |
| -w|--work) | |
| WORK_DIR="$2" | |
| shift 2 | |
| ;; | |
| -h|--help) | |
| usage | |
| exit 0 | |
| ;; | |
| -*) | |
| echo "Unknown option: $1" >&2 | |
| usage >&2 | |
| exit 1 | |
| ;; | |
| *) | |
| VERSIONS+=("$1") | |
| shift | |
| ;; | |
| esac | |
| done | |
| for tool in git uv python3; do | |
| if ! command -v "${tool}" >/dev/null 2>&1; then | |
| echo "${tool} is required." >&2 | |
| exit 1 | |
| fi | |
| done | |
| # Releases listed in the version picker manifest followed by the older | |
| # releases that are published but not in the picker, without duplicates. | |
| list_versions() { | |
| python3 - "${MANIFEST}" "${OLD_MANIFEST}" <<'PY' | |
| import json | |
| import sys | |
| seen = set() | |
| for manifest in sys.argv[1:]: | |
| with open(manifest) as f: | |
| for entry in json.load(f): | |
| version = entry["version"] | |
| if version != "main" and version not in seen: | |
| seen.add(version) | |
| print(version) | |
| PY | |
| } | |
| if [[ ${#VERSIONS[@]} -eq 0 ]]; then | |
| while IFS= read -r version; do | |
| VERSIONS+=("${version}") | |
| done < <(list_versions) | |
| fi | |
| if [[ ${#VERSIONS[@]} -eq 0 ]]; then | |
| echo "No versions to build." >&2 | |
| exit 1 | |
| fi | |
| TEMP_WORK_DIR="" | |
| if [[ -z "${WORK_DIR}" ]]; then | |
| TEMP_WORK_DIR="$(mktemp -d -t datafusion-docs-versions.XXXXXX)" | |
| WORK_DIR="${TEMP_WORK_DIR}" | |
| fi | |
| mkdir -p "${WORK_DIR}" "${OUTPUT_DIR}" | |
| WORK_DIR="$(cd "${WORK_DIR}" && pwd)" | |
| OUTPUT_DIR="$(cd "${OUTPUT_DIR}" && pwd)" | |
| cleanup() { | |
| if [[ -n "${TEMP_WORK_DIR}" ]]; then | |
| for worktree in "${TEMP_WORK_DIR}"/*/; do | |
| [[ -d "${worktree}" ]] || continue | |
| git -C "${REPO_DIR}" worktree remove --force "${worktree}" >/dev/null 2>&1 || true | |
| done | |
| rm -rf "${TEMP_WORK_DIR}" | |
| git -C "${REPO_DIR}" worktree prune | |
| fi | |
| } | |
| trap cleanup EXIT | |
| # Make sure this checkout has the release tag, fetching it from upstream | |
| # otherwise (a shallow CI checkout stays shallow). | |
| fetch_tag() { | |
| local version="$1" | |
| if git -C "${REPO_DIR}" rev-parse -q --verify "refs/tags/${version}^{commit}" >/dev/null; then | |
| return | |
| fi | |
| echo "Fetching tag ${version} from ${UPSTREAM_URL}" | |
| local depth=() | |
| if [[ "$(git -C "${REPO_DIR}" rev-parse --is-shallow-repository)" == "true" ]]; then | |
| depth=(--depth 1) | |
| fi | |
| git -C "${REPO_DIR}" fetch "${depth[@]}" "${UPSTREAM_URL}" "refs/tags/${version}:refs/tags/${version}" | |
| } | |
| build_version() { | |
| local version="$1" | |
| local worktree="${WORK_DIR}/${version}" | |
| local output="${OUTPUT_DIR}/${version}" | |
| echo "==> Building documentation for ${version}" | |
| fetch_tag "${version}" | |
| if [[ -e "${worktree}" ]]; then | |
| git -C "${REPO_DIR}" worktree remove --force "${worktree}" >/dev/null 2>&1 || rm -rf "${worktree}" | |
| fi | |
| git -C "${REPO_DIR}" worktree add --detach "${worktree}" "refs/tags/${version}" | |
| # The workspace dependency graph is generated at build time and embedded in | |
| # the contributor guide (docs/build.sh does the same for the current docs). | |
| if [[ -x "${worktree}/docs/scripts/generate_dependency_graph.sh" ]]; then | |
| "${worktree}/docs/scripts/generate_dependency_graph.sh" | |
| fi | |
| # Sphinx's incremental build state (doctrees, .buildinfo) is not part of the | |
| # published site: keep the doctrees in the worktree, which is removed below. | |
| rm -rf "${output}" | |
| ( | |
| cd "${DOCS_DIR}" | |
| DATAFUSION_DOCS_SOURCE="${worktree}/docs/source" \ | |
| DATAFUSION_DOCS_VERSION="${version}" \ | |
| uv run --package datafusion-docs \ | |
| sphinx-build -b html -W -c "${OVERLAY_DIR}" \ | |
| -d "${worktree}/docs/build/doctrees" \ | |
| "${worktree}/docs/source" "${output}" | |
| ) | |
| rm -f "${output}/.buildinfo" | |
| git -C "${REPO_DIR}" worktree remove --force "${worktree}" | |
| echo "==> Wrote ${output}" | |
| } | |
| for version in "${VERSIONS[@]}"; do | |
| build_version "${version}" | |
| done |