Skip to content

feat: add available_upgrades opt-in to databases API#415

Open
tsivaprasad wants to merge 2 commits into
PLAT-600-pin-database-image-to-prevent-silent-changes-on-cp-upgradefrom
PLAT-602-check-available-image-upgrades-for-a-database
Open

feat: add available_upgrades opt-in to databases API#415
tsivaprasad wants to merge 2 commits into
PLAT-600-pin-database-image-to-prevent-silent-changes-on-cp-upgradefrom
PLAT-602-check-available-image-upgrades-for-a-database

Conversation

@tsivaprasad

@tsivaprasad tsivaprasad commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Summary

This PR adds support for the optional ?include=available_upgrades query parameter to GET /v1/databases/{id} and GET /v1/databases. When specified, the response includes an available_upgrades field for each database, listing newer stable manifest versions available within the same (postgres_major, spock_major) compatibility bucket as the database's current version.

Changes

  • orchestrator/swarm/images.go: Added Stability field to Images struct; added AvailableUpgrades() method to *Versions that scans the manifest for newer stable entries in the same (postgres_major, spock_major) bucket using ds.Version.Compare
  • orchestrator/swarm/manifest_loader.go: buildVersions now propagates Stability from manifest JSON into Images.Stability
  • database/orchestrator.go: Added AvailableUpgrade struct and AvailableUpgrades method to the Orchestrator interface
  • orchestrator/swarm/orchestrator.go: Implements AvailableUpgrades delegating to o.versions
  • orchestrator/systemd/orchestrator.go: No-op AvailableUpgrades returning nil
  • database/service.go: Exposes AvailableUpgrades so handlers don't need direct orchestrator access
  • api/apiv1/design/api.go + database.go: Added AvailableUpgrade Goa type, available_upgrades field on Database/DatabaseSummary, include query param on both endpoints; regenerated API layer
  • api/apiv1/post_init_handlers.go: Computes and sets available_upgrades when include=available_upgrades is present
  • api/apiv1/convert.go: Added includesAvailableUpgrades and availableUpgradesToAPI helpers
  • client/single.go: Passes empty payload to ListDatabases — client interface unchanged

Testing

Verification:

  1. Created Cluster
  2. Created DB using
    cp1-req create-database < ../demo/Images/create_db_for_upgrade.json
  3. Without the param: available_upgrades must be
cp1-req get-database storefront | jq 'has("available_upgrades")'
# → false

false
  1. With the param: upgrades list appears
cp1-req get-database storefront --rsh-query include=available_upgrades \
  | jq .available_upgrades

[
  {
    "image": "ghcr.io/pgedge/pgedge-postgres:17.10-spock5.0.8-standard-1",
    "postgres_version": "17.10",
    "spock_version": "5"
  }
]
cp1-req list-databases --rsh-query include=available_upgrades \
  | jq '.databases[0].available_upgrades'

[
  {
    "image": "ghcr.io/pgedge/pgedge-postgres:17.10-spock5.0.8-standard-1",
    "postgres_version": "17.10",
    "spock_version": "5"
  }
]
  1. At latest version: empty list
cp1-req create-database < ../demo/Images/create_db_with_no_image.json   
HTTP/1.1 200 OK
Content-Length: 590
Content-Type: application/json
Date: Thu, 18 Jun 2026 14:19:46 GMT

{
  database: {
    created_at: "2026-06-18T14:19:46Z"
    id: "storefront-no-image"
    spec: {
      database_name: "storefront"
      database_users: [
        {
          attributes: ["SUPERUSER", "LOGIN"]
          db_owner: true
          username: "admin"
        }
      ]
      nodes: [
        {
          host_ids: ["host-1", "host-2", "host-3"]
          name: "n1"
        }
      ]
      postgres_version: "18.4"
      spock_version: "5"
    }
    state: "creating"
    updated_at: "2026-06-18T14:19:46Z"
  }
  task: {
    created_at: "2026-06-18T14:19:46Z"
    database_id: "storefront-no-image"
    entity_id: "storefront-no-image"
    scope: "database"
    status: "pending"
    task_id: "019edb1a-2ddd-709f-a8bc-7a3c615b9c90"
    type: "create"
  }
}
cp1-req list-databases --rsh-query include=available_upgrades \
  | jq '.databases[1].available_upgrades'

null

Checklist

  • Tests added or updated (unit and/or e2e, as needed)

PLAT-602

@coderabbitai

coderabbitai Bot commented Jun 18, 2026

Copy link
Copy Markdown

Review Change Stack

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 8c87db29-f7dc-481b-9769-bea9c79c73ef

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds an optional ?include=available_upgrades query parameter to the list-databases and get-database API endpoints. When requested, each database response is enriched with a list of newer stable image candidates from the same Postgres/Spock major version bucket. The feature spans Goa schema definitions, swarm manifest filtering logic, the database service interface, and API handler wiring.

Changes

Available Upgrades via ?include=available_upgrades

Layer / File(s) Summary
Goa API schema: include param and AvailableUpgrade type
api/apiv1/design/database.go, api/apiv1/design/api.go
Defines the AvailableUpgrade Goa schema type with postgres_version, spock_version, and image fields; extends Database and DatabaseSummary with optional available_upgrades arrays; wires the include query parameter into list-databases and get-database payloads and HTTP routing.
Swarm upgrade discovery
server/internal/orchestrator/swarm/images.go, server/internal/orchestrator/swarm/manifest_loader.go, server/internal/orchestrator/swarm/available_upgrades_test.go
Adds Stability field to Images, propagates it from the manifest loader, and implements Versions.AvailableUpgrades to filter supported versions by same-major bucket, newer-than-current, stable-only constraints. Tests cover bucket filtering, nil input, latest-version nil return, dev-stability exclusion, and Image field presence.
Database layer interface and orchestrator implementations
server/internal/database/orchestrator.go, server/internal/database/service.go, server/internal/orchestrator/swarm/orchestrator.go, server/internal/orchestrator/systemd/orchestrator.go
Adds AvailableUpgrade struct and AvailableUpgrades method to the Orchestrator interface; delegates through Service.AvailableUpgrades; swarm orchestrator delegates to versions; systemd orchestrator returns nil.
API handler wiring and conversion
server/internal/api/apiv1/convert.go, server/internal/api/apiv1/post_init_handlers.go, server/internal/api/apiv1/pre_init_handlers.go, client/single.go
Adds includesAvailableUpgrades and availableUpgradesToAPI helpers; updates PostInitHandlers.ListDatabases and GetDatabase to conditionally populate AvailableUpgrades; updates PreInitHandlers.ListDatabases signature to match; updates the single-server client to pass an empty ListDatabasesPayload.

Poem

A bunny hopped down the version trail,
sniffing out upgrades without fail.
"stable" images only, please!
No dev builds hiding in the trees.
?include=available_upgrades — hooray!
New Postgres paths found every day. 🐇✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main change: adding an opt-in available_upgrades parameter to the databases API endpoints.
Description check ✅ Passed The description is comprehensive, covering all required template sections with detailed changes, verification testing, and issue link, though the Changelog entry is not explicitly mentioned as completed.
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.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch PLAT-602-check-available-image-upgrades-for-a-database

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 and usage tips.

@tsivaprasad

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@codacy-production

codacy-production Bot commented Jun 18, 2026

Copy link
Copy Markdown

Up to standards ✅

🟢 Issues 1 medium

Results:
1 new issue

Category Results
Complexity 1 medium

View in Codacy

🟢 Metrics 23 complexity · 0 duplication

Metric Results
Complexity 23
Duplication 0

View in Codacy

NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.

@coderabbitai

coderabbitai Bot commented Jun 18, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@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: 1

🤖 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 `@server/internal/api/apiv1/post_init_handlers.go`:
- Around line 291-294: The code silently ignores errors from
ds.ParsePgEdgeVersion() when checking for available upgrades, causing the
available_upgrades field to disappear from the API response even when explicitly
requested. Fix this by adding structured error logging (using zerolog) in the
else block when the parse error occurs, ensuring you include database
identifiers in the log message for debugging context, and optionally map the
error to an appropriate Goa HTTP error if strict validation is desired. Apply
this fix to both occurrences mentioned: the main occurrence around line 291-294
and the second occurrence around line 359-362 in the same file.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 905db74f-ea87-40ec-a4f0-fac40b1b7a8f

📥 Commits

Reviewing files that changed from the base of the PR and between 82c5ac8 and 85e73b0.

⛔ Files ignored due to path filters (15)
  • api/apiv1/gen/control_plane/client.go is excluded by !**/gen/**
  • api/apiv1/gen/control_plane/endpoints.go is excluded by !**/gen/**
  • api/apiv1/gen/control_plane/service.go is excluded by !**/gen/**
  • api/apiv1/gen/http/cli/control_plane/cli.go is excluded by !**/gen/**
  • api/apiv1/gen/http/control_plane/client/cli.go is excluded by !**/gen/**
  • api/apiv1/gen/http/control_plane/client/client.go is excluded by !**/gen/**
  • api/apiv1/gen/http/control_plane/client/encode_decode.go is excluded by !**/gen/**
  • api/apiv1/gen/http/control_plane/client/types.go is excluded by !**/gen/**
  • api/apiv1/gen/http/control_plane/server/encode_decode.go is excluded by !**/gen/**
  • api/apiv1/gen/http/control_plane/server/server.go is excluded by !**/gen/**
  • api/apiv1/gen/http/control_plane/server/types.go is excluded by !**/gen/**
  • api/apiv1/gen/http/openapi.json is excluded by !**/gen/**
  • api/apiv1/gen/http/openapi.yaml is excluded by !**/gen/**
  • api/apiv1/gen/http/openapi3.json is excluded by !**/gen/**
  • api/apiv1/gen/http/openapi3.yaml is excluded by !**/gen/**
📒 Files selected for processing (13)
  • api/apiv1/design/api.go
  • api/apiv1/design/database.go
  • client/single.go
  • server/internal/api/apiv1/convert.go
  • server/internal/api/apiv1/post_init_handlers.go
  • server/internal/api/apiv1/pre_init_handlers.go
  • server/internal/database/orchestrator.go
  • server/internal/database/service.go
  • server/internal/orchestrator/swarm/available_upgrades_test.go
  • server/internal/orchestrator/swarm/images.go
  • server/internal/orchestrator/swarm/manifest_loader.go
  • server/internal/orchestrator/swarm/orchestrator.go
  • server/internal/orchestrator/systemd/orchestrator.go

Comment on lines +291 to +294
if includesAvailableUpgrades(req.Include) {
if version, err := ds.ParsePgEdgeVersion(db.Spec.PostgresVersion, db.Spec.SpockVersion); err == nil {
apiDB.AvailableUpgrades = availableUpgradesToAPI(s.dbSvc.AvailableUpgrades(version))
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Avoid silently dropping requested available_upgrades on parse failures.

Line 292 and Line 360 ignore ds.ParsePgEdgeVersion errors, which makes available_upgrades silently disappear for malformed stored versions even when explicitly requested. Please at least emit structured error/warn logs with database identifiers (or map to a Goa error if you want strict behavior).

As per coding guidelines, server/internal/**/*.go should use structured error logging with zerolog and map domain-specific errors to HTTP status codes via Goa.

Also applies to: 359-362

🤖 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 `@server/internal/api/apiv1/post_init_handlers.go` around lines 291 - 294, The
code silently ignores errors from ds.ParsePgEdgeVersion() when checking for
available upgrades, causing the available_upgrades field to disappear from the
API response even when explicitly requested. Fix this by adding structured error
logging (using zerolog) in the else block when the parse error occurs, ensuring
you include database identifiers in the log message for debugging context, and
optionally map the error to an appropriate Goa HTTP error if strict validation
is desired. Apply this fix to both occurrences mentioned: the main occurrence
around line 291-294 and the second occurrence around line 359-362 in the same
file.

Source: Coding guidelines

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