Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 13 additions & 9 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,19 @@ jobs:
# the rpms can be signed before they are attached to the release.
GORELEASER_CURRENT_TAG=${CIRCLE_TAG} goreleaser release \
--release-notes=${release_notes} --skip=nfpm

# Build and publish the control plane image now, while the archives
# from the first goreleaser run (named with CIRCLE_TAG) are still in
# dist/. The second goreleaser run below uses --clean, which wipes
# dist/ and recreates archives with PKG_TAG — if the image build ran
# after that, docker buildx would look for the CIRCLE_TAG archive and
# fail because only the PKG_TAG archive exists.
echo "${IMAGE_PUBLISH_TOKEN}" \
| docker login ghcr.io --username "${IMAGE_PUBLISH_USER}" --password-stdin
CONTROL_PLANE_IMAGE_REPO='ghcr.io/pgedge/control-plane' \
CONTROL_PLANE_VERSION="${CIRCLE_TAG}" \
make control-plane-images

GORELEASER_CURRENT_TAG=${PKG_TAG} goreleaser release \
--clean --skip=publish,announce,validate,sbom

Expand All @@ -250,15 +263,6 @@ jobs:
gh release upload "${CIRCLE_TAG}" dist/*.rpm dist/*.deb --clobber
gh release edit "${CIRCLE_TAG}" --draft=false

# log into control plane ECR repo
echo "${IMAGE_PUBLISH_TOKEN}" \
| docker login ghcr.io --username "${IMAGE_PUBLISH_USER}" --password-stdin

# build and publish control plane image
CONTROL_PLANE_IMAGE_REPO='ghcr.io/pgedge/control-plane' \
CONTROL_PLANE_VERSION="${CIRCLE_TAG}" \
make control-plane-images

build_image:
executor: common
steps:
Expand Down
43 changes: 42 additions & 1 deletion .goreleaser.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -64,17 +64,58 @@ nfpms:
scripts:
postinstall: packaging/deb/postinstall.sh
preremove: packaging/deb/preremove.sh
# Every entry sets file_info.mode explicitly. Without it, nfpm stats the
# source file as checked out on the builder and strips its own Umask
# (defaults to 0o02) from that mode, so whatever mode the file happened to
# have on the builder shipped in the packages (that's how group-writable
# 0664 files ended up in prior builds). config.json is 0600 because it may
# hold credentials and only the unit (which runs as root) needs to read it.
contents:
- src: packaging/pgedge-control-plane.service
dst: /usr/lib/systemd/system/pgedge-control-plane.service
type: config
file_info:
mode: 0644
Comment thread
coderabbitai[bot] marked this conversation as resolved.
- src: packaging/config.json
dst: /etc/pgedge-control-plane/config.json
type: config|noreplace
file_info:
mode: 0600
- src: .sbom/sbom.json
dst: /usr/share/pgedge-control-plane/pgedge-control-plane-sbom.json
file_info:
mode: 0644
- src: ".sbom/sbom.{{ .Format }}.asc"
dst: /usr/share/pgedge-control-plane/pgedge-control-plane-sbom.json.asc
file_info:
mode: 0644
# README shares the same path in both formats; LICENSE does not, since
# rpm and deb have different conventional license paths. The 'doc' and
# 'license' types add the %doc/%license markers to the rpm spec, but nfpm
# drops content of those types from non-rpm packages, so the deb needs its
# own plain-file entries (scoped with `packager` so each format gets
# exactly one entry per path).
- src: README.md
dst: /usr/share/doc/pgedge-control-plane/README.md
type: doc
Comment thread
jason-lynch marked this conversation as resolved.
packager: rpm
file_info:
mode: 0644
- src: README.md
dst: /usr/share/doc/pgedge-control-plane/README.md
packager: deb
file_info:
mode: 0644
- src: LICENSE.md
dst: /usr/share/licenses/pgedge-control-plane/LICENSE.md
type: license
Comment thread
jason-lynch marked this conversation as resolved.
packager: rpm
file_info:
mode: 0644
- src: LICENSE.md
dst: /usr/share/doc/pgedge-control-plane/copyright
packager: deb
file_info:
mode: 0644
Comment thread
coderabbitai[bot] marked this conversation as resolved.
formats: [rpm]
release: "1.el9"
- <<: *nfpm_defaults
Expand Down
31 changes: 31 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,36 @@
# Changelog

## v0.10.0 - 2026-07-24

### Added

- The Control Plane now rejects database specs that remove `spock` from `postgresql_conf.shared_preload_libraries`, preventing accidental disabling of the replication extension.
- Added image upgrade support. Use `GET /v1/databases/{id}?include=available_upgrades` to list newer stable images within the same Postgres major and Spock major version bucket, and `POST /v1/databases/{id}/upgrade` to apply an upgrade without changing the Postgres major version.
- Added support for custom container image pinning per database or node via `orchestrator_opts.swarm.image`. pgEdge-formatted image tags are validated against the spec's declared versions; unrecognized tags are accepted without version checks. The Control Plane also persists the resolved image at creation time, preventing silent image changes during Control Plane upgrades.
- Version resolution is now fully manifest-driven. Supported versions update with manifest refreshes without requiring a Control Plane upgrade.
- The Control Plane now falls back to the first available IPv6 address when no IPv4 address is found during IP autodetection.
- Cancelling a task now propagates to any in-progress activities, interrupting long-running operations rather than waiting for them to complete.
- RPM and DEB packages are now published to the pgEdge dnf and apt repositories on every release, enabling installation via `dnf` and `apt-get` in addition to the existing Docker and binary distribution methods.
- Added support for Spock 5.0.10 on Postgres 16.14, 17.10, and 18.4.

### Changed

- **Breaking:** Changed the default `password_encryption` from `md5` to `scram-sha-256`. If you're using the default password encryption, every role in a database's `database_users` will be automatically updated to `scram-sha-256` the next time you update that database. Roles created outside of `database_users` will need their passwords updated manually. To keep using `md5`, set `postgresql_conf.password_encryption` to `md5` in your database spec.

### Fixed

- Fixed an issue where resources pending recreation were not correctly planned for creation in the right reconciliation phase, causing reconciliation errors.
- Fixed Patroni rejecting connections from IPv4 addresses presented as IPv4-mapped IPv6 addresses (e.g. `::ffff:192.168.1.1`) on dual-stack hosts.
- Fixed rolling updates failing on multi-node databases with replica instances due to replication slot timing during instance initialization.
- Fixed an issue where services configured with `"version": "latest"` failed at runtime because `"latest"` was not registered in the version map.
- The RPM and DEB packages now bundle the project documentation and license, installing `README.md` to `/usr/share/doc/pgedge-control-plane/` and `LICENSE.md` to `/usr/share/licenses/pgedge-control-plane/`.
- RPM and DEB packages now install files with explicit, deterministic permissions rather than inheriting the build machine's umask, which produced group-writable `0664` files. `/usr/lib/systemd/system/pgedge-control-plane.service` is now `0644` and `/etc/pgedge-control-plane/config.json` is now `0640`.

### Security

- Update vulnerable dependencies (pgx v5.10.0, OpenTelemetry v1.44.0, golang.org/x/crypto v0.54.0, golang.org/x/net v0.57.0) and bump the Go toolchain to 1.26.5 to remediate Trivy-flagged CVEs in the control-plane image (PLAT-686). github.com/docker/docker CVE-2026-41567/CVE-2026-42306 have no fix in the v27.x line in use; risk-accepted in .trivy/pgedge-control-plane.trivyignore.yaml since the vulnerable docker-cp/archive-copy code paths are never invoked by this codebase.
- Fixed a SQL injection vulnerability in role attribute handling during database creation and updates.

## v0.9.0 - 2026-06-16

### Added
Expand Down
2 changes: 1 addition & 1 deletion api/apiv1/gen/control_plane/service.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion api/apiv1/gen/http/openapi.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion api/apiv1/gen/http/openapi.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion api/apiv1/gen/http/openapi3.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion api/apiv1/gen/http/openapi3.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion api/version.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
v0.9.0
v0.10.0
3 changes: 0 additions & 3 deletions changes/unreleased/Added-20260625-000000.yaml

This file was deleted.

3 changes: 0 additions & 3 deletions changes/unreleased/Added-20260701-000000.yaml

This file was deleted.

3 changes: 0 additions & 3 deletions changes/unreleased/Added-20260701-000001.yaml

This file was deleted.

3 changes: 0 additions & 3 deletions changes/unreleased/Added-20260707-000000.yaml

This file was deleted.

3 changes: 0 additions & 3 deletions changes/unreleased/Added-20260707-000001.yaml

This file was deleted.

3 changes: 0 additions & 3 deletions changes/unreleased/Added-20260713-000000.yaml

This file was deleted.

3 changes: 0 additions & 3 deletions changes/unreleased/Added-20260723-000000.yaml

This file was deleted.

3 changes: 0 additions & 3 deletions changes/unreleased/Added-20260724-000000.yaml

This file was deleted.

3 changes: 0 additions & 3 deletions changes/unreleased/Changed-20260706-204431.yaml

This file was deleted.

3 changes: 0 additions & 3 deletions changes/unreleased/Fixed-20260706-000000.yaml

This file was deleted.

3 changes: 0 additions & 3 deletions changes/unreleased/Fixed-20260708-000000.yaml

This file was deleted.

3 changes: 0 additions & 3 deletions changes/unreleased/Fixed-20260715-000001.yaml

This file was deleted.

3 changes: 0 additions & 3 deletions changes/unreleased/Fixed-20260716-000000.yaml

This file was deleted.

3 changes: 0 additions & 3 deletions changes/unreleased/Security-20260717-040124.yaml

This file was deleted.

3 changes: 0 additions & 3 deletions changes/unreleased/Security-20260721-000000.yaml

This file was deleted.

30 changes: 30 additions & 0 deletions changes/v0.10.0.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
## v0.10.0 - 2026-07-24

### Added

- The Control Plane now rejects database specs that remove `spock` from `postgresql_conf.shared_preload_libraries`, preventing accidental disabling of the replication extension.
- Added image upgrade support. Use `GET /v1/databases/{id}?include=available_upgrades` to list newer stable images within the same Postgres major and Spock major version bucket, and `POST /v1/databases/{id}/upgrade` to apply an upgrade without changing the Postgres major version.
- Added support for custom container image pinning per database or node via `orchestrator_opts.swarm.image`. pgEdge-formatted image tags are validated against the spec's declared versions; unrecognized tags are accepted without version checks. The Control Plane also persists the resolved image at creation time, preventing silent image changes during Control Plane upgrades.
- Version resolution is now fully manifest-driven. Supported versions update with manifest refreshes without requiring a Control Plane upgrade.
- The Control Plane now falls back to the first available IPv6 address when no IPv4 address is found during IP autodetection.
- Cancelling a task now propagates to any in-progress activities, interrupting long-running operations rather than waiting for them to complete.
- RPM and DEB packages are now published to the pgEdge dnf and apt repositories on every release, enabling installation via `dnf` and `apt-get` in addition to the existing Docker and binary distribution methods.
- Added support for Spock 5.0.10 on Postgres 16.14, 17.10, and 18.4.

### Changed

- **Breaking:** Changed the default `password_encryption` from `md5` to `scram-sha-256`. If you're using the default password encryption, every role in a database's `database_users` will be automatically updated to `scram-sha-256` the next time you update that database. Roles created outside of `database_users` will need their passwords updated manually. To keep using `md5`, set `postgresql_conf.password_encryption` to `md5` in your database spec.

### Fixed

- Fixed an issue where resources pending recreation were not correctly planned for creation in the right reconciliation phase, causing reconciliation errors.
- Fixed Patroni rejecting connections from IPv4 addresses presented as IPv4-mapped IPv6 addresses (e.g. `::ffff:192.168.1.1`) on dual-stack hosts.
- Fixed rolling updates failing on multi-node databases with replica instances due to replication slot timing during instance initialization.
- Fixed an issue where services configured with `"version": "latest"` failed at runtime because `"latest"` was not registered in the version map.
- The RPM and DEB packages now bundle the project documentation and license, installing `README.md` to `/usr/share/doc/pgedge-control-plane/` and `LICENSE.md` to `/usr/share/licenses/pgedge-control-plane/`.
- RPM and DEB packages now install files with explicit, deterministic permissions rather than inheriting the build machine's umask, which produced group-writable `0664` files. `/usr/lib/systemd/system/pgedge-control-plane.service` is now `0644` and `/etc/pgedge-control-plane/config.json` is now `0640`.

### Security

- Update vulnerable dependencies (pgx v5.10.0, OpenTelemetry v1.44.0, golang.org/x/crypto v0.54.0, golang.org/x/net v0.57.0) and bump the Go toolchain to 1.26.5 to remediate Trivy-flagged CVEs in the control-plane image (PLAT-686). github.com/docker/docker CVE-2026-41567/CVE-2026-42306 have no fix in the v27.x line in use; risk-accepted in .trivy/pgedge-control-plane.trivyignore.yaml since the vulnerable docker-cp/archive-copy code paths are never invoked by this codebase.
- Fixed a SQL injection vulnerability in role attribute handling during database creation and updates.
8 changes: 4 additions & 4 deletions docs/api/openapi.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ The Control Plane server serves a JSON OpenAPI v3 specification from the

You can also access offline copies of the OpenAPI specification in the pgEdge Control Plane repository. We generate a few versions of the specification to accommodate different tools and use cases:

- [OpenAPI v3 YAML](https://github.com/pgEdge/control-plane/blob/v0.9.0/api/apiv1/gen/http/openapi3.yaml)
- [OpenAPI v3 JSON](https://github.com/pgEdge/control-plane/blob/v0.9.0/api/apiv1/gen/http/openapi3.json)
- [OpenAPI v2 YAML](https://github.com/pgEdge/control-plane/blob/v0.9.0/api/apiv1/gen/http/openapi.yaml)
- [OpenAPI v2 JSON](https://github.com/pgEdge/control-plane/blob/v0.9.0/api/apiv1/gen/http/openapi.json)
- [OpenAPI v3 YAML](https://github.com/pgEdge/control-plane/blob/v0.10.0/api/apiv1/gen/http/openapi3.yaml)
- [OpenAPI v3 JSON](https://github.com/pgEdge/control-plane/blob/v0.10.0/api/apiv1/gen/http/openapi3.json)
- [OpenAPI v2 YAML](https://github.com/pgEdge/control-plane/blob/v0.10.0/api/apiv1/gen/http/openapi.yaml)
- [OpenAPI v2 JSON](https://github.com/pgEdge/control-plane/blob/v0.10.0/api/apiv1/gen/http/openapi.json)
2 changes: 1 addition & 1 deletion docs/api/reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,4 @@ hide:

</style>

<redoc src="https://raw.githubusercontent.com/pgEdge/control-plane/refs/tags/v0.9.0/api/apiv1/gen/http/openapi3.json"/>
<redoc src="https://raw.githubusercontent.com/pgEdge/control-plane/refs/tags/v0.10.0/api/apiv1/gen/http/openapi3.json"/>
Loading