Skip to content

Commit 89fd8f0

Browse files
gbartolinimnenciaNiccoloFei
authored
docs: harmonize contribution guidelines and licensing policy (#125)
Add a new file, `CONTRIBUTING_NEW_EXTENSION.md`, governing the entire step-by-step workflow to add a new extension to the project. Harmonized the content of the other files. Closes #86 Signed-off-by: Gabriele Bartolini <gabriele.bartolini@enterprisedb.com> Signed-off-by: Marco Nenciarini <marco.nenciarini@enterprisedb.com> Signed-off-by: Niccolò Fei <niccolo.fei@enterprisedb.com> Co-authored-by: Marco Nenciarini <marco.nenciarini@enterprisedb.com> Co-authored-by: Niccolò Fei <niccolo.fei@enterprisedb.com> Assisted-by: Google Gemini
1 parent 7eed986 commit 89fd8f0

4 files changed

Lines changed: 317 additions & 8 deletions

File tree

BUILD.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,12 @@ This guide explains how to build Postgres extensions container images for
44
[CloudNativePG](https://cloudnative-pg.io) locally, using
55
[Docker Bake](https://docs.docker.com/build/bake/).
66

7+
> [!IMPORTANT]
8+
> If you are looking to contribute a new PostgreSQL extension to this
9+
> repository, please refer to the [`CONTRIBUTING_NEW_EXTENSION.md` file](CONTRIBUTING_NEW_EXTENSION.md).
10+
> This guide covers the entire lifecycle, from proposing the extension and
11+
> scaffolding the project to local validation and submitting a Pull Request.
12+
713
## Prerequisites
814

915
Before you begin, ensure that you have met the following
@@ -45,6 +51,8 @@ following scaffolded files:
4551
> [!NOTE]
4652
> These files are generated from generic templates and should be customized to
4753
> meet your extension's specific requirements.
54+
> For a complete walkthrough of the requirements and package discovery phase,
55+
> see [`CONTRIBUTING_NEW_EXTENSION.md`](./CONTRIBUTING_NEW_EXTENSION.md).
4856
4957
### Advanced Scaffolding
5058

CONTRIBUTING.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,18 @@ contribution workflows.
88

99
Please review the [CloudNativePG Project contributing guidelines](https://github.com/cloudnative-pg/governance/blob/main/CONTRIBUTING.md)
1010
before searching for issues, reporting bugs, or submitting a pull request.
11+
12+
## Adding a New Extension
13+
14+
This repository is specifically designed for the lifecycle of PostgreSQL
15+
extension container images. If you are looking to add a new extension, we have
16+
a dedicated guide that covers everything from environment setup and package
17+
discovery to local testing and submission:
18+
19+
- [Guide to adding a new extension: `CONTRIBUTING_NEW_EXTENSION.md`](CONTRIBUTING_NEW_EXTENSION.md)
20+
21+
## Development Environment
22+
23+
If you are working on the build system or testing framework itself, please
24+
refer to [BUILD.md](./BUILD.md) for technical details on how Dagger and Task are
25+
used to manage the pipeline.

CONTRIBUTING_NEW_EXTENSION.md

Lines changed: 277 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,277 @@
1+
# Contributing: Adding a New PostgreSQL Extension
2+
3+
This guide walks you through the lifecycle of adding a new extension, from
4+
setting up your environment to submitting a Pull Request.
5+
6+
> [!IMPORTANT]
7+
> Please ensure you have also read the general
8+
> [CONTRIBUTING.md](https://github.com/cloudnative-pg/governance/blob/main/CONTRIBUTING.md)
9+
> for CloudNativePG before proceeding.
10+
11+
## 1. Phase One: Fork, Clone, and Validate
12+
13+
Before proposing a change, ensure your local machine is compatible with the
14+
[build stack](BUILD.md).
15+
16+
1. **Fork** the [cloudnative-pg/postgres-extensions-containers](https://github.com/cloudnative-pg/postgres-extensions-containers) repository.
17+
2. **Clone** your fork and enter the directory:
18+
```sh
19+
git clone https://github.com/<your-username>/postgres-extensions-containers.git
20+
cd postgres-extensions-containers
21+
```
22+
3. **Verify the Environment:** Run the following to ensure you can build the
23+
existing project ecosystem.
24+
```sh
25+
task prereqs # Check if Go, Task, and Docker are ready
26+
task checks:all # Validate current configurations
27+
task bake:all # Optional: build all existing extensions to confirm the Dagger engine
28+
```
29+
30+
---
31+
32+
## 2. Phase Two: The Proposal & Package Discovery
33+
34+
To maintain high standards and avoid duplicated effort or architectural
35+
conflicts, every new extension begins with a formal proposal.
36+
During this phase, you must verify that the extension is available in the PGDG
37+
(PostgreSQL Global Development Group) repositories and identify its versioning
38+
logic.
39+
40+
### Identifying the Package & Version
41+
42+
You must verify the package across both the current Debian `stable` and
43+
`oldstable` distributions to ensure compatibility. Use a temporary container to
44+
search the repositories:
45+
46+
For Debian `stable` (13, `trixie`):
47+
48+
```sh
49+
docker run -u root -ti --rm ghcr.io/cloudnative-pg/postgresql:18-minimal-trixie
50+
```
51+
52+
For Debian `oldstable` (12, `bookworm`):
53+
54+
```sh
55+
docker run -u root -ti --rm ghcr.io/cloudnative-pg/postgresql:18-minimal-bookworm
56+
```
57+
58+
Then, inside the container:
59+
60+
```sh
61+
apt update && apt search <EXTENSION_NAME>
62+
```
63+
64+
#### Understanding the Version String
65+
66+
Take note of both the **package name** and the **version string**.
67+
Using `pgvector` as an example, you will notice that while the package name
68+
remains constant, the versioning reflects the underlying Debian release:
69+
70+
- `trixie`: `0.8.2-1.pgdg13+1`
71+
- `bookworm`: `0.8.2-1.pgdg12+1`
72+
73+
> [!IMPORTANT]
74+
> The `pgdg13` or `pgdg12` suffix is critical. Correctly identifying this
75+
> versioning pattern ensures that `renovate` can automatically monitor the
76+
> upstream repositories and trigger update Pull Requests once your extension is
77+
> merged.
78+
79+
#### Inspecting the Package Content
80+
81+
If you want to get a list of the files contained in the package, you need to
82+
first install the extension in the disposable container:
83+
84+
```sh
85+
apt install <package-name>
86+
```
87+
88+
Then, list the content of the package with:
89+
90+
```sh
91+
dpkg -L <full-package-name>
92+
```
93+
94+
Confirm that `.control` and `.sql` files are present in the expected PostgreSQL
95+
paths.
96+
97+
> [!IMPORTANT]
98+
> If the package doesn't contain any `.control` file, it is likely to be a
99+
> **PostgreSQL module** rather than an extension. In this case, remember to set
100+
> the `create_extension` option to `false` in your `metadata.hcl` file.
101+
102+
### Opening an Issue
103+
104+
> [!IMPORTANT]
105+
> **Community Commitment:** By opening the issue, you are confirming your
106+
> intent to help maintain this extension on behalf of the CloudNativePG
107+
> community.
108+
109+
After gathering the package details and verifying the extension's license,
110+
submit your proposal:
111+
112+
1. Point your browser to ["New Extension Proposal"](https://github.com/cloudnative-pg/postgres-extensions-containers/issues/new/choose).
113+
2. Provide the package name, versioning info, and a link to the upstream source.
114+
3. State the license clearly:
115+
- CNCF-Allowed: licenses on the [CNCF Allowlist](https://github.com/cncf/foundation/blob/main/policies-guidance/allowed-third-party-license-policy.md) (e.g., Apache-2.0, MIT, or PostgreSQL) are generally pre-approved.
116+
- Other Open Source: licenses like FSF-approved (GNU GPL) will be evaluated on a case-by-case basis.
117+
- Redistribution: since we redistribute unmodified software, ensure you
118+
identify where the upstream source code can be found (required for GNU
119+
GPL compliance).
120+
121+
> [!NOTE]
122+
> You do not need to wait for maintainer approval to begin development or
123+
> submit your PR. You are encouraged to proceed immediately; however, please be
124+
> aware that if a fundamental issue (e.g., licensing) is discovered during the
125+
> proposal review, you may need to modify or discard your work.
126+
127+
---
128+
129+
## 3. Phase Three: Implementation & Scaffolding
130+
131+
### Creating a Branch
132+
133+
```sh
134+
git checkout -b dev/<extension-name>
135+
```
136+
137+
### Scaffolding
138+
139+
Generate the directory structure automatically:
140+
141+
```sh
142+
task create-extension NAME=<extension-name>
143+
```
144+
145+
> [!NOTE]
146+
> For advanced scaffolding (custom distros or versions), see
147+
> [`BUILD.md`](./BUILD.md#advanced-scaffolding).
148+
149+
### Customizing the Files
150+
151+
The scaffolding generates `metadata.hcl`, `Dockerfile`, and `README.md`.
152+
Follow the specific instructions and "TODO" comments found within each
153+
generated file to finalize your extension.
154+
155+
> [!TIP]
156+
> Pay close attention to the `// renovate:` comments in the metadata; these are
157+
> required for automated version tracking.
158+
159+
---
160+
161+
## 4. Phase Four: Local Testing & Validation
162+
163+
Testing is the most critical part of the lifecycle.
164+
165+
### Automated E2E Testing
166+
167+
> [!NOTE]
168+
> For a detailed breakdown of the testing infrastructure, refer to
169+
> [`BUILD.md`](./BUILD.md#local-testing-guide).
170+
171+
The repository provides a framework for full End-to-End validation. Ensure that
172+
the entire pipeline is working:
173+
174+
```sh
175+
task checks:all
176+
```
177+
178+
Then run the full E2E tests for the extension. This task will build your image,
179+
push it to a local registry, spin up a Kind cluster, and run the functional
180+
tests:
181+
182+
```sh
183+
task e2e:test:full TARGET="<extension-name>"
184+
```
185+
186+
### Local Manual Verification
187+
188+
Once the automated tests have run, the Kind cluster remains active. You can
189+
"drop in" to this environment to verify the instructions you wrote in your
190+
`README.md`.
191+
192+
#### Exporting the Kubeconfig
193+
194+
```sh
195+
task e2e:export-kubeconfig KUBECONFIG_PATH=./kubeconfig
196+
export KUBECONFIG=$PWD/kubeconfig
197+
```
198+
199+
#### Identifying the Image Tag
200+
201+
Once the image is built and pushed to the local registry (`localhost:5000`),
202+
you should verify the generated tags. You can use tools like `skopeo` to
203+
inspect the local registry:
204+
205+
```bash
206+
skopeo list-tags --tls-verify=false docker://localhost:5000/<extension-name>-testing
207+
```
208+
209+
> [!IMPORTANT]
210+
> Remember to add the `-testing` suffix to the container registry.
211+
212+
Verify that the output lists tags for all expected PostgreSQL and Debian
213+
version combinations.
214+
215+
#### Testing the Extension
216+
217+
Create a `Cluster` resource using the instructions from your `README.md`.
218+
Pay close attention to the image location. Inside the Kubernetes cluster, the
219+
local registry is reachable at `registry.pg-extensions:5000`:
220+
221+
```yaml
222+
image: registry.pg-extensions:5000/<extension-name>-testing:<tag>
223+
```
224+
225+
### Extending Tests
226+
227+
While the framework provides a generic smoke test, we highly encourage you to
228+
add **extension-specific tests**. Review the [`postgis`](./postgis) directory
229+
for an example of additional testing using the Chainsaw framework.
230+
231+
### Cleaning up
232+
233+
Once you have finished your manual verification, tear down the test
234+
environment:
235+
236+
```bash
237+
task e2e:cleanup
238+
```
239+
240+
---
241+
242+
## 5. Phase Five: Documentation & The Pull Request
243+
244+
### The `README.md` file
245+
246+
The `README.md` is typically the last file you complete. A clear, professional
247+
`README.md` makes an extension successful. Ensure it includes YAML examples for
248+
`Cluster` and `Database` resources so users can immediately adopt your work.
249+
250+
### Commit and Submit
251+
252+
Once you have verified your extension locally and are satisfied with the
253+
results, it is time to submit your contribution.
254+
255+
To maintain a clean and searchable history, we require a specific commit
256+
format. If you have multiple experimental commits on your branch, please squash
257+
them into a single commit before submitting.
258+
259+
Format:
260+
261+
```text
262+
feat: add `<extension-name>` container image
263+
264+
<DESCRIPTION: Explain what the extension does and why it's being added.>
265+
266+
Closes #<issue-id>
267+
```
268+
269+
Submission Requirements:
270+
271+
- **DCO Compliance**: All commits must be signed (`git commit -s`) to certify
272+
that you have the right to submit the code under the project's license.
273+
- **Upstream Target**: Ensure your Pull Request is targeting the `main` branch of
274+
the upstream repository.
275+
276+
By submitting, you confirm your commitment to maintain this extension on behalf
277+
of the CloudNativePG Community.

README.md

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,16 @@
55
This repository provides **maintenance scripts** for building **immutable
66
container images** containing PostgreSQL extensions supported by
77
[CloudNativePG](https://cloudnative-pg.io/). These images are designed to
8-
integrate seamlessly with the [`image volume extensions` feature](https://cloudnative-pg.io/documentation/current/imagevolume_extensions/)
9-
in CloudNativePG.
8+
integrate seamlessly with the image volume extensions feature in CloudNativePG.
109

11-
For detailed instructions on building the images, see the [`BUILD.md` file](BUILD.md).
10+
## Documentation
11+
12+
- [Adding a New Extension](./CONTRIBUTING_NEW_EXTENSION.md): A step-by-step
13+
guide for contributors.
14+
- [Building Locally](./BUILD.md): Technical instructions for the build system
15+
(Dagger/Task).
16+
- [CloudNativePG Documentation](https://cloudnative-pg.io/documentation/current/imagevolume_extensions/):
17+
How to use these images in your cluster.
1218

1319
---
1420

@@ -56,17 +62,20 @@ The project adheres to the following frameworks:
5662

5763
When proposing a new extension, the following criteria must be met:
5864

59-
- **Licensing and IP ownership:** the extension's licensing must be compatible
60-
with the project's goals. We approve all licences that are on the CNCF
61-
Allowed Third-Party Licence Policy list (see
62-
[CNCF Allowed Licence Policy](https://github.com/cncf/foundation/blob/main/policies-guidance/allowed-third-party-license-policy.md#cncf-allowlist-license-policy)).
65+
- **Licensing and IP ownership:** We redistribute unmodified third-party
66+
software as container images. We prioritize licenses explicitly allowed by the
67+
[CNCF License Policy](https://github.com/cncf/foundation/blob/main/policies-guidance/allowed-third-party-license-policy.md),
68+
which includes the PostgreSQL License (relevant to this project). Other
69+
open-source licenses, such as FSF-approved licenses (e.g., GNU GPL), will be
70+
considered on a case-by-case basis to ensure compliance with redistribution
71+
requirements.
6372
- **Structure:** only one extension can be included within an extension folder.
6473
- **Debian Packages:** Extension images must be built using a Debian package
6574
provided by a trusted source like the
6675
[PostgreSQL Global Development Group (PGDG)](https://wiki.postgresql.org/wiki/Apt).
6776
This ensures compatibility with the base images and standard package
6877
management procedures.
69-
- **Licence inclusion:** all necessary licence agreements for the extension and
78+
- **License inclusion:** all necessary license agreements for the extension and
7079
its dependencies must be included within the extension folder (refer to the
7180
examples in the `pgvector` and `postgis` folders).
7281

0 commit comments

Comments
 (0)