Skip to content

Catd graphql play#2100

Draft
grokspawn wants to merge 7 commits intooperator-framework:mainfrom
grokspawn:catd-graphql-play
Draft

Catd graphql play#2100
grokspawn wants to merge 7 commits intooperator-framework:mainfrom
grokspawn:catd-graphql-play

Conversation

@grokspawn
Copy link
Copy Markdown
Contributor

Description

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 a1b458e
🔍 Latest deploy log https://app.netlify.com/projects/olmv1/deploys/69ebe2c027f2e50008e03fe0
😎 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.

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 59.84000% with 251 lines in your changes missing coverage. Please review.
✅ Project coverage is 67.01%. Comparing base (7277a46) to head (a1b458e).

Files with missing lines Patch % Lines
internal/catalogd/graphql/graphql.go 61.41% 128 Missing and 14 partials ⚠️
internal/catalogd/server/handlers.go 55.31% 58 Missing and 5 partials ⚠️
internal/catalogd/service/graphql_service.go 53.73% 22 Missing and 9 partials ⚠️
internal/catalogd/storage/localdir.go 60.60% 11 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   67.97%   67.01%   -0.96%     
==========================================
  Files         144      147       +3     
  Lines       10573    11118     +545     
==========================================
+ Hits         7187     7451     +264     
- Misses       2866     3122     +256     
- Partials      520      545      +25     
Flag Coverage Δ
e2e 38.07% <46.24%> (+0.73%) ⬆️
experimental-e2e 52.45% <47.52%> (-0.13%) ⬇️
unit 51.85% <32.16%> (-1.78%) ⬇️

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
features:
enabled:
- APIV1MetasHandler
- GraphQLCatalogQueries
Comment thread go.mod Outdated
Comment thread internal/catalogd/storage/localdir.go
@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 force-pushed the catd-graphql-play branch from 0d2d4e4 to 711c9d8 Compare April 8, 2026 13:11
@openshift-ci openshift-ci Bot removed the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Apr 8, 2026
Copilot AI review requested due to automatic review settings April 8, 2026 15:53
@grokspawn grokspawn force-pushed the catd-graphql-play branch from 711c9d8 to 888a0d6 Compare April 8, 2026 15:53
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 17 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.

Comment thread manifests/experimental.yaml
Comment thread manifests/experimental-e2e.yaml
Comment thread internal/catalogd/graphql/graphql.go Outdated
Comment thread internal/catalogd/server/handlers.go
Comment thread internal/catalogd/server/handlers.go
Comment thread internal/shared/util/tlsprofiles/mozilla_data.go Outdated
Comment thread internal/catalogd/graphql/graphql_test.go
@openshift-ci openshift-ci Bot added the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Apr 12, 2026
@openshift-ci openshift-ci Bot removed the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Apr 13, 2026
Copilot AI review requested due to automatic review settings April 24, 2026 15:43
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 17 out of 18 changed files in this pull request and generated 4 comments.

Comments suppressed due to low confidence (1)

internal/catalogd/storage/localdir.go:1

  • Typo in comment: slightflight should be singleflight.
package storage

💡 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
Comment thread internal/catalogd/server/handlers.go Outdated
Comment thread internal/catalogd/server/handlers.go
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 5 comments.


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

Comment thread manifests/experimental-e2e.yaml
Comment thread internal/catalogd/storage/localdir.go
Comment on lines +9 to +23
The GraphQL endpoint is now available as part of the catalogd storage server at:

```
{catalog}/api/v1/graphql
```

Where `{catalog}` is replaced by the actual catalog name at runtime.

## Example Usage

### Making a GraphQL Request

```bash
curl -X POST http://localhost:8080/my-catalog/api/v1/graphql \
-H "Content-Type: application/json" \
Copy link

Copilot AI Apr 24, 2026

Choose a reason for hiding this comment

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

The README’s endpoint examples omit the /catalogs/ prefix used by catalogd (e.g. https://.../catalogs/<catalog>/api/v1/graphql), which can mislead users trying to hit the endpoint. Please update the documented URL and curl example to match the actual route registered by CatalogHandlers.

Copilot uses AI. Check for mistakes.
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.

Addressed

Comment on lines +29 to +106
// CachedGraphQLService implements GraphQLService with an in-memory schema cache
type CachedGraphQLService struct {
schemaMux sync.RWMutex
schemaCache map[string]*gql.DynamicSchema
buildGroup singleflight.Group // Prevents duplicate concurrent schema builds
}

// NewCachedGraphQLService creates a new GraphQL service with caching
func NewCachedGraphQLService() *CachedGraphQLService {
return &CachedGraphQLService{
schemaCache: make(map[string]*gql.DynamicSchema),
}
}

// GetSchema returns the GraphQL schema for a catalog, using cache if available
func (s *CachedGraphQLService) GetSchema(catalog string, catalogFS fs.FS) (*gql.DynamicSchema, error) {
// Check cache first (read lock)
s.schemaMux.RLock()
if cachedSchema, ok := s.schemaCache[catalog]; ok {
s.schemaMux.RUnlock()
return cachedSchema, nil
}
s.schemaMux.RUnlock()

// Use singleflight to prevent duplicate concurrent builds for the same catalog
result, err, _ := s.buildGroup.Do(catalog, func() (interface{}, error) {
// Double-check cache after acquiring singleflight lock
s.schemaMux.RLock()
if cachedSchema, ok := s.schemaCache[catalog]; ok {
s.schemaMux.RUnlock()
return cachedSchema, nil
}
s.schemaMux.RUnlock()

// Schema not in cache, build it
dynamicSchema, err := buildSchemaFromFS(catalogFS)
if err != nil {
return nil, err
}

// Cache the result (write lock)
s.schemaMux.Lock()
s.schemaCache[catalog] = dynamicSchema
s.schemaMux.Unlock()

return dynamicSchema, nil
})

if err != nil {
return nil, err
}

return result.(*gql.DynamicSchema), nil
}

// ExecuteQuery executes a GraphQL query against a catalog
func (s *CachedGraphQLService) ExecuteQuery(catalog string, catalogFS fs.FS, query string) (*graphql.Result, error) {
// Get or build the schema (uses cache and singleflight)
dynamicSchema, err := s.GetSchema(catalog, catalogFS)
if err != nil {
return nil, fmt.Errorf("failed to get GraphQL schema: %w", err)
}

// Execute the query
result := graphql.Do(graphql.Params{
Schema: dynamicSchema.Schema,
RequestString: query,
})

return result, nil
}

// InvalidateCache removes the cached schema for a catalog
func (s *CachedGraphQLService) InvalidateCache(catalog string) {
s.schemaMux.Lock()
delete(s.schemaCache, catalog)
s.schemaMux.Unlock()
}
Copy link

Copilot AI Apr 24, 2026

Choose a reason for hiding this comment

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

New caching/singleflight behavior in CachedGraphQLService (schema cache hits, invalidation, and concurrent build de-duplication) is not covered by tests. Adding focused unit tests would help prevent regressions (e.g., cache reuse across calls, InvalidateCache behavior, and only-one-build under concurrency).

Copilot uses AI. Check for mistakes.
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.

Addressed

httpError(w, err)
return
}
catalogDir := s.catalogDir(catalog)
Copy link

Copilot AI Apr 24, 2026

Choose a reason for hiding this comment

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

GetCatalogFS returns os.DirFS(catalogDir) without checking that catalogDir exists. For a nonexistent catalog, this returns nil error and later GraphQL execution will likely surface a non-fs.ErrNotExist error, producing a 500 instead of a 404. Consider os.Stat(catalogDir) (or the expected file within it) and returning fs.ErrNotExist when missing so the HTTP layer maps it to 404.

Suggested change
catalogDir := s.catalogDir(catalog)
catalogDir := s.catalogDir(catalog)
info, err := os.Stat(catalogDir)
if err != nil {
if errors.Is(err, os.ErrNotExist) {
return nil, fs.ErrNotExist
}
return nil, err
}
if !info.IsDir() {
return nil, fmt.Errorf("catalog path %q is not a directory", catalogDir)
}

Copilot uses AI. Check for mistakes.
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.

Addressed

Signed-off-by: Jordan <jordan@nimblewidget.com>
Copilot AI review requested due to automatic review settings April 24, 2026 21:38
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 2 comments.


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

Comment thread docs/draft/howto/catalog-queries-graphql-endpoint.md
Comment on lines +9 to +15
The GraphQL endpoint is now available as part of the catalogd storage server at:

```
{catalog}/api/v1/graphql
```

Where `{catalog}` is replaced by the actual catalog name at runtime.
Copy link

Copilot AI Apr 24, 2026

Choose a reason for hiding this comment

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

The endpoint path shown here (and in the curl example below) omits the "/catalogs/" prefix used by catalogd’s storage server (baseStorageURL is ".../catalogs/"). To prevent confusion, update the examples to use the full path, e.g. "/catalogs//api/v1/graphql" (and the correct scheme/port per the deployment docs).

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. 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