From 6019798241c8767d6239433fb48cc03ff0f5c1af Mon Sep 17 00:00:00 2001 From: Husn E Rabbi Date: Mon, 8 Dec 2025 18:20:29 +0500 Subject: [PATCH 1/5] feat(pg_ivm): add pg_ivm extension container image - Add pg_ivm Dockerfile with multi-stage build - Create pg_ivm README with usage instructions for CloudNativePG clusters - Add pg_ivm metadata.hcl with version configuration for PostgreSQL 18 - Update main README.md to include pg_ivm in the extensions table Signed-off-by: Husn E Rabbi --- README.md | 1 + pg_ivm/Dockerfile | 35 ++++++++++++++++++++++++++ pg_ivm/README.md | 60 +++++++++++++++++++++++++++++++++++++++++++++ pg_ivm/metadata.hcl | 20 +++++++++++++++ 4 files changed, 116 insertions(+) create mode 100644 pg_ivm/Dockerfile create mode 100644 pg_ivm/README.md create mode 100644 pg_ivm/metadata.hcl diff --git a/README.md b/README.md index 597e271..7278c36 100644 --- a/README.md +++ b/README.md @@ -29,6 +29,7 @@ they are maintained by their respective authors, and PostgreSQL Debian Group | Extension | Description | Project URL | | :--- | :--- | :--- | | **[pgAudit](pgaudit)** | PostgreSQL audit extension | [https://github.com/pgaudit/pgaudit](https://github.com/pgaudit/pgaudit) | +| **[pg_ivm](pg_ivm)** | Incremental View Maintenance for PostgreSQL | [https://github.com/sraoss/pg_ivm](https://github.com/sraoss/pg_ivm) | | **[pgvector](pgvector)** | Vector similarity search for PostgreSQL | [https://github.com/pgvector/pgvector](https://github.com/pgvector/pgvector) | | **[PostGIS](postgis)** | Geospatial database extension for PostgreSQL | [https://postgis.net/](https://postgis.net/) | diff --git a/pg_ivm/Dockerfile b/pg_ivm/Dockerfile new file mode 100644 index 0000000..8606413 --- /dev/null +++ b/pg_ivm/Dockerfile @@ -0,0 +1,35 @@ +ARG BASE=ghcr.io/cloudnative-pg/postgresql:18-minimal-trixie +FROM $BASE AS builder + +ARG PG_MAJOR +ARG EXT_VERSION + +USER 0 + +RUN set -eux; \ + apt-get update; \ + apt-get install -y --no-install-recommends \ + build-essential \ + ca-certificates \ + git \ + postgresql-server-dev-${PG_MAJOR}; \ + # Clone and build pg_ivm from source + git clone --branch "v${EXT_VERSION}" --depth 1 https://github.com/sraoss/pg_ivm.git /build/pg_ivm; \ + cd /build/pg_ivm; \ + make USE_PGXS=1; \ + make USE_PGXS=1 install + +FROM scratch +ARG PG_MAJOR + +# Licenses +COPY --from=builder /tmp/licenses/LICENSE /licenses/pg_ivm/LICENSE + +# Libraries +COPY --from=builder /usr/lib/postgresql/${PG_MAJOR}/lib/pg_ivm* /lib/ +COPY --from=builder /usr/lib/postgresql/${PG_MAJOR}/lib/bitcode /usr/lib/postgresql/${PG_MAJOR}/lib/bitcode/ + +# Share +COPY --from=builder /usr/share/postgresql/${PG_MAJOR}/extension/pg_ivm* /share/extension/ + +USER 65532:65532 \ No newline at end of file diff --git a/pg_ivm/README.md b/pg_ivm/README.md new file mode 100644 index 0000000..b65aacf --- /dev/null +++ b/pg_ivm/README.md @@ -0,0 +1,60 @@ +# pg_ivm Extension + +[pg_ivm](https://github.com/sraoss/pg_ivm) is an open-source extension +that provides **Incremental View Maintenance (IVM)** for PostgreSQL, allowing +materialized views to be updated incrementally when base tables change. + +## Usage + +### 1. Add the pg_ivm extension image to your Cluster + +Define the `pg_ivm` extension under the `postgresql.extensions` section of +your `Cluster` resource. For example: + +```yaml +apiVersion: postgresql.cnpg.io/v1 +kind: Cluster +metadata: + name: cluster-pg-ivm +spec: + imageName: ghcr.io/cloudnative-pg/postgresql:18-minimal-trixie + instances: 1 + + storage: + size: 1Gi + + postgresql: + extensions: + - name: pg_ivm + image: + reference: ghcr.io/cloudnative-pg/pg_ivm:1.13-18-trixie +``` + +### 2. Enable the extension in a database + +You can install `pg_ivm` in a specific database by creating or updating a +`Database` resource. For example, to enable it in the `app` database: + +```yaml +apiVersion: postgresql.cnpg.io/v1 +kind: Database +metadata: + name: cluster-pg-ivm-app +spec: + name: app + owner: app + cluster: + name: cluster-pg-ivm + extensions: + - name: pg_ivm +``` + +### 3. Verify installation + +Once the database is ready, connect to it with `psql` and run: + +```sql +\dx +``` + +You should see `pg_ivm` listed among the installed extensions. diff --git a/pg_ivm/metadata.hcl b/pg_ivm/metadata.hcl new file mode 100644 index 0000000..d858659 --- /dev/null +++ b/pg_ivm/metadata.hcl @@ -0,0 +1,20 @@ +metadata = { + name = "pg_ivm" + sql_name = "pg_ivm" + image_name = "pg_ivm" + shared_preload_libraries = [] + extension_control_path = [] + dynamic_library_path = [] + ld_library_path = [] + + versions = { + bookworm = { + // pg_ivm version from GitHub releases + "18" = "1.13" + } + trixie = { + // pg_ivm version from GitHub releases + "18" = "1.13" + } + } +} \ No newline at end of file From d8c3bf909d1eb7689573b60e72b9907924643cb9 Mon Sep 17 00:00:00 2001 From: Husn E Rabbi Date: Mon, 8 Dec 2025 18:33:53 +0500 Subject: [PATCH 2/5] ci(bake): add pg_ivm extension to build workflow - Enable pg_ivm in automated build pipeline Signed-off-by: Husn E Rabbi --- .github/workflows/bake.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/bake.yml b/.github/workflows/bake.yml index bf45b5d..d812e94 100644 --- a/.github/workflows/bake.yml +++ b/.github/workflows/bake.yml @@ -12,6 +12,7 @@ on: - pgvector - postgis - pgaudit + - pg_ivm defaults: run: @@ -52,6 +53,9 @@ jobs: pgaudit: - 'pgaudit/**' - *shared + pg_ivm: + - 'pg_ivm/**' + - *shared # Compute a matrix containing the list of all extensions that have been modified - name: Compute matrix From c15368ea2e4650137e1000bf979c767e9501f8b1 Mon Sep 17 00:00:00 2001 From: Husn E Rabbi Date: Mon, 8 Dec 2025 19:52:23 +0500 Subject: [PATCH 3/5] Ensures license file is properly included in final container image Signed-off-by: Husn E Rabbi --- pg_ivm/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pg_ivm/Dockerfile b/pg_ivm/Dockerfile index 8606413..ddd1d40 100644 --- a/pg_ivm/Dockerfile +++ b/pg_ivm/Dockerfile @@ -23,7 +23,7 @@ FROM scratch ARG PG_MAJOR # Licenses -COPY --from=builder /tmp/licenses/LICENSE /licenses/pg_ivm/LICENSE +COPY --from=builder /build/pg_ivm/LICENSE /licenses/pg_ivm/LICENSE # Libraries COPY --from=builder /usr/lib/postgresql/${PG_MAJOR}/lib/pg_ivm* /lib/ From 553d7dec4139c7861fcb40ee543e029cfa1e988c Mon Sep 17 00:00:00 2001 From: Husn E Rabbi Date: Tue, 9 Dec 2025 14:45:48 +0500 Subject: [PATCH 4/5] docs(pg_ivm): update README with shared_preload_libraries configuration Signed-off-by: Husn E Rabbi --- pg_ivm/README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pg_ivm/README.md b/pg_ivm/README.md index b65aacf..6de71da 100644 --- a/pg_ivm/README.md +++ b/pg_ivm/README.md @@ -23,6 +23,9 @@ spec: storage: size: 1Gi + postgresql: + shared_preload_libraries: + - "pg_ivm" postgresql: extensions: - name: pg_ivm From 0d14730d69808c61623ba62b70bd852f7a22b45d Mon Sep 17 00:00:00 2001 From: Husn E Rabbi Date: Sat, 21 Feb 2026 06:52:48 +0500 Subject: [PATCH 5/5] chore(pg_ivm): update package source and versions Signed-off-by: Husn E Rabbi --- CODEOWNERS | 2 + pg_ivm/Dockerfile | 63 +++++----- pg_ivm/README.md | 150 ++++++++++++++---------- pg_ivm/metadata.hcl | 45 +++---- pg_ivm/test/chainsaw-test.yaml | 28 +++++ pg_ivm/test/check-extension-assert.yaml | 6 + pg_ivm/test/check-extension.yaml | 31 +++++ pg_ivm/test/cluster-assert.yaml | 8 ++ pg_ivm/test/cluster.yaml | 14 +++ pg_ivm/test/database-assert.yaml | 10 ++ pg_ivm/test/database.yaml | 12 ++ 11 files changed, 252 insertions(+), 117 deletions(-) create mode 100644 pg_ivm/test/chainsaw-test.yaml create mode 100644 pg_ivm/test/check-extension-assert.yaml create mode 100644 pg_ivm/test/check-extension.yaml create mode 100644 pg_ivm/test/cluster-assert.yaml create mode 100644 pg_ivm/test/cluster.yaml create mode 100644 pg_ivm/test/database-assert.yaml create mode 100644 pg_ivm/test/database.yaml diff --git a/CODEOWNERS b/CODEOWNERS index f4dd1e7..471f9c6 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -3,3 +3,5 @@ # https://docs.github.com/en/free-pro-team@latest/github/creating-cloning-and-archiving-repositories/about-code-owners * @cloudnative-pg/maintainers @NiccoloFei +# pg_ivm +/pg_ivm/ @shusaan @cloudnative-pg/maintainers @NiccoloFei \ No newline at end of file diff --git a/pg_ivm/Dockerfile b/pg_ivm/Dockerfile index ddd1d40..382793e 100644 --- a/pg_ivm/Dockerfile +++ b/pg_ivm/Dockerfile @@ -1,35 +1,30 @@ -ARG BASE=ghcr.io/cloudnative-pg/postgresql:18-minimal-trixie -FROM $BASE AS builder - -ARG PG_MAJOR -ARG EXT_VERSION - -USER 0 - -RUN set -eux; \ - apt-get update; \ - apt-get install -y --no-install-recommends \ - build-essential \ - ca-certificates \ - git \ - postgresql-server-dev-${PG_MAJOR}; \ - # Clone and build pg_ivm from source - git clone --branch "v${EXT_VERSION}" --depth 1 https://github.com/sraoss/pg_ivm.git /build/pg_ivm; \ - cd /build/pg_ivm; \ - make USE_PGXS=1; \ - make USE_PGXS=1 install - -FROM scratch -ARG PG_MAJOR - -# Licenses -COPY --from=builder /build/pg_ivm/LICENSE /licenses/pg_ivm/LICENSE - -# Libraries -COPY --from=builder /usr/lib/postgresql/${PG_MAJOR}/lib/pg_ivm* /lib/ -COPY --from=builder /usr/lib/postgresql/${PG_MAJOR}/lib/bitcode /usr/lib/postgresql/${PG_MAJOR}/lib/bitcode/ - -# Share -COPY --from=builder /usr/share/postgresql/${PG_MAJOR}/extension/pg_ivm* /share/extension/ - +# SPDX-FileCopyrightText: Copyright © contributors to CloudNativePG, established as CloudNativePG a Series of LF Projects, LLC. +# SPDX-License-Identifier: Apache-2.0 + +ARG BASE=ghcr.io/cloudnative-pg/postgresql:18-minimal-trixie +FROM $BASE AS builder + +ARG PG_MAJOR +ARG EXT_VERSION + +USER 0 + +RUN set -eux; \ + apt-get update; \ + apt-get install -y --no-install-recommends \ + postgresql-${PG_MAJOR}-pg-ivm=${EXT_VERSION}* + +FROM scratch +ARG PG_MAJOR + +# Licenses +COPY --from=builder /usr/share/doc/postgresql-${PG_MAJOR}-pg-ivm/copyright /licenses/pg_ivm/ + +# Libraries +COPY --from=builder /usr/lib/postgresql/${PG_MAJOR}/lib/pg_ivm* /lib/ +COPY --from=builder /usr/lib/postgresql/${PG_MAJOR}/lib/bitcode/pg_ivm* /lib/bitcode/ + +# Share +COPY --from=builder /usr/share/postgresql/${PG_MAJOR}/extension/pg_ivm* /share/extension/ + USER 65532:65532 \ No newline at end of file diff --git a/pg_ivm/README.md b/pg_ivm/README.md index 6de71da..4bc21a0 100644 --- a/pg_ivm/README.md +++ b/pg_ivm/README.md @@ -1,63 +1,87 @@ -# pg_ivm Extension - -[pg_ivm](https://github.com/sraoss/pg_ivm) is an open-source extension -that provides **Incremental View Maintenance (IVM)** for PostgreSQL, allowing -materialized views to be updated incrementally when base tables change. - -## Usage - -### 1. Add the pg_ivm extension image to your Cluster - -Define the `pg_ivm` extension under the `postgresql.extensions` section of -your `Cluster` resource. For example: - -```yaml -apiVersion: postgresql.cnpg.io/v1 -kind: Cluster -metadata: - name: cluster-pg-ivm -spec: - imageName: ghcr.io/cloudnative-pg/postgresql:18-minimal-trixie - instances: 1 - - storage: - size: 1Gi - - postgresql: - shared_preload_libraries: - - "pg_ivm" - postgresql: - extensions: - - name: pg_ivm - image: - reference: ghcr.io/cloudnative-pg/pg_ivm:1.13-18-trixie -``` - -### 2. Enable the extension in a database - -You can install `pg_ivm` in a specific database by creating or updating a -`Database` resource. For example, to enable it in the `app` database: - -```yaml -apiVersion: postgresql.cnpg.io/v1 -kind: Database -metadata: - name: cluster-pg-ivm-app -spec: - name: app - owner: app - cluster: - name: cluster-pg-ivm - extensions: - - name: pg_ivm -``` - -### 3. Verify installation - -Once the database is ready, connect to it with `psql` and run: - -```sql -\dx -``` - -You should see `pg_ivm` listed among the installed extensions. +# pg_ivm + +[pg_ivm](https://github.com/sraoss/pg_ivm) is an open-source extension +that provides **Incremental View Maintenance (IVM)** for PostgreSQL, allowing +materialized views to be updated incrementally when base tables change. + +## Usage + + + +### 1. Add the pg_ivm extension image to your Cluster + +Define the `pg_ivm` extension under the `postgresql.extensions` section of +your `Cluster` resource. For example: + +```yaml +apiVersion: postgresql.cnpg.io/v1 +kind: Cluster +metadata: + name: cluster-pg_ivm +spec: + imageName: ghcr.io/cloudnative-pg/postgresql:18-minimal-trixie + instances: 1 + + storage: + size: 1Gi + + postgresql: + extensions: + - name: pg_ivm + image: + reference: ghcr.io/cloudnative-pg/pg_ivm:1.0-18-trixie +``` + +### 2. Enable the extension in a database + +You can install `pg_ivm` in a specific database by creating or updating a +`Database` resource. For example, to enable it in the `app` database: + +```yaml +apiVersion: postgresql.cnpg.io/v1 +kind: Database +metadata: + name: cluster-pg_ivm-app +spec: + name: app + owner: app + cluster: + name: cluster-pg_ivm + extensions: + - name: pg_ivm + version: '1.13' +``` + +### 3. Verify installation + +Once the database is ready, connect to it with `psql` and run: + +```sql +\dx +``` + +You should see `pg_ivm` listed among the installed extensions. + +## Maintainers + +This container image is maintained by @shuusan. + +--- + +## Licenses and Copyright + +This container image contains software that may be licensed under various +open-source licenses. + +All relevant license and copyright information for the `pg_ivm` extension +and its dependencies are bundled within the image at: + +```text +/licenses/ +``` + +By using this image, you agree to comply with the terms of the licenses +contained therein. diff --git a/pg_ivm/metadata.hcl b/pg_ivm/metadata.hcl index d858659..9eb9de1 100644 --- a/pg_ivm/metadata.hcl +++ b/pg_ivm/metadata.hcl @@ -1,20 +1,25 @@ -metadata = { - name = "pg_ivm" - sql_name = "pg_ivm" - image_name = "pg_ivm" - shared_preload_libraries = [] - extension_control_path = [] - dynamic_library_path = [] - ld_library_path = [] - - versions = { - bookworm = { - // pg_ivm version from GitHub releases - "18" = "1.13" - } - trixie = { - // pg_ivm version from GitHub releases - "18" = "1.13" - } - } -} \ No newline at end of file +# SPDX-FileCopyrightText: Copyright © contributors to CloudNativePG, established as CloudNativePG a Series of LF Projects, LLC. +# SPDX-License-Identifier: Apache-2.0 +metadata = { + name = "pg_ivm" + sql_name = "pg_ivm" + image_name = "pg_ivm" + shared_preload_libraries = [] + extension_control_path = [] + dynamic_library_path = [] + ld_library_path = [] + auto_update_os_libs = false + required_extensions = [] + create_extension = true + + versions = { + trixie = { + // renovate: suite=trixie-pgdg depName=postgresql-18-pg-ivm + "18" = "1.13-1.pgdg13+1" + } + bookworm = { + // renovate: suite=bookworm-pgdg depName=postgresql-18-pg-ivm + "18" = "1.13-1.pgdg12+1" + } + } +} diff --git a/pg_ivm/test/chainsaw-test.yaml b/pg_ivm/test/chainsaw-test.yaml new file mode 100644 index 0000000..45aefb5 --- /dev/null +++ b/pg_ivm/test/chainsaw-test.yaml @@ -0,0 +1,28 @@ +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + name: verify-pg-ivm-extension +spec: + timeouts: + apply: 5s + assert: 3m + delete: 30s + description: Verify pg_ivm extension is properly installed + steps: + - name: Create a Cluster with the extension + try: + - apply: + file: cluster.yaml + - apply: + file: database.yaml + - assert: + file: cluster-assert.yaml + - assert: + file: database-assert.yaml + + - name: Verify extension is installed + try: + - apply: + file: check-extension.yaml + - assert: + file: check-extension-assert.yaml diff --git a/pg_ivm/test/check-extension-assert.yaml b/pg_ivm/test/check-extension-assert.yaml new file mode 100644 index 0000000..966d4a3 --- /dev/null +++ b/pg_ivm/test/check-extension-assert.yaml @@ -0,0 +1,6 @@ +apiVersion: batch/v1 +kind: Job +metadata: + name: extension-installed +status: + succeeded: 1 diff --git a/pg_ivm/test/check-extension.yaml b/pg_ivm/test/check-extension.yaml new file mode 100644 index 0000000..79335d5 --- /dev/null +++ b/pg_ivm/test/check-extension.yaml @@ -0,0 +1,31 @@ +apiVersion: batch/v1 +kind: Job +metadata: + name: extension-installed +spec: + template: + spec: + restartPolicy: OnFailure + containers: + - name: data-test + env: + - name: EXT_VERSION + value: ($values.version) + - name: DB_URI + valueFrom: + secretKeyRef: + name: (join('-', [$values.name, 'app'])) + key: uri + image: alpine/psql:latest + command: ['sh', '-c'] + args: + - | + set -e + DB_URI=$(echo $DB_URI | sed "s|/\*|/|") + test "$(psql "$DB_URI" -tAc "SELECT EXISTS (SELECT FROM pg_catalog.pg_extension WHERE extname = 'pg_ivm' AND extversion = '${EXT_VERSION}')" -q)" = "t" + psql "$DB_URI" -c "CREATE TABLE base_table (id INT PRIMARY KEY, value TEXT);" + psql "$DB_URI" -c "INSERT INTO base_table VALUES (1, 'test');" + psql "$DB_URI" -c "CREATE INCREMENTAL MATERIALIZED VIEW test_ivm AS SELECT * FROM base_table;" + test "$(psql "$DB_URI" -tAc "SELECT COUNT(*) FROM test_ivm" -q)" = "1" + psql "$DB_URI" -c "INSERT INTO base_table VALUES (2, 'test2');" + test "$(psql "$DB_URI" -tAc "SELECT COUNT(*) FROM test_ivm" -q)" = "2" diff --git a/pg_ivm/test/cluster-assert.yaml b/pg_ivm/test/cluster-assert.yaml new file mode 100644 index 0000000..2b8d478 --- /dev/null +++ b/pg_ivm/test/cluster-assert.yaml @@ -0,0 +1,8 @@ +apiVersion: postgresql.cnpg.io/v1 +kind: Cluster +metadata: + name: ($values.name) +status: + readyInstances: 1 + phase: Cluster in healthy state + image: ($values.pg_image) diff --git a/pg_ivm/test/cluster.yaml b/pg_ivm/test/cluster.yaml new file mode 100644 index 0000000..d936937 --- /dev/null +++ b/pg_ivm/test/cluster.yaml @@ -0,0 +1,14 @@ +apiVersion: postgresql.cnpg.io/v1 +kind: Cluster +metadata: + name: ($values.name) +spec: + imageName: ($values.pg_image) + instances: 1 + + storage: + size: 1Gi + + postgresql: + shared_preload_libraries: ($values.shared_preload_libraries) + extensions: ($values.extensions) diff --git a/pg_ivm/test/database-assert.yaml b/pg_ivm/test/database-assert.yaml new file mode 100644 index 0000000..a515f07 --- /dev/null +++ b/pg_ivm/test/database-assert.yaml @@ -0,0 +1,10 @@ +apiVersion: postgresql.cnpg.io/v1 +kind: Database +metadata: + name: (join('-', [$values.name, 'app'])) +status: + applied: true + extensions: + - applied: true + name: ($values.sql_name) + observedGeneration: 1 diff --git a/pg_ivm/test/database.yaml b/pg_ivm/test/database.yaml new file mode 100644 index 0000000..f2abe39 --- /dev/null +++ b/pg_ivm/test/database.yaml @@ -0,0 +1,12 @@ +apiVersion: postgresql.cnpg.io/v1 +kind: Database +metadata: + name: (join('-', [$values.name, 'app'])) +spec: + name: app + owner: app + cluster: + name: ($values.name) + extensions: + - name: ($values.sql_name) + version: ($values.version)