diff --git a/nix/checks.nix b/nix/checks.nix index 42053caef4..2b1edae39e 100644 --- a/nix/checks.nix +++ b/nix/checks.nix @@ -942,6 +942,51 @@ postgresql_17_src ; psql_orioledb-17_exts_orioledb_debug = self'.legacyPackages.psql_orioledb-17.exts.orioledb.debug; + glibc-version-check = + let + checkScript = pkgs.writers.writeNuBin "check-glibc-version" ( + builtins.readFile ./tools/check-glibc-version.nu + ); + # supautils is dlopened into already-running legacy pre-nix postgres, so it needs a lower floor than an AMI build. + legacyPaths = [ + self'.legacyPackages.psql_15.exts.supautils + self'.legacyPackages.psql_17.exts.supautils + self'.legacyPackages."psql_orioledb-17".exts.supautils + ]; + # gatekeeper is dlopened by the base os pam stack; pin it + pamPaths = [ self'.packages.gatekeeper ]; + # ships to user's development machines, not our fleet + portablePaths = [ self'.packages.psql_17_cli_portable ]; + in + pkgs.runCommand "glibc-version-check" + { + nativeBuildInputs = [ pkgs.binutils ]; + inherit legacyPaths pamPaths portablePaths; + } + '' + # 2.31: Ubuntu 20.04's glibc. + ${lib.getExe checkScript} 2.31 $legacyPaths + # 2.39: Ubuntu 24.04's glibc. + ${lib.getExe checkScript} 2.39 $portablePaths + # 2.40: current core floor. + ${lib.getExe checkScript} 2.40 $pamPaths + touch $out + ''; + collation-version-check = + let + baseline = "glibc-2.40-66"; + check = + name: actual: + lib.assertMsg (actual == baseline) '' + glibc version changed: baseline is ${baseline}, ${name} has ${actual}. Checked + glibc version, not actual collation data, as a proxy for collation drift. + This can change collation versions and require a reindex. + If this bump has been reviewed for collation safety, update the baseline in nix/checks.nix to match. + ''; + in + assert check "postgresql_15" self'.packages.postgresql_15.stdenv.cc.libc.name; + assert check "postgresql_17" self'.packages.postgresql_17.stdenv.cc.libc.name; + pkgs.runCommand "collation-version-check" { } "touch $out"; }; }; } diff --git a/nix/tools/check-glibc-version.nu b/nix/tools/check-glibc-version.nu new file mode 100755 index 0000000000..d785dc2bd3 --- /dev/null +++ b/nix/tools/check-glibc-version.nu @@ -0,0 +1,38 @@ +#!/usr/bin/env nu + +def parse-version [] { + split row "." | each { into int } +} + +def is-elf []: path -> bool { + (open --raw $in | bytes at 0..<4) == ("\u{7f}ELF" | into binary) +} + +def max-glibc-version [path: path] { + ^objdump -T $path | complete | get stdout + | parse -r 'GLIBC_(?[0-9.]+)' | get ver + | each { parse-version } + | sort + | last +} + +# Fails if any file under the given paths requires a newer glibc than max_version. +def main [max_version: string, ...paths: path] { + let offenders = ( + $paths + | each { glob $"($in)/**/*" } | flatten + | where { ($in | path type) == file } + | where { is-elf } + | par-each { |f| { file: $f, version: (max-glibc-version $f) } } + | compact version + | where version > ($max_version | parse-version) + ) + + if ($offenders | is-empty) { + print $"glibc version OK \(<= ($max_version)\)" + exit 0 + } + + print ($offenders | update version { str join "." } | table --width 200) + exit 1 +}