#!/usr/bin/env bash set -euo pipefail # Recorded in $DEST/VERSION only — the archive itself is fetched by the `main` # label, since the archive URL uses a plugin-version coordinate that cannot be # reconstructed from the commit alone. SCHEMA_COMMIT="${1:?usage: regen.sh }" # Transitive deps. Buf does not expose pinned versions for these from the # openstatus/api module, so we track main. The PHP plan ships empty initOnce() # stubs for these; in Python we vendor the real generated modules — they are # pure annotation/descriptor protos with no runtime impact on JSON transport. readonly BUF_VALIDATE_REF="bufbuild/protovalidate" readonly GNOSTIC_REF="gnostic/gnostic" ARCHIVE_BASE="https://buf.build/gen/archive" ROOT="$(cd "$(dirname "$0")/.." && pwd)" DEST="${ROOT}/src/openstatus/_gen" TMP="$(mktemp -d)" trap 'rm -rf "$TMP"' EXIT rm -rf "$DEST" mkdir -p "$DEST" fetch() { # fetch local ref="$1" plugin="$2" version="$3" name="$4" local url="${ARCHIVE_BASE}/${ref}/protocolbuffers/${plugin}/${version}.zip" echo "Fetching ${ref} ${plugin} ${version}..." curl -fsSL -L "$url" -o "${TMP}/${name}-${plugin}.zip" mkdir -p "${TMP}/${name}-${plugin}" unzip -q "${TMP}/${name}-${plugin}.zip" -d "${TMP}/${name}-${plugin}" } fetch "openstatus/api" python main openstatus fetch "openstatus/api" pyi main openstatus fetch "${BUF_VALIDATE_REF}" python main bufvalidate fetch "${BUF_VALIDATE_REF}" pyi main bufvalidate fetch "${GNOSTIC_REF}" python main gnostic fetch "${GNOSTIC_REF}" pyi main gnostic # Merge a top-level package from a buf archive into $DEST. # - archive layout: /_//... # e.g. openstatus-python/api_python/openstatus, bufvalidate-python/protovalidate_python/buf merge() { local archive_dir="$1" pkg_root="$2" local src src="$(find "${TMP}/${archive_dir}" -type d -name "${pkg_root}" -maxdepth 3 | head -1)" if [[ -z "$src" ]]; then echo "ERROR: could not locate '${pkg_root}' tree inside ${archive_dir}" >&2 find "${TMP}/${archive_dir}" -maxdepth 3 -type d >&2 exit 1 fi # tar pipe preserves dir merges (rsync-style) without depending on rsync. ( cd "$(dirname "$src")" && tar cf - "$(basename "$src")" ) | ( cd "$DEST" && tar xf - ) } merge openstatus-python openstatus merge openstatus-pyi openstatus merge bufvalidate-python buf merge bufvalidate-pyi buf merge gnostic-python gnostic merge gnostic-pyi gnostic # The generated *.py and *.pyi files use absolute imports # (`from openstatus...`, `from buf...`, `from gnostic...`). Rewrite them to # resolve under our private `openstatus._gen.*` namespace so the public # `openstatus` package is not polluted and so the buf/gnostic vendored copies # do not collide with any user-installed packages of the same name. find "$DEST" -type f \( -name '*.py' -o -name '*.pyi' \) -print0 \ | xargs -0 sed -i \ -e 's|^from openstatus\.|from openstatus._gen.openstatus.|g' \ -e 's|^from buf\.|from openstatus._gen.buf.|g' \ -e 's|^from gnostic\.|from openstatus._gen.gnostic.|g' \ -e 's|^import openstatus\.|import openstatus._gen.openstatus.|g' \ -e 's|^import buf\.|import openstatus._gen.buf.|g' \ -e 's|^import gnostic\.|import openstatus._gen.gnostic.|g' # Generated trees ship no __init__.py — create empty shims so packages import. find "$DEST" -type d -exec sh -c 'touch "$0/__init__.py"' {} \; echo "${SCHEMA_COMMIT}" > "$DEST/VERSION" echo echo "Done. Generated tree at $DEST" echo "Schema commit recorded at $DEST/VERSION"