Skip to content

Dev#69

Merged
RambokDev merged 3 commits into
mainfrom
dev
Jun 27, 2026
Merged

Dev#69
RambokDev merged 3 commits into
mainfrom
dev

Conversation

@RambokDev

@RambokDev RambokDev commented Jun 27, 2026

Copy link
Copy Markdown
Contributor
  • feat: add as_str/from_str to PostgresDumpFormat

  • feat: resolve pg_dumpall/psql binary names

  • feat: add include_globals field to database config

  • feat: add pg_dumpall/psql globals dump and apply

  • feat: add postgres backup bundle (manifest + build + resolve)

  • feat: bundle globals into postgres backup when include_globals is set

  • feat: replay globals before pg_restore when backup archive is a bundle

  • refactor: bind FD restore tempdir guard once to clear unused warnings

  • docs: demonstrate include_globals in sample databases.json

  • chore: silence test-only re-export warning in non-test builds

  • revert: remove include_globals feature, restore plain pg_dump/pg_restore

  • feat: add pg_dumpall/psql binary names and is_superuser check

  • feat: add postgresql-cluster db type and config parsing

  • feat: pg_dumpall cluster backup and psql restore

  • feat: route postgresql-cluster through PostgresClusterDatabase

  • docs: add postgresql-cluster sample to databases.json

  • refactor: split cluster mode into cluster/ module (backup, restore, database)

  • test: mirror cluster tests into src/tests/domain/cluster/

Summary by CodeRabbit

  • New Features

    • Added support for PostgreSQL cluster backups and restores.
    • Added Google Cloud Storage as a new backup storage option.
    • PostgreSQL cluster configurations now accept the postgresql-cluster database type and default to the postgres database when not set.
  • Bug Fixes

    • Improved handling of PostgreSQL command execution across platforms.
    • Backup and restore flows now validate required database permissions earlier and provide clearer failures.

* feat: add as_str/from_str to PostgresDumpFormat

* feat: resolve pg_dumpall/psql binary names

* feat: add include_globals field to database config

* feat: add pg_dumpall/psql globals dump and apply

* feat: add postgres backup bundle (manifest + build + resolve)

* feat: bundle globals into postgres backup when include_globals is set

* feat: replay globals before pg_restore when backup archive is a bundle

* refactor: bind FD restore tempdir guard once to clear unused warnings

* docs: demonstrate include_globals in sample databases.json

* chore: silence test-only re-export warning in non-test builds

* revert: remove include_globals feature, restore plain pg_dump/pg_restore

* feat: add pg_dumpall/psql binary names and is_superuser check

* feat: add postgresql-cluster db type and config parsing

* feat: pg_dumpall cluster backup and psql restore

* feat: route postgresql-cluster through PostgresClusterDatabase

* docs: add postgresql-cluster sample to databases.json

* refactor: split cluster mode into cluster/ module (backup, restore, database)

* test: mirror cluster tests into src/tests/domain/cluster/
@coderabbitai

coderabbitai Bot commented Jun 27, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@RambokDev, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 45 minutes and 36 seconds. Learn how PR review limits work.

Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file).

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits.

🚦 How do rate limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: cf67ce7b-01b1-4ef2-99ea-08aaf55e5008

📥 Commits

Reviewing files that changed from the base of the PR and between 29ca5a3 and 16a37e0.

📒 Files selected for processing (3)
  • src/services/storage/providers/azure_blob/mod.rs
  • src/services/storage/providers/azure_blob/models.rs
  • src/tests/storage/azure_blob.rs
📝 Walkthrough

Walkthrough

Adds DbType::PostgresqlCluster with full backup (pg_dumpall) and restore (psql) support wired through DatabaseFactory. Introduces a Google Cloud Storage provider with authenticated streaming upload. Removes Azure Blob doc comments and updates docker-compose EDGE_KEY.

Changes

PostgreSQL Cluster Support

Layer / File(s) Summary
Config type and connection helpers
src/services/config.rs, src/domain/postgres/connection.rs
Adds DbType::PostgresqlCluster with serde rename postgresql-cluster, required-field validation in ConfigService::load(), and is_superuser(), pg_dumpall_binary_name(), psql_binary_name() helpers.
Cluster backup, restore, and Database trait
src/domain/postgres/cluster/mod.rs, src/domain/postgres/cluster/backup.rs, src/domain/postgres/cluster/restore.rs, src/domain/postgres/cluster/database.rs, src/domain/postgres/mod.rs
Implements backup::run (pg_dumpall), restore::run (psql), and PostgresClusterDatabase with lock-guarded backup/restore/ping.
Factory wiring
src/domain/factory.rs
Adds DbType::PostgresqlCluster arms to create_for_backup and create_for_restore.
Integration and unit tests
src/tests/domain/cluster/*, src/tests/domain/postgres.rs, src/tests/services/config_tests.rs, src/tests/services/mod.rs, src/tests/domain/mod.rs
Adds cluster test module with start_cluster/env_for helpers, backup/restore/database integration tests, config parsing tests, and connection helper tests.

Google Cloud Storage Provider

Layer / File(s) Summary
GCS config, credentials, and streaming upload helpers
Cargo.toml, src/services/storage/providers/google_cloud_storage/models.rs, src/services/storage/providers/mod.rs, src/services/storage/providers/google_cloud_storage/helpers.rs
Adds GoogleCloudStorageProviderConfig, build_credentials, build_client, StreamSource, and upload_with_client. Adds google-cloud-storage/google-cloud-auth dependencies.
GoogleCloudStorageProvider upload and routing
src/services/storage/providers/google_cloud_storage/mod.rs, src/services/storage/mod.rs
Implements StorageProvider::upload with validation, stream setup, client construction, and upload dispatch. Wires "google-cloud-storage" into get_provider.
GCS integration test
src/tests/storage/google_cloud_storage.rs, src/tests/storage/mod.rs
Adds round-trip upload test against a fake GCS container with single-shot enforcement.

Azure doc cleanup and docker-compose update

Layer / File(s) Summary
Azure doc removal and docker-compose update
src/services/storage/providers/azure_blob/helpers.rs, src/services/storage/providers/azure_blob/models.rs, docker-compose.yml
Removes doc comments from Azure Blob helpers/models; updates EDGE_KEY in docker-compose.

Sequence Diagram(s)

sequenceDiagram
  participant Caller
  participant GoogleCloudStorageProvider
  participant build_client
  participant upload_with_client
  participant GCS

  Caller->>GoogleCloudStorageProvider: upload(result, storage)
  GoogleCloudStorageProvider->>GoogleCloudStorageProvider: validate backup_file, get metadata
  GoogleCloudStorageProvider->>GoogleCloudStorageProvider: build_stream(encrypt, file)
  GoogleCloudStorageProvider->>build_client: build_client(cfg)
  build_client-->>GoogleCloudStorageProvider: Storage client
  GoogleCloudStorageProvider->>GoogleCloudStorageProvider: StreamSource::from_stream(stream, total_size)
  GoogleCloudStorageProvider->>upload_with_client: upload_with_client(client, bucket, path, source, force_single_shot)
  upload_with_client->>GCS: write_object (single-shot or resumable)
  GCS-->>upload_with_client: success/failure
  upload_with_client-->>GoogleCloudStorageProvider: Result
  GoogleCloudStorageProvider-->>Caller: UploadResult
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • Portabase/agent#47: Modifies the same DatabaseFactory::create_for_backup/create_for_restore match arms in src/domain/factory.rs.
  • Portabase/agent#51: Also extends DbType enum and updates DatabaseFactory match arms for a new database variant.
  • Portabase/agent#60: Introduced Arc<JobLogger> threading into backup/restore flows that this PR's cluster implementation depends on.

🐇 Two new features hopped in today,
Clusters dumped with pg_dumpall hooray!
And GCS streams its bytes up high,
Single-shot uploads, no hang, no cry.
The rabbit cheers — backup complete! 🎉

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 34.88% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title is too vague to describe the substantial PostgreSQL cluster and GCS storage changes in this PR. Use a concise, specific title that highlights the main change, such as PostgreSQL cluster support or Google Cloud Storage integration.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch dev

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@databases.json`:
- Around line 118-119: The fixture in databases.json contains a real-looking
cluster password that should not be checked into source control. Replace the
hardcoded password entry with an obvious placeholder like changeme, or switch
the fixture to read the value from test environment configuration; update the
databases.json sample data so only non-sensitive dummy credentials remain.

In `@src/domain/postgres/cluster/database.rs`:
- Around line 40-44: The backup flow in `Database::backup` currently acquires a
`FileLock` and releases it manually, which is not cancellation-safe. Replace the
manual acquire/release pair with an RAII lock guard/helper in `backup` (and the
matching restore path if present) so the lock is released automatically on drop,
even if `backup::run` is aborted or returns early.

In `@src/domain/postgres/cluster/restore.rs`:
- Line 50: The restore command is hardcoding the maintenance database to
postgres, which overrides the explicit database preserved by
ConfigService::load() for postgresql-cluster. Update the restore flow in the
restore logic to use the configured maintenance database from the loaded config
instead of forcing postgres, and make sure the argument passed to the command
builder reflects that value consistently wherever the restore command is
assembled.
- Around line 46-53: The restore command in the `Command::new(&psql)` flow is
not stopping on the first SQL error because `psql -f` can continue after
failures. Update the restore invocation in `restore.rs` to pass the
`ON_ERROR_STOP` setting via psql’s `-v` flag before `-f`, so the process exit
code correctly reflects any SQL error during restore.

In `@src/tests/domain/cluster/mod.rs`:
- Around line 22-26: Fail fast in the cluster test setup instead of falling back
to a local PostgreSQL endpoint when container resolution fails. Update the
host/port lookup in the test helper that prepares the `connection::connect()`
config so it propagates the `get_host()` and `get_host_port_ipv4()` errors
rather than defaulting to `127.0.0.1:5432`, ensuring the test only runs against
the intended container.

In `@src/tests/domain/cluster/restore.rs`:
- Around line 69-76: The negative-path test is using a non-superuser username
but still passes the superuser password, so auth fails before the intended
pre-check in cluster::restore::run. Update the test setup for weak to use the
appuser password created in the fixture, and keep the call to restore::run with
env_for(&weak) so the test reaches and asserts the superuser check rather than
authentication.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: f9f795fb-93e5-494b-9835-9aa0fbe429f2

📥 Commits

Reviewing files that changed from the base of the PR and between 0b7b7ef and 01f5d34.

📒 Files selected for processing (17)
  • databases.json
  • src/domain/factory.rs
  • src/domain/postgres/cluster/backup.rs
  • src/domain/postgres/cluster/database.rs
  • src/domain/postgres/cluster/mod.rs
  • src/domain/postgres/cluster/restore.rs
  • src/domain/postgres/connection.rs
  • src/domain/postgres/mod.rs
  • src/services/config.rs
  • src/tests/domain/cluster/backup.rs
  • src/tests/domain/cluster/database.rs
  • src/tests/domain/cluster/mod.rs
  • src/tests/domain/cluster/restore.rs
  • src/tests/domain/mod.rs
  • src/tests/domain/postgres.rs
  • src/tests/services/config_tests.rs
  • src/tests/services/mod.rs

Comment thread databases.json Outdated
Comment thread src/domain/postgres/cluster/database.rs
Comment thread src/domain/postgres/cluster/restore.rs
Comment thread src/domain/postgres/cluster/restore.rs
Comment thread src/tests/domain/cluster/mod.rs
Comment thread src/tests/domain/cluster/restore.rs
* fix: refactoring

* chore: add google-cloud-storage and google-cloud-auth deps

* feat: add GCS provider config model

* feat: add GCS credential, client, and stream-source helpers

StreamSource bridges build_stream's Send-only byte stream into the SDK's
StreamingSource (which send_buffered requires to be Send+Sync+'static) via a
bounded mpsc channel, avoiding any change to the shared UploadStream type.

* feat: implement GCS StorageProvider upload

* feat: register google-cloud-storage provider in factory

* test: GCS upload roundtrip against fake-gcs-server

* fix: format GCS bucket as projects/_/buckets/<name> in upload_with_client

write_object rejects the bare bucket id with "malformed bucket name"; the
production provider passed config.bucket_name unformatted, so real uploads
would always fail. Format once in upload_with_client so prod and the
fake-gcs-server test share the corrected path.

* style: cargo fmt GCS provider files

* fix: gcs

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (1)
src/tests/storage/google_cloud_storage.rs (1)

20-23: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Pin fsouza/fake-gcs-server to a known-good tag.

Using latest makes this integration test non-reproducible; an upstream image change can start breaking CI with no repo change here. Please pin a specific version or digest and bump it intentionally.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/tests/storage/google_cloud_storage.rs` around lines 20 - 23, Pin the fake
GCS container image used in the google_cloud_storage test to a specific
known-good tag or digest instead of using latest. Update the GenericImage::new
call in the test setup so the image version is explicit and reproducible, and
only change it intentionally when bumping the dependency.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docker-compose.yml`:
- Line 22: The docker-compose configuration currently hardcodes a real EDGE_KEY
secret, which should not be committed. Remove the inline credential from the
compose file and update the service configuration to read EDGE_KEY from an
external, untracked environment source instead; use the affected docker-compose
service definition to locate the change and then rotate/revoke the leaked key.

In `@src/services/storage/providers/google_cloud_storage/mod.rs`:
- Around line 42-58: The upload path in google_cloud_storage::mod::upload is
forwarding fs::metadata-derived total_size as an exact size hint even though
build_stream can transform the payload when encryption is enabled. Update the
upload flow so build_stream returns the post-transformation size (or another
accurate hint) and use that value instead of the pre-encryption file size. If
the transformed length cannot be known, remove the exact SizeHint for this
stream rather than advertising a potentially wrong length.

In `@src/services/storage/providers/google_cloud_storage/models.rs`:
- Around line 3-10: The GoogleCloudStorageProviderConfig struct currently
derives Debug while storing the raw service-account private_key, which can leak
secrets in logs. Update GoogleCloudStorageProviderConfig in models.rs to avoid
exposing private_key through Debug by either removing the Debug derive or
wrapping private_key in a redacted secret type and providing a custom Debug
implementation that masks it. Ensure any Debug output for this config cannot
print the PEM contents.

---

Nitpick comments:
In `@src/tests/storage/google_cloud_storage.rs`:
- Around line 20-23: Pin the fake GCS container image used in the
google_cloud_storage test to a specific known-good tag or digest instead of
using latest. Update the GenericImage::new call in the test setup so the image
version is explicit and reproducible, and only change it intentionally when
bumping the dependency.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 2f2ba059-4dc6-4d4b-8d61-2ba0a2ba33fe

📥 Commits

Reviewing files that changed from the base of the PR and between 01f5d34 and 29ca5a3.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (11)
  • Cargo.toml
  • docker-compose.yml
  • src/services/storage/mod.rs
  • src/services/storage/providers/azure_blob/helpers.rs
  • src/services/storage/providers/azure_blob/models.rs
  • src/services/storage/providers/google_cloud_storage/helpers.rs
  • src/services/storage/providers/google_cloud_storage/mod.rs
  • src/services/storage/providers/google_cloud_storage/models.rs
  • src/services/storage/providers/mod.rs
  • src/tests/storage/google_cloud_storage.rs
  • src/tests/storage/mod.rs
💤 Files with no reviewable changes (2)
  • src/services/storage/providers/azure_blob/models.rs
  • src/services/storage/providers/azure_blob/helpers.rs

Comment thread docker-compose.yml
Comment thread src/services/storage/providers/google_cloud_storage/mod.rs
Comment thread src/services/storage/providers/google_cloud_storage/models.rs
@RambokDev RambokDev merged commit 610d443 into main Jun 27, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant