diff --git a/.github/scripts/download_packages.sh b/.github/scripts/download_packages.sh
index 9496060..3291c08 100755
--- a/.github/scripts/download_packages.sh
+++ b/.github/scripts/download_packages.sh
@@ -4,11 +4,11 @@ set -e
REPO="documentdb/documentdb"
OUT_DIR="out"
DOCUMENTDB_VERSION="${DOCUMENTDB_VERSION:-latest}"
-MULTI_VERSION="${MULTI_VERSION:-true}"
SUITE="${SUITE:-stable}"
COMPONENTS="${COMPONENTS:-main}"
ORIGIN="${ORIGIN:-DocumentDB}"
DESCRIPTION="${DESCRIPTION:-DocumentDB APT and YUM Repository}"
+APT_METADATA_COMPONENTS="main deb11 deb12 deb13 ubuntu22 ubuntu24"
sign_deb_package() {
local package_file="$1"
@@ -76,24 +76,11 @@ echo "Downloading packages from $REPO releases"
# ---------------------------------------------------------------------------
# Release selection
#
-# The primary release supplies the site's release-info.json and is the version
-# users are told about. But a release only ships the distributions that were
-# in its own build matrix: v0.116-0, for example, ships Tier-1 (ubuntu24 +
-# rhel9) only, while v0.114-0 shipped seven distributions. Rebuilding the
-# repository from the primary release alone would therefore DELETE the
-# deb11/deb12/deb13/ubuntu22 components and the whole rhel8 repository from
-# documentdb.io, and every host already pointed at one of them would start
-# failing `apt update` with "Component 'ubuntu22' is not defined". That is a
-# client-visible outage, not a cosmetic regression.
-#
-# So the repository is built additively: the primary release fills every
-# distribution it ships, then progressively older releases are consulted ONLY
-# to fill distributions still missing. A distribution is claimed by the newest
-# release that ships it and is never overwritten by an older one. Once a
-# release ships every distribution again, the older ones stop contributing
-# by themselves - no cleanup required.
+# The selected release is the package repository's single source of truth.
+# Older releases must not fill gaps: those combinations are on-demand builds,
+# not assets of the current official release, and mixing them into the pool
+# makes stale versions look supported.
# ---------------------------------------------------------------------------
-MAX_RELEASES="${MAX_RELEASES:-8}"
RELEASES_JSON=$(mktemp)
if ! curl -fqs "https://api.github.com/repos/${REPO}/releases?per_page=100" > "$RELEASES_JSON"; then
@@ -101,9 +88,8 @@ if ! curl -fqs "https://api.github.com/repos/${REPO}/releases?per_page=100" > "$
exit 1
fi
-# Ordered list of tags to consider, newest first. Drafts and prereleases are
-# skipped: they are not what a repository-backed `apt install` should serve.
-TAG_LIST=$(DOCUMENTDB_VERSION="$DOCUMENTDB_VERSION" python3 - "$RELEASES_JSON" <<'PY'
+# Select exactly one published release. Drafts and prereleases are skipped.
+SELECTED_TAG=$(DOCUMENTDB_VERSION="$DOCUMENTDB_VERSION" python3 - "$RELEASES_JSON" <<'PY'
import json, os, sys
releases = json.load(open(sys.argv[1]))
@@ -113,26 +99,17 @@ if not published:
requested = os.environ.get("DOCUMENTDB_VERSION", "latest")
if requested != "latest":
- # The API returns releases newest-first.
- index = next((i for i, r in enumerate(published)
- if r["tag_name"] == requested), None)
- if index is None:
+ selected = next((r for r in published if r["tag_name"] == requested), None)
+ if selected is None:
sys.exit(f"Error: Version {requested} not found in releases")
- # A pin means "serve this version". Only the pinned release and OLDER ones
- # may contribute: pulling gap-fillers from NEWER releases would defeat the
- # pin, and worse, it would mix releases that depend on each other. Pinning
- # to a release that predates the multi-package layout would otherwise add a
- # newer `documentdb` meta package whose `documentdb-N (>= X)` dependency the
- # pinned extension cannot satisfy - an unsatisfiable repository.
- ordered = published[index:]
else:
- ordered = published
+ selected = published[0]
-print("\n".join(r["tag_name"] for r in ordered))
+print(selected["tag_name"])
PY
)
-PRIMARY_TAG=$(printf '%s\n' "$TAG_LIST" | head -n 1)
+PRIMARY_TAG="$SELECTED_TAG"
echo "Primary release: $PRIMARY_TAG"
# Packages already placed, keyed by "pool|name|arch". A newer release always
@@ -140,6 +117,9 @@ echo "Primary release: $PRIMARY_TAG"
# provide at all. That is what keeps `postgresql-16-documentdb` alive on
# ubuntu24/rhel9 after v0.116-0 narrowed Tier 1 to PostgreSQL 17/18, instead of
# silently deleting a package the install docs still tell people to use.
+# The paragraph above describes the removed gap-fill implementation. The
+# current implementation accepts assets only from PRIMARY_TAG and preserves
+# retired URLs with empty metadata rather than stale packages.
SEEN_FILE=$(mktemp)
is_claimed() { case " $1 " in *" $2 "*) return 0 ;; *) return 1 ;; esac; }
@@ -223,13 +203,11 @@ rpm_pool_for() {
mkdir -p out/packages
-for tag in $TAG_LIST; do
- MAX_RELEASES=$((MAX_RELEASES - 1))
- [ "$MAX_RELEASES" -lt 0 ] && break
+for tag in "$PRIMARY_TAG"; do
if ! release=$(curl -fqs "https://api.github.com/repos/${REPO}/releases/tags/$tag"); then
- echo "::warning::Could not fetch release $tag, skipping"
- continue
+ echo "::error::Could not fetch selected release $tag"
+ exit 1
fi
ASSETS_FILE=$(mktemp)
@@ -263,7 +241,10 @@ for asset in data.get('assets', []):
comp=$(deb_component_for "$filename")
[ -z "$comp" ] && continue
claim_package "$comp" "$filename" || continue
- wget -q -P out/packages "$download_url" || { echo "::warning::download failed: $filename"; continue; }
+ wget -q -P out/packages "$download_url" || {
+ echo "::error::Download failed: $filename"
+ exit 1
+ }
GOT_DEB=1
pool=$(deb_pool_for "$comp")
mkdir -p "$pool"
@@ -296,7 +277,10 @@ for asset in data.get('assets', []):
*) continue ;;
esac
if [ "$downloaded" -eq 0 ]; then
- wget -q -P out/packages "$download_url" || { echo "::warning::download failed: $filename"; break; }
+ wget -q -P out/packages "$download_url" || {
+ echo "::error::Download failed: $filename"
+ exit 1
+ }
downloaded=1
GOT_RPM=1
fi
@@ -309,7 +293,12 @@ for asset in data.get('assets', []):
*)
# Non-package assets (SHA256SUMS, manifest.txt, ...) are mirrored only
# for the primary release, which is what the site links to.
- [ "$tag" = "$PRIMARY_TAG" ] && wget -q -P out/packages "$download_url" ;;
+ if [ "$tag" = "$PRIMARY_TAG" ]; then
+ wget -q -P out/packages "$download_url" || {
+ echo "::error::Download failed: $filename"
+ exit 1
+ }
+ fi ;;
esac
done < "$ASSETS_FILE"
@@ -353,7 +342,7 @@ for pool in "$RPM_POOL_RHEL8" "$RPM_POOL_RHEL9"; do
done
if [ "$GOT_DEB" = "1" ]; then
- echo "Building APT repository with multiple distribution components..."
+ echo "Building APT repository with active and retired compatibility components..."
pushd out/deb >/dev/null
if [ -d "pool/ubuntu22" ] && [ "$(ls -A pool/ubuntu22/*.deb 2>/dev/null)" ]; then
@@ -472,25 +461,25 @@ if [ "$GOT_DEB" = "1" ]; then
dpkg-scanpackages --arch arm64 pool/ubuntu24/ > "${DEB_DISTS_UBUNTU24_ARM64}/Packages"
gzip -k -f "${DEB_DISTS_UBUNTU24_ARM64}/Packages"
fi
+
+ # Keep retired component URLs valid without retaining packages from older
+ # releases. Existing apt sources can refresh cleanly, but package lookup
+ # returns no stale binaries.
+ for component in $APT_METADATA_COMPONENTS; do
+ for arch in amd64 arm64; do
+ metadata_dir="${DEB_DISTS}/${component}/binary-${arch}"
+ packages_file="${metadata_dir}/Packages"
+ mkdir -p "$metadata_dir"
+ if [ ! -f "$packages_file" ]; then
+ : > "$packages_file"
+ gzip -k -f "$packages_file"
+ fi
+ done
+ done
pushd "${DEB_DISTS}" >/dev/null
echo "Creating Release file"
- # Determine which components we actually have
- AVAILABLE_COMPONENTS=""
- [ -d "${COMPONENTS}/binary-amd64" ] && AVAILABLE_COMPONENTS="${AVAILABLE_COMPONENTS} ${COMPONENTS}"
- [ -d "deb11/binary-amd64" ] && AVAILABLE_COMPONENTS="${AVAILABLE_COMPONENTS} deb11"
- [ -d "deb12/binary-amd64" ] && AVAILABLE_COMPONENTS="${AVAILABLE_COMPONENTS} deb12"
- [ -d "deb13/binary-amd64" ] && AVAILABLE_COMPONENTS="${AVAILABLE_COMPONENTS} deb13"
- [ -d "ubuntu22/binary-amd64" ] && AVAILABLE_COMPONENTS="${AVAILABLE_COMPONENTS} ubuntu22"
- [ -d "ubuntu24/binary-amd64" ] && AVAILABLE_COMPONENTS="${AVAILABLE_COMPONENTS} ubuntu24"
- AVAILABLE_COMPONENTS=$(echo $AVAILABLE_COMPONENTS | sed 's/^ *//')
-
- # Determine available architectures
- AVAILABLE_ARCHITECTURES=""
- [ -d "${COMPONENTS}/binary-amd64" ] || [ -d "deb11/binary-amd64" ] || [ -d "deb12/binary-amd64" ] || [ -d "deb13/binary-amd64" ] || [ -d "ubuntu22/binary-amd64" ] || [ -d "ubuntu24/binary-amd64" ] && AVAILABLE_ARCHITECTURES="${AVAILABLE_ARCHITECTURES} amd64"
- [ -d "${COMPONENTS}/binary-arm64" ] || [ -d "deb11/binary-arm64" ] || [ -d "deb12/binary-arm64" ] || [ -d "deb13/binary-arm64" ] || [ -d "ubuntu22/binary-arm64" ] || [ -d "ubuntu24/binary-arm64" ] && AVAILABLE_ARCHITECTURES="${AVAILABLE_ARCHITECTURES} arm64"
- AVAILABLE_ARCHITECTURES=$(echo $AVAILABLE_ARCHITECTURES | sed 's/^ *//')
{
echo "Origin: ${ORIGIN}"
@@ -498,9 +487,9 @@ if [ "$GOT_DEB" = "1" ]; then
echo "Suite: ${SUITE}"
echo "Codename: ${SUITE}"
echo "Version: 1.0"
- echo "Architectures: ${AVAILABLE_ARCHITECTURES}"
- echo "Components: ${AVAILABLE_COMPONENTS}"
- echo "Description: ${DESCRIPTION} - Multiple distributions supported"
+ echo "Architectures: amd64 arm64"
+ echo "Components: ${APT_METADATA_COMPONENTS}"
+ echo "Description: ${DESCRIPTION}"
echo "Date: $(date -Ru)"
generate_hashes MD5Sum md5sum
generate_hashes SHA1 sha1sum
@@ -526,7 +515,7 @@ if [ "$GOT_DEB" = "1" ]; then
popd >/dev/null
- echo "APT repository built successfully with multiple distribution support"
+ echo "APT repository built successfully"
fi
if [ "$GOT_RPM" = "1" ]; then
@@ -544,52 +533,48 @@ if [ "$GOT_RPM" = "1" ]; then
fi
for POOL in "$RHEL8_POOL" "$RHEL9_POOL"; do
- if [ -d "$POOL" ] && [ "$(find "$POOL" -name "*.rpm" -type f | wc -l)" -gt 0 ]; then
- echo "Processing YUM repository: $POOL"
- pushd "$POOL" >/dev/null
-
- if [ -n "$GPG_FINGERPRINT" ]; then
- for rpm_file in *.rpm; do
- rpm --define "%_signature gpg" --define "%_gpg_name ${GPG_FINGERPRINT}" --addsign "$rpm_file" 2>/dev/null || true
- done
- fi
-
- echo "Running createrepo_c in $(pwd)"
- if createrepo_c .; then
- echo "Repository metadata created successfully"
- ls -la repodata/ 2>/dev/null || echo "No repodata directory found"
- else
- echo "ERROR: createrepo_c failed for $POOL"
- fi
-
- if [ -n "$GPG_FINGERPRINT" ] && [ -f repodata/repomd.xml ]; then
- gpg --default-key "$GPG_FINGERPRINT" --detach-sign --armor repodata/repomd.xml 2>/dev/null || true
- fi
-
- popd >/dev/null
- else
- echo "Skipping $POOL: directory not found or no RPM files"
+ mkdir -p "$POOL"
+ echo "Processing YUM repository: $POOL"
+ pushd "$POOL" >/dev/null
+
+ if [ -n "$GPG_FINGERPRINT" ]; then
+ for rpm_file in *.rpm; do
+ [ -f "$rpm_file" ] || continue
+ rpm --define "%_signature gpg" --define "%_gpg_name ${GPG_FINGERPRINT}" --addsign "$rpm_file"
+ signature=$(rpm -qp --qf '%{RSAHEADER:pgpsig}' "$rpm_file" 2>/dev/null)
+ if [ -z "$signature" ] || [ "$signature" = "(none)" ]; then
+ echo "::error::$rpm_file was not signed"
+ exit 1
+ fi
+ done
fi
+
+ echo "Running createrepo_c in $(pwd)"
+ createrepo_c .
+
+ if [ -n "$GPG_FINGERPRINT" ]; then
+ gpg --batch --yes --default-key "$GPG_FINGERPRINT" \
+ --detach-sign --armor repodata/repomd.xml
+ fi
+
+ popd >/dev/null
done
- # Create main repository for backward compatibility
- if [ -d "$RHEL8_POOL" ] && [ "$(find "$RHEL8_POOL" -name "*.rpm" -type f | wc -l)" -gt 0 ]; then
- echo "Creating main YUM repository"
- mkdir -p "$MAIN_POOL"
+ # Keep the legacy main URL valid. It mirrors RHEL 8 only when the selected
+ # release actually contains RHEL 8 packages; otherwise it is an empty
+ # compatibility repository.
+ echo "Creating main YUM compatibility repository"
+ mkdir -p "$MAIN_POOL"
+ if [ "$(find "$RHEL8_POOL" -name "*.rpm" -type f | wc -l)" -gt 0 ]; then
cp "$RHEL8_POOL"/*.rpm "$MAIN_POOL"/ 2>/dev/null || true
- pushd "$MAIN_POOL" >/dev/null
- echo "Running createrepo_c for main repository in $(pwd)"
- if createrepo_c .; then
- echo "Main repository metadata created successfully"
- ls -la repodata/ 2>/dev/null || echo "No repodata directory found"
- else
- echo "ERROR: createrepo_c failed for main repository"
- fi
- if [ -n "$GPG_FINGERPRINT" ] && [ -f repodata/repomd.xml ]; then
- gpg --default-key "$GPG_FINGERPRINT" --detach-sign --armor repodata/repomd.xml 2>/dev/null || true
- fi
- popd >/dev/null
fi
+ pushd "$MAIN_POOL" >/dev/null
+ createrepo_c .
+ if [ -n "$GPG_FINGERPRINT" ]; then
+ gpg --batch --yes --default-key "$GPG_FINGERPRINT" \
+ --detach-sign --armor repodata/repomd.xml
+ fi
+ popd >/dev/null
echo "YUM repositories built successfully"
fi
@@ -598,6 +583,7 @@ fi
echo "Package repository setup complete!"
echo ""
echo "Repository URLs:"
-echo " APT: https://documentdb.io/deb stable main"
-echo " YUM: https://documentdb.io/rpm/rhel8 (or /rhel9, /main)"
+echo " APT: https://documentdb.io/deb stable ubuntu24"
+echo " YUM: https://documentdb.io/rpm/rhel9"
+echo " Retired URLs retain empty metadata for package-manager compatibility."
echo " Browse: https://documentdb.io/packages/"
diff --git a/.github/scripts/smoke_test_package_repository.sh b/.github/scripts/smoke_test_package_repository.sh
new file mode 100644
index 0000000..2dc6cbc
--- /dev/null
+++ b/.github/scripts/smoke_test_package_repository.sh
@@ -0,0 +1,150 @@
+#!/bin/bash
+set -euo pipefail
+
+SIGN="${SIGN:-false}"
+PORT="${PACKAGE_REPOSITORY_PORT:-8099}"
+NETWORK="documentdb-package-test-$$"
+SERVER_NAME="documentdb-package-repo-$$"
+
+if ! ls out/deb/pool/ubuntu24/documentdb_*_all.deb >/dev/null 2>&1; then
+ echo "::error::out/deb/pool/ubuntu24 has no documentdb meta package."
+ exit 1
+fi
+if ! ls out/rpm/rhel9/documentdb-*.noarch.rpm >/dev/null 2>&1; then
+ echo "::error::out/rpm/rhel9 has no documentdb meta package."
+ exit 1
+fi
+
+cleanup() {
+ docker rm -f "$SERVER_NAME" >/dev/null 2>&1 || true
+ docker network rm "$NETWORK" >/dev/null 2>&1 || true
+}
+trap cleanup EXIT
+
+docker network create "$NETWORK" >/dev/null
+docker run -d --rm \
+ --name "$SERVER_NAME" \
+ --network "$NETWORK" \
+ -v "$PWD/out:/srv:ro" \
+ python:3.13-alpine \
+ python -m http.server "$PORT" --directory /srv >/dev/null
+
+for _ in $(seq 1 30); do
+ if docker exec "$SERVER_NAME" \
+ wget -q -O /dev/null "http://127.0.0.1:${PORT}/deb/dists/stable/Release"; then
+ break
+ fi
+ sleep 1
+done
+docker exec "$SERVER_NAME" \
+ wget -q -O /dev/null "http://127.0.0.1:${PORT}/rpm/rhel8/repodata/repomd.xml"
+docker exec "$SERVER_NAME" \
+ wget -q -O /dev/null "http://127.0.0.1:${PORT}/rpm/main/repodata/repomd.xml"
+
+echo "::group::APT dependency resolution"
+docker run --rm --network "$NETWORK" \
+ -e DOCUMENTDB_REPOSITORY_HOST="$SERVER_NAME" \
+ -e DOCUMENTDB_REPOSITORY_PORT="$PORT" \
+ -e DOCUMENTDB_REPOSITORY_SIGNED="$SIGN" \
+ ubuntu:24.04 bash -c '
+ set -euo pipefail
+ export DEBIAN_FRONTEND=noninteractive
+ apt-get update -qq >/dev/null
+ apt-get install -y -qq curl ca-certificates gnupg >/dev/null
+ curl -fsSL https://www.postgresql.org/media/keys/ACCC4CF8.asc \
+ | gpg --dearmor -o /usr/share/keyrings/postgresql.gpg
+ echo "deb [signed-by=/usr/share/keyrings/postgresql.gpg] https://apt.postgresql.org/pub/repos/apt noble-pgdg main" \
+ > /etc/apt/sources.list.d/pgdg.list
+
+ if [ "$DOCUMENTDB_REPOSITORY_SIGNED" = true ]; then
+ curl -fsSL "http://${DOCUMENTDB_REPOSITORY_HOST}:${DOCUMENTDB_REPOSITORY_PORT}/documentdb-archive-keyring.gpg" \
+ | gpg --dearmor -o /usr/share/keyrings/documentdb.gpg
+ echo "deb [signed-by=/usr/share/keyrings/documentdb.gpg] http://${DOCUMENTDB_REPOSITORY_HOST}:${DOCUMENTDB_REPOSITORY_PORT}/deb stable ubuntu24" \
+ > /etc/apt/sources.list.d/documentdb.list
+ else
+ echo "deb [trusted=yes] http://${DOCUMENTDB_REPOSITORY_HOST}:${DOCUMENTDB_REPOSITORY_PORT}/deb stable ubuntu24" \
+ > /etc/apt/sources.list.d/documentdb.list
+ fi
+
+ apt-get update -qq
+ for major in 17 18; do
+ apt-get install -s "documentdb-${major}" > "/tmp/apt-${major}.txt"
+ for pkg in "documentdb-${major}" documentdb-common documentdb-gateway documentdb-postgresql-tools; do
+ grep -q "Inst ${pkg} " "/tmp/apt-${major}.txt" || {
+ echo "APT PG${major} plan is missing ${pkg}"
+ cat "/tmp/apt-${major}.txt"
+ exit 1
+ }
+ done
+ grep -q "Inst postgresql-${major}-documentdb " "/tmp/apt-${major}.txt" || {
+ echo "APT PG${major} plan is missing its extension package"
+ cat "/tmp/apt-${major}.txt"
+ exit 1
+ }
+ done
+
+ if [ "$DOCUMENTDB_REPOSITORY_SIGNED" = true ]; then
+ echo "deb [signed-by=/usr/share/keyrings/documentdb.gpg] http://${DOCUMENTDB_REPOSITORY_HOST}:${DOCUMENTDB_REPOSITORY_PORT}/deb stable deb13" \
+ > /etc/apt/sources.list.d/documentdb.list
+ else
+ echo "deb [trusted=yes] http://${DOCUMENTDB_REPOSITORY_HOST}:${DOCUMENTDB_REPOSITORY_PORT}/deb stable deb13" \
+ > /etc/apt/sources.list.d/documentdb.list
+ fi
+ apt-get update -qq
+ echo "APT PG17/PG18 resolution and retired-component refresh succeeded."
+ '
+echo "::endgroup::"
+
+echo "::group::DNF dependency resolution"
+docker run --rm --network "$NETWORK" \
+ -e DOCUMENTDB_REPOSITORY_HOST="$SERVER_NAME" \
+ -e DOCUMENTDB_REPOSITORY_PORT="$PORT" \
+ -e DOCUMENTDB_REPOSITORY_SIGNED="$SIGN" \
+ rockylinux/rockylinux:9 bash -c '
+ set -euo pipefail
+ dnf install -y -q dnf-plugins-core >/dev/null 2>&1
+ dnf install -y -q https://download.postgresql.org/pub/repos/yum/reporpms/EL-9-x86_64/pgdg-redhat-repo-latest.noarch.rpm >/dev/null 2>&1
+ dnf install -y -q epel-release >/dev/null 2>&1
+ dnf config-manager --set-enabled crb
+ dnf -qy module disable postgresql >/dev/null 2>&1
+
+ {
+ echo "[documentdb]"
+ echo "name=DocumentDB"
+ echo "baseurl=http://${DOCUMENTDB_REPOSITORY_HOST}:${DOCUMENTDB_REPOSITORY_PORT}/rpm/rhel9"
+ echo "enabled=1"
+ if [ "$DOCUMENTDB_REPOSITORY_SIGNED" = true ]; then
+ echo "gpgcheck=1"
+ echo "gpgkey=http://${DOCUMENTDB_REPOSITORY_HOST}:${DOCUMENTDB_REPOSITORY_PORT}/documentdb-archive-keyring.gpg"
+ else
+ echo "gpgcheck=0"
+ fi
+ } > /etc/yum.repos.d/documentdb.repo
+
+ for major in 17 18; do
+ dnf install --assumeno "documentdb-${major}" > "/tmp/dnf-${major}.txt" 2>&1 || true
+ if grep -qE "^Error|nothing provides|Problem:" "/tmp/dnf-${major}.txt"; then
+ echo "DNF could not resolve documentdb-${major}:"
+ cat "/tmp/dnf-${major}.txt"
+ exit 1
+ fi
+ for pkg in "documentdb-${major}" documentdb-common documentdb-gateway documentdb-postgresql-tools "postgresql${major}-documentdb"; do
+ grep -q "$pkg" "/tmp/dnf-${major}.txt" || {
+ echo "DNF PG${major} plan is missing ${pkg}"
+ cat "/tmp/dnf-${major}.txt"
+ exit 1
+ }
+ done
+ done
+
+ {
+ echo "[documentdb-retired]"
+ echo "name=DocumentDB retired compatibility endpoint"
+ echo "baseurl=http://${DOCUMENTDB_REPOSITORY_HOST}:${DOCUMENTDB_REPOSITORY_PORT}/rpm/rhel8"
+ echo "enabled=1"
+ echo "gpgcheck=0"
+ } > /etc/yum.repos.d/documentdb-retired.repo
+ dnf -q makecache --disablerepo="*" --enablerepo=documentdb-retired
+ echo "DNF PG17/PG18 resolution and retired-repository refresh succeeded."
+ '
+echo "::endgroup::"
diff --git a/.github/scripts/verify_package_inventory.py b/.github/scripts/verify_package_inventory.py
new file mode 100644
index 0000000..b9ad1ef
--- /dev/null
+++ b/.github/scripts/verify_package_inventory.py
@@ -0,0 +1,185 @@
+#!/usr/bin/env python3
+"""Verify that the published pools contain only the selected release assets."""
+
+import json
+import re
+from pathlib import Path
+
+
+ROOT = Path("out")
+RELEASE_INFO = ROOT / "packages" / "release-info.json"
+
+DEB_PREFIXES = {
+ "deb11-": "deb11",
+ "deb12-": "deb12",
+ "deb13-": "deb13",
+ "ubuntu22.04-": "ubuntu22",
+ "ubuntu24.04-": "ubuntu24",
+}
+RPM_POOLS = ("rhel8", "rhel9")
+APT_METADATA_COMPONENTS = {"main", "deb11", "deb12", "deb13", "ubuntu22", "ubuntu24"}
+RPM_METADATA_POOLS = {"main", "rhel8", "rhel9"}
+
+
+def rpm_pool(name: str) -> str | None:
+ for pool in RPM_POOLS:
+ if name.startswith(f"{pool}-") or f".el{pool[-1]}." in name:
+ return pool
+ return None
+
+
+def fail(message: str) -> None:
+ raise SystemExit(message)
+
+
+if not RELEASE_INFO.exists():
+ fail(f"Missing {RELEASE_INFO}")
+
+release = json.loads(RELEASE_INFO.read_text())
+asset_names = {
+ asset["name"]
+ for asset in release.get("assets", [])
+ if isinstance(asset, dict) and isinstance(asset.get("name"), str)
+}
+package_assets = {
+ name
+ for name in asset_names
+ if (name.endswith(".deb") and "dbgsym" not in name)
+ or (
+ name.endswith(".rpm")
+ and "debuginfo" not in name
+ and "debugsource" not in name
+ )
+}
+
+downloaded = {
+ path.name
+ for path in (ROOT / "packages").iterdir()
+ if path.suffix in {".deb", ".rpm"}
+}
+if downloaded != package_assets:
+ fail(
+ "Direct package mirror does not match release assets.\n"
+ f"Missing: {sorted(package_assets - downloaded)}\n"
+ f"Unexpected: {sorted(downloaded - package_assets)}"
+ )
+
+expected_deb: dict[str, set[str]] = {}
+for name in sorted(package_assets):
+ if not name.endswith(".deb"):
+ continue
+ match = next(
+ ((prefix, component) for prefix, component in DEB_PREFIXES.items() if name.startswith(prefix)),
+ None,
+ )
+ if match is None:
+ fail(f"Unrecognized DEB release asset: {name}")
+ prefix, component = match
+ expected_deb.setdefault(component, set()).add(name.removeprefix(prefix))
+
+deb_pool_root = ROOT / "deb" / "pool"
+actual_deb_components = {
+ path.name for path in deb_pool_root.iterdir() if path.is_dir()
+} if deb_pool_root.exists() else set()
+if actual_deb_components != set(expected_deb):
+ fail(
+ "APT components do not match the selected release.\n"
+ f"Expected: {sorted(expected_deb)}\n"
+ f"Actual: {sorted(actual_deb_components)}"
+ )
+
+for component, expected in expected_deb.items():
+ actual = {path.name for path in (deb_pool_root / component).glob("*.deb")}
+ if actual != expected:
+ fail(
+ f"APT pool {component} does not match the selected release.\n"
+ f"Missing: {sorted(expected - actual)}\n"
+ f"Unexpected: {sorted(actual - expected)}"
+ )
+
+release_file = ROOT / "deb" / "dists" / "stable" / "Release"
+if expected_deb:
+ if not release_file.exists():
+ fail(f"Missing {release_file}")
+ match = re.search(r"^Components:\s*(.+)$", release_file.read_text(), re.MULTILINE)
+ components = set(match.group(1).split()) if match else set()
+ if components != APT_METADATA_COMPONENTS:
+ fail(
+ "APT Release components do not include the compatibility metadata set.\n"
+ f"Expected: {sorted(APT_METADATA_COMPONENTS)}\n"
+ f"Actual: {sorted(components)}"
+ )
+
+ for component in APT_METADATA_COMPONENTS:
+ expected_packages = expected_deb.get(component, set())
+ if component == "main":
+ expected_packages = expected_deb.get("ubuntu22", set())
+
+ for arch in ("amd64", "arm64"):
+ packages = ROOT / "deb" / "dists" / "stable" / component / f"binary-{arch}" / "Packages"
+ packages_gz = packages.with_name("Packages.gz")
+ if not packages.exists() or not packages_gz.exists():
+ fail(f"Missing APT metadata for {component}/{arch}")
+
+ listed = set(re.findall(r"^Filename:\s+.*/([^/\s]+\.deb)$", packages.read_text(), re.MULTILINE))
+ expected_for_arch = {
+ name
+ for name in expected_packages
+ if name.endswith(f"_{arch}.deb") or name.endswith("_all.deb")
+ }
+ if listed != expected_for_arch:
+ fail(
+ f"APT metadata {component}/{arch} does not match the selected release.\n"
+ f"Expected: {sorted(expected_for_arch)}\n"
+ f"Actual: {sorted(listed)}"
+ )
+
+rpm_assets = {name for name in package_assets if name.endswith(".rpm")}
+explicit_rpm_pools = {pool for name in rpm_assets if (pool := rpm_pool(name))}
+expected_rpm: dict[str, set[str]] = {pool: set() for pool in explicit_rpm_pools}
+
+for name in rpm_assets:
+ pool = rpm_pool(name)
+ if pool:
+ expected_rpm[pool].add(re.sub(r"^rhel[89]-", "", name))
+ elif name.endswith(".noarch.rpm"):
+ for target in explicit_rpm_pools:
+ expected_rpm[target].add(name)
+ else:
+ fail(f"Unrecognized RPM release asset: {name}")
+
+rpm_root = ROOT / "rpm"
+actual_rpm_pools = {
+ path.name
+ for path in rpm_root.iterdir()
+ if path.is_dir()
+} if rpm_root.exists() else set()
+if actual_rpm_pools != RPM_METADATA_POOLS:
+ fail(
+ "RPM repositories do not include the compatibility metadata set.\n"
+ f"Expected: {sorted(RPM_METADATA_POOLS)}\n"
+ f"Actual: {sorted(actual_rpm_pools)}"
+ )
+
+for pool in RPM_POOLS:
+ expected = expected_rpm.get(pool, set())
+ actual = {path.name for path in (rpm_root / pool).glob("*.rpm")}
+ if actual != expected:
+ fail(
+ f"RPM pool {pool} does not match the selected release.\n"
+ f"Missing: {sorted(expected - actual)}\n"
+ f"Unexpected: {sorted(actual - expected)}"
+ )
+ if not (rpm_root / pool / "repodata" / "repomd.xml").exists():
+ fail(f"Missing RPM metadata for {pool}")
+
+actual_main = {path.name for path in (rpm_root / "main").glob("*.rpm")}
+if actual_main != expected_rpm.get("rhel8", set()):
+ fail("Legacy RPM main pool does not match the selected release's RHEL 8 pool.")
+if not (rpm_root / "main" / "repodata" / "repomd.xml").exists():
+ fail("Missing RPM metadata for main")
+
+print(
+ f"Package pools exactly match {release.get('tag_name', 'the selected release')}: "
+ f"{len(package_assets)} release assets."
+)
diff --git a/.github/scripts/verify_package_signatures.sh b/.github/scripts/verify_package_signatures.sh
new file mode 100644
index 0000000..196cda7
--- /dev/null
+++ b/.github/scripts/verify_package_signatures.sh
@@ -0,0 +1,53 @@
+#!/bin/bash
+set -euo pipefail
+
+if [ "${SIGN:-false}" != "true" ]; then
+ echo "Signing is disabled; skipping signature verification."
+ exit 0
+fi
+
+for artifact in \
+ out/documentdb-archive-keyring.gpg \
+ out/deb/dists/stable/InRelease \
+ out/deb/dists/stable/Release.gpg; do
+ if [ ! -s "$artifact" ]; then
+ echo "::error::Signing is enabled but $artifact is missing or empty."
+ exit 1
+ fi
+done
+
+GNUPGHOME=$(mktemp -d)
+RPM_DB=$(mktemp -d)
+export GNUPGHOME
+trap 'rm -rf "$GNUPGHOME" "$RPM_DB"' EXIT
+
+gpg --batch --import out/documentdb-archive-keyring.gpg
+gpg --batch --verify out/deb/dists/stable/InRelease
+gpg --batch --verify \
+ out/deb/dists/stable/Release.gpg \
+ out/deb/dists/stable/Release
+
+rpm --dbpath "$RPM_DB" --initdb
+rpm --dbpath "$RPM_DB" --import out/documentdb-archive-keyring.gpg
+
+verified_rpms=0
+while IFS= read -r rpm_file; do
+ rpmkeys --dbpath "$RPM_DB" --checksig --verbose "$rpm_file"
+ verified_rpms=$((verified_rpms + 1))
+done < <(find out/rpm/rhel8 out/rpm/rhel9 -type f -name '*.rpm' | sort)
+
+if [ "$verified_rpms" -eq 0 ]; then
+ echo "::error::Signing is enabled but no RPM packages were found to verify."
+ exit 1
+fi
+
+while IFS= read -r repomd; do
+ signature="${repomd}.asc"
+ if [ ! -s "$signature" ]; then
+ echo "::error::Signing is enabled but $signature is missing or empty."
+ exit 1
+ fi
+ gpg --batch --verify "$signature" "$repomd"
+done < <(find out/rpm -path '*/repodata/repomd.xml' -type f | sort)
+
+echo "Verified APT metadata, $verified_rpms RPM packages, and all RPM repository metadata."
diff --git a/.github/workflows/continuous-deployment.yml b/.github/workflows/continuous-deployment.yml
index 4032dd1..c9c2f71 100644
--- a/.github/workflows/continuous-deployment.yml
+++ b/.github/workflows/continuous-deployment.yml
@@ -104,10 +104,8 @@ jobs:
KEY_ID: ${{ steps.import_gpg.outputs.keyid }}
KEY_NAME: ${{ steps.import_gpg.outputs.name }}
KEY_EMAIL: ${{ steps.import_gpg.outputs.email }}
- # Configure which DocumentDB release to mirror. Both can be
- # overridden by repository variables.
+ # Configure which DocumentDB release to mirror.
DOCUMENTDB_VERSION: ${{ vars.DOCUMENTDB_VERSION || 'latest' }}
- MULTI_VERSION: ${{ vars.MULTI_VERSION || 'true' }}
run: |
set -euo pipefail
if [ "$SIGN" = 'true' ]; then
@@ -124,9 +122,7 @@ jobs:
echo "No GPG key configured - packages will not be signed."
echo "To enable signing, add GPG_PRIVATE_KEY to the repository secrets."
fi
-
echo "DOCUMENTDB_VERSION=$DOCUMENTDB_VERSION" >> "$GITHUB_ENV"
- echo "MULTI_VERSION=$MULTI_VERSION" >> "$GITHUB_ENV"
- name: Setup Node.js
uses: actions/setup-node@v7
with:
@@ -189,6 +185,7 @@ jobs:
SIGN: ${{ steps.features.outputs.sign }}
run: |
set -euo pipefail
+ python3 .github/scripts/verify_package_inventory.py
python3 - <<'PY'
import json
import os
@@ -245,12 +242,11 @@ jobs:
f"Signing was enabled but {artifact} was not produced"
)
- # RPM metadata signing is best-effort inside the download script,
- # so surface it as a warning instead of failing the deployment.
for repomd in sorted(Path("out/rpm").glob("*/repodata/repomd.xml")):
if not Path(f"{repomd}.asc").exists():
- print(f"::warning::{repomd} was not signed")
+ raise SystemExit(f"Signing is enabled but {repomd}.asc was not produced")
PY
+ bash .github/scripts/verify_package_signatures.sh
# The metadata checks above prove the repository FILES exist. They do not
# prove the repository is INSTALLABLE, and that gap has already shipped a
# broken repository once: when v0.116-0 introduced the multi-package
@@ -271,6 +267,8 @@ jobs:
run: node .github/scripts/check_release_drift.js
- name: Smoke test the generated repository (dependency resolution)
if: steps.features.outputs.packages == 'true'
+ env:
+ SIGN: ${{ steps.features.outputs.sign }}
run: |
set -euo pipefail
@@ -327,15 +325,24 @@ jobs:
echo "::endgroup::"
echo "::group::DNF resolution (rhel9 pool)"
- docker run --rm --network host rockylinux/rockylinux:9 bash -c '
+ docker run --rm --network host -e SIGN="$SIGN" rockylinux/rockylinux:9 bash -c '
set -e
dnf install -y -q dnf-plugins-core >/dev/null 2>&1
dnf install -y -q https://download.postgresql.org/pub/repos/yum/reporpms/EL-9-x86_64/pgdg-redhat-repo-latest.noarch.rpm >/dev/null 2>&1
dnf install -y -q epel-release >/dev/null 2>&1
dnf config-manager --set-enabled crb
dnf -qy module disable postgresql >/dev/null 2>&1
- printf "%s\n" "[documentdb]" "name=DocumentDB" "baseurl=http://127.0.0.1:8099/rpm/rhel9" "enabled=1" "gpgcheck=0" \
- > /etc/yum.repos.d/documentdb.repo
+ if [ "$SIGN" = true ]; then
+ printf "%s\n" "[documentdb]" "name=DocumentDB" \
+ "baseurl=http://127.0.0.1:8099/rpm/rhel9" "enabled=1" \
+ "gpgcheck=1" \
+ "gpgkey=http://127.0.0.1:8099/documentdb-archive-keyring.gpg" \
+ > /etc/yum.repos.d/documentdb.repo
+ else
+ printf "%s\n" "[documentdb]" "name=DocumentDB" \
+ "baseurl=http://127.0.0.1:8099/rpm/rhel9" "enabled=1" "gpgcheck=0" \
+ > /etc/yum.repos.d/documentdb.repo
+ fi
# --assumeno always exits non-zero (the answer is "no"), so judge the
# transaction it printed rather than the exit code.
dnf install --assumeno documentdb > /tmp/sim.txt 2>&1 || true
diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/continuous-integration.yml
index f51ec27..829b4e7 100644
--- a/.github/workflows/continuous-integration.yml
+++ b/.github/workflows/continuous-integration.yml
@@ -85,3 +85,24 @@ jobs:
#
# Use the built-in NPM script to build the site
run: npm run build
+ package-repository-validation:
+ name: Validate package repository
+ runs-on: ubuntu-latest
+ timeout-minutes: 25
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v7
+ - name: Install package repository tools
+ run: |
+ sudo apt-get update
+ sudo apt-get install -y createrepo-c dpkg-dev rpm python3
+ - name: Generate repository from v0.116-0
+ env:
+ DOCUMENTDB_VERSION: v0.116-0
+ run: .github/scripts/download_packages.sh
+ - name: Verify release inventory and metadata
+ run: python3 .github/scripts/verify_package_inventory.py
+ - name: Resolve both PostgreSQL majors and retired endpoints
+ env:
+ SIGN: "false"
+ run: bash .github/scripts/smoke_test_package_repository.sh
diff --git a/PACKAGE-INSTALL.md b/PACKAGE-INSTALL.md
index 7005c68..a7c0f8c 100644
--- a/PACKAGE-INSTALL.md
+++ b/PACKAGE-INSTALL.md
@@ -5,37 +5,53 @@ Repository-backed installation commands for DocumentDB.
## What is published
Starting with **v0.116-0**, DocumentDB ships a multi-package layout with a setup wizard and
-systemd integration, instead of just a bare PostgreSQL extension package. Not every
-distribution has caught up to it yet, so the repository currently serves two shapes:
+systemd integration, instead of just a bare PostgreSQL extension package. The website mirrors
+the package assets attached to one official release; it does not combine the current release
+with stale packages from older releases. This deliberately reduces the hosted package matrix
+compared with earlier releases so every advertised combination corresponds to the current,
+first-party-built release.
| Distribution | Repository component | Packages available |
|---|---|---|
-| Ubuntu 24.04 | `ubuntu24` | **Full stack** (v0.116-0): `documentdb` meta, `documentdb-N`, `documentdb-common`, `documentdb-gateway`, `documentdb-postgresql-tools`, plus the `postgresql-N-documentdb` extension |
-| RHEL-compatible 9 | `rpm/rhel9` | **Full stack** (v0.116-0), same package set |
-| Ubuntu 22.04, Debian 11/12/13, RHEL-compatible 8 | `ubuntu22`, `deb11`, `deb12`, `deb13`, `rpm/rhel8` | **Extension only** (v0.114-0): `postgresql-N-documentdb` |
+| Ubuntu 24.04 | `ubuntu24` | **Full stack**: `documentdb` meta, `documentdb-N`, `documentdb-common`, `documentdb-gateway`, `documentdb-postgresql-tools`, plus the `postgresql-N-documentdb` extension |
+| RHEL-compatible 9 | `rpm/rhel9` | **Full stack**, same package set |
- Both `amd64`/`x86_64` and `arm64`/`aarch64` variants are published.
-- The full stack is published for PostgreSQL **17** and **18**. The extension package alone is
- additionally available for PostgreSQL **16** on every distribution.
-- **PostgreSQL 16 is extension-only everywhere**, including Ubuntu 24.04 and RHEL 9: there is no
- `documentdb-16`, and `postgresql-16-documentdb` is served at **0.114**, while 17/18 are at
- 0.116. Choosing PostgreSQL 16 therefore gives you no gateway and no `documentdb-setup`.
-- Debian 11 currently resolves PostgreSQL `16` and `17` only.
-- **Debian 13 only:** `apt.postgresql.org` also publishes DocumentDB for Trixie, and its version
- string (`0.114-0-1.pgdg13+1`) outranks this repository's (`0.114-0`), so PGDG's build installs
- by default.
-
-> On the extension-only distributions there is still no packaged gateway, setup helper, or
-> systemd service. To get a MongoDB-compatible endpoint there, follow
-> [Extension-only hosts](#extension-only-hosts-run-the-gateway-from-source) below.
+- The full stack is published for PostgreSQL **17** and **18**.
+- Other accepted build-script combinations (PostgreSQL 15/16; Debian 11/12/13;
+ Ubuntu 22.04; RHEL-compatible 8) are build-on-demand targets in the source repository.
+ They are not part of the current official release and are not served by documentdb.io.
+
+### Targets retired from the hosted repository
+
+Starting with v0.116, documentdb.io no longer publishes packages for Ubuntu 22.04,
+Debian 11/12/13, RHEL-compatible 8, or PostgreSQL 16. This includes the older PG16
+extension packages previously present in the `ubuntu24` and `rpm/rhel9` repositories.
+
+Existing installations keep running, but receive no package updates and cannot reinstall
+those packages from documentdb.io. Empty signed metadata remains at the retired APT
+components and RPM repository URLs so package-manager refreshes do not break unrelated
+operations.
+
+Remove the repository configuration on a host that will not move to the current matrix:
+
+```bash
+# Debian / Ubuntu
+sudo rm -f /etc/apt/sources.list.d/documentdb.list
+sudo apt update
+
+# RHEL-compatible
+sudo rm -f /etc/yum.repos.d/documentdb.repo
+sudo dnf clean all
+```
+
+To remain on an older target, use the matching GitHub release assets or build from that
+release tag. Those paths are not part of the current hosted support matrix.
## Supported PostgreSQL Versions
-- Ubuntu 24.04, RHEL-compatible 9: 16, 17, 18 (full stack on 17 and 18)
-- Ubuntu 22.04: 16, 17, 18 (extension only)
-- Debian 11: 16, 17 (extension only)
-- Debian 12 / 13: 16, 17, 18 (extension only)
-- RHEL-compatible 8: 16, 17, 18 (extension only)
+- Ubuntu 24.04: PostgreSQL 17 and 18
+- RHEL-compatible 9: PostgreSQL 17 and 18
## Quickstart — Ubuntu 24.04 and RHEL 9
@@ -217,99 +233,14 @@ If you installed the `documentdb` meta package rather than `documentdb-18`, name
To install the extension by itself on these distributions, use `postgresql-18-documentdb`
(APT) or `postgresql18-documentdb` (RPM) instead of the `documentdb` meta package.
-## Extension-only distributions
-
-Ubuntu 22.04, Debian 11/12/13 and RHEL-compatible 8 currently serve the extension package
-only. The commands below add the DocumentDB repository and install it.
-
-### Ubuntu 22.04 (Jammy)
-
-```bash
-sudo apt update && \
-sudo apt install -y curl ca-certificates gnupg && \
-curl -fsSL https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo gpg --dearmor --yes -o /usr/share/keyrings/postgresql.gpg && \
-echo "deb [signed-by=/usr/share/keyrings/postgresql.gpg] https://apt.postgresql.org/pub/repos/apt jammy-pgdg main" | sudo tee /etc/apt/sources.list.d/pgdg.list >/dev/null && \
-curl -fsSL https://documentdb.io/documentdb-archive-keyring.gpg | sudo gpg --dearmor --yes -o /usr/share/keyrings/documentdb-archive-keyring.gpg && \
-echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/documentdb-archive-keyring.gpg] https://documentdb.io/deb stable ubuntu22" | sudo tee /etc/apt/sources.list.d/documentdb.list >/dev/null && \
-sudo apt update && \
-sudo apt install -y postgresql-16-documentdb
-```
-
-### Debian 11 (Bullseye)
-
-```bash
-sudo apt update && \
-sudo apt install -y curl ca-certificates gnupg && \
-curl -fsSL https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo gpg --dearmor --yes -o /usr/share/keyrings/postgresql.gpg && \
-echo "deb [signed-by=/usr/share/keyrings/postgresql.gpg] https://apt.postgresql.org/pub/repos/apt bullseye-pgdg main" | sudo tee /etc/apt/sources.list.d/pgdg.list >/dev/null && \
-curl -fsSL https://documentdb.io/documentdb-archive-keyring.gpg | sudo gpg --dearmor --yes -o /usr/share/keyrings/documentdb-archive-keyring.gpg && \
-echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/documentdb-archive-keyring.gpg] https://documentdb.io/deb stable deb11" | sudo tee /etc/apt/sources.list.d/documentdb.list >/dev/null && \
-sudo apt update && \
-sudo apt install -y postgresql-16-documentdb
-```
-
-### Debian 12 (Bookworm)
-
-```bash
-sudo apt update && \
-sudo apt install -y curl ca-certificates gnupg && \
-curl -fsSL https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo gpg --dearmor --yes -o /usr/share/keyrings/postgresql.gpg && \
-echo "deb [signed-by=/usr/share/keyrings/postgresql.gpg] https://apt.postgresql.org/pub/repos/apt bookworm-pgdg main" | sudo tee /etc/apt/sources.list.d/pgdg.list >/dev/null && \
-curl -fsSL https://documentdb.io/documentdb-archive-keyring.gpg | sudo gpg --dearmor --yes -o /usr/share/keyrings/documentdb-archive-keyring.gpg && \
-echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/documentdb-archive-keyring.gpg] https://documentdb.io/deb stable deb12" | sudo tee /etc/apt/sources.list.d/documentdb.list >/dev/null && \
-sudo apt update && \
-sudo apt install -y postgresql-16-documentdb
-```
-
-### Debian 13 (Trixie)
-
-```bash
-sudo apt update && \
-sudo apt install -y curl ca-certificates gnupg && \
-curl -fsSL https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo gpg --dearmor --yes -o /usr/share/keyrings/postgresql.gpg && \
-echo "deb [signed-by=/usr/share/keyrings/postgresql.gpg] https://apt.postgresql.org/pub/repos/apt trixie-pgdg main" | sudo tee /etc/apt/sources.list.d/pgdg.list >/dev/null && \
-curl -fsSL https://documentdb.io/documentdb-archive-keyring.gpg | sudo gpg --dearmor --yes -o /usr/share/keyrings/documentdb-archive-keyring.gpg && \
-echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/documentdb-archive-keyring.gpg] https://documentdb.io/deb stable deb13" | sudo tee /etc/apt/sources.list.d/documentdb.list >/dev/null && \
-sudo apt update && \
-sudo apt install -y postgresql-16-documentdb
-```
-
-### RHEL-compatible 8
-
-```bash
-sudo dnf install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm && \
-sudo dnf install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-8-$(uname -m)/pgdg-redhat-repo-latest.noarch.rpm && \
-sudo dnf -qy module disable postgresql && \
-sudo dnf install -y dnf-plugins-core && \
-(sudo dnf config-manager --set-enabled powertools || \
- sudo dnf config-manager --set-enabled crb || \
- sudo dnf config-manager --set-enabled codeready-builder-for-rhel-8-$(uname -m)-rpms) && \
-sudo rpm --import https://documentdb.io/documentdb-archive-keyring.gpg && \
-printf '%s\n' \
- '[documentdb]' \
- 'name=DocumentDB Repository' \
- 'baseurl=https://documentdb.io/rpm/rhel8' \
- 'enabled=1' \
- 'gpgcheck=1' \
- 'gpgkey=https://documentdb.io/documentdb-archive-keyring.gpg' | sudo tee /etc/yum.repos.d/documentdb.repo >/dev/null && \
-sudo dnf install -y postgresql16-documentdb
-```
-
## Installing a different PostgreSQL major
-Swap the package name at the end of the command:
-
-- APT: `postgresql-17-documentdb` or `postgresql-18-documentdb`
-- RPM: `postgresql17-documentdb` or `postgresql18-documentdb`
-
-> Debian 11 currently supports PostgreSQL `16` and `17` in the repository-backed install flow.
-> PostgreSQL `18` on Debian 11 is blocked by the missing `postgresql-18-postgis-3` dependency
-> in the upstream Bullseye packages.
+The current release publishes PostgreSQL 17 and 18. Install `documentdb-17` or
+`documentdb-18`; the `documentdb` meta package selects PostgreSQL 18.
## Upgrading an existing install
-The package repository serves the newest build for each distribution, so once v0.116-0 is
-published a host already running v0.114-0 will see it as an available upgrade.
+The package repository serves the selected official release for its published matrix.
**A package upgrade only replaces files on disk.** It does not touch the SQL objects already
created in your databases, so after upgrading you must update the extensions in **every
@@ -321,8 +252,8 @@ ALTER EXTENSION documentdb UPDATE;
ALTER EXTENSION documentdb_extended_rum UPDATE; -- only if it is installed
```
-PostgreSQL applies the intermediate upgrade scripts automatically, so 0.114-0 → 0.116-0 is
-applied as 0.114-0 → 0.115-0 → 0.116-0 in one step. Confirm afterwards with:
+PostgreSQL applies available intermediate extension upgrade scripts automatically. Confirm
+afterwards with:
```sql
SELECT extname, extversion FROM pg_extension WHERE extname LIKE 'documentdb%';
@@ -345,120 +276,47 @@ Run the repository setup for your distro first, then:
### APT
```bash
-apt-cache madison postgresql-16-documentdb
-sudo apt install postgresql-16-documentdb=
Linux Packages
- Best for: persistent Linux VM or server environments. Debian/Ubuntu and RHEL family. + Best for: persistent Ubuntu 24.04 or RHEL-compatible 9 VM and server environments.
+ The prebuilt package matrix was reduced in v0.116 +
++ documentdb.io now publishes only the combinations built and tested for the + current release: Ubuntu 24.04 and RHEL-compatible 9, PostgreSQL 17 or 18, on + both supported architectures. Packages from earlier releases are not carried + forward to make unsupported targets appear current. This also withdraws the + older PostgreSQL 16 extension packages previously served for Ubuntu 24.04 and + RHEL-compatible 9. +
++ Need another distribution or PostgreSQL major? We welcome community builds. + Check out the matching source tag and use our version-parameterized{" "} + + packaging scripts + + . The extension, gateway, and remaining stand-alone packages use separate + scripts. PostgreSQL 15 is extension-only. These builds are on demand and are + not official release assets hosted by documentdb.io. +
+Package Finder
pg_cron,{" "}
pgvector, PostGIS, and{" "}
- rum for PostgreSQL 16/17.
+ rum for PostgreSQL 17.
- {isFullStack - ? "It installs the full DocumentDB stack for this target: the extension, the gateway runtime, the administrator tools and the systemd units." - : "It installs the PostgreSQL extension package. This target is not yet covered by the v0.116-0 package layout, so the repository serves the extension alone — no gateway package, setup helper, or systemd service."} + It installs the full DocumentDB stack for this target: the extension, the gateway + runtime, the administrator tools and the systemd units.
{isFullStack ? ( <> @@ -366,7 +391,7 @@ export default function PackagesPage() { ) : null} {packageFamily === "apt" ? (
- Running in a clean Debian/Ubuntu container as root?
+ Running in a clean Ubuntu container as root?
Run export DEBIAN_FRONTEND=noninteractive in the shell first
(and omit sudo from the command above).
Without it, tzdata prompts for input partway through
@@ -382,9 +407,10 @@ export default function PackagesPage() {
{isFullStack ? (
<>
- DocumentDB ships as five packages. Installing{" "}
+ A per-major DocumentDB install resolves five package names. Installing{" "}
{selectedPackageNames} pulls in
- everything below.
+ everything below; the optional documentdb{" "}
+ meta package selects PostgreSQL 18.
- Debian 13 is now supported in the APT repository-backed install flow. Debian - 11 currently supports only PostgreSQL 16 and 17. -
- ) : null}| APT | -Ubuntu 24.04 (full stack) · ubuntu24 |
+ Ubuntu 24.04 · ubuntu24 |
amd64, arm64 | 17, 18 |
documentdb-<pg>
|
- 0.116 | -
| APT | -Ubuntu 24.04 (extension only) · ubuntu24 |
- amd64, arm64 | -16 | -
- postgresql-16-documentdb
- |
- 0.114 | -|
| APT | -Ubuntu 22.04 · ubuntu22Debian 11/12/13 · deb11 / deb12 / deb13(extension only) |
- amd64, arm64 | -16, 17, 18 (Debian 11: 16, 17) | -
- postgresql-<pg>-documentdb
- |
- 0.114 | +{release.metaVersion} |
| RPM | -RHEL-compatible 9 (full stack) · rpm/rhel9 |
+ RHEL-compatible 9 · rpm/rhel9 |
x86_64, aarch64 | 17, 18 |
documentdb-<pg>
|
- 0.116 | -
| RPM | -RHEL-compatible 9 (extension only) · rpm/rhel9 |
- x86_64, aarch64 | -16 | -
- postgresql16-documentdb
- |
- 0.114 | -|
| RPM | -
- RHEL-compatible 8 (extension only, tested on Rocky Linux) · rpm/rhel8
- |
- x86_64, aarch64 | -16, 17, 18 | -
- postgresql<pg>-documentdb
- |
- 0.114 | +{release.metaRpmVersion} |
- PostgreSQL 16 is extension-only on every distribution, including
- Ubuntu 24.04 and RHEL 9. There is no documentdb-16 — requesting it
- fails with "has no installation candidate" (APT) or{" "}
- "No match for argument" (DNF). On PostgreSQL 16 you get the
- extension alone, at 0.114: no gateway, no documentdb-setup, no
- systemd units. The packaged stack requires PostgreSQL 17 or 18.
+ Compared with earlier releases, v0.116 reduces the hosted package matrix. The
+ repository contains only package combinations attached to{" "}
+
+ {release.tagName}
+
+ . Other combinations remain build-on-demand targets in the source repository;
+ see the{" "}
+
+ packaging guide
+ {" "}
+ to build the package you need from the matching tag.
Use Package Finder above to generate the exact command for your selected @@ -520,11 +508,39 @@ export default function PackagesPage() { Linux Packages Quick Start {" "} - for every repository component and install command written out in full. + for the supported repository components and install commands written out in full. +
++ documentdb.io no longer publishes packages for Ubuntu 22.04, Debian 11/12/13, + RHEL-compatible 8, or PostgreSQL 16. Existing installations keep running, but + they receive no package updates and cannot reinstall those packages from the + documentdb.io repository.
-
- Debian 13 packages are available in the deb13 APT component and
- remain downloadable as direct .deb assets from GitHub Releases.
+
+ Empty signed metadata remains at the retired repository URLs so{" "}
+ apt update and{" "}
+ dnf makecache do not break unrelated
+ package operations. Remove the DocumentDB source if that host will not move to
+ the current matrix:
+
+ To remain on an older target, use the matching GitHub release assets or build + from that release tag. Those paths are not part of the current hosted support + matrix.
- Swap the distribution, PostgreSQL version, architecture, and version string to match - the exact asset you need. + Choose an asset whose PostgreSQL version and architecture match your host.
sudo documentdb-setup --admin-user admin, - which creates the database and starts the gateway. On the extension-only - distributions the Linux package guide covers the additional source-gateway steps - needed to expose a MongoDB-compatible endpoint. + which creates the database and starts the gateway.