Skip to content

✨ graphql service endpoint for catalogd#2100

Open
grokspawn wants to merge 9 commits into
operator-framework:mainfrom
grokspawn:catd-graphql-play
Open

✨ graphql service endpoint for catalogd#2100
grokspawn wants to merge 9 commits into
operator-framework:mainfrom
grokspawn:catd-graphql-play

Conversation

@grokspawn
Copy link
Copy Markdown
Contributor

@grokspawn grokspawn commented Jul 15, 2025

Description

This PR includes two significant changes:

  1. introduces a graphql service endpoint for retrieving catalog data from catalogd. This approach defines the relevant graphql schema when it unpacks the catalog, so that a hardcoded schema does not need to be updated every time the declcfg (FBC) schema updates or a new aspect is added.
  2. separates the server+storage into a layered approach (albeit primarily for graphql, because 'all' API access is closely coupled with the storage -- it just streams bytes -- so the abstraction feels like a poor fit for it).

GraphQL data is served using the existing HTTP(S) service endpoint via a specified API path, which is only enabled when the featuregate is enabled (defaulted to off for 'stable' build; enabled for 'experimental' build).

This facilitates an approach where clients can request only the schema of interest for a query.

The previous architecture for service+storage looked like:

┌───────────────────────────────────────────────────────────┐
│        internal/catalogd/storage                          │
│                                                           │
│  ┌────────────────────────────────────────────────────┐   │
│  │  localdir.go - LocalDirV1 (Everything!)            │   │
│  │                                                    │   │
│  │  Storage Operations:                               │   │
│  │  • Store(ctx, catalog, fs.FS) - Atomic writes      │   │
│  │  • Delete(catalog) - Remove catalog                │   │
│  │  • ContentExists(catalog) - Validation             │   │
│  │  • File I/O, temp dirs, orphan cleanup             │   │
│  │  • Index building (if EnableMetasHandler)          │   │
│  │                                                    │   │
│  │  HTTP Layer:                                       │   │
│  │  • StorageServerHandler() - mux setup              │   │
│  │  • handleV1All(w, r) - Full catalog endpoint       │   │
│  │  • handleV1Metas(w, r) - Filtered endpoint         │   │
│  │  • httpError(w, err) - Error mapping               │   │
│  │  • serveJSONLines(w, r, reader)                    │   │
│  │  • catalogData(catalog) - File opening             │   │
│  │  • getIndex(catalog) - Index loading               │   │
│  │  • allowedMethodsHandler (inline function)         │   │
│  │                                                    │   │
│  │  Fields:                                           │   │
│  │  • RootDir, RootURL                                │   │
│  │  • EnableMetasHandler bool                         │   │
│  │  • m sync.RWMutex (protects file ops)              │   │
│  │  • sf singleflight.Group (index loading)           │   │
│  └────────────────────────────────────────────────────┘   │
│                                                           │
│  ┌────────────────────────────────────────────────────┐   │
│  │  http_preconditions_check.go                       │   │
│  │  • checkPreconditions(w, r, modtime)               │   │
│  │  • HTTP caching (If-Modified-Since, ETag, etc.)    │   │
│  └────────────────────────────────────────────────────┘   │
│                                                           │
│  ┌────────────────────────────────────────────────────┐   │
│  │  index.go                                          │   │
│  │  • Index structure for /api/v1/metas filtering     │   │
│  │  • Get(file, schema, pkg, name) io.Reader          │   │
│  └────────────────────────────────────────────────────┘   │
│                                                           │
└───────────────────────────────────────────────────────────┘

The new architecture splits between

  • a generic HTTP service layer (implementing support for serving 'all', 'metas' ),
  • an abstracted service layer which extends the HTTP layer with additional services (graphql), and
  • a storage layer where any file I/O for the service(s) takes place.
┌────────────────────────────────────────────────────────────────────┐
│                    HTTP Layer (NEW)                                │
│  internal/catalogd/server/handlers.go (294 lines)                  │
│                                                                    │
│  ┌────────────────────────────────────────────────────┐            │
│  │  CatalogHandlers struct                            │            │
│  │  • HTTP routing (mux setup in Handler())           │            │
│  │  • Request validation (catalog names, params)      │            │
│  │  • Method filtering (GET/HEAD/POST via middleware) │            │
│  │  • handleV1All(w, r) - Full catalog                │            │
│  │  • handleV1Metas(w, r) - Filtered catalog          │            │
│  │  • handleV1GraphQL(w, r) - GraphQL queries         │  ← NEW!    │
│  │  • Error translation (httpError)                   │            │
│  │  • Depends on: CatalogStore interface              │            │
│  └──────────┬─────────────────────┬───────────────────┘            │
│             │                     │                                │
│  ┌──────────────────────────────────────────────────────┐          │
│  │  http_preconditions_check.go (moved from storage/)   │          │
│  │  • checkPreconditions(w, r, modtime)                 │          │
│  │  • HTTP caching headers (If-Modified-Since, etc.)    │          │
│  └──────────────────────────────────────────────────────┘          │
└──────────────┼─────────────────────┼───────────────────────────────┘
               │                     │
               ▼                     ▼
┌───────────────────────────┐  ┌─────────────────────────────────────┐
│   Service Layer (NEW)     │  │    Future Service Layer             │
│   internal/catalogd/      │  │                                     │
│   service/                │  │                                     │
│   graphql_service.go      │  │ ┌─────────────────────────────────┐ │
│   (163 lines)             │  │ │  (Future: MetasService)         │ │
│                           │  │ │  • Query optimization           │ │
│ ┌───────────────────────┐ │  │ │  • Filter logic                 │ │
│ │ CachedGraphQLService  │ │  │ │  • Response formatting          │ │
│ │                       │ │  │ └─────────────────────────────────┘ │
│ │ • GetSchema(catalog)  │ │  │                                     │
│ │ • ExecuteQuery(...)   │ │  │                                     │
│ │ • InvalidateCache()   │ │  │                                     │
│ │ • In-memory cache     │ │  │                                     │
│ │ • Singleflight builds │ │  │                                     │
│ └─────────┬─────────────┘ │  │                                     │
│           │               │  │                                     │
└───────────┼───────────────┘  └─────────────────────────────────────┘
            │
            ▼
┌────────────────────────────────────────────────────────────────────┐
│                   Discovery Layer (NEW)                            │
│  internal/catalogd/graphql/ (1,562 lines total)                    │
│                                                                    │
│  ┌────────────────────────────────────────────────────┐            │
│  │  graphql.go (692 lines)                            │            │
│  │  • DiscoverSchemaFromMetas([]*Meta) - Analyzer     │            │
│  │  • BuildDynamicGraphQLSchema(...) - Generator      │            │
│  │  • determineFieldType(value) - Type inference      │            │
│  │  • analyzeFieldValue(value) - Nested detection     │            │
│  │  • remapFieldName(name) - GraphQL naming rules     │            │
│  │  • createFieldResolver(fieldName) - Resolvers      │            │
│  └────────────────────────────────────────────────────┘            │
│                                                                    │
│  ┌────────────────────────────────────────────────────┐            │
│  │  discovery_test.go (453 lines) + graphql_test.go   │            │
│  │  • Schema discovery tests                          │            │
│  │  • Field type inference validation                 │            │
│  │  • Nested structure tests                          │            │
│  │  • GraphQL query execution tests                   │            │
│  └────────────────────────────────────────────────────┘            │
└────────────────────────────────────────────────────────────────────┘
            │
            ▼
┌──────────────────────────────────────────────────────────────────┐
│                   Storage Layer (REFACTORED)                     │
│  internal/catalogd/storage/localdir.go                           │
│  (Was 364 lines → Now ~340 lines, -148 deletions)                │
│                                                                  │
│  ┌────────────────────────────────────────────────────┐          │
│  │  LocalDirV1 (Pure Storage Implementation)          │          │
│  │                                                    │          │
│  │  Storage Operations (UNCHANGED):                   │          │
│  │  • Store(ctx, catalog, fs.FS)                      │          │
│  │  • Delete(catalog)                                 │          │
│  │  • ContentExists(catalog)                          │          │
│  │  • File I/O, indexing                              │          │
│  │                                                    │          │
│  │  NEW: Implements CatalogStore interface            │          │
│  │  • GetCatalogData(catalog) (*File, FileInfo, err)  │          │
│  │  • GetCatalogFS(catalog) (fs.FS, error)            │          │
│  │  • GetIndex(catalog) (Index, error)                │          │
│  │                                                    │          │
│  │  NEW: GraphQL integration                          │          │
│  │  • graphqlSvc GraphQLService field                 │          │
│  │  • Cache pre-warming on Store()                    │          │
│  │  • Cache invalidation on Delete()                  │          │
│  │                                                    │          │
│  │  NEW: Typed modes (was plain bool)                 │          │
│  │  • EnableMetasHandler   MetasHandlerMode           │          │
│  │  • EnableGraphQLQueries GraphQLQueriesMode         │          │
│  │                                                    │          │
│  │  REMOVED: HTTP handling (moved to server/)         │          │
│  │  ✗ handleV1All() - gone                            │          │
│  │  ✗ handleV1Metas() - gone                          │          │
│  │  ✗ httpError() - gone                              │          │
│  │  ✗ serveJSONLines() - gone                         │          │
│  │  ✗ catalogData() - gone                            │          │
│  │  ✗ getIndex() - gone                               │          │
│  │  ✓ StorageServerHandler() - delegates to server    │          │
│  └────────────────────────────────────────────────────┘          │
│                                                                  │
│  ┌────────────────────────────────────────────────────┐          │
│  │  index.go (UNCHANGED)                              │          │
│  │  • Index structure and Get() method                │          │
│  └────────────────────────────────────────────────────┘          │
└──────────────────────────────────────────────────────────────────┘

DEMO

graphql-demo

in-progress RFC here

Reviewer Checklist

  • API Go Documentation
  • Tests: Unit Tests (and E2E Tests, if appropriate)
  • Comprehensive Commit Messages
  • Links to related GitHub Issue(s)

@openshift-ci openshift-ci Bot added the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Jul 15, 2025
@netlify
Copy link
Copy Markdown

netlify Bot commented Jul 15, 2025

Deploy Preview for olmv1 ready!

Name Link
🔨 Latest commit b9f6591
🔍 Latest deploy log https://app.netlify.com/projects/olmv1/deploys/6a0cc7d7844c63000817bd8c
😎 Deploy Preview https://deploy-preview-2100--olmv1.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

@codecov
Copy link
Copy Markdown

codecov Bot commented Jul 15, 2025

Codecov Report

❌ Patch coverage is 57.63889% with 305 lines in your changes missing coverage. Please review.
✅ Project coverage is 66.94%. Comparing base (ea98453) to head (41610d7).
⚠️ Report is 4 commits behind head on main.

Files with missing lines Patch % Lines
internal/catalogd/graphql/graphql.go 59.84% 143 Missing and 16 partials ⚠️
internal/catalogd/server/handlers.go 61.53% 56 Missing and 4 partials ⚠️
hack/demo/graphql-demo-server/main.go 0.00% 44 Missing ⚠️
internal/catalogd/service/graphql_service.go 68.65% 12 Missing and 9 partials ⚠️
internal/catalogd/storage/localdir.go 53.65% 17 Missing and 2 partials ⚠️
cmd/catalogd/main.go 87.50% 0 Missing and 2 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2100      +/-   ##
==========================================
- Coverage   68.14%   66.94%   -1.20%     
==========================================
  Files         145      149       +4     
  Lines       10698    11339     +641     
==========================================
+ Hits         7290     7591     +301     
- Misses       2879     3191     +312     
- Partials      529      557      +28     
Flag Coverage Δ
e2e 35.18% <8.13%> (-1.99%) ⬇️
experimental-e2e 52.56% <49.11%> (-0.08%) ⬇️
unit 52.10% <36.11%> (-1.71%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@perdasilva
Copy link
Copy Markdown
Contributor

closing this as stale - please reopen if needed

@perdasilva perdasilva closed this Sep 17, 2025
@grokspawn grokspawn reopened this Oct 28, 2025
Copilot AI review requested due to automatic review settings October 30, 2025 13:10
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This pull request refactors the catalogd storage layer to introduce GraphQL support for querying catalog data. The changes extract HTTP handler logic into a separate server package, introduce a service layer for GraphQL schema management with caching, and replace direct struct initialization with a constructor pattern for LocalDirV1.

  • Introduces a new GraphQL endpoint at /api/v1/graphql with dynamic schema generation
  • Refactors HTTP handlers into a dedicated server package with cleaner separation of concerns
  • Adds a GraphQL service layer with schema caching to improve performance
  • Updates LocalDirV1 to use a constructor pattern (NewLocalDirV1) for proper initialization

Reviewed Changes

Copilot reviewed 13 out of 14 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
internal/catalogd/storage/localdir.go Refactored to use constructor pattern, added GraphQL service integration, moved HTTP handlers to server package
internal/catalogd/storage/localdir_test.go Updated all test instantiations to use new NewLocalDirV1 constructor
internal/catalogd/storage/http_preconditions_check.go Removed (moved to server package with simplified implementation)
internal/catalogd/server/handlers.go New file implementing HTTP handlers extracted from storage layer
internal/catalogd/server/http_helpers.go New file with simplified HTTP precondition checking
internal/catalogd/service/graphql_service.go New GraphQL service with caching for schema generation
internal/catalogd/graphql/graphql.go New dynamic GraphQL schema generation implementation
internal/catalogd/graphql/graphql_test.go Tests for GraphQL schema discovery
internal/catalogd/graphql/discovery_test.go Additional comprehensive tests for schema discovery edge cases
internal/catalogd/graphql/sample-queries.txt Documentation of sample GraphQL queries
internal/catalogd/graphql/README.md Documentation for GraphQL integration
cmd/catalogd/main.go Updated to use NewLocalDirV1 constructor
go.mod, go.sum Added graphql-go/graphql dependency

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread internal/catalogd/server/http_helpers.go Outdated
Comment thread internal/catalogd/server/http_helpers.go Outdated
Comment thread internal/catalogd/server/handlers.go Outdated
Comment thread internal/catalogd/server/handlers.go Outdated
Comment thread internal/catalogd/storage/localdir.go Outdated
Comment thread internal/catalogd/graphql/graphql.go Outdated
Copilot AI review requested due to automatic review settings November 17, 2025 13:39
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

Copilot reviewed 15 out of 16 changed files in this pull request and generated 12 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread internal/catalogd/server/handlers.go Outdated
Comment thread internal/catalogd/service/graphql_service.go Outdated
Comment thread internal/catalogd/storage/localdir_test.go
Comment thread internal/catalogd/storage/localdir.go Outdated
Comment thread internal/catalogd/server/http_helpers.go Outdated
Comment thread internal/catalogd/service/graphql_service.go Outdated
Comment thread internal/catalogd/graphql/graphql.go Outdated
Comment thread internal/catalogd/server/handlers.go
Comment thread internal/catalogd/server/http_helpers.go Outdated
Comment thread internal/catalogd/features/features.go Outdated
@openshift-merge-robot openshift-merge-robot added the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Nov 20, 2025
@perdasilva
Copy link
Copy Markdown
Contributor

closing as stale

@perdasilva perdasilva closed this Dec 16, 2025
@grokspawn grokspawn reopened this Dec 16, 2025
@grokspawn grokspawn added the lifecycle/frozen Indicates that an issue or PR should not be auto-closed due to staleness. label Dec 16, 2025
@openshift-ci
Copy link
Copy Markdown

openshift-ci Bot commented Mar 13, 2026

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by:
Once this PR has been reviewed and has the lgtm label, please assign kevinrizza for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@openshift-merge-robot openshift-merge-robot removed the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Mar 13, 2026
Copilot AI review requested due to automatic review settings March 13, 2026 23:25
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 18 out of 19 changed files in this pull request and generated 7 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

Comment thread internal/catalogd/server/handlers.go Outdated
Comment thread internal/catalogd/server/http_helpers.go Outdated
Comment thread internal/catalogd/storage/localdir.go
Comment thread internal/catalogd/graphql/README.md Outdated
Comment thread helm/experimental.yaml
Comment thread go.mod Outdated
Comment thread internal/catalogd/storage/localdir.go Outdated
@grokspawn grokspawn force-pushed the catd-graphql-play branch from 2752f1f to e358467 Compare April 3, 2026 21:09
Copilot AI review requested due to automatic review settings April 7, 2026 14:30
@grokspawn grokspawn force-pushed the catd-graphql-play branch from e358467 to 0d2d4e4 Compare April 7, 2026 14:30
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 19 out of 20 changed files in this pull request and generated 3 comments.

Comments suppressed due to low confidence (2)

internal/shared/util/tlsprofiles/mozilla_data.go:17

  • internal/shared/util/tlsprofiles/mozilla_data.go appears to have been truncated to ~17 lines (missing closing braces and the intermediateTLSProfile/oldTLSProfile definitions). This will not compile and also breaks TLS profile selection at runtime. Re-run hack/tools/update-tls-profiles.sh (and ensure the generated file is fully committed and gofmt’d) so all profiles are present and the modernTLSProfile literal is complete.
import (
"crypto/tls"
)

var modernTLSProfile = tlsProfile{
ciphers: cipherSlice{
cipherNums: []uint16{
tls.TLS_AES_128_GCM_SHA256,
tls.TLS_AES_256_GCM_SHA384,
tls.TLS_CHACHA20_POLY1305_SHA256,

internal/catalogd/storage/localdir_test.go:252

  • The new /api/v1/graphql HTTP route isn’t covered by the existing storage/server handler tests (e.g., TestLocalDirServerHandler and TestMetasEndpoint cover /all and /metas only). Add an HTTP-level test that exercises the GraphQL endpoint (method handling, invalid body/query, and a basic successful query) to prevent regressions in request parsing and wiring.
func TestLocalDirServerHandler(t *testing.T) {
	store := NewLocalDirV1(t.TempDir(), &url.URL{Path: urlPrefix}, MetasHandlerDisabled, GraphQLQueriesDisabled)
	if store.Store(context.Background(), "test-catalog", createTestFS(t)) != nil {
		t.Fatal("failed to store test catalog and start server")
	}

	testServer := httptest.NewServer(store.StorageServerHandler())
	defer testServer.Close()

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread internal/catalogd/storage/localdir.go
Comment thread internal/catalogd/graphql/graphql.go Outdated
Comment thread internal/catalogd/server/handlers.go
@grokspawn grokspawn marked this pull request as ready for review May 15, 2026 18:34
@openshift-ci openshift-ci Bot removed the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label May 15, 2026
@openshift-ci openshift-ci Bot requested review from camilamacedo86 and tmshort May 15, 2026 18:34
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 20 out of 21 changed files in this pull request and generated 5 comments.

Comments suppressed due to low confidence (1)

internal/catalogd/graphql/graphql.go:710

  • The sample query emitted by PrintCatalogSummary uses bundles(...)/packages(...), but the generated GraphQL fields are schema-derived (e.g. olm.bundleolmbundles). This output is likely to confuse users debugging catalogs. Consider emitting the sanitized schema-derived field names instead (or omitting this sample block).
	if _, ok := catalogSchema.Schemas[declcfg.SchemaBundle]; ok {
		fmt.Printf("  bundles(limit: 5) { name package }\n")
	}
	if _, ok := catalogSchema.Schemas[declcfg.SchemaPackage]; ok {
		fmt.Printf("  packages(limit: 5) { name }\n")

Comment thread internal/catalogd/graphql/graphql.go
Comment thread internal/catalogd/graphql/graphql.go
Comment thread internal/catalogd/service/graphql_service.go
Comment thread internal/catalogd/service/graphql_service.go
Comment thread internal/catalogd/graphql/graphql.go
@grokspawn grokspawn force-pushed the catd-graphql-play branch from 53e8200 to a4eaf83 Compare May 15, 2026 19:43
Comment thread internal/catalogd/storage/localdir.go
Comment thread internal/catalogd/server/handlers.go Outdated
Comment on lines +271 to +280
if r.Method == http.MethodPost {
// Check if this is the GraphQL endpoint - must end with exactly "/api/v1/graphql"
if !strings.HasSuffix(r.URL.Path, "/api/v1/graphql") {
http.Error(w, http.StatusText(http.StatusMethodNotAllowed), http.StatusMethodNotAllowed)
return
}
} else if !allowedMethodSet.Has(r.Method) {
http.Error(w, http.StatusText(http.StatusMethodNotAllowed), http.StatusMethodNotAllowed)
return
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The structure of this check means that allowedMethodSet doesn't need to have http.MethodPost in it. So maybe keep the method check first, and then special-case Post (although, not as efficient). But this seems fragile, unfortunately, you can't register a POST-only handler.

Should the string "/api/v1/graphql" be made into a constant? And it used elsewhere as needed (or broken up)?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This block is redundant. I initially was modifying here instead of distributing across the a separate post check, and I forgot to delete it I guess.
Thanks for catching it!

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Whoops! It's not redundant, because only graphql supports POST. But the original approach is easy to grow with different services, so long as each supports an homogeneous set of request types. Since these do not, I broke it into a formal struct which allows each service to specify the supported request types and access paths individually.

Comment thread internal/catalogd/graphql/graphql.go Outdated
Comment thread internal/catalogd/graphql/sample-queries.txt Outdated
@openshift-ci openshift-ci Bot added the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label May 16, 2026
Copilot AI review requested due to automatic review settings May 19, 2026 14:05
@grokspawn grokspawn force-pushed the catd-graphql-play branch from a4eaf83 to 4717ccc Compare May 19, 2026 14:05
@openshift-ci openshift-ci Bot removed the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label May 19, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 20 out of 21 changed files in this pull request and generated 3 comments.

Comment thread manifests/experimental-e2e.yaml
Comment thread internal/catalogd/server/handlers.go
Comment thread internal/catalogd/graphql/graphql.go
grokspawn added 2 commits May 19, 2026 11:24
Signed-off-by: Jordan <jordan@nimblewidget.com>
Signed-off-by: Jordan <jordan@nimblewidget.com>
@grokspawn grokspawn force-pushed the catd-graphql-play branch from 4717ccc to dc703e3 Compare May 19, 2026 16:29
Copilot AI review requested due to automatic review settings May 19, 2026 16:31
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 22 out of 24 changed files in this pull request and generated 3 comments.

Files not reviewed (1)
  • hack/demo/graphql-demo.cast: Language not supported

Comment thread manifests/experimental.yaml
Comment thread manifests/experimental-e2e.yaml
Comment thread internal/catalogd/storage/localdir.go
Signed-off-by: grokspawn <jordan@nimblewidget.com>
Copilot AI review requested due to automatic review settings May 19, 2026 21:03
@grokspawn grokspawn force-pushed the catd-graphql-play branch from b9f6591 to 41610d7 Compare May 19, 2026 21:03
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 22 out of 23 changed files in this pull request and generated 3 comments.

Comments suppressed due to low confidence (2)

docs/draft/howto/catalog-queries-graphql-endpoint.md:171

  • In the “Complex Bundle Properties” section, the text says GraphQL will return the full JSON structure for properties.value, but in the current implementation complex values (maps/slices) are marshaled to JSON strings (e.g., value will be a JSON-encoded string). Update the wording and/or the query examples to reflect that clients need to fromjson/decode the string to access nested fields.
### Complex Bundle Properties

Query bundle properties with their type and value fields:

``` terminal
curl -k -X POST 'https://localhost:8443/catalogs/operatorhubio/api/v1/graphql' \
  -H "Content-Type: application/json" \
  -d '{
    "query": "{ olmbundles(limit: 5) { name properties { type value } } }"
  }' | jq

Note: The properties field contains an array of objects, each with a type string and a value field that can contain complex nested data. GraphQL will return the full JSON structure for the value field.

**internal/catalogd/graphql/sample-queries.txt:90**
* The sample queries for bundle properties use a `bundles` root field and selection sets under `properties.value` (union/object fragments). The current dynamic schema generation uses fully-qualified schema names for root fields (e.g., `olmbundles`) and represents complex nested values like `properties.value` as JSON strings (not object unions), so these examples will fail as written. Please update the sample queries to use the actual root field names and treat `value` as a scalar (decoded client-side if needed).

Get bundles with all properties

{
bundles(limit: 5) {
name
package
version
properties {
type
value {
... on PropertyValueFeaturesOperatorsOpenshiftIo {
disconnected

</details>

Comment thread internal/catalogd/service/graphql_service.go
Comment thread docs/draft/howto/catalog-queries-graphql-endpoint.md
Comment thread internal/catalogd/graphql/sample-queries.txt
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

lifecycle/frozen Indicates that an issue or PR should not be auto-closed due to staleness.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants