From d20cab091fb28eaf0782e1f623ed74713233a2a4 Mon Sep 17 00:00:00 2001 From: Sam Rose Date: Wed, 21 Jan 2026 12:40:54 -0500 Subject: [PATCH 1/3] feat(nix): add latestOnly parameter support to postgres.nix Add latestOnly parameter that flows through makeOurPostgresPkgs, makePostgresBin, and makePostgres functions. When true, this parameter will enable building only the latest version of each extension. Also adds psql_17_slim package that uses latestOnly=true. feat(ext): add latestOnly support to pgvector feat(ext): add latestOnly support to wrappers Add latestOnly parameter to wrappers extension that: - Filters versionsToUse when latestOnly=true to build only latest version - Skips migration SQL file generation when latestOnly=true - Skips previously packaged version symlinks when latestOnly=true - Updates library count verification for slim builds (expects 2 files) - Updates passthru metadata with versionsBuilt and latestOnly flag This is part of the psql_17_slim implementation to reduce image size. feat(ext): add latestOnly support to pg_graphql feat(ext): add latestOnly support to pg_net --- .../plans/2026-01-21-psql-slim-latest-only.md | 536 ++++++++++++++++++ nix/apps.nix | 1 + nix/ext/pg_graphql/default.nix | 22 +- nix/ext/pg_net.nix | 24 +- nix/ext/pgvector.nix | 22 +- nix/ext/wrappers/default.nix | 136 +++-- nix/packages/default.nix | 1 + nix/packages/image-size-analyzer.nix | 378 ++++++++++++ nix/packages/postgres.nix | 35 +- 9 files changed, 1079 insertions(+), 76 deletions(-) create mode 100644 docs/plans/2026-01-21-psql-slim-latest-only.md create mode 100644 nix/packages/image-size-analyzer.nix diff --git a/docs/plans/2026-01-21-psql-slim-latest-only.md b/docs/plans/2026-01-21-psql-slim-latest-only.md new file mode 100644 index 000000000..9654b2009 --- /dev/null +++ b/docs/plans/2026-01-21-psql-slim-latest-only.md @@ -0,0 +1,536 @@ +# PostgreSQL Slim Image (Latest Extensions Only) Implementation Plan + +> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task. + +**Goal:** Create a new `psql_17_slim/bin` flake output that includes only the latest version of each PostgreSQL extension, reducing image size by ~40-60%. + +**Architecture:** Add a `latestOnly` parameter to extension nix files. When true, only build the latest version instead of all versions. Create new `makePostgresBinSlim` function in postgres.nix that passes this parameter. + +**Tech Stack:** Nix, flake-parts + +**Estimated size reduction:** ~700MB+ (wrappers alone has 13 versions → 1) + +--- + +## Task 1: Update postgres.nix to Support Slim Builds + +**Files:** +- Modify: `nix/packages/postgres.nix` + +**Step 1: Add latestOnly parameter to extCallPackage** + +In `makeOurPostgresPkgs`, modify the `extCallPackage` call to accept a `latestOnly` parameter: + +```nix +# Around line 94, modify makeOurPostgresPkgs to accept latestOnly parameter +makeOurPostgresPkgs = + version: + { latestOnly ? false }: + let + postgresql = getPostgresqlPackage version; + extensionsToUse = + if (builtins.elem version [ "orioledb-17" ]) then + orioledbExtensions + else if (builtins.elem version [ "17" ]) then + dbExtensions17 + else + ourExtensions; + extCallPackage = pkgs.lib.callPackageWith ( + pkgs + // { + inherit postgresql latestOnly; + switch-ext-version = extCallPackage ./switch-ext-version.nix { }; + overlayfs-on-package = extCallPackage ./overlayfs-on-package.nix { }; + } + ); + in + map (path: extCallPackage path { }) extensionsToUse; +``` + +**Step 2: Update makePostgresBin to accept latestOnly** + +```nix +# Around line 143, modify makePostgresBin +makePostgresBin = + version: + { latestOnly ? false }: + let + postgresql = getPostgresqlPackage version; + postgres-pkgs = makeOurPostgresPkgs version { inherit latestOnly; }; + ourExts = map (ext: { + name = ext.name; + version = ext.version; + }) postgres-pkgs; + + pgbin = postgresql.withPackages (_ps: postgres-pkgs); + in + pkgs.symlinkJoin { + inherit (pgbin) name version; + paths = [ + pgbin + (makeReceipt pgbin ourExts) + ]; + }; +``` + +**Step 3: Update makePostgres to accept latestOnly** + +```nix +# Around line 172, modify makePostgres +makePostgres = + version: + { latestOnly ? false }: + lib.recurseIntoAttrs { + bin = makePostgresBin version { inherit latestOnly; }; + exts = makeOurPostgresPkgsSet version; + }; +``` + +**Step 4: Add slim packages to basePackages** + +```nix +# Around line 178 +basePackages = { + psql_15 = makePostgres "15" { }; + psql_17 = makePostgres "17" { }; + psql_orioledb-17 = makePostgres "orioledb-17" { }; +}; + +slimPackages = { + psql_17_slim = makePostgres "17" { latestOnly = true; }; +}; +``` + +**Step 5: Update binPackages to include slim variants** + +```nix +# Around line 183 +binPackages = lib.mapAttrs' (name: value: { + name = "${name}/bin"; + value = value.bin; +}) (basePackages // slimPackages); +``` + +**Step 6: Commit** + +```bash +git add nix/packages/postgres.nix +git commit -m "feat(nix): add latestOnly parameter support to postgres.nix" +``` + +--- + +## Task 2: Update pgvector.nix (Template Pattern) + +**Files:** +- Modify: `nix/ext/pgvector.nix` + +This is the template pattern that will be applied to all multi-version extensions. + +**Step 1: Add latestOnly parameter to function signature** + +```nix +# Line 1-7, add latestOnly parameter +{ + pkgs, + lib, + stdenv, + fetchFromGitHub, + postgresql, + latestOnly ? false, +}: +``` + +**Step 2: Modify version selection to respect latestOnly** + +```nix +# After line 21 (after latestVersion = lib.last versions;) +# Replace: +# packages = builtins.attrValues ( +# lib.mapAttrs (name: value: build name value.hash) supportedVersions +# ); +# With: +versionsToUse = if latestOnly + then { "${latestVersion}" = supportedVersions.${latestVersion}; } + else supportedVersions; +packages = builtins.attrValues ( + lib.mapAttrs (name: value: build name value.hash) versionsToUse +); +versionsBuilt = if latestOnly then [ latestVersion ] else versions; +numberOfVersionsBuilt = builtins.length versionsBuilt; +``` + +**Step 3: Update passthru to reflect actual versions built** + +```nix +# Around line 85-91, update passthru +passthru = { + versions = versionsBuilt; + numberOfVersions = numberOfVersionsBuilt; + inherit pname latestOnly; + version = if latestOnly + then latestVersion + else "multi-" + lib.concatStringsSep "-" (map (v: lib.replaceStrings [ "." ] [ "-" ] v) versions); + pgRegressTestName = "pgvector"; +}; +``` + +**Step 4: Commit** + +```bash +git add nix/ext/pgvector.nix +git commit -m "feat(ext): add latestOnly support to pgvector" +``` + +--- + +## Task 3: Update wrappers/default.nix + +**Files:** +- Modify: `nix/ext/wrappers/default.nix` + +This is the most complex extension with migration SQL files. Since we don't need migrations for slim, simplify significantly. + +**Step 1: Add latestOnly parameter** + +```nix +# Line 1-12, add latestOnly parameter +{ + lib, + stdenv, + callPackages, + fetchFromGitHub, + openssl, + pkg-config, + postgresql, + buildEnv, + rust-bin, + git, + latestOnly ? false, +}: +``` + +**Step 2: Modify version selection** + +```nix +# After line 208 (after latestVersion = lib.last versions;) +versionsToUse = if latestOnly + then lib.filterAttrs (n: _: n == latestVersion) supportedVersions + else supportedVersions; +versionsBuilt = if latestOnly then [ latestVersion ] else versions; +numberOfVersionsBuilt = builtins.length versionsBuilt; + +# Update packagesAttrSet to use versionsToUse +packagesAttrSet = lib.mapAttrs' (name: value: { + name = lib.replaceStrings [ "." ] [ "_" ] name; + value = build name value.hash value.rust value.pgrx; +}) versionsToUse; +``` + +**Step 3: Simplify postBuild for latestOnly** + +```nix +# Around line 229, modify postBuild to skip migrations when latestOnly +postBuild = '' + create_control_files() { + { + echo "default_version = '${latestVersion}'" + cat $out/share/postgresql/extension/${pname}--${latestVersion}.control + } > $out/share/postgresql/extension/${pname}.control + } + + create_lib_files() { + ln -sfn ${pname}-${latestVersion}${postgresql.dlSuffix} $out/lib/${pname}${postgresql.dlSuffix} + ${lib.optionalString (!latestOnly) '' + # Create symlinks for all previously packaged versions to main library + for v in ${lib.concatStringsSep " " previouslyPackagedVersions}; do + ln -sfn $out/lib/${pname}${postgresql.dlSuffix} $out/lib/${pname}-$v${postgresql.dlSuffix} + done + ''} + } + + ${lib.optionalString (!latestOnly) '' + create_migration_sql_files() { + # ... existing migration logic ... + } + ''} + + create_control_files + create_lib_files + ${lib.optionalString (!latestOnly) "create_migration_sql_files"} + + # Verify library count matches expected + ${if latestOnly then '' + (test "$(ls -A $out/lib/${pname}*${postgresql.dlSuffix} | wc -l)" = "2") + '' else '' + (test "$(ls -A $out/lib/${pname}*${postgresql.dlSuffix} | wc -l)" = "${ + toString (numberOfVersions + numberOfPreviouslyPackagedVersions + 1) + }") + ''} +''; +``` + +**Step 4: Update passthru** + +```nix +passthru = { + versions = versionsBuilt; + numberOfVersions = numberOfVersionsBuilt; + pname = "${pname}"; + inherit latestOnly; + version = if latestOnly + then latestVersion + else "multi-" + lib.concatStringsSep "-" (map (v: lib.replaceStrings [ "." ] [ "-" ] v) versions); + packages = packagesAttrSet // { + recurseForDerivations = true; + }; +}; +``` + +**Step 5: Commit** + +```bash +git add nix/ext/wrappers/default.nix +git commit -m "feat(ext): add latestOnly support to wrappers" +``` + +--- + +## Task 4: Update pg_graphql/default.nix + +**Files:** +- Modify: `nix/ext/pg_graphql/default.nix` + +**Step 1: Add latestOnly parameter and modify version selection** + +Apply the same pattern as pgvector: +1. Add `latestOnly ? false` to function parameters +2. Create `versionsToUse` filtered by latestOnly +3. Update packages list to use versionsToUse +4. Update passthru + +**Step 2: Commit** + +```bash +git add nix/ext/pg_graphql/default.nix +git commit -m "feat(ext): add latestOnly support to pg_graphql" +``` + +--- + +## Task 5: Update pg_net.nix + +**Files:** +- Modify: `nix/ext/pg_net.nix` + +Apply the same pattern as pgvector. + +**Step 1: Add latestOnly parameter and modify version selection** + +**Step 2: Update library count check for latestOnly** + +```nix +# In postBuild, update the check +${if latestOnly then '' + (test "$(ls -A $out/lib/${pname}*${postgresql.dlSuffix} | wc -l)" = "2") +'' else '' + (test "$(ls -A $out/lib/${pname}*${postgresql.dlSuffix} | wc -l)" = "${ + toString (numberOfVersions + 1) + }") +''} +``` + +**Step 3: Commit** + +```bash +git add nix/ext/pg_net.nix +git commit -m "feat(ext): add latestOnly support to pg_net" +``` + +--- + +## Task 6: Update pgsodium.nix + +**Files:** +- Modify: `nix/ext/pgsodium.nix` + +Apply the same pattern as pgvector. + +**Commit:** +```bash +git add nix/ext/pgsodium.nix +git commit -m "feat(ext): add latestOnly support to pgsodium" +``` + +--- + +## Task 7: Update pgaudit.nix + +**Files:** +- Modify: `nix/ext/pgaudit.nix` + +Apply the same pattern as pgvector. + +**Commit:** +```bash +git add nix/ext/pgaudit.nix +git commit -m "feat(ext): add latestOnly support to pgaudit" +``` + +--- + +## Task 8: Update pg_jsonschema/default.nix + +**Files:** +- Modify: `nix/ext/pg_jsonschema/default.nix` + +Apply the same pattern as pgvector. + +**Commit:** +```bash +git add nix/ext/pg_jsonschema/default.nix +git commit -m "feat(ext): add latestOnly support to pg_jsonschema" +``` + +--- + +## Task 9: Update Remaining Multi-Version Extensions + +Apply the same pattern to these extensions (4 or fewer versions each): + +**Files:** +- `nix/ext/pg_cron/default.nix` +- `nix/ext/pg_repack.nix` +- `nix/ext/pg_tle.nix` +- `nix/ext/plv8/default.nix` +- `nix/ext/pgsql-http.nix` +- `nix/ext/hypopg.nix` +- `nix/ext/pgmq/default.nix` +- `nix/ext/pgroonga/default.nix` +- `nix/ext/pgrouting/default.nix` +- `nix/ext/vault.nix` +- `nix/ext/rum.nix` +- `nix/ext/postgis.nix` +- `nix/ext/supautils.nix` + +For single-version extensions, just add the parameter with no-op behavior: +```nix +latestOnly ? false, # unused, for API compatibility +``` + +**Commit:** +```bash +git add nix/ext/ +git commit -m "feat(ext): add latestOnly support to remaining extensions" +``` + +--- + +## Task 10: Update Dockerfile-17 to Use Slim Package + +**Files:** +- Modify: `Dockerfile-17` + +**Step 1: Change nix profile add command** + +Find the line: +```dockerfile +RUN nix profile add path:.#psql_17/bin +``` + +Change to: +```dockerfile +RUN nix profile add path:.#psql_17_slim/bin +``` + +**Step 2: Commit** + +```bash +git add Dockerfile-17 +git commit -m "feat(docker): use psql_17_slim for smaller image size" +``` + +--- + +## Task 11: Test and Verify + +**Step 1: Build the slim package** + +```bash +nix build .#psql_17_slim/bin +``` + +Expected: Build succeeds with only latest versions. + +**Step 2: Verify extension count** + +```bash +ls -la result/lib/*.so | wc -l +``` + +Expected: Significantly fewer .so files than full build. + +**Step 3: Verify receipt.json** + +```bash +cat result/receipt.json | jq '.extensions | length' +``` + +Expected: Same number of extensions, but each with single version. + +**Step 4: Build Docker image and compare size** + +```bash +nix run .#image-size-analyzer -- --image Dockerfile-17 +``` + +Expected: Total size reduced by 40-60%. + +**Step 5: Commit any fixes** + +--- + +## Task 12: Update Documentation + +**Files:** +- Modify: `nix/docs/image-size-analyzer-usage.md` + +Add section explaining the slim vs full packages: + +```markdown +## Package Variants + +### Full Package (`psql_17/bin`) +Includes all versions of each extension for migration support. +Use for: Production databases that need `ALTER EXTENSION ... UPDATE`. + +### Slim Package (`psql_17_slim/bin`) +Includes only the latest version of each extension. +Use for: CI/CD, testing, new deployments without migration needs. +Typical size savings: 40-60% smaller. +``` + +**Commit:** +```bash +git add nix/docs/ +git commit -m "docs: document slim vs full package variants" +``` + +--- + +## Summary + +| Task | Files Modified | Estimated Savings | +|------|---------------|-------------------| +| 1 | postgres.nix | - | +| 2 | pgvector.nix | ~100MB | +| 3 | wrappers/default.nix | ~700MB | +| 4 | pg_graphql/default.nix | ~200MB | +| 5 | pg_net.nix | ~150MB | +| 6 | pgsodium.nix | ~50MB | +| 7 | pgaudit.nix | ~30MB | +| 8 | pg_jsonschema/default.nix | ~30MB | +| 9 | Remaining extensions | ~100MB | +| 10 | Dockerfile-17 | - | + +**Total estimated savings: 1.2-1.5 GB** diff --git a/nix/apps.nix b/nix/apps.nix index acf42910c..46fc12500 100644 --- a/nix/apps.nix +++ b/nix/apps.nix @@ -21,6 +21,7 @@ pg-restore = mkApp "pg-restore" "pg-restore"; local-infra-bootstrap = mkApp "local-infra-bootstrap" "local-infra-bootstrap"; dbmate-tool = mkApp "dbmate-tool" "dbmate-tool"; + image-size-analyzer = mkApp "image-size-analyzer" "image-size-analyzer"; update-readme = mkApp "update-readme" "update-readme"; show-commands = mkApp "show-commands" "show-commands"; build-test-ami = mkApp "build-test-ami" "build-test-ami"; diff --git a/nix/ext/pg_graphql/default.nix b/nix/ext/pg_graphql/default.nix index a7f6d1065..11ea156dc 100644 --- a/nix/ext/pg_graphql/default.nix +++ b/nix/ext/pg_graphql/default.nix @@ -7,6 +7,7 @@ postgresql, rust-bin, rsync, + latestOnly ? false, }: let @@ -124,9 +125,15 @@ let ) allVersions; versions = lib.naturalSort (lib.attrNames supportedVersions); latestVersion = lib.last versions; - numberOfVersions = builtins.length versions; + versionsToUse = + if latestOnly then + { "${latestVersion}" = supportedVersions.${latestVersion}; } + else + supportedVersions; + versionsBuilt = if latestOnly then [ latestVersion ] else versions; + numberOfVersionsBuilt = builtins.length versionsBuilt; packages = builtins.attrValues ( - lib.mapAttrs (name: value: build name value.hash value.rust value.pgrx) supportedVersions + lib.mapAttrs (name: value: build name value.hash value.rust value.pgrx) versionsToUse ); in (buildEnv { @@ -167,14 +174,19 @@ in # checks (set -x test "$(ls -A $out/lib/${pname}*${postgresql.dlSuffix} | wc -l)" = "${ - toString (numberOfVersions + 1) + toString (numberOfVersionsBuilt + 1) }" ) ''; passthru = { - inherit versions numberOfVersions pname; + versions = versionsBuilt; + numberOfVersions = numberOfVersionsBuilt; + inherit pname latestOnly; version = - "multi-" + lib.concatStringsSep "-" (map (v: lib.replaceStrings [ "." ] [ "-" ] v) versions); + if latestOnly then + latestVersion + else + "multi-" + lib.concatStringsSep "-" (map (v: lib.replaceStrings [ "." ] [ "-" ] v) versions); }; }).overrideAttrs (_: { diff --git a/nix/ext/pg_net.nix b/nix/ext/pg_net.nix index 60304138d..d6b934901 100644 --- a/nix/ext/pg_net.nix +++ b/nix/ext/pg_net.nix @@ -8,6 +8,7 @@ makeWrapper, switch-ext-version, curl_8_6, + latestOnly ? false, }: let @@ -98,10 +99,14 @@ let ) platformFilteredVersions; versions = lib.naturalSort (lib.attrNames supportedVersions); latestVersion = lib.last versions; - numberOfVersions = builtins.length versions; - packages = builtins.attrValues ( - lib.mapAttrs (name: value: build name value.hash) supportedVersions - ); + versionsToUse = + if latestOnly then + { "${latestVersion}" = supportedVersions.${latestVersion}; } + else + supportedVersions; + packages = builtins.attrValues (lib.mapAttrs (name: value: build name value.hash) versionsToUse); + versionsBuilt = if latestOnly then [ latestVersion ] else versions; + numberOfVersionsBuilt = builtins.length versionsBuilt; in pkgs.buildEnv { name = pname; @@ -118,7 +123,7 @@ pkgs.buildEnv { # checks (set -x test "$(ls -A $out/lib/${pname}*${postgresql.dlSuffix} | wc -l)" = "${ - toString (numberOfVersions + 1) + toString (numberOfVersionsBuilt + 1) }" ) @@ -127,12 +132,17 @@ pkgs.buildEnv { ''; passthru = { - inherit versions numberOfVersions pname; + versions = versionsBuilt; + numberOfVersions = numberOfVersionsBuilt; + inherit pname latestOnly; hasBackgroundWorker = true; defaultSettings = { shared_preload_libraries = [ "pg_net" ]; }; version = - "multi-" + lib.concatStringsSep "-" (map (v: lib.replaceStrings [ "." ] [ "-" ] v) versions); + if latestOnly then + latestVersion + else + "multi-" + lib.concatStringsSep "-" (map (v: lib.replaceStrings [ "." ] [ "-" ] v) versions); }; } diff --git a/nix/ext/pgvector.nix b/nix/ext/pgvector.nix index bcf86ebfb..12b8816d6 100644 --- a/nix/ext/pgvector.nix +++ b/nix/ext/pgvector.nix @@ -4,6 +4,7 @@ stdenv, fetchFromGitHub, postgresql, + latestOnly ? false, }: let pname = "vector"; @@ -19,10 +20,14 @@ let # Derived version information versions = lib.naturalSort (lib.attrNames supportedVersions); latestVersion = lib.last versions; - numberOfVersions = builtins.length versions; - packages = builtins.attrValues ( - lib.mapAttrs (name: value: build name value.hash) supportedVersions - ); + versionsToUse = + if latestOnly then + { "${latestVersion}" = supportedVersions.${latestVersion}; } + else + supportedVersions; + packages = builtins.attrValues (lib.mapAttrs (name: value: build name value.hash) versionsToUse); + versionsBuilt = if latestOnly then [ latestVersion ] else versions; + numberOfVersionsBuilt = builtins.length versionsBuilt; # Build function for individual versions build = @@ -83,9 +88,14 @@ pkgs.buildEnv { ]; passthru = { - inherit versions numberOfVersions pname; + versions = versionsBuilt; + numberOfVersions = numberOfVersionsBuilt; + inherit pname latestOnly; version = - "multi-" + lib.concatStringsSep "-" (map (v: lib.replaceStrings [ "." ] [ "-" ] v) versions); + if latestOnly then + latestVersion + else + "multi-" + lib.concatStringsSep "-" (map (v: lib.replaceStrings [ "." ] [ "-" ] v) versions); pgRegressTestName = "pgvector"; }; } diff --git a/nix/ext/wrappers/default.nix b/nix/ext/wrappers/default.nix index 696358ea4..5383e30ec 100644 --- a/nix/ext/wrappers/default.nix +++ b/nix/ext/wrappers/default.nix @@ -9,6 +9,7 @@ buildEnv, rust-bin, git, + latestOnly ? false, }: let pname = "wrappers"; @@ -207,6 +208,13 @@ let versions = lib.naturalSort (lib.attrNames supportedVersions); latestVersion = lib.last versions; numberOfVersions = builtins.length versions; + versionsToUse = + if latestOnly then + lib.filterAttrs (n: _: n == latestVersion) supportedVersions + else + supportedVersions; + versionsBuilt = if latestOnly then [ latestVersion ] else versions; + numberOfVersionsBuilt = builtins.length versionsBuilt; # Filter out previously packaged versions that are actually built for this PG version # This prevents double-counting when a version appears in both lists previouslyPackagedVersions = builtins.filter ( @@ -216,7 +224,7 @@ let packagesAttrSet = lib.mapAttrs' (name: value: { name = lib.replaceStrings [ "." ] [ "_" ] name; value = build name value.hash value.rust value.pgrx; - }) supportedVersions; + }) versionsToUse; packages = builtins.attrValues packagesAttrSet; in (buildEnv { @@ -240,69 +248,101 @@ in # Create main library symlink to latest version ln -sfn ${pname}-${latestVersion}${postgresql.dlSuffix} $out/lib/${pname}${postgresql.dlSuffix} - # Create symlinks for all previously packaged versions to main library - for v in ${lib.concatStringsSep " " previouslyPackagedVersions}; do - ln -sfn $out/lib/${pname}${postgresql.dlSuffix} $out/lib/${pname}-$v${postgresql.dlSuffix} - done + ${ + if latestOnly then + '' + # latestOnly mode: skip previouslyPackagedVersions symlinks + '' + else + '' + # Create symlinks for all previously packaged versions to main library + for v in ${lib.concatStringsSep " " previouslyPackagedVersions}; do + ln -sfn $out/lib/${pname}${postgresql.dlSuffix} $out/lib/${pname}-$v${postgresql.dlSuffix} + done + '' + } } - create_migration_sql_files() { + ${ + if latestOnly then + '' + # latestOnly mode: skip migration SQL files entirely + '' + else + '' + create_migration_sql_files() { - PREVIOUS_VERSION="" - while IFS= read -r i; do - FILENAME=$(basename "$i") - VERSION="$(grep -oE '[0-9]+\.[0-9]+\.[0-9]+' <<< $FILENAME)" - if [[ "$PREVIOUS_VERSION" != "" ]]; then - # Always write to $out/share/postgresql/extension, not $DIRNAME - # because $DIRNAME might be a symlinked read-only path from the Nix store - # We use -L with cp to dereference symlinks (copy the actual file content, not the symlink) - MIGRATION_FILENAME="$out/share/postgresql/extension/''${FILENAME/$VERSION/$PREVIOUS_VERSION--$VERSION}" - cp -L "$i" "$MIGRATION_FILENAME" - fi - PREVIOUS_VERSION="$VERSION" - done < <(find $out -name '*.sql' | sort -V) + PREVIOUS_VERSION="" + while IFS= read -r i; do + FILENAME=$(basename "$i") + VERSION="$(grep -oE '[0-9]+\.[0-9]+\.[0-9]+' <<< $FILENAME)" + if [[ "$PREVIOUS_VERSION" != "" ]]; then + # Always write to $out/share/postgresql/extension, not $DIRNAME + # because $DIRNAME might be a symlinked read-only path from the Nix store + # We use -L with cp to dereference symlinks (copy the actual file content, not the symlink) + MIGRATION_FILENAME="$out/share/postgresql/extension/''${FILENAME/$VERSION/$PREVIOUS_VERSION--$VERSION}" + cp -L "$i" "$MIGRATION_FILENAME" + fi + PREVIOUS_VERSION="$VERSION" + done < <(find $out -name '*.sql' | sort -V) - # Create empty SQL files for previously packaged versions that don't exist - # This compensates for versions that failed to produce SQL files in the past - for prev_version in ${lib.concatStringsSep " " previouslyPackagedVersions}; do - sql_file="$out/share/postgresql/extension/wrappers--$prev_version.sql" - if [ ! -f "$sql_file" ]; then - echo "-- Empty migration file for previously packaged version $prev_version" > "$sql_file" - fi - done + # Create empty SQL files for previously packaged versions that don't exist + # This compensates for versions that failed to produce SQL files in the past + for prev_version in ${lib.concatStringsSep " " previouslyPackagedVersions}; do + sql_file="$out/share/postgresql/extension/wrappers--$prev_version.sql" + if [ ! -f "$sql_file" ]; then + echo "-- Empty migration file for previously packaged version $prev_version" > "$sql_file" + fi + done - # Create migration SQL files from previous versions to newer versions - # Skip if the migration file already exists (to avoid conflicts with the first loop) - for prev_version in ${lib.concatStringsSep " " previouslyPackagedVersions}; do - for curr_version in ${lib.concatStringsSep " " versions}; do - if [[ "$(printf '%s\n%s' "$prev_version" "$curr_version" | sort -V | head -n1)" == "$prev_version" ]] && [[ "$prev_version" != "$curr_version" ]]; then - main_sql_file="$out/share/postgresql/extension/wrappers--$curr_version.sql" - new_file="$out/share/postgresql/extension/wrappers--$prev_version--$curr_version.sql" - # Only create if it doesn't already exist (first loop may have created it) - if [ -f "$main_sql_file" ] && [ ! -f "$new_file" ]; then - cp "$main_sql_file" "$new_file" - sed -i 's|$libdir/wrappers-[0-9.]*|$libdir/wrappers|g' "$new_file" - fi - fi - done - done + # Create migration SQL files from previous versions to newer versions + # Skip if the migration file already exists (to avoid conflicts with the first loop) + for prev_version in ${lib.concatStringsSep " " previouslyPackagedVersions}; do + for curr_version in ${lib.concatStringsSep " " versions}; do + if [[ "$(printf '%s\n%s' "$prev_version" "$curr_version" | sort -V | head -n1)" == "$prev_version" ]] && [[ "$prev_version" != "$curr_version" ]]; then + main_sql_file="$out/share/postgresql/extension/wrappers--$curr_version.sql" + new_file="$out/share/postgresql/extension/wrappers--$prev_version--$curr_version.sql" + # Only create if it doesn't already exist (first loop may have created it) + if [ -f "$main_sql_file" ] && [ ! -f "$new_file" ]; then + cp "$main_sql_file" "$new_file" + sed -i 's|$libdir/wrappers-[0-9.]*|$libdir/wrappers|g' "$new_file" + fi + fi + done + done + } + '' } create_control_files create_lib_files - create_migration_sql_files + ${if latestOnly then "" else "create_migration_sql_files"} # Verify library count matches expected - (test "$(ls -A $out/lib/${pname}*${postgresql.dlSuffix} | wc -l)" = "${ - toString (numberOfVersions + numberOfPreviouslyPackagedVersions + 1) - }") + ${ + if latestOnly then + '' + (test "$(ls -A $out/lib/${pname}*${postgresql.dlSuffix} | wc -l)" = "2") + '' + else + '' + (test "$(ls -A $out/lib/${pname}*${postgresql.dlSuffix} | wc -l)" = "${ + toString (numberOfVersions + numberOfPreviouslyPackagedVersions + 1) + }") + '' + } ''; passthru = { - inherit versions numberOfVersions; + versions = versionsBuilt; + numberOfVersions = numberOfVersionsBuilt; pname = "${pname}"; + inherit latestOnly; version = - "multi-" + lib.concatStringsSep "-" (map (v: lib.replaceStrings [ "." ] [ "-" ] v) versions); + if latestOnly then + latestVersion + else + "multi-" + lib.concatStringsSep "-" (map (v: lib.replaceStrings [ "." ] [ "-" ] v) versions); # Expose individual packages for CI to build separately packages = packagesAttrSet // { recurseForDerivations = true; diff --git a/nix/packages/default.nix b/nix/packages/default.nix index c146e0096..60694333d 100644 --- a/nix/packages/default.nix +++ b/nix/packages/default.nix @@ -45,6 +45,7 @@ gatekeeper = pkgs.callPackage ./gatekeeper.nix { inherit inputs pkgs; }; supabase-groonga = pkgs.callPackage ../ext/pgroonga/groonga.nix { }; http-mock-server = pkgs.callPackage ./http-mock-server.nix { }; + image-size-analyzer = pkgs.callPackage ./image-size-analyzer.nix { }; local-infra-bootstrap = pkgs.callPackage ./local-infra-bootstrap.nix { }; mecab-naist-jdic = pkgs.callPackage ./mecab-naist-jdic.nix { }; migrate-tool = pkgs.callPackage ./migrate-tool.nix { psql_15 = self'.packages."psql_15/bin"; }; diff --git a/nix/packages/image-size-analyzer.nix b/nix/packages/image-size-analyzer.nix new file mode 100644 index 000000000..c1671fef7 --- /dev/null +++ b/nix/packages/image-size-analyzer.nix @@ -0,0 +1,378 @@ +{ + runCommand, + makeWrapper, + dive, + jq, + docker, + coreutils, + gawk, + gnused, + bc, +}: +runCommand "image-size-analyzer" + { + nativeBuildInputs = [ makeWrapper ]; + buildInputs = [ + dive + jq + docker + coreutils + gawk + gnused + bc + ]; + } + '' + mkdir -p $out/bin + cat > $out/bin/image-size-analyzer << 'SCRIPT' + #!/usr/bin/env bash + set -euo pipefail + + # Default values + OUTPUT_JSON=false + NO_BUILD=false + declare -a IMAGES=() + ALL_DOCKERFILES=("Dockerfile-15" "Dockerfile-17" "Dockerfile-orioledb-17") + TIMESTAMP=$(date +%s) + TEMP_DIR="/tmp/image-size-analyzer-$TIMESTAMP" + + show_help() { + cat << EOF + Usage: image-size-analyzer [OPTIONS] + + Analyze Docker image sizes for Supabase Postgres images. + + Options: + --json Output results as JSON instead of TUI + --image DOCKERFILE Analyze specific Dockerfile (can be used multiple times) + Valid values: Dockerfile-15, Dockerfile-17, Dockerfile-orioledb-17 + --no-build Skip building images, analyze existing ones + --help Show this help message + + Examples: + image-size-analyzer # Analyze all images + image-size-analyzer --json # Output as JSON + image-size-analyzer --image Dockerfile-17 # Analyze only Dockerfile-17 + image-size-analyzer --image Dockerfile-15 --image Dockerfile-17 + image-size-analyzer --no-build # Skip build step + EOF + } + + cleanup() { + rm -rf "$TEMP_DIR" 2>/dev/null || true + } + trap cleanup EXIT + + # Parse arguments + while [[ $# -gt 0 ]]; do + case $1 in + --json) + OUTPUT_JSON=true + shift + ;; + --no-build) + NO_BUILD=true + shift + ;; + --image) + if [[ -z "$2" ]]; then + echo "Error: --image requires a value" + exit 1 + fi + IMAGES+=("$2") + shift 2 + ;; + --help) + show_help + exit 0 + ;; + *) + echo "Error: Unknown option: $1" + show_help + exit 1 + ;; + esac + done + + # If no images specified, use all + num_images=''${#IMAGES[@]} + if [[ $num_images -eq 0 ]]; then + IMAGES=("''${ALL_DOCKERFILES[@]}") + fi + + # Validate image names + for img in "''${IMAGES[@]}"; do + valid=false + for valid_img in "''${ALL_DOCKERFILES[@]}"; do + if [[ "$img" == "$valid_img" ]]; then + valid=true + break + fi + done + if [[ "$valid" == "false" ]]; then + echo "Error: Invalid Dockerfile: $img" + echo "Valid options: ''${ALL_DOCKERFILES[*]}" + exit 1 + fi + done + + # Check Docker is running + if ! docker info &>/dev/null; then + echo "Error: Docker daemon is not running" + exit 3 + fi + + mkdir -p "$TEMP_DIR" + + # Helper to format bytes + format_bytes() { + local bytes=$1 + if [[ $bytes -ge 1073741824 ]]; then + printf "%.2f GB" "$(echo "scale=2; $bytes / 1073741824" | bc)" + elif [[ $bytes -ge 1048576 ]]; then + printf "%.2f MB" "$(echo "scale=2; $bytes / 1048576" | bc)" + elif [[ $bytes -ge 1024 ]]; then + printf "%.2f KB" "$(echo "scale=2; $bytes / 1024" | bc)" + else + printf "%d B" "$bytes" + fi + } + + # Get tag name from Dockerfile name + get_tag() { + local dockerfile=$1 + local suffix=''${dockerfile#Dockerfile-} + echo "supabase-postgres:$suffix-analyze" + } + + # Build a single image + build_image() { + local dockerfile=$1 + local tag + tag=$(get_tag "$dockerfile") + + echo "Building $dockerfile as $tag..." + if ! docker build -f "$dockerfile" -t "$tag" . ; then + echo "Error: Failed to build $dockerfile" + return 1 + fi + } + + # Get total image size + get_total_size() { + local tag=$1 + docker inspect --format='{{.Size}}' "$tag" 2>/dev/null || echo "0" + } + + # Get layer info using dive + get_layers() { + local tag=$1 + local safe_tag=''${tag//[:\/]/-} + local output_file="$TEMP_DIR/dive-$safe_tag.json" + + if ! dive "$tag" --json "$output_file" >/dev/null; then + echo "Warning: dive failed for $tag" >&2 + echo "[]" + return + fi + + # Extract layer info from dive output (note: dive uses sizeBytes not size) + jq -c '[.layer[] | {index: .index, size_bytes: .sizeBytes, command: .command}] | sort_by(-.size_bytes) | .[0:10]' "$output_file" 2>/dev/null || echo "[]" + } + + # Get directory sizes from dive output + get_directories() { + local tag=$1 + local safe_tag=''${tag//[:\/]/-} + local output_file="$TEMP_DIR/dive-$safe_tag.json" + + if [[ ! -f "$output_file" ]]; then + echo "[]" + return + fi + + # Aggregate file sizes by top-level directory from all layers + jq -c ' + [.layer[].fileList[] | select(.isDir == false and .size > 0)] + | group_by(.path | split("/")[0]) + | map({path: ("/" + (.[0].path | split("/")[0])), size_bytes: (map(.size) | add)}) + | sort_by(-.size_bytes) + | .[0:10] + ' "$output_file" 2>/dev/null || echo "[]" + } + + # Get Nix package sizes + get_nix_packages() { + local tag=$1 + + docker run --rm "$tag" sh -c 'du -sb /nix/store/*/ 2>/dev/null | sort -rn | head -15' 2>/dev/null | \ + awk '{ + size=$1 + path=$2 + # Extract package name from path like /nix/store/abc123-packagename-1.0/ + n=split(path, parts, "/") + store_path=parts[n-1] # Get the nix store hash-name part + # Remove the hash prefix (32 chars + dash) + if (length(store_path) > 33) { + name=substr(store_path, 34) + } else { + name=store_path + } + # Remove trailing slash from name + gsub(/\/$/, "", name) + printf "{\"name\":\"%s\",\"size_bytes\":%d}\n", name, size + }' | jq -s '.' 2>/dev/null || echo "[]" + } + + # Get APT package sizes + get_apt_packages() { + local tag=$1 + + docker run --rm "$tag" dpkg-query -W -f="\''${Package}\t\''${Installed-Size}\n" 2>/dev/null | \ + sort -t$'\t' -k2 -rn | head -15 | \ + awk -F'\t' '{ + # Installed-Size is in KB, convert to bytes + printf "{\"name\":\"%s\",\"size_bytes\":%d}\n", $1, $2 * 1024 + }' | jq -s '.' 2>/dev/null || echo "[]" + } + + # Analyze a single image + analyze_image() { + local dockerfile=$1 + local tag + tag=$(get_tag "$dockerfile") + + local total_size + total_size=$(get_total_size "$tag") + + local layers + layers=$(get_layers "$tag") + + local directories + directories=$(get_directories "$tag") + + local nix_packages + nix_packages=$(get_nix_packages "$tag") + + local apt_packages + apt_packages=$(get_apt_packages "$tag") + + # Build JSON result for this image + jq -n \ + --arg dockerfile "$dockerfile" \ + --argjson total_size "$total_size" \ + --argjson layers "$layers" \ + --argjson directories "$directories" \ + --argjson nix_packages "$nix_packages" \ + --argjson apt_packages "$apt_packages" \ + '{ + dockerfile: $dockerfile, + total_size_bytes: $total_size, + layers: $layers, + directories: $directories, + nix_packages: $nix_packages, + apt_packages: $apt_packages + }' + } + + # Print TUI output for a single image + print_tui() { + local json=$1 + + local dockerfile + dockerfile=$(echo "$json" | jq -r '.dockerfile') + + local total_size + total_size=$(echo "$json" | jq -r '.total_size_bytes') + + echo "" + echo "================================================================================" + echo "IMAGE: $dockerfile" + echo "================================================================================" + echo "Total Size: $(format_bytes "$total_size")" + echo "" + + echo "LAYERS (top 10 by size)" + echo "--------------------------------------------------------------------------------" + printf " %-4s %-12s %s\n" "#" "SIZE" "COMMAND" + echo "$json" | jq -r '.layers[] | "\(.index)\t\(.size_bytes)\t\(.command)"' 2>/dev/null | \ + while IFS=$'\t' read -r idx size cmd; do + cmd_short=$(echo "$cmd" | cut -c1-60) + printf " %-4s %-12s %s\n" "$idx" "$(format_bytes "$size")" "$cmd_short" + done + echo "" + + echo "DIRECTORIES (top 10 by size)" + echo "--------------------------------------------------------------------------------" + echo "$json" | jq -r '.directories[] | "\(.path)\t\(.size_bytes)"' 2>/dev/null | \ + while IFS=$'\t' read -r path size; do + printf " %-45s %s\n" "$path" "$(format_bytes "$size")" + done + echo "" + + echo "NIX PACKAGES (top 15 by size)" + echo "--------------------------------------------------------------------------------" + echo "$json" | jq -r '.nix_packages[] | "\(.name)\t\(.size_bytes)"' 2>/dev/null | \ + while IFS=$'\t' read -r name size; do + printf " %-45s %s\n" "$name" "$(format_bytes "$size")" + done + echo "" + + echo "APT PACKAGES (top 15 by size)" + echo "--------------------------------------------------------------------------------" + echo "$json" | jq -r '.apt_packages[] | "\(.name)\t\(.size_bytes)"' 2>/dev/null | \ + while IFS=$'\t' read -r name size; do + printf " %-45s %s\n" "$name" "$(format_bytes "$size")" + done + } + + # Main execution + main() { + # Build images if needed + if [[ "$NO_BUILD" == "false" ]]; then + for dockerfile in "''${IMAGES[@]}"; do + build_image "$dockerfile" || exit 1 + done + fi + + # Analyze each image + declare -a results=() + for dockerfile in "''${IMAGES[@]}"; do + local tag + tag=$(get_tag "$dockerfile") + + # Check image exists + if ! docker image inspect "$tag" &>/dev/null; then + echo "Error: Image $tag not found. Run without --no-build to build it first." + exit 1 + fi + + echo "Analyzing $dockerfile..." >&2 + local result + result=$(analyze_image "$dockerfile") + results+=("$result") + done + + # Output results + if [[ "$OUTPUT_JSON" == "true" ]]; then + # Combine all results into JSON array + printf '%s\n' "''${results[@]}" | jq -s '{images: .}' + else + for result in "''${results[@]}"; do + print_tui "$result" + done + fi + } + + main + SCRIPT + chmod +x $out/bin/image-size-analyzer + wrapProgram $out/bin/image-size-analyzer \ + --prefix PATH : ${dive}/bin \ + --prefix PATH : ${jq}/bin \ + --prefix PATH : ${docker}/bin \ + --prefix PATH : ${coreutils}/bin \ + --prefix PATH : ${gawk}/bin \ + --prefix PATH : ${gnused}/bin \ + --prefix PATH : ${bc}/bin + '' diff --git a/nix/packages/postgres.nix b/nix/packages/postgres.nix index ad1779f68..17cf760c6 100644 --- a/nix/packages/postgres.nix +++ b/nix/packages/postgres.nix @@ -93,6 +93,9 @@ makeOurPostgresPkgs = version: + { + latestOnly ? false, + }: let postgresql = getPostgresqlPackage version; extensionsToUse = @@ -105,7 +108,7 @@ extCallPackage = pkgs.lib.callPackageWith ( pkgs // { - inherit postgresql; + inherit postgresql latestOnly; switch-ext-version = extCallPackage ./switch-ext-version.nix { }; overlayfs-on-package = extCallPackage ./overlayfs-on-package.nix { }; } @@ -116,8 +119,11 @@ # Create an attrset that contains all the extensions included in a server. makeOurPostgresPkgsSet = version: + { + latestOnly ? false, + }: let - pkgsList = makeOurPostgresPkgs version; + pkgsList = makeOurPostgresPkgs version { inherit latestOnly; }; baseAttrs = builtins.listToAttrs ( map (drv: { name = drv.name; @@ -142,9 +148,12 @@ # basis for building extensions, etc. makePostgresBin = version: + { + latestOnly ? false, + }: let postgresql = getPostgresqlPackage version; - postgres-pkgs = makeOurPostgresPkgs version; + postgres-pkgs = makeOurPostgresPkgs version { inherit latestOnly; }; ourExts = map (ext: { name = ext.name; version = ext.version; @@ -171,22 +180,28 @@ # package names. makePostgres = version: + { + latestOnly ? false, + }: lib.recurseIntoAttrs { - bin = makePostgresBin version; - exts = makeOurPostgresPkgsSet version; + bin = makePostgresBin version { inherit latestOnly; }; + exts = makeOurPostgresPkgsSet version { inherit latestOnly; }; }; basePackages = { - psql_15 = makePostgres "15"; - psql_17 = makePostgres "17"; - psql_orioledb-17 = makePostgres "orioledb-17"; + psql_15 = makePostgres "15" { }; + psql_17 = makePostgres "17" { }; + psql_orioledb-17 = makePostgres "orioledb-17" { }; + }; + slimPackages = { + psql_17_slim = makePostgres "17" { latestOnly = true; }; }; binPackages = lib.mapAttrs' (name: value: { name = "${name}/bin"; value = value.bin; - }) basePackages; + }) (basePackages // slimPackages); in { packages = binPackages; - legacyPackages = basePackages; + legacyPackages = basePackages // slimPackages; }; } From db96c624bd640211e55db99731edfac0c51ec5ae Mon Sep 17 00:00:00 2001 From: Sam Rose Date: Sun, 25 Jan 2026 22:35:46 -0500 Subject: [PATCH 2/3] feat: variant of pkgs for image size reduce --- Dockerfile-17 | 331 +++++++++----------------- nix/docs/image-size-analyzer-usage.md | 269 +++++++++++++++++++++ nix/ext/hypopg.nix | 24 +- nix/ext/index_advisor.nix | 22 +- nix/ext/pg-safeupdate.nix | 24 +- nix/ext/pg_cron/default.nix | 22 +- nix/ext/pg_hashids.nix | 22 +- nix/ext/pg_jsonschema/default.nix | 22 +- nix/ext/pg_net.nix | 4 + nix/ext/pg_partman.nix | 29 ++- nix/ext/pg_plan_filter.nix | 22 +- nix/ext/pg_repack.nix | 24 +- nix/ext/pg_stat_monitor.nix | 22 +- nix/ext/pg_tle.nix | 24 +- nix/ext/pgaudit.nix | 24 +- nix/ext/pgjwt.nix | 22 +- nix/ext/pgmq/default.nix | 22 +- nix/ext/pgroonga/default.nix | 24 +- nix/ext/pgrouting/default.nix | 24 +- nix/ext/pgsodium.nix | 24 +- nix/ext/pgsql-http.nix | 24 +- nix/ext/plpgsql-check.nix | 22 +- nix/ext/plv8/default.nix | 24 +- nix/ext/postgis.nix | 26 +- nix/ext/rum.nix | 22 +- nix/ext/timescaledb.nix | 20 +- nix/ext/vault.nix | 22 +- nix/ext/wal2json.nix | 22 +- nix/packages/image-size-analyzer.nix | 30 ++- nix/postgresql/default.nix | 2 + nix/postgresql/generic.nix | 13 +- 31 files changed, 845 insertions(+), 383 deletions(-) create mode 100644 nix/docs/image-size-analyzer-usage.md diff --git a/Dockerfile-17 b/Dockerfile-17 index 0dc465bdc..178f093c9 100644 --- a/Dockerfile-17 +++ b/Dockerfile-17 @@ -1,215 +1,132 @@ # syntax=docker/dockerfile:1.6 -ARG postgresql_major=17-orioledb -ARG postgresql_release=${postgresql_major}.1 - -# Bump default build arg to build a package from source -# Bump vars.yml to specify runtime package version -ARG sfcgal_release=1.3.10 -ARG postgis_release=3.3.2 -ARG pgrouting_release=3.4.1 -ARG pgtap_release=1.2.0 -ARG pg_cron_release=1.6.2 -ARG pgaudit_release=1.7.0 -ARG pgjwt_release=9742dab1b2f297ad3811120db7b21451bca2d3c9 -ARG pgsql_http_release=1.5.0 -ARG plpgsql_check_release=2.2.5 -ARG pg_safeupdate_release=1.4 -ARG timescaledb_release=2.9.1 -ARG wal2json_release=2_5 -ARG pljava_release=1.6.4 -ARG plv8_release=3.1.5 -ARG pg_plan_filter_release=5081a7b5cb890876e67d8e7486b6a64c38c9a492 -ARG pg_net_release=0.7.1 -ARG rum_release=1.3.13 -ARG pg_hashids_release=cd0e1b31d52b394a0df64079406a14a4f7387cd6 -ARG libsodium_release=1.0.18 -ARG pgsodium_release=3.1.6 -ARG pg_graphql_release=1.5.11 -ARG pg_stat_monitor_release=1.1.1 -ARG pg_jsonschema_release=0.1.4 -ARG pg_repack_release=1.4.8 -ARG vault_release=0.2.8 -ARG groonga_release=12.0.8 -ARG pgroonga_release=2.4.0 -ARG wrappers_release=0.5.7 -ARG hypopg_release=1.3.1 -ARG pgvector_release=0.4.0 -ARG pg_tle_release=1.3.2 -ARG index_advisor_release=0.2.0 -ARG supautils_release=2.2.0 -ARG wal_g_release=3.0.5 - -FROM ubuntu:noble as base - -# Create reusable apt mirror fallback function -RUN echo '#!/bin/bash\n\ -apt_update_with_fallback() {\n\ - local sources_file="/etc/apt/sources.list.d/ubuntu.sources"\n\ - local max_attempts=2\n\ - local attempt=1\n\ - local mirrors="archive.ubuntu.com us.archive.ubuntu.com"\n\ - \n\ - for mirror in $mirrors; do\n\ - echo "========================================="\n\ - echo "Attempting apt-get update with mirror: ${mirror}"\n\ - echo "Attempt ${attempt} of ${max_attempts}"\n\ - echo "========================================="\n\ - \n\ - if [ -f "${sources_file}" ]; then\n\ - sed -i "s|http://[^/]*/ubuntu/|http://${mirror}/ubuntu/|g" "${sources_file}"\n\ - fi\n\ - \n\ - if timeout 300 apt-get update 2>&1; then\n\ - echo "========================================="\n\ - echo "✓ Successfully updated apt cache using mirror: ${mirror}"\n\ - echo "========================================="\n\ - return 0\n\ - else\n\ - local exit_code=$?\n\ - echo "========================================="\n\ - echo "✗ Failed to update using mirror: ${mirror}"\n\ - echo "Exit code: ${exit_code}"\n\ - echo "========================================="\n\ - \n\ - apt-get clean\n\ - rm -rf /var/lib/apt/lists/*\n\ - \n\ - if [ ${attempt} -lt ${max_attempts} ]; then\n\ - local sleep_time=$((attempt * 5))\n\ - echo "Waiting ${sleep_time} seconds before trying next mirror..."\n\ - sleep ${sleep_time}\n\ - fi\n\ - fi\n\ - \n\ - attempt=$((attempt + 1))\n\ - done\n\ - \n\ - echo "========================================="\n\ - echo "ERROR: All mirror tiers failed after ${max_attempts} attempts"\n\ - echo "========================================="\n\ - return 1\n\ -}' > /usr/local/bin/apt-update-fallback.sh && chmod +x /usr/local/bin/apt-update-fallback.sh - -RUN bash -c 'source /usr/local/bin/apt-update-fallback.sh && apt_update_with_fallback' && apt install -y \ +# Alpine-based slim PostgreSQL image with Nix extensions + +#################### +# Stage 1: Nix builder +#################### +FROM alpine:3.21 AS nix-builder + +# Install dependencies for nix installer (coreutils for GNU cp, sudo for installer) +RUN apk add --no-cache \ + bash \ + coreutils \ curl \ - gnupg \ - lsb-release \ - software-properties-common \ - wget \ + shadow \ sudo \ - tree \ - && apt clean + xz +# Create users (Alpine syntax) +RUN addgroup -S postgres && \ + adduser -S -h /var/lib/postgresql -s /bin/bash -G postgres postgres && \ + addgroup -S wal-g && \ + adduser -S -s /bin/bash -G wal-g wal-g -RUN adduser --system --home /var/lib/postgresql --no-create-home --shell /bin/bash --group --gecos "PostgreSQL administrator" postgres -RUN adduser --system --no-create-home --shell /bin/bash --group wal-g +# Create nix config RUN cat < /tmp/extra-nix.conf extra-experimental-features = nix-command flakes extra-substituters = https://nix-postgres-artifacts.s3.amazonaws.com extra-trusted-public-keys = nix-postgres-artifacts:dGZlQOvKcNEjvT7QEAJbcV6b6uk7VF/hWMjhYleiaLI= EOF + +# Install nix RUN curl -L https://releases.nixos.org/nix/nix-2.32.2/install | sh -s -- --daemon --no-channel-add --yes --nix-extra-conf-file /tmp/extra-nix.conf ENV PATH="${PATH}:/nix/var/nix/profiles/default/bin" -COPY . /nixpg - WORKDIR /nixpg +COPY . . -RUN nix profile add path:.#psql_17/bin +# Build PostgreSQL with extensions +RUN nix profile add path:.#psql_17_slim/bin RUN nix store gc -WORKDIR / - - -RUN mkdir -p /usr/lib/postgresql/bin \ - /usr/lib/postgresql/share/postgresql \ - /usr/share/postgresql \ - /var/lib/postgresql \ - && chown -R postgres:postgres /usr/lib/postgresql \ - && chown -R postgres:postgres /var/lib/postgresql \ - && chown -R postgres:postgres /usr/share/postgresql - -# Create symbolic links -RUN ln -s /nix/var/nix/profiles/default/bin/* /usr/lib/postgresql/bin/ \ - && ln -s /nix/var/nix/profiles/default/bin/* /usr/bin/ \ - && chown -R postgres:postgres /usr/bin - -# Create symbolic links for PostgreSQL shares -RUN ln -s /nix/var/nix/profiles/default/share/postgresql/* /usr/lib/postgresql/share/postgresql/ -RUN ln -s /nix/var/nix/profiles/default/share/postgresql/* /usr/share/postgresql/ -RUN chown -R postgres:postgres /usr/lib/postgresql/share/postgresql/ -RUN chown -R postgres:postgres /usr/share/postgresql/ - -RUN tree /nix > /tmp/tree.txt && cat /tmp/tree.txt && cat /tmp/tree.txt >&2 - -RUN chown -R postgres:postgres /usr/lib/postgresql - -RUN ln -sf /usr/lib/postgresql/share/postgresql/timezonesets /usr/share/postgresql/timezonesets +# Build groonga and copy plugins +RUN nix profile add path:.#supabase-groonga && \ + mkdir -p /tmp/groonga-plugins && \ + cp -r /nix/var/nix/profiles/default/lib/groonga/plugins /tmp/groonga-plugins/ +RUN nix store gc -RUN bash -c 'source /usr/local/bin/apt-update-fallback.sh && apt_update_with_fallback' && \ - apt-get install -y --no-install-recommends tzdata +#################### +# Stage 2: Gosu builder +#################### +FROM alpine:3.21 AS gosu-builder -RUN ln -fs /usr/share/zoneinfo/Etc/UTC /etc/localtime && \ - dpkg-reconfigure --frontend noninteractive tzdata +ARG TARGETARCH +ARG GOSU_VERSION=1.16 -RUN bash -c 'source /usr/local/bin/apt-update-fallback.sh && apt_update_with_fallback' && \ - apt-get install -y --no-install-recommends \ - build-essential \ - checkinstall \ - cmake +RUN apk add --no-cache gnupg curl -ENV PGDATA=/var/lib/postgresql/data +# Download and verify gosu +RUN curl -fsSL "https://github.com/tianon/gosu/releases/download/${GOSU_VERSION}/gosu-${TARGETARCH}" -o /usr/local/bin/gosu && \ + curl -fsSL "https://github.com/tianon/gosu/releases/download/${GOSU_VERSION}/gosu-${TARGETARCH}.asc" -o /usr/local/bin/gosu.asc && \ + GNUPGHOME="$(mktemp -d)" && \ + export GNUPGHOME && \ + gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4 && \ + gpg --batch --verify /usr/local/bin/gosu.asc /usr/local/bin/gosu && \ + rm -rf "$GNUPGHOME" /usr/local/bin/gosu.asc && \ + chmod +x /usr/local/bin/gosu -WORKDIR / #################### -# setup-groonga +# Stage 3: Final production image #################### -FROM base as groonga +FROM alpine:3.21 AS production -WORKDIR /nixpg - -RUN nix profile add path:.#supabase-groonga && \ - mkdir -p /tmp/groonga-plugins && \ - cp -r /nix/var/nix/profiles/default/lib/groonga/plugins /tmp/groonga-plugins/ +# Install minimal runtime dependencies +RUN apk add --no-cache \ + bash \ + curl \ + shadow \ + su-exec \ + tzdata \ + musl-locales \ + musl-locales-lang \ + && rm -rf /var/cache/apk/* + +# Create postgres user/group +RUN addgroup -S postgres && \ + adduser -S -G postgres -h /var/lib/postgresql -s /bin/bash postgres && \ + addgroup -S wal-g && \ + adduser -S -G wal-g -s /bin/bash wal-g && \ + adduser postgres wal-g + +# Copy Nix store and profiles from builder (profile already created by nix profile install) +COPY --from=nix-builder /nix /nix + +# Copy groonga plugins +COPY --from=nix-builder /tmp/groonga-plugins/plugins /usr/lib/groonga/plugins + +# Copy gosu +COPY --from=gosu-builder /usr/local/bin/gosu /usr/local/bin/gosu + +# Setup PostgreSQL directories +RUN mkdir -p /usr/lib/postgresql/bin \ + /usr/lib/postgresql/share/postgresql \ + /usr/share/postgresql \ + /var/lib/postgresql/data \ + /var/run/postgresql \ + && chown -R postgres:postgres /usr/lib/postgresql \ + && chown -R postgres:postgres /var/lib/postgresql \ + && chown -R postgres:postgres /usr/share/postgresql \ + && chown -R postgres:postgres /var/run/postgresql -RUN nix store gc +# Create symbolic links for binaries +RUN for f in /nix/var/nix/profiles/default/bin/*; do \ + ln -sf "$f" /usr/lib/postgresql/bin/ 2>/dev/null || true; \ + ln -sf "$f" /usr/bin/ 2>/dev/null || true; \ + done -WORKDIR / -# #################### -# # Download gosu for easy step-down from root -# #################### -FROM base as gosu -ARG TARGETARCH -# Install dependencies -RUN bash -c 'source /usr/local/bin/apt-update-fallback.sh && apt_update_with_fallback' && apt-get install -y --no-install-recommends \ - gnupg \ - ca-certificates \ - && rm -rf /var/lib/apt/lists/* -# Download binary -ARG GOSU_VERSION=1.16 -ARG GOSU_GPG_KEY=B42F6819007F00F88E364FD4036A9C25BF357DD4 -ADD https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$TARGETARCH \ - /usr/local/bin/gosu -ADD https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$TARGETARCH.asc \ - /usr/local/bin/gosu.asc -# Verify checksum -RUN gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys $GOSU_GPG_KEY && \ - gpg --batch --verify /usr/local/bin/gosu.asc /usr/local/bin/gosu && \ - gpgconf --kill all && \ - chmod +x /usr/local/bin/gosu +# Create symbolic links for PostgreSQL shares +RUN ln -sf /nix/var/nix/profiles/default/share/postgresql/* /usr/lib/postgresql/share/postgresql/ 2>/dev/null || true && \ + ln -sf /nix/var/nix/profiles/default/share/postgresql/* /usr/share/postgresql/ 2>/dev/null || true && \ + ln -sf /usr/lib/postgresql/share/postgresql/timezonesets /usr/share/postgresql/timezonesets 2>/dev/null || true -# #################### -# # Build final image -# #################### -FROM gosu as production -RUN id postgres || (echo "postgres user does not exist" && exit 1) -# # Setup extensions -COPY --from=groonga /tmp/groonga-plugins/plugins /usr/lib/groonga/plugins +# Set permissions +RUN chown -R postgres:postgres /usr/lib/postgresql && \ + chown -R postgres:postgres /usr/share/postgresql -# # Initialise configs +# Setup configs COPY --chown=postgres:postgres ansible/files/postgresql_config/postgresql.conf.j2 /etc/postgresql/postgresql.conf COPY --chown=postgres:postgres ansible/files/postgresql_config/pg_hba.conf.j2 /etc/postgresql/pg_hba.conf COPY --chown=postgres:postgres ansible/files/postgresql_config/pg_ident.conf.j2 /etc/postgresql/pg_ident.conf @@ -221,60 +138,50 @@ COPY --chown=postgres:postgres ansible/files/pgsodium_getkey_urandom.sh.j2 /usr/ COPY --chown=postgres:postgres ansible/files/walg_helper_scripts/wal_fetch.sh /home/postgres/wal_fetch.sh COPY ansible/files/walg_helper_scripts/wal_change_ownership.sh /root/wal_change_ownership.sh +# Configure PostgreSQL settings RUN sed -i \ -e "s|#session_preload_libraries = ''|session_preload_libraries = 'supautils'|g" \ -e "s|#include = '/etc/postgresql-custom/supautils.conf'|include = '/etc/postgresql-custom/supautils.conf'|g" \ /etc/postgresql/postgresql.conf && \ echo "pgsodium.getkey_script= '/usr/lib/postgresql/bin/pgsodium_getkey.sh'" >> /etc/postgresql/postgresql.conf && \ echo "vault.getkey_script= '/usr/lib/postgresql/bin/pgsodium_getkey.sh'" >> /etc/postgresql/postgresql.conf && \ - usermod -aG postgres wal-g && \ chown -R postgres:postgres /etc/postgresql-custom - # Remove items from postgresql.conf -RUN sed -i 's/ timescaledb,//g;' "/etc/postgresql/postgresql.conf" - #as of pg 16.4 + this db_user_namespace totally deprecated and will break the server if setting is present -RUN sed -i 's/db_user_namespace = off/#db_user_namespace = off/g;' "/etc/postgresql/postgresql.conf" -RUN sed -i 's/ timescaledb,//g; s/ plv8,//g' "/etc/postgresql-custom/supautils.conf" +# Remove timescaledb and plv8 references (not in pg17) +RUN sed -i 's/ timescaledb,//g;' "/etc/postgresql/postgresql.conf" && \ + sed -i 's/db_user_namespace = off/#db_user_namespace = off/g;' "/etc/postgresql/postgresql.conf" && \ + sed -i 's/ timescaledb,//g; s/ plv8,//g' "/etc/postgresql-custom/supautils.conf" - - -# # Include schema migrations +# Include schema migrations COPY migrations/db /docker-entrypoint-initdb.d/ COPY ansible/files/pgbouncer_config/pgbouncer_auth_schema.sql /docker-entrypoint-initdb.d/init-scripts/00-schema.sql COPY ansible/files/stat_extension.sql /docker-entrypoint-initdb.d/migrations/00-extension.sql -# # Add upstream entrypoint script pinned for now to last tested version -COPY --from=gosu /usr/local/bin/gosu /usr/local/bin/gosu +# Add entrypoint script ADD --chmod=0755 \ https://github.com/docker-library/postgres/raw/889f9447cd2dfe21cccfbe9bb7945e3b037e02d8/17/bullseye/docker-entrypoint.sh \ /usr/local/bin/docker-entrypoint.sh -RUN mkdir -p /var/run/postgresql && chown postgres:postgres /var/run/postgresql - -ENTRYPOINT ["docker-entrypoint.sh"] - -HEALTHCHECK --interval=2s --timeout=2s --retries=10 CMD pg_isready -U postgres -h localhost -STOPSIGNAL SIGINT -EXPOSE 5432 +# Setup pgsodium key script +RUN mkdir -p /usr/share/postgresql/extension/ && \ + ln -s /usr/lib/postgresql/bin/pgsodium_getkey.sh /usr/share/postgresql/extension/pgsodium_getkey && \ + chmod +x /usr/lib/postgresql/bin/pgsodium_getkey.sh +# Environment variables +ENV PATH="/nix/var/nix/profiles/default/bin:/usr/lib/postgresql/bin:${PATH}" +ENV PGDATA=/var/lib/postgresql/data ENV POSTGRES_HOST=/var/run/postgresql ENV POSTGRES_USER=supabase_admin ENV POSTGRES_DB=postgres ENV POSTGRES_INITDB_ARGS="--allow-group-access --locale-provider=icu --encoding=UTF-8 --icu-locale=en_US.UTF-8" -RUN bash -c 'source /usr/local/bin/apt-update-fallback.sh && apt_update_with_fallback' && apt-get install -y --no-install-recommends \ - locales \ - && rm -rf /var/lib/apt/lists/* && \ - localedef -i en_US -c -f UTF-8 -A /usr/share/locale/locale.alias en_US.UTF-8 \ - && localedef -i C -c -f UTF-8 -A /usr/share/locale/locale.alias C.UTF-8 -RUN echo "C.UTF-8 UTF-8" > /etc/locale.gen && echo "en_US.UTF-8 UTF-8" >> /etc/locale.gen && locale-gen -ENV LANG en_US.UTF-8 -ENV LANGUAGE en_US:en -ENV LC_ALL en_US.UTF-8 -ENV LOCALE_ARCHIVE /usr/lib/locale/locale-archive -RUN mkdir -p /usr/share/postgresql/extension/ && \ - ln -s /usr/lib/postgresql/bin/pgsodium_getkey.sh /usr/share/postgresql/extension/pgsodium_getkey && \ - chmod +x /usr/lib/postgresql/bin/pgsodium_getkey.sh - +ENV LANG=en_US.UTF-8 +ENV LANGUAGE=en_US:en +ENV LC_ALL=en_US.UTF-8 ENV GRN_PLUGINS_DIR=/usr/lib/groonga/plugins +ENTRYPOINT ["docker-entrypoint.sh"] +HEALTHCHECK --interval=2s --timeout=2s --retries=10 CMD pg_isready -U postgres -h localhost +STOPSIGNAL SIGINT +EXPOSE 5432 + CMD ["postgres", "-D", "/etc/postgresql"] diff --git a/nix/docs/image-size-analyzer-usage.md b/nix/docs/image-size-analyzer-usage.md new file mode 100644 index 000000000..dc5845b06 --- /dev/null +++ b/nix/docs/image-size-analyzer-usage.md @@ -0,0 +1,269 @@ +# Image Size Analyzer - Usage Guide + +A tool to analyze Docker image sizes for Supabase Postgres images, providing breakdowns by layers, directories, Nix packages, and APT packages. + +## Local Usage + +### Prerequisites + +- Nix with flakes enabled +- Docker daemon running + +### Basic Commands + +```bash +# Analyze all images (Dockerfile-15, Dockerfile-17, Dockerfile-orioledb-17) +# This will build all images first, then analyze them +nix run .#image-size-analyzer + +# Analyze a specific image +nix run .#image-size-analyzer -- --image Dockerfile-17 + +# Analyze multiple specific images +nix run .#image-size-analyzer -- --image Dockerfile-15 --image Dockerfile-17 + +# Skip building (analyze existing images) +# Images must already exist with the -analyze tag suffix +nix run .#image-size-analyzer -- --no-build + +# Output as JSON instead of TUI +nix run .#image-size-analyzer -- --json + +# Combine flags +nix run .#image-size-analyzer -- --image Dockerfile-17 --json --no-build +``` + +### Understanding the Output + +The TUI output shows four sections per image: + +1. **Total Size** - Overall image size +2. **Layers** - Top 10 Docker layers by size, showing which Dockerfile instructions add the most +3. **Directories** - Top 10 directories by size inside the image +4. **Nix Packages** - Top 15 Nix store packages by size (e.g., postgresql, postgis, extensions) +5. **APT Packages** - Top 15 Debian packages by size + +### Example Workflow + +```bash +# 1. Make changes to reduce image size (e.g., remove an extension) + +# 2. Build and analyze the specific image you changed +nix run .#image-size-analyzer -- --image Dockerfile-17 + +# 3. Compare with JSON output for precise numbers +nix run .#image-size-analyzer -- --image Dockerfile-17 --json > before.json + +# 4. Make more changes, then compare +nix run .#image-size-analyzer -- --image Dockerfile-17 --json > after.json +diff before.json after.json +``` + +--- + +## CI Usage + +### GitHub Actions Example + +```yaml +name: Image Size Analysis + +on: + pull_request: + paths: + - 'docker/**' + - 'nix/**' + workflow_dispatch: + +jobs: + analyze-image-size: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Install Nix + uses: cachix/install-nix-action@v27 + with: + extra_nix_config: | + extra-substituters = https://nix-postgres-artifacts.s3.amazonaws.com + extra-trusted-public-keys = nix-postgres-artifacts:dGZlQOvKcNEjvT7QEAJbcV6b6uk7VF/hWMjhYleiaLI= + + - name: Analyze image sizes + run: | + nix run .#image-size-analyzer -- --json > image-sizes.json + + - name: Upload size report + uses: actions/upload-artifact@v4 + with: + name: image-size-report + path: image-sizes.json + + - name: Comment PR with sizes + if: github.event_name == 'pull_request' + uses: actions/github-script@v7 + with: + script: | + const fs = require('fs'); + const report = JSON.parse(fs.readFileSync('image-sizes.json', 'utf8')); + + let comment = '## Docker Image Size Report\n\n'; + for (const image of report.images) { + const sizeGB = (image.total_size_bytes / 1073741824).toFixed(2); + comment += `### ${image.dockerfile}: ${sizeGB} GB\n\n`; + + comment += '**Top 5 Nix Packages:**\n'; + for (const pkg of image.nix_packages.slice(0, 5)) { + const sizeMB = (pkg.size_bytes / 1048576).toFixed(1); + comment += `- ${pkg.name}: ${sizeMB} MB\n`; + } + comment += '\n'; + } + + github.rest.issues.createComment({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + body: comment + }); +``` + +### Size Threshold Check + +Add a job that fails if images exceed a size threshold: + +```yaml + check-size-threshold: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Install Nix + uses: cachix/install-nix-action@v27 + with: + extra_nix_config: | + extra-substituters = https://nix-postgres-artifacts.s3.amazonaws.com + extra-trusted-public-keys = nix-postgres-artifacts:dGZlQOvKcNEjvT7QEAJbcV6b6uk7VF/hWMjhYleiaLI= + + - name: Check image sizes + run: | + nix run .#image-size-analyzer -- --json > sizes.json + + # Set threshold (2.5 GB in bytes) + THRESHOLD=2684354560 + + # Check each image + for dockerfile in Dockerfile-15 Dockerfile-17 Dockerfile-orioledb-17; do + size=$(jq -r ".images[] | select(.dockerfile == \"$dockerfile\") | .total_size_bytes" sizes.json) + if [ "$size" -gt "$THRESHOLD" ]; then + echo "ERROR: $dockerfile exceeds size threshold" + echo " Size: $((size / 1048576)) MB" + echo " Threshold: $((THRESHOLD / 1048576)) MB" + exit 1 + fi + echo "OK: $dockerfile = $((size / 1048576)) MB" + done +``` + +### Size Regression Check + +Compare against a baseline to catch size regressions: + +```yaml + check-size-regression: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 # Need full history for base branch + + - name: Install Nix + uses: cachix/install-nix-action@v27 + with: + extra_nix_config: | + extra-substituters = https://nix-postgres-artifacts.s3.amazonaws.com + extra-trusted-public-keys = nix-postgres-artifacts:dGZlQOvKcNEjvT7QEAJbcV6b6uk7VF/hWMjhYleiaLI= + + - name: Analyze PR branch + run: | + nix run .#image-size-analyzer -- --image Dockerfile-17 --json > pr-sizes.json + + - name: Analyze base branch + run: | + git checkout ${{ github.base_ref }} + nix run .#image-size-analyzer -- --image Dockerfile-17 --json > base-sizes.json + git checkout - + + - name: Compare sizes + run: | + PR_SIZE=$(jq -r '.images[0].total_size_bytes' pr-sizes.json) + BASE_SIZE=$(jq -r '.images[0].total_size_bytes' base-sizes.json) + + DIFF=$((PR_SIZE - BASE_SIZE)) + DIFF_MB=$((DIFF / 1048576)) + + # Allow up to 50MB increase + MAX_INCREASE=52428800 + + if [ "$DIFF" -gt "$MAX_INCREASE" ]; then + echo "ERROR: Image size increased by ${DIFF_MB}MB (max allowed: 50MB)" + echo "Base: $((BASE_SIZE / 1048576))MB" + echo "PR: $((PR_SIZE / 1048576))MB" + exit 1 + fi + + echo "Size change: ${DIFF_MB}MB" +``` + +--- + +## JSON Output Schema + +```json +{ + "images": [ + { + "dockerfile": "Dockerfile-17", + "total_size_bytes": 1954000000, + "layers": [ + { + "index": 0, + "size_bytes": 890000000, + "command": "COPY /nix/store /nix/store" + } + ], + "directories": [ + { + "path": "/nix/store", + "size_bytes": 1200000000 + } + ], + "nix_packages": [ + { + "name": "postgresql-17.6", + "size_bytes": 152000000 + } + ], + "apt_packages": [ + { + "name": "libc6", + "size_bytes": 12500000 + } + ] + } + ] +} +``` + +--- + +## Tips + +1. **Use `--no-build` for iteration** - Once you've built an image, use `--no-build` to quickly re-analyze without rebuilding. + +2. **Focus on Nix packages** - Most of the image size comes from `/nix/store/`. The Nix packages breakdown helps identify which extensions or dependencies are largest. + +3. **Check layers for optimization opportunities** - If a layer is unexpectedly large, investigate the corresponding Dockerfile instruction. + +4. **Use JSON for automation** - The JSON output is stable and can be parsed with `jq` for scripting and CI integration. + +5. **Compare before/after** - Always capture baseline sizes before making changes so you can measure the impact. diff --git a/nix/ext/hypopg.nix b/nix/ext/hypopg.nix index 92784a8de..b3e880a1b 100644 --- a/nix/ext/hypopg.nix +++ b/nix/ext/hypopg.nix @@ -4,6 +4,7 @@ buildEnv, fetchFromGitHub, postgresql, + latestOnly ? false, }: let @@ -14,7 +15,13 @@ let ) allVersions; versions = lib.naturalSort (lib.attrNames supportedVersions); latestVersion = lib.last versions; - numberOfVersions = builtins.length versions; + versionsToUse = + if latestOnly then + { "${latestVersion}" = supportedVersions.${latestVersion}; } + else + supportedVersions; + versionsBuilt = if latestOnly then [ latestVersion ] else versions; + numberOfVersionsBuilt = builtins.length versionsBuilt; build = version: hash: stdenv.mkDerivation rec { @@ -66,9 +73,7 @@ let inherit (postgresql.meta) platforms; }; }; - packages = builtins.attrValues ( - lib.mapAttrs (name: value: build name value.hash) supportedVersions - ); + packages = builtins.attrValues (lib.mapAttrs (name: value: build name value.hash) versionsToUse); in buildEnv { name = pname; @@ -81,14 +86,19 @@ buildEnv { # checks (set -x test "$(ls -A $out/lib/${pname}*${postgresql.dlSuffix} | wc -l)" = "${ - toString (numberOfVersions + 1) + toString (numberOfVersionsBuilt + 1) }" ) ''; passthru = { - inherit versions numberOfVersions pname; + versions = versionsBuilt; + numberOfVersions = numberOfVersionsBuilt; + inherit pname latestOnly; version = - "multi-" + lib.concatStringsSep "-" (map (v: lib.replaceStrings [ "." ] [ "-" ] v) versions); + if latestOnly then + latestVersion + else + "multi-" + lib.concatStringsSep "-" (map (v: lib.replaceStrings [ "." ] [ "-" ] v) versions); }; } diff --git a/nix/ext/index_advisor.nix b/nix/ext/index_advisor.nix index 85a23bfd0..3130d4bcc 100644 --- a/nix/ext/index_advisor.nix +++ b/nix/ext/index_advisor.nix @@ -5,6 +5,7 @@ fetchFromGitHub, postgresql, callPackage, + latestOnly ? false, }: let @@ -15,7 +16,13 @@ let ) allVersions; versions = lib.naturalSort (lib.attrNames supportedVersions); latestVersion = lib.last versions; - numberOfVersions = builtins.length versions; + versionsToUse = + if latestOnly then + { "${latestVersion}" = supportedVersions.${latestVersion}; } + else + supportedVersions; + versionsBuilt = if latestOnly then [ latestVersion ] else versions; + numberOfVersionsBuilt = builtins.length versionsBuilt; build = version: hash: stdenv.mkDerivation rec { @@ -64,9 +71,7 @@ let inherit (postgresql.meta) platforms; }; }; - packages = builtins.attrValues ( - lib.mapAttrs (name: value: build name value.hash) supportedVersions - ); + packages = builtins.attrValues (lib.mapAttrs (name: value: build name value.hash) versionsToUse); in pkgs.buildEnv { name = pname; @@ -78,8 +83,13 @@ pkgs.buildEnv { ]; passthru = { - inherit versions numberOfVersions pname; + versions = versionsBuilt; + numberOfVersions = numberOfVersionsBuilt; + inherit pname latestOnly; version = - "multi-" + lib.concatStringsSep "-" (map (v: lib.replaceStrings [ "." ] [ "-" ] v) versions); + if latestOnly then + latestVersion + else + "multi-" + lib.concatStringsSep "-" (map (v: lib.replaceStrings [ "." ] [ "-" ] v) versions); }; } diff --git a/nix/ext/pg-safeupdate.nix b/nix/ext/pg-safeupdate.nix index ee31f4371..97921c9c6 100644 --- a/nix/ext/pg-safeupdate.nix +++ b/nix/ext/pg-safeupdate.nix @@ -5,6 +5,7 @@ fetchFromGitHub, postgresql, makeWrapper, + latestOnly ? false, }: let @@ -49,10 +50,14 @@ let ) allVersions; versions = lib.naturalSort (lib.attrNames supportedVersions); latestVersion = lib.last versions; - numberOfVersions = builtins.length versions; - packages = builtins.attrValues ( - lib.mapAttrs (name: value: build name value.hash) supportedVersions - ); + versionsToUse = + if latestOnly then + { "${latestVersion}" = supportedVersions.${latestVersion}; } + else + supportedVersions; + versionsBuilt = if latestOnly then [ latestVersion ] else versions; + numberOfVersionsBuilt = builtins.length versionsBuilt; + packages = builtins.attrValues (lib.mapAttrs (name: value: build name value.hash) versionsToUse); in pkgs.buildEnv { name = pname; @@ -68,18 +73,23 @@ pkgs.buildEnv { # checks (set -x test "$(ls -A $out/lib/${pname}*${postgresql.dlSuffix} | wc -l)" = "${ - toString (numberOfVersions + 1) + toString (numberOfVersionsBuilt + 1) }" ) ''; passthru = { - inherit versions numberOfVersions pname; + versions = versionsBuilt; + numberOfVersions = numberOfVersionsBuilt; + inherit pname latestOnly; defaultSettings = { shared_preload_libraries = [ "safeupdate" ]; }; pgRegressTestName = "pg-safeupdate"; version = - "multi-" + lib.concatStringsSep "-" (map (v: lib.replaceStrings [ "." ] [ "-" ] v) versions); + if latestOnly then + latestVersion + else + "multi-" + lib.concatStringsSep "-" (map (v: lib.replaceStrings [ "." ] [ "-" ] v) versions); }; } diff --git a/nix/ext/pg_cron/default.nix b/nix/ext/pg_cron/default.nix index cec9d8ec4..a823fa450 100644 --- a/nix/ext/pg_cron/default.nix +++ b/nix/ext/pg_cron/default.nix @@ -6,6 +6,7 @@ buildEnv, makeWrapper, switch-ext-version, + latestOnly ? false, }: let pname = "pg_cron"; @@ -15,7 +16,13 @@ let ) allVersions; versions = lib.naturalSort (lib.attrNames supportedVersions); latestVersion = lib.last versions; - numberOfVersions = builtins.length versions; + versionsToUse = + if latestOnly then + { "${latestVersion}" = supportedVersions.${latestVersion}; } + else + supportedVersions; + versionsBuilt = if latestOnly then [ latestVersion ] else versions; + numberOfVersionsBuilt = builtins.length versionsBuilt; build = version: versionData: stdenv.mkDerivation rec { @@ -71,7 +78,7 @@ let license = licenses.postgresql; }; }; - packages = builtins.attrValues (lib.mapAttrs (name: value: build name value) supportedVersions); + packages = builtins.attrValues (lib.mapAttrs (name: value: build name value) versionsToUse); in buildEnv { name = pname; @@ -93,7 +100,7 @@ buildEnv { # checks (set -x test "$(ls -A $out/lib/${pname}*${postgresql.dlSuffix} | wc -l)" = "${ - toString (numberOfVersions + 1) + toString (numberOfVersionsBuilt + 1) }" ) @@ -109,13 +116,18 @@ buildEnv { }; passthru = { - inherit versions numberOfVersions switch-ext-version; + versions = versionsBuilt; + numberOfVersions = numberOfVersionsBuilt; + inherit switch-ext-version latestOnly; hasBackgroundWorker = true; defaultSettings = { shared_preload_libraries = [ "pg_cron" ]; "cron.database_name" = "postgres"; }; version = - "multi-" + lib.concatStringsSep "-" (map (v: lib.replaceStrings [ "." ] [ "-" ] v) versions); + if latestOnly then + latestVersion + else + "multi-" + lib.concatStringsSep "-" (map (v: lib.replaceStrings [ "." ] [ "-" ] v) versions); }; } diff --git a/nix/ext/pg_hashids.nix b/nix/ext/pg_hashids.nix index b11c5ce68..c8fc3fef5 100644 --- a/nix/ext/pg_hashids.nix +++ b/nix/ext/pg_hashids.nix @@ -4,6 +4,7 @@ fetchFromGitHub, postgresql, buildEnv, + latestOnly ? false, }: let pname = "pg_hashids"; @@ -71,9 +72,15 @@ let ) allVersions; versions = lib.naturalSort (lib.attrNames supportedVersions); latestVersion = lib.last versions; - numberOfVersions = builtins.length versions; + versionsToUse = + if latestOnly then + { "${latestVersion}" = supportedVersions.${latestVersion}; } + else + supportedVersions; + versionsBuilt = if latestOnly then [ latestVersion ] else versions; + numberOfVersionsBuilt = builtins.length versionsBuilt; packages = builtins.attrValues ( - lib.mapAttrs (name: value: build name value.hash (value.revision or name)) supportedVersions + lib.mapAttrs (name: value: build name value.hash (value.revision or name)) versionsToUse ); in buildEnv { @@ -87,14 +94,19 @@ buildEnv { # checks (set -x test "$(ls -A $out/lib/${pname}*${postgresql.dlSuffix} | wc -l)" = "${ - toString (numberOfVersions + 1) + toString (numberOfVersionsBuilt + 1) }" ) ''; passthru = { - inherit versions numberOfVersions pname; + versions = versionsBuilt; + numberOfVersions = numberOfVersionsBuilt; + inherit pname latestOnly; version = - "multi-" + lib.concatStringsSep "-" (map (v: lib.replaceStrings [ "." ] [ "-" ] v) versions); + if latestOnly then + latestVersion + else + "multi-" + lib.concatStringsSep "-" (map (v: lib.replaceStrings [ "." ] [ "-" ] v) versions); }; } diff --git a/nix/ext/pg_jsonschema/default.nix b/nix/ext/pg_jsonschema/default.nix index d3a72036f..4ec4f97a9 100644 --- a/nix/ext/pg_jsonschema/default.nix +++ b/nix/ext/pg_jsonschema/default.nix @@ -6,6 +6,7 @@ fetchFromGitHub, postgresql, rust-bin, + latestOnly ? false, }: let pname = "pg_jsonschema"; @@ -131,10 +132,16 @@ let ) allVersions; versions = lib.naturalSort (lib.attrNames supportedVersions); latestVersion = lib.last versions; - numberOfVersions = builtins.length versions; + versionsToUse = + if latestOnly then + { "${latestVersion}" = supportedVersions.${latestVersion}; } + else + supportedVersions; packages = builtins.attrValues ( - lib.mapAttrs (name: value: build name value.hash value.rust value.pgrx) supportedVersions + lib.mapAttrs (name: value: build name value.hash value.rust value.pgrx) versionsToUse ); + versionsBuilt = if latestOnly then [ latestVersion ] else versions; + numberOfVersionsBuilt = builtins.length versionsBuilt; in (pkgs.buildEnv { name = pname; @@ -147,7 +154,7 @@ in # checks (set -x test "$(ls -A $out/lib/${pname}*${postgresql.dlSuffix} | wc -l)" = "${ - toString (numberOfVersions + 1) + toString (numberOfVersionsBuilt + 1) }" ) @@ -171,9 +178,14 @@ in ''; passthru = { - inherit versions numberOfVersions pname; + versions = versionsBuilt; + numberOfVersions = numberOfVersionsBuilt; + inherit pname latestOnly; version = - "multi-" + lib.concatStringsSep "-" (map (v: lib.replaceStrings [ "." ] [ "-" ] v) versions); + if latestOnly then + latestVersion + else + "multi-" + lib.concatStringsSep "-" (map (v: lib.replaceStrings [ "." ] [ "-" ] v) versions); }; }).overrideAttrs (_: { diff --git a/nix/ext/pg_net.nix b/nix/ext/pg_net.nix index d6b934901..09692b6ac 100644 --- a/nix/ext/pg_net.nix +++ b/nix/ext/pg_net.nix @@ -112,6 +112,10 @@ pkgs.buildEnv { name = pname; paths = packages; nativeBuildInputs = [ makeWrapper ]; + pathsToLink = [ + "/lib" + "/share/postgresql/extension" + ]; postBuild = '' { echo "default_version = '${latestVersion}'" diff --git a/nix/ext/pg_partman.nix b/nix/ext/pg_partman.nix index 809861d52..4c36e765f 100644 --- a/nix/ext/pg_partman.nix +++ b/nix/ext/pg_partman.nix @@ -6,6 +6,7 @@ postgresql, makeWrapper, switch-ext-version, + latestOnly ? false, }: let @@ -60,10 +61,14 @@ let ) allVersions; versions = lib.naturalSort (lib.attrNames supportedVersions); latestVersion = lib.last versions; - numberOfVersions = builtins.length versions; - packages = builtins.attrValues ( - lib.mapAttrs (name: value: build name value.hash) supportedVersions - ); + versionsToUse = + if latestOnly then + { "${latestVersion}" = supportedVersions.${latestVersion}; } + else + supportedVersions; + versionsBuilt = if latestOnly then [ latestVersion ] else versions; + numberOfVersionsBuilt = builtins.length versionsBuilt; + packages = builtins.attrValues (lib.mapAttrs (name: value: build name value.hash) versionsToUse); in pkgs.buildEnv { name = pname; @@ -86,7 +91,7 @@ pkgs.buildEnv { # checks (set -x test "$(ls -A $out/lib/${pname}*${postgresql.dlSuffix} | wc -l)" = "${ - toString (numberOfVersions + 1) + toString (numberOfVersionsBuilt + 1) }" ) @@ -95,12 +100,9 @@ pkgs.buildEnv { ''; passthru = { - inherit - versions - numberOfVersions - switch-ext-version - libName - ; + versions = versionsBuilt; + numberOfVersions = numberOfVersionsBuilt; + inherit switch-ext-version libName latestOnly; pname = "${pname}-all"; hasBackgroundWorker = true; defaultSchema = "partman"; @@ -108,6 +110,9 @@ pkgs.buildEnv { shared_preload_libraries = [ libName ]; }; version = - "multi-" + lib.concatStringsSep "-" (map (v: lib.replaceStrings [ "." ] [ "-" ] v) versions); + if latestOnly then + latestVersion + else + "multi-" + lib.concatStringsSep "-" (map (v: lib.replaceStrings [ "." ] [ "-" ] v) versions); }; } diff --git a/nix/ext/pg_plan_filter.nix b/nix/ext/pg_plan_filter.nix index dfb3262b7..402f6b192 100644 --- a/nix/ext/pg_plan_filter.nix +++ b/nix/ext/pg_plan_filter.nix @@ -5,6 +5,7 @@ fetchFromGitHub, postgresql, makeWrapper, + latestOnly ? false, }: let @@ -50,9 +51,15 @@ let ) allVersions; versions = lib.naturalSort (lib.attrNames supportedVersions); latestVersion = lib.last versions; - numberOfVersions = builtins.length versions; + versionsToUse = + if latestOnly then + { "${latestVersion}" = supportedVersions.${latestVersion}; } + else + supportedVersions; + versionsBuilt = if latestOnly then [ latestVersion ] else versions; + numberOfVersionsBuilt = builtins.length versionsBuilt; packages = builtins.attrValues ( - lib.mapAttrs (name: value: build name value.rev value.hash) supportedVersions + lib.mapAttrs (name: value: build name value.rev value.hash) versionsToUse ); in pkgs.buildEnv { @@ -69,18 +76,23 @@ pkgs.buildEnv { # checks (set -x test "$(ls -A $out/lib/${pname}*${postgresql.dlSuffix} | wc -l)" = "${ - toString (numberOfVersions + 1) + toString (numberOfVersionsBuilt + 1) }" ) ''; passthru = { - inherit versions numberOfVersions pname; + versions = versionsBuilt; + numberOfVersions = numberOfVersionsBuilt; + inherit pname latestOnly; defaultSettings = { shared_preload_libraries = [ "plan_filter" ]; }; pgRegressTestName = "pg_plan_filter"; version = - "multi-" + lib.concatStringsSep "-" (map (v: lib.replaceStrings [ "." ] [ "-" ] v) versions); + if latestOnly then + latestVersion + else + "multi-" + lib.concatStringsSep "-" (map (v: lib.replaceStrings [ "." ] [ "-" ] v) versions); }; } diff --git a/nix/ext/pg_repack.nix b/nix/ext/pg_repack.nix index 153cebd76..89b1d1118 100644 --- a/nix/ext/pg_repack.nix +++ b/nix/ext/pg_repack.nix @@ -6,6 +6,7 @@ postgresqlTestHook, testers, buildEnv, + latestOnly ? false, }: let pname = "pg_repack"; @@ -21,10 +22,14 @@ let # Derived version information versions = lib.naturalSort (lib.attrNames supportedVersions); latestVersion = lib.last versions; - numberOfVersions = builtins.length versions; - packages = builtins.attrValues ( - lib.mapAttrs (name: value: build name value.hash) supportedVersions - ); + versionsToUse = + if latestOnly then + { "${latestVersion}" = supportedVersions.${latestVersion}; } + else + supportedVersions; + versionsBuilt = if latestOnly then [ latestVersion ] else versions; + numberOfVersionsBuilt = builtins.length versionsBuilt; + packages = builtins.attrValues (lib.mapAttrs (name: value: build name value.hash) versionsToUse); # Build function for individual versions build = @@ -117,7 +122,7 @@ buildEnv { postBuild = '' # Verify all expected library files are present - expectedFiles=${toString (numberOfVersions + 1)} + expectedFiles=${toString (numberOfVersionsBuilt + 1)} actualFiles=$(ls -l $out/lib/${pname}*${postgresql.dlSuffix} | wc -l) if [[ "$actualFiles" != "$expectedFiles" ]]; then @@ -129,8 +134,13 @@ buildEnv { ''; passthru = { - inherit versions numberOfVersions pname; + versions = versionsBuilt; + numberOfVersions = numberOfVersionsBuilt; + inherit pname latestOnly; version = - "multi-" + lib.concatStringsSep "-" (map (v: lib.replaceStrings [ "." ] [ "-" ] v) versions); + if latestOnly then + latestVersion + else + "multi-" + lib.concatStringsSep "-" (map (v: lib.replaceStrings [ "." ] [ "-" ] v) versions); }; } diff --git a/nix/ext/pg_stat_monitor.nix b/nix/ext/pg_stat_monitor.nix index ddf46de30..c82eaf830 100644 --- a/nix/ext/pg_stat_monitor.nix +++ b/nix/ext/pg_stat_monitor.nix @@ -4,6 +4,7 @@ fetchFromGitHub, postgresql, buildEnv, + latestOnly ? false, }: let pname = "pg_stat_monitor"; @@ -19,9 +20,15 @@ let # Derived version information versions = lib.naturalSort (lib.attrNames supportedVersions); latestVersion = lib.last versions; - numberOfVersions = builtins.length versions; + versionsToUse = + if latestOnly then + { "${latestVersion}" = supportedVersions.${latestVersion}; } + else + supportedVersions; + versionsBuilt = if latestOnly then [ latestVersion ] else versions; + numberOfVersionsBuilt = builtins.length versionsBuilt; packages = builtins.attrValues ( - lib.mapAttrs (name: value: build name value.hash value.revision) supportedVersions + lib.mapAttrs (name: value: build name value.hash value.revision) versionsToUse ); # Build function for individual versions @@ -85,7 +92,7 @@ buildEnv { postBuild = '' # Verify all expected library files are present - expectedFiles=${toString (numberOfVersions + 1)} + expectedFiles=${toString (numberOfVersionsBuilt + 1)} actualFiles=$(ls -l $out/lib/${pname}*${postgresql.dlSuffix} | wc -l) if [[ "$actualFiles" != "$expectedFiles" ]]; then @@ -97,8 +104,13 @@ buildEnv { ''; passthru = { - inherit versions numberOfVersions pname; + versions = versionsBuilt; + numberOfVersions = numberOfVersionsBuilt; + inherit pname latestOnly; version = - "multi-" + lib.concatStringsSep "-" (map (v: lib.replaceStrings [ "." ] [ "-" ] v) versions); + if latestOnly then + latestVersion + else + "multi-" + lib.concatStringsSep "-" (map (v: lib.replaceStrings [ "." ] [ "-" ] v) versions); }; } diff --git a/nix/ext/pg_tle.nix b/nix/ext/pg_tle.nix index 7101952a2..d5d1e4446 100644 --- a/nix/ext/pg_tle.nix +++ b/nix/ext/pg_tle.nix @@ -7,6 +7,7 @@ flex, openssl, libkrb5, + latestOnly ? false, }: let pname = "pg_tle"; @@ -78,10 +79,14 @@ let ) allVersions; versions = lib.naturalSort (lib.attrNames supportedVersions); latestVersion = lib.last versions; - numberOfVersions = builtins.length versions; - packages = builtins.attrValues ( - lib.mapAttrs (name: value: build name value.hash) supportedVersions - ); + versionsToUse = + if latestOnly then + { "${latestVersion}" = supportedVersions.${latestVersion}; } + else + supportedVersions; + versionsBuilt = if latestOnly then [ latestVersion ] else versions; + numberOfVersionsBuilt = builtins.length versionsBuilt; + packages = builtins.attrValues (lib.mapAttrs (name: value: build name value.hash) versionsToUse); in buildEnv { name = pname; @@ -94,17 +99,22 @@ buildEnv { # checks (set -x test "$(ls -A $out/lib/${pname}*${postgresql.dlSuffix} | wc -l)" = "${ - toString (numberOfVersions + 1) + toString (numberOfVersionsBuilt + 1) }" ) ''; passthru = { - inherit versions numberOfVersions pname; + versions = versionsBuilt; + numberOfVersions = numberOfVersionsBuilt; + inherit pname latestOnly; defaultSettings = { shared_preload_libraries = [ "pg_tle" ]; }; version = - "multi-" + lib.concatStringsSep "-" (map (v: lib.replaceStrings [ "." ] [ "-" ] v) versions); + if latestOnly then + latestVersion + else + "multi-" + lib.concatStringsSep "-" (map (v: lib.replaceStrings [ "." ] [ "-" ] v) versions); }; } diff --git a/nix/ext/pgaudit.nix b/nix/ext/pgaudit.nix index 55dd237f7..06e4bca40 100644 --- a/nix/ext/pgaudit.nix +++ b/nix/ext/pgaudit.nix @@ -6,6 +6,7 @@ libkrb5, openssl, postgresql, + latestOnly ? false, }: #adapted from https://github.com/NixOS/nixpkgs/blob/master/pkgs/servers/sql/postgresql/ext/pgaudit.nix let @@ -24,12 +25,16 @@ let # Supported versions sorted (for libraries) versions = lib.naturalSort (lib.attrNames supportedVersions); latestVersion = lib.last versions; - numberOfVersions = builtins.length versions; + versionsToUse = + if latestOnly then + { "${latestVersion}" = supportedVersions.${latestVersion}; } + else + supportedVersions; + versionsBuilt = if latestOnly then [ latestVersion ] else versions; + numberOfVersionsBuilt = builtins.length versionsBuilt; # Build packages only for supported versions (with libraries) - packages = builtins.attrValues ( - lib.mapAttrs (name: value: build name value.hash) supportedVersions - ); + packages = builtins.attrValues (lib.mapAttrs (name: value: build name value.hash) versionsToUse); # Helper function to generate migration SQL file pairs # Returns a list of {from, to} pairs for sequential migrations @@ -217,7 +222,7 @@ buildEnv { '') versions} # Verify all expected library files are present (one per version + symlink) - expectedFiles=${toString (numberOfVersions + 1)} + expectedFiles=${toString (numberOfVersionsBuilt + 1)} actualFiles=$(ls -A $out/lib/${pname}*${postgresql.dlSuffix} | wc -l) if [[ "$actualFiles" != "$expectedFiles" ]]; then @@ -229,9 +234,14 @@ buildEnv { ''; passthru = { - inherit versions numberOfVersions pname; + versions = versionsBuilt; + numberOfVersions = numberOfVersionsBuilt; + inherit pname latestOnly; version = - "multi-" + lib.concatStringsSep "-" (map (v: lib.replaceStrings [ "." ] [ "-" ] v) versions); + if latestOnly then + latestVersion + else + "multi-" + lib.concatStringsSep "-" (map (v: lib.replaceStrings [ "." ] [ "-" ] v) versions); defaultSettings = { shared_preload_libraries = "pgaudit"; }; diff --git a/nix/ext/pgjwt.nix b/nix/ext/pgjwt.nix index 6bac9dcd8..348b534c3 100644 --- a/nix/ext/pgjwt.nix +++ b/nix/ext/pgjwt.nix @@ -5,6 +5,7 @@ fetchFromGitHub, postgresql, unstableGitUpdater, + latestOnly ? false, }: let pname = "pgjwt"; @@ -14,9 +15,13 @@ let ) allVersions; versions = lib.naturalSort (lib.attrNames supportedVersions); latestVersion = lib.last versions; - numberOfVersions = builtins.trace "Versions: ${toString (builtins.length versions)}" ( - builtins.length versions - ); + versionsToUse = + if latestOnly then + { "${latestVersion}" = supportedVersions.${latestVersion}; } + else + supportedVersions; + versionsBuilt = if latestOnly then [ latestVersion ] else versions; + numberOfVersionsBuilt = builtins.length versionsBuilt; build = version: hash: revision: stdenv.mkDerivation { @@ -68,7 +73,7 @@ let }; }; packages = builtins.attrValues ( - lib.mapAttrs (name: value: build name value.hash value.revision) supportedVersions + lib.mapAttrs (name: value: build name value.hash value.revision) versionsToUse ); in buildEnv { @@ -77,8 +82,13 @@ buildEnv { pathsToLink = [ "/share/postgresql/extension" ]; passthru = { - inherit versions numberOfVersions pname; + versions = versionsBuilt; + numberOfVersions = numberOfVersionsBuilt; + inherit pname latestOnly; version = - "multi-" + lib.concatStringsSep "-" (map (v: lib.replaceStrings [ "." ] [ "-" ] v) versions); + if latestOnly then + latestVersion + else + "multi-" + lib.concatStringsSep "-" (map (v: lib.replaceStrings [ "." ] [ "-" ] v) versions); }; } diff --git a/nix/ext/pgmq/default.nix b/nix/ext/pgmq/default.nix index 518308211..42613b6ac 100644 --- a/nix/ext/pgmq/default.nix +++ b/nix/ext/pgmq/default.nix @@ -4,6 +4,7 @@ fetchFromGitHub, postgresql, buildEnv, + latestOnly ? false, }: let pname = "pgmq"; @@ -19,10 +20,14 @@ let # Derived version information versions = lib.naturalSort (lib.attrNames supportedVersions); latestVersion = lib.last versions; - numberOfVersions = builtins.length versions; - packages = builtins.attrValues ( - lib.mapAttrs (name: value: build name value.hash) supportedVersions - ); + versionsToUse = + if latestOnly then + { "${latestVersion}" = supportedVersions.${latestVersion}; } + else + supportedVersions; + versionsBuilt = if latestOnly then [ latestVersion ] else versions; + numberOfVersionsBuilt = builtins.length versionsBuilt; + packages = builtins.attrValues (lib.mapAttrs (name: value: build name value.hash) versionsToUse); # Build function for individual versions build = @@ -99,11 +104,16 @@ buildEnv { pathsToLink = [ "/share/postgresql/extension" ]; passthru = { - inherit versions numberOfVersions pname; + versions = versionsBuilt; + numberOfVersions = numberOfVersionsBuilt; + inherit pname latestOnly; defaultSettings = { search_path = "\"$user\", public, auth, extensions"; }; version = - "multi-" + lib.concatStringsSep "-" (map (v: lib.replaceStrings [ "." ] [ "-" ] v) versions); + if latestOnly then + latestVersion + else + "multi-" + lib.concatStringsSep "-" (map (v: lib.replaceStrings [ "." ] [ "-" ] v) versions); }; } diff --git a/nix/ext/pgroonga/default.nix b/nix/ext/pgroonga/default.nix index 89aca72a2..4a824ac25 100644 --- a/nix/ext/pgroonga/default.nix +++ b/nix/ext/pgroonga/default.nix @@ -11,6 +11,7 @@ buildEnv, supabase-groonga, mecab-naist-jdic, + latestOnly ? false, }: let pname = "pgroonga"; @@ -26,10 +27,14 @@ let # Derived version information versions = lib.naturalSort (lib.attrNames supportedVersions); latestVersion = lib.last versions; - numberOfVersions = builtins.length versions; - packages = builtins.attrValues ( - lib.mapAttrs (name: value: build name value.hash) supportedVersions - ); + versionsToUse = + if latestOnly then + { "${latestVersion}" = supportedVersions.${latestVersion}; } + else + supportedVersions; + versionsBuilt = if latestOnly then [ latestVersion ] else versions; + numberOfVersionsBuilt = builtins.length versionsBuilt; + packages = builtins.attrValues (lib.mapAttrs (name: value: build name value.hash) versionsToUse); # List of C extensions to be included in the build cExtensions = [ @@ -159,7 +164,7 @@ buildEnv { ]; postBuild = '' # Verify all expected library files are present - expectedFiles=${toString ((numberOfVersions + 1) * (builtins.length cExtensions))} + expectedFiles=${toString ((numberOfVersionsBuilt + 1) * (builtins.length cExtensions))} actualFiles=$(ls -l $out/lib/${pname}*${postgresql.dlSuffix} | wc -l) if [[ "$actualFiles" != "$expectedFiles" ]]; then @@ -171,8 +176,13 @@ buildEnv { ''; passthru = { - inherit versions numberOfVersions pname; + versions = versionsBuilt; + numberOfVersions = numberOfVersionsBuilt; + inherit pname latestOnly; version = - "multi-" + lib.concatStringsSep "-" (map (v: lib.replaceStrings [ "." ] [ "-" ] v) versions); + if latestOnly then + latestVersion + else + "multi-" + lib.concatStringsSep "-" (map (v: lib.replaceStrings [ "." ] [ "-" ] v) versions); }; } diff --git a/nix/ext/pgrouting/default.nix b/nix/ext/pgrouting/default.nix index a05101dd8..cff4e7d86 100644 --- a/nix/ext/pgrouting/default.nix +++ b/nix/ext/pgrouting/default.nix @@ -7,6 +7,7 @@ cmake, boost, buildEnv, + latestOnly ? false, }: let pname = "pgrouting"; @@ -22,10 +23,14 @@ let # Derived version information versions = lib.naturalSort (lib.attrNames supportedVersions); latestVersion = lib.last versions; - numberOfVersions = builtins.length versions; - packages = builtins.attrValues ( - lib.mapAttrs (name: value: build name value.hash) supportedVersions - ); + versionsToUse = + if latestOnly then + { "${latestVersion}" = supportedVersions.${latestVersion}; } + else + supportedVersions; + versionsBuilt = if latestOnly then [ latestVersion ] else versions; + numberOfVersionsBuilt = builtins.length versionsBuilt; + packages = builtins.attrValues (lib.mapAttrs (name: value: build name value.hash) versionsToUse); # Build function for individual versions build = @@ -130,7 +135,7 @@ buildEnv { postBuild = '' #Verify all expected library files are present - expectedFiles=${toString (numberOfVersions + 1)} + expectedFiles=${toString (numberOfVersionsBuilt + 1)} actualFiles=$(ls -l $out/lib/lib${pname}*${postgresql.dlSuffix} | wc -l) if [[ "$actualFiles" != "$expectedFiles" ]]; then @@ -142,8 +147,13 @@ buildEnv { ''; passthru = { - inherit versions numberOfVersions pname; + versions = versionsBuilt; + numberOfVersions = numberOfVersionsBuilt; + inherit pname latestOnly; version = - "multi-" + lib.concatStringsSep "-" (map (v: lib.replaceStrings [ "." ] [ "-" ] v) versions); + if latestOnly then + latestVersion + else + "multi-" + lib.concatStringsSep "-" (map (v: lib.replaceStrings [ "." ] [ "-" ] v) versions); }; } diff --git a/nix/ext/pgsodium.nix b/nix/ext/pgsodium.nix index fa111d8a5..ad5cd008b 100644 --- a/nix/ext/pgsodium.nix +++ b/nix/ext/pgsodium.nix @@ -5,6 +5,7 @@ fetchFromGitHub, postgresql, libsodium, + latestOnly ? false, }: let pname = "pgsodium"; @@ -20,10 +21,14 @@ let # Derived version information versions = lib.naturalSort (lib.attrNames supportedVersions); latestVersion = lib.last versions; - numberOfVersions = builtins.length versions; - packages = builtins.attrValues ( - lib.mapAttrs (name: value: build name value.hash) supportedVersions - ); + versionsToUse = + if latestOnly then + { "${latestVersion}" = supportedVersions.${latestVersion}; } + else + supportedVersions; + packages = builtins.attrValues (lib.mapAttrs (name: value: build name value.hash) versionsToUse); + versionsBuilt = if latestOnly then [ latestVersion ] else versions; + numberOfVersionsBuilt = builtins.length versionsBuilt; # Build function for individual pgsodium versions build = @@ -89,7 +94,7 @@ pkgs.buildEnv { postBuild = '' # Verify all expected library files are present - expectedFiles=${toString (numberOfVersions + 1)} + expectedFiles=${toString (numberOfVersionsBuilt + 1)} actualFiles=$(ls -A $out/lib/${pname}*${postgresql.dlSuffix} | wc -l) if [[ "$actualFiles" != "$expectedFiles" ]]; then @@ -101,8 +106,13 @@ pkgs.buildEnv { ''; passthru = { - inherit versions numberOfVersions pname; + versions = versionsBuilt; + numberOfVersions = numberOfVersionsBuilt; + inherit pname latestOnly; version = - "multi-" + lib.concatStringsSep "-" (map (v: lib.replaceStrings [ "." ] [ "-" ] v) versions); + if latestOnly then + latestVersion + else + "multi-" + lib.concatStringsSep "-" (map (v: lib.replaceStrings [ "." ] [ "-" ] v) versions); }; } diff --git a/nix/ext/pgsql-http.nix b/nix/ext/pgsql-http.nix index 3ad03b80c..e36f4a218 100644 --- a/nix/ext/pgsql-http.nix +++ b/nix/ext/pgsql-http.nix @@ -5,6 +5,7 @@ fetchFromGitHub, postgresql, curl, + latestOnly ? false, }: let pname = "http"; @@ -20,10 +21,14 @@ let # Derived version information versions = lib.naturalSort (lib.attrNames supportedVersions); latestVersion = lib.last versions; - numberOfVersions = builtins.length versions; - packages = builtins.attrValues ( - lib.mapAttrs (name: value: build name value.hash) supportedVersions - ); + versionsToUse = + if latestOnly then + { "${latestVersion}" = supportedVersions.${latestVersion}; } + else + supportedVersions; + versionsBuilt = if latestOnly then [ latestVersion ] else versions; + numberOfVersionsBuilt = builtins.length versionsBuilt; + packages = builtins.attrValues (lib.mapAttrs (name: value: build name value.hash) versionsToUse); # Build function for individual versions build = @@ -91,7 +96,7 @@ pkgs.buildEnv { ]; postBuild = '' # Verify all expected library files are present - expectedFiles=${toString (numberOfVersions + 1)} + expectedFiles=${toString (numberOfVersionsBuilt + 1)} actualFiles=$(ls -A $out/lib/${pname}*${postgresql.dlSuffix} | wc -l) if [[ "$actualFiles" != "$expectedFiles" ]]; then @@ -103,8 +108,13 @@ pkgs.buildEnv { ''; passthru = { - inherit versions numberOfVersions pname; + versions = versionsBuilt; + numberOfVersions = numberOfVersionsBuilt; + inherit pname latestOnly; version = - "multi-" + lib.concatStringsSep "-" (map (v: lib.replaceStrings [ "." ] [ "-" ] v) versions); + if latestOnly then + latestVersion + else + "multi-" + lib.concatStringsSep "-" (map (v: lib.replaceStrings [ "." ] [ "-" ] v) versions); }; } diff --git a/nix/ext/plpgsql-check.nix b/nix/ext/plpgsql-check.nix index faf918c67..05542b949 100644 --- a/nix/ext/plpgsql-check.nix +++ b/nix/ext/plpgsql-check.nix @@ -7,6 +7,7 @@ buildEnv, makeWrapper, switch-ext-version, + latestOnly ? false, }: let pname = "plpgsql_check"; @@ -22,9 +23,15 @@ let # Derived version information versions = lib.naturalSort (lib.attrNames supportedVersions); latestVersion = lib.last versions; - numberOfVersions = builtins.length versions; + versionsToUse = + if latestOnly then + { "${latestVersion}" = supportedVersions.${latestVersion}; } + else + supportedVersions; + versionsBuilt = if latestOnly then [ latestVersion ] else versions; + numberOfVersionsBuilt = builtins.length versionsBuilt; packages = builtins.attrValues ( - lib.mapAttrs (name: value: build name value.hash value.revision) supportedVersions + lib.mapAttrs (name: value: build name value.hash value.revision) versionsToUse ); # Build function for individual versions @@ -108,7 +115,7 @@ buildEnv { ln -sfn ${pname}-${latestVersion}${postgresql.dlSuffix} $out/lib/${pname}${postgresql.dlSuffix} # Verify all expected library files are present - expectedFiles=${toString (numberOfVersions + 1)} + expectedFiles=${toString (numberOfVersionsBuilt + 1)} actualFiles=$(ls -l $out/lib/${pname}*${postgresql.dlSuffix} | wc -l) if [[ "$actualFiles" != "$expectedFiles" ]]; then @@ -133,7 +140,9 @@ buildEnv { ''; passthru = { - inherit versions numberOfVersions switch-ext-version; + versions = versionsBuilt; + numberOfVersions = numberOfVersionsBuilt; + inherit switch-ext-version latestOnly; hasBackgroundWorker = true; defaultSettings = { shared_preload_libraries = [ @@ -142,6 +151,9 @@ buildEnv { ]; }; version = - "multi-" + lib.concatStringsSep "-" (map (v: lib.replaceStrings [ "." ] [ "-" ] v) versions); + if latestOnly then + latestVersion + else + "multi-" + lib.concatStringsSep "-" (map (v: lib.replaceStrings [ "." ] [ "-" ] v) versions); }; } diff --git a/nix/ext/plv8/default.nix b/nix/ext/plv8/default.nix index 50927521b..93a17434a 100644 --- a/nix/ext/plv8/default.nix +++ b/nix/ext/plv8/default.nix @@ -14,6 +14,7 @@ nodejs_20, libcxx, v8_oldstable, + latestOnly ? false, }: let @@ -30,10 +31,14 @@ let # Derived version information versions = lib.naturalSort (lib.attrNames supportedVersions); latestVersion = lib.last versions; - numberOfVersions = builtins.length versions; - packages = builtins.attrValues ( - lib.mapAttrs (name: value: build name value.hash) supportedVersions - ); + versionsToUse = + if latestOnly then + { "${latestVersion}" = supportedVersions.${latestVersion}; } + else + supportedVersions; + versionsBuilt = if latestOnly then [ latestVersion ] else versions; + numberOfVersionsBuilt = builtins.length versionsBuilt; + packages = builtins.attrValues (lib.mapAttrs (name: value: build name value.hash) versionsToUse); # plv8 3.1 requires an older version of v8 (we cannot use nodejs.libv8) v8 = v8_oldstable; @@ -221,7 +226,7 @@ buildEnv { ]; postBuild = '' # Verify all expected library files are present - expectedFiles=${toString (numberOfVersions + 1)} + expectedFiles=${toString (numberOfVersionsBuilt + 1)} actualFiles=$(ls -A $out/lib/${pname}*${postgresql.dlSuffix} | wc -l) if [[ "$actualFiles" != "$expectedFiles" ]]; then @@ -233,8 +238,13 @@ buildEnv { ''; passthru = { - inherit versions numberOfVersions pname; + versions = versionsBuilt; + numberOfVersions = numberOfVersionsBuilt; + inherit pname latestOnly; version = - "multi-" + lib.concatStringsSep "-" (map (v: lib.replaceStrings [ "." ] [ "-" ] v) versions); + if latestOnly then + latestVersion + else + "multi-" + lib.concatStringsSep "-" (map (v: lib.replaceStrings [ "." ] [ "-" ] v) versions); }; } diff --git a/nix/ext/postgis.nix b/nix/ext/postgis.nix index 3989e8aae..74539e5de 100644 --- a/nix/ext/postgis.nix +++ b/nix/ext/postgis.nix @@ -17,6 +17,7 @@ callPackage, buildEnv, sfcgal, + latestOnly ? false, }: let @@ -34,10 +35,14 @@ let # Derived version information versions = lib.naturalSort (lib.attrNames supportedVersions); latestVersion = lib.last versions; - numberOfVersions = builtins.length versions; - packages = builtins.attrValues ( - lib.mapAttrs (name: value: build name value.hash) supportedVersions - ); + versionsToUse = + if latestOnly then + { "${latestVersion}" = supportedVersions.${latestVersion}; } + else + supportedVersions; + versionsBuilt = if latestOnly then [ latestVersion ] else versions; + numberOfVersionsBuilt = builtins.length versionsBuilt; + packages = builtins.attrValues (lib.mapAttrs (name: value: build name value.hash) versionsToUse); # List of C extensions to be included in the build cExtensions = [ @@ -190,9 +195,9 @@ in ]; postBuild = '' # Verify all expected library files are present - # We expect: (numberOfVersions * cExtensions) versioned libraries + cExtensions symlinks + # We expect: (numberOfVersionsBuilt * cExtensions) versioned libraries + cExtensions symlinks expectedFiles=${ - toString ((numberOfVersions * builtins.length cExtensions) + builtins.length cExtensions) + toString ((numberOfVersionsBuilt * builtins.length cExtensions) + builtins.length cExtensions) } actualFiles=$(ls -A $out/lib/*${postgresql.dlSuffix} | wc -l) @@ -205,9 +210,14 @@ in ''; passthru = { - inherit versions numberOfVersions pname; + versions = versionsBuilt; + numberOfVersions = numberOfVersionsBuilt; + inherit pname latestOnly; version = - "multi-" + lib.concatStringsSep "-" (map (v: lib.replaceStrings [ "." ] [ "-" ] v) versions); + if latestOnly then + latestVersion + else + "multi-" + lib.concatStringsSep "-" (map (v: lib.replaceStrings [ "." ] [ "-" ] v) versions); }; }).overrideAttrs (_: { diff --git a/nix/ext/rum.nix b/nix/ext/rum.nix index 6a9492e38..a16be47c9 100644 --- a/nix/ext/rum.nix +++ b/nix/ext/rum.nix @@ -4,6 +4,7 @@ fetchFromGitHub, postgresql, buildEnv, + latestOnly ? false, }: let pname = "rum"; @@ -19,9 +20,15 @@ let # Derived version information versions = lib.naturalSort (lib.attrNames supportedVersions); latestVersion = lib.last versions; - numberOfVersions = builtins.length versions; + versionsToUse = + if latestOnly then + { "${latestVersion}" = supportedVersions.${latestVersion}; } + else + supportedVersions; + versionsBuilt = if latestOnly then [ latestVersion ] else versions; + numberOfVersionsBuilt = builtins.length versionsBuilt; packages = builtins.attrValues ( - lib.mapAttrs (name: value: build name value.hash value.revision) supportedVersions + lib.mapAttrs (name: value: build name value.hash value.revision) versionsToUse ); # Build function for individual versions @@ -82,7 +89,7 @@ buildEnv { postBuild = '' # Verify all expected library files are present - expectedFiles=${toString (numberOfVersions + 1)} + expectedFiles=${toString (numberOfVersionsBuilt + 1)} actualFiles=$(ls -l $out/lib/${pname}*${postgresql.dlSuffix} | wc -l) if [[ "$actualFiles" != "$expectedFiles" ]]; then @@ -94,8 +101,13 @@ buildEnv { ''; passthru = { - inherit versions numberOfVersions pname; + versions = versionsBuilt; + numberOfVersions = numberOfVersionsBuilt; + inherit pname latestOnly; version = - "multi-" + lib.concatStringsSep "-" (map (v: lib.replaceStrings [ "." ] [ "-" ] v) versions); + if latestOnly then + latestVersion + else + "multi-" + lib.concatStringsSep "-" (map (v: lib.replaceStrings [ "." ] [ "-" ] v) versions); }; } diff --git a/nix/ext/timescaledb.nix b/nix/ext/timescaledb.nix index 765ca5267..dbfb2a836 100644 --- a/nix/ext/timescaledb.nix +++ b/nix/ext/timescaledb.nix @@ -11,6 +11,7 @@ switch-ext-version, coreutils, writeShellApplication, + latestOnly ? false, }: let @@ -97,9 +98,15 @@ let ) allVersions; versions = lib.naturalSort (lib.attrNames supportedVersions); latestVersion = lib.last versions; - numberOfVersions = builtins.length versions; + versionsToUse = + if latestOnly then + { "${latestVersion}" = supportedVersions.${latestVersion}; } + else + supportedVersions; + versionsBuilt = if latestOnly then [ latestVersion ] else versions; + numberOfVersionsBuilt = builtins.length versionsBuilt; packages = builtins.attrValues ( - lib.mapAttrs (name: value: build name value.hash (value.revision or name)) supportedVersions + lib.mapAttrs (name: value: build name value.hash (value.revision or name)) versionsToUse ); switch-timescaledb-loader = writeShellApplication { name = "switch_timescaledb_loader"; @@ -145,13 +152,18 @@ buildEnv { ]; passthru = { - inherit versions numberOfVersions switch-ext-version; + versions = versionsBuilt; + numberOfVersions = numberOfVersionsBuilt; + inherit switch-ext-version latestOnly; hasBackgroundWorker = true; libName = "timescaledb-loader"; defaultSettings = { shared_preload_libraries = [ "timescaledb" ]; }; version = - "multi-" + lib.concatStringsSep "-" (map (v: lib.replaceStrings [ "." ] [ "-" ] v) versions); + if latestOnly then + latestVersion + else + "multi-" + lib.concatStringsSep "-" (map (v: lib.replaceStrings [ "." ] [ "-" ] v) versions); }; } diff --git a/nix/ext/vault.nix b/nix/ext/vault.nix index 537febc0b..c48546ecb 100644 --- a/nix/ext/vault.nix +++ b/nix/ext/vault.nix @@ -5,6 +5,7 @@ fetchFromGitHub, libsodium, postgresql, + latestOnly ? false, }: let pname = "supabase_vault"; @@ -20,10 +21,14 @@ let # Derived version information versions = lib.naturalSort (lib.attrNames supportedVersions); latestVersion = lib.last versions; - numberOfVersions = builtins.length versions; - packages = builtins.attrValues ( - lib.mapAttrs (name: value: build name value.hash) supportedVersions - ); + versionsToUse = + if latestOnly then + { "${latestVersion}" = supportedVersions.${latestVersion}; } + else + supportedVersions; + versionsBuilt = if latestOnly then [ latestVersion ] else versions; + numberOfVersionsBuilt = builtins.length versionsBuilt; + packages = builtins.attrValues (lib.mapAttrs (name: value: build name value.hash) versionsToUse); # Build function for individual pgsodium versions build = @@ -86,9 +91,14 @@ pkgs.buildEnv { ]; passthru = { - inherit versions numberOfVersions pname; + versions = versionsBuilt; + numberOfVersions = numberOfVersionsBuilt; + inherit pname latestOnly; version = - "multi-" + lib.concatStringsSep "-" (map (v: lib.replaceStrings [ "." ] [ "-" ] v) versions); + if latestOnly then + latestVersion + else + "multi-" + lib.concatStringsSep "-" (map (v: lib.replaceStrings [ "." ] [ "-" ] v) versions); pgRegressTestName = "vault"; }; } diff --git a/nix/ext/wal2json.nix b/nix/ext/wal2json.nix index 43ddab8df..f1ccd273b 100644 --- a/nix/ext/wal2json.nix +++ b/nix/ext/wal2json.nix @@ -5,6 +5,7 @@ fetchFromGitHub, postgresql, makeWrapper, + latestOnly ? false, }: let @@ -56,9 +57,15 @@ let ) allVersions; versions = lib.naturalSort (lib.attrNames supportedVersions); latestVersion = lib.last versions; - numberOfVersions = builtins.length versions; + versionsToUse = + if latestOnly then + { "${latestVersion}" = supportedVersions.${latestVersion}; } + else + supportedVersions; + versionsBuilt = if latestOnly then [ latestVersion ] else versions; + numberOfVersionsBuilt = builtins.length versionsBuilt; packages = builtins.attrValues ( - lib.mapAttrs (name: value: build name value.rev value.hash) supportedVersions + lib.mapAttrs (name: value: build name value.rev value.hash) versionsToUse ); in pkgs.buildEnv { @@ -89,15 +96,20 @@ pkgs.buildEnv { # checks (set -x test "$(ls -A $out/lib/${pname}*${postgresql.dlSuffix} | wc -l)" = "${ - toString (numberOfVersions + 1) + toString (numberOfVersionsBuilt + 1) }" ) ''; passthru = { - inherit versions numberOfVersions pname; + versions = versionsBuilt; + numberOfVersions = numberOfVersionsBuilt; + inherit pname latestOnly; version = - "multi-" + lib.concatStringsSep "-" (map (v: lib.replaceStrings [ "." ] [ "-" ] v) versions); + if latestOnly then + latestVersion + else + "multi-" + lib.concatStringsSep "-" (map (v: lib.replaceStrings [ "." ] [ "-" ] v) versions); defaultSettings = { wal_level = "logical"; }; diff --git a/nix/packages/image-size-analyzer.nix b/nix/packages/image-size-analyzer.nix index c1671fef7..a91cacc50 100644 --- a/nix/packages/image-size-analyzer.nix +++ b/nix/packages/image-size-analyzer.nix @@ -224,16 +224,27 @@ runCommand "image-size-analyzer" }' | jq -s '.' 2>/dev/null || echo "[]" } - # Get APT package sizes + # Get APT/APK package sizes (handles both Debian and Alpine) get_apt_packages() { local tag=$1 + local result + + # Try dpkg first (Debian/Ubuntu), then apk (Alpine) + result=$(docker run --rm "$tag" sh -c ' + if command -v dpkg-query >/dev/null 2>&1; then + dpkg-query -W -f="''${Package}\t''${Installed-Size}\n" 2>/dev/null | sort -t" " -k2 -rn | head -15 | awk -F"\t" "{printf \"{\\\"name\\\":\\\"%s\\\",\\\"size_bytes\\\":%d}\\n\", \$1, \$2 * 1024}" + elif command -v apk >/dev/null 2>&1; then + apk info -s 2>/dev/null | paste - - | sort -t" " -k2 -rn | head -15 | awk -F"\t" "{gsub(/ /, \"\", \$2); printf \"{\\\"name\\\":\\\"%s\\\",\\\"size_bytes\\\":%s}\\n\", \$1, \$2}" + else + echo "" + fi + ' 2>/dev/null) - docker run --rm "$tag" dpkg-query -W -f="\''${Package}\t\''${Installed-Size}\n" 2>/dev/null | \ - sort -t$'\t' -k2 -rn | head -15 | \ - awk -F'\t' '{ - # Installed-Size is in KB, convert to bytes - printf "{\"name\":\"%s\",\"size_bytes\":%d}\n", $1, $2 * 1024 - }' | jq -s '.' 2>/dev/null || echo "[]" + if [[ -n "$result" ]]; then + echo "$result" | jq -s '.' 2>/dev/null || echo "[]" + else + echo "[]" + fi } # Analyze a single image @@ -244,18 +255,23 @@ runCommand "image-size-analyzer" local total_size total_size=$(get_total_size "$tag") + [[ -z "$total_size" || "$total_size" == "" ]] && total_size="0" local layers layers=$(get_layers "$tag") + [[ -z "$layers" || "$layers" == "" ]] && layers="[]" local directories directories=$(get_directories "$tag") + [[ -z "$directories" || "$directories" == "" ]] && directories="[]" local nix_packages nix_packages=$(get_nix_packages "$tag") + [[ -z "$nix_packages" || "$nix_packages" == "" ]] && nix_packages="[]" local apt_packages apt_packages=$(get_apt_packages "$tag") + [[ -z "$apt_packages" || "$apt_packages" == "" ]] && apt_packages="[]" # Build JSON result for this image jq -n \ diff --git a/nix/postgresql/default.nix b/nix/postgresql/default.nix index 0d65a1ad7..90e15193a 100644 --- a/nix/postgresql/default.nix +++ b/nix/postgresql/default.nix @@ -22,6 +22,8 @@ let inherit isOrioleDB; inherit (config) version hash revision; jitSupport = jitSupport; + # Disable systemd support - not needed in Docker containers + systemdSupport = false; self = pkgs; } ) diff --git a/nix/postgresql/generic.nix b/nix/postgresql/generic.nix index a99ecad6d..c9dcae841 100644 --- a/nix/postgresql/generic.nix +++ b/nix/postgresql/generic.nix @@ -132,7 +132,13 @@ let ++ lib.optionals pythonSupport [ python3 ] ++ lib.optionals gssSupport [ libkrb5 ] ++ lib.optionals stdenv'.isLinux [ linux-pam ] - ++ lib.optionals (!stdenv'.isDarwin) [ libossp_uuid ] + ++ lib.optionals (!stdenv'.isDarwin) [ libossp_uuid ]; + + nativeBuildInputs = [ + makeWrapper + pkg-config + ] + # Build tools for PG17+ and OrioleDB - these are NOT runtime dependencies ++ lib.optionals (isOrioleDB || (lib.versionAtLeast version "17")) [ perl bison @@ -141,11 +147,6 @@ let docbook_xml_dtd_45 docbook_xsl_ns libxslt - ]; - - nativeBuildInputs = [ - makeWrapper - pkg-config ] ++ lib.optionals jitSupport [ llvmPackages.llvm.dev From fa8a1bee4d959be860ef630fd6a050356d9ce948 Mon Sep 17 00:00:00 2001 From: Sam Rose Date: Wed, 28 Jan 2026 10:01:46 -0500 Subject: [PATCH 3/3] fix: deal with systemd in slim vs regular --- nix/checks.nix | 41 +++++++++++++++++++++++++++++++++----- nix/packages/postgres.nix | 13 +++++++++--- nix/postgresql/default.nix | 2 -- 3 files changed, 46 insertions(+), 10 deletions(-) diff --git a/nix/checks.nix b/nix/checks.nix index 6e68c734e..fbfedddf9 100644 --- a/nix/checks.nix +++ b/nix/checks.nix @@ -28,6 +28,10 @@ # deadnix: skip makeCheckHarness = pgpkg: + # legacyPkgName: the name used in legacyPackages (e.g., "psql_17" or "psql_17_slim") + { + legacyPkgName ? null, + }: let pg_prove = pkgs.perlPackages.TAPParserSourceHandlerpgTAP; inherit (self'.packages) pg_regress; @@ -87,11 +91,23 @@ in builtins.trace "Major version result: ${result}" result; + # Determine the legacy package name for selecting extensions + effectiveLegacyPkgName = if legacyPkgName != null then legacyPkgName else "psql_${majorVersion}"; + # Select the appropriate pgroonga package for this PostgreSQL version - pgroonga = self'.legacyPackages."psql_${majorVersion}".exts.pgroonga; + pgroonga = self'.legacyPackages.${effectiveLegacyPkgName}.exts.pgroonga; + # Use different ports to allow parallel test runs + # slim packages get their own ports to avoid conflicts + isSlim = lib.hasSuffix "_slim" effectiveLegacyPkgName; pgPort = - if (majorVersion == "17") then + if (majorVersion == "17" && isSlim) then + "5538" + else if (majorVersion == "15" && isSlim) then + "5539" + else if (majorVersion == "orioledb-17" && isSlim) then + "5540" + else if (majorVersion == "17") then "5535" else if (majorVersion == "15") then "5536" @@ -424,13 +440,28 @@ in { psql_15 = pkgs.runCommand "run-check-harness-psql-15" { } ( - lib.getExe (makeCheckHarness self'.packages."psql_15/bin") + lib.getExe (makeCheckHarness self'.packages."psql_15/bin" { legacyPkgName = "psql_15"; }) ); psql_17 = pkgs.runCommand "run-check-harness-psql-17" { } ( - lib.getExe (makeCheckHarness self'.packages."psql_17/bin") + lib.getExe (makeCheckHarness self'.packages."psql_17/bin" { legacyPkgName = "psql_17"; }) ); psql_orioledb-17 = pkgs.runCommand "run-check-harness-psql-orioledb-17" { } ( - lib.getExe (makeCheckHarness self'.packages."psql_orioledb-17/bin") + lib.getExe ( + makeCheckHarness self'.packages."psql_orioledb-17/bin" { legacyPkgName = "psql_orioledb-17"; } + ) + ); + psql_15_slim = pkgs.runCommand "run-check-harness-psql-15-slim" { } ( + lib.getExe (makeCheckHarness self'.packages."psql_15_slim/bin" { legacyPkgName = "psql_15_slim"; }) + ); + psql_17_slim = pkgs.runCommand "run-check-harness-psql-17-slim" { } ( + lib.getExe (makeCheckHarness self'.packages."psql_17_slim/bin" { legacyPkgName = "psql_17_slim"; }) + ); + psql_orioledb-17_slim = pkgs.runCommand "run-check-harness-psql-orioledb-17-slim" { } ( + lib.getExe ( + makeCheckHarness self'.packages."psql_orioledb-17_slim/bin" { + legacyPkgName = "psql_orioledb-17_slim"; + } + ) ); inherit (self'.packages) wal-g-2 diff --git a/nix/packages/postgres.nix b/nix/packages/postgres.nix index 17cf760c6..b58429fec 100644 --- a/nix/packages/postgres.nix +++ b/nix/packages/postgres.nix @@ -55,7 +55,12 @@ orioledbExtensions = orioleFilteredExtensions ++ [ ../ext/orioledb.nix ]; dbExtensions17 = orioleFilteredExtensions; - getPostgresqlPackage = version: pkgs."postgresql_${version}"; + getPostgresqlPackage = + version: latestOnly: + let + base = pkgs."postgresql_${version}"; + in + if latestOnly then base.override { systemdSupport = false; } else base; # Create a 'receipt' file for a given postgresql package. This is a way # of adding a bit of metadata to the package, which can be used by other # tools to inspect what the contents of the install are: the PSQL @@ -97,7 +102,7 @@ latestOnly ? false, }: let - postgresql = getPostgresqlPackage version; + postgresql = getPostgresqlPackage version latestOnly; extensionsToUse = if (builtins.elem version [ "orioledb-17" ]) then orioledbExtensions @@ -152,7 +157,7 @@ latestOnly ? false, }: let - postgresql = getPostgresqlPackage version; + postgresql = getPostgresqlPackage version latestOnly; postgres-pkgs = makeOurPostgresPkgs version { inherit latestOnly; }; ourExts = map (ext: { name = ext.name; @@ -193,7 +198,9 @@ psql_orioledb-17 = makePostgres "orioledb-17" { }; }; slimPackages = { + psql_15_slim = makePostgres "15" { latestOnly = true; }; psql_17_slim = makePostgres "17" { latestOnly = true; }; + psql_orioledb-17_slim = makePostgres "orioledb-17" { latestOnly = true; }; }; binPackages = lib.mapAttrs' (name: value: { name = "${name}/bin"; diff --git a/nix/postgresql/default.nix b/nix/postgresql/default.nix index 90e15193a..0d65a1ad7 100644 --- a/nix/postgresql/default.nix +++ b/nix/postgresql/default.nix @@ -22,8 +22,6 @@ let inherit isOrioleDB; inherit (config) version hash revision; jitSupport = jitSupport; - # Disable systemd support - not needed in Docker containers - systemdSupport = false; self = pkgs; } )