Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: Adds Federation 2 Support #2115

Merged
merged 9 commits into from
Apr 25, 2022
Merged

Feature: Adds Federation 2 Support #2115

merged 9 commits into from
Apr 25, 2022

Conversation

lleadbet
Copy link
Contributor

@lleadbet lleadbet commented Apr 22, 2022

This PR adds in support for Apollo's Federation 2 standard, as requested per issue #2114.

This adds a new configuration value to set the federation version manually as well as a method to detect federation 2 schemas using a small regex string.

Largely, this doesn't change much about the generated code, but instead allows for graphql-parser to not error by adding the new Federation 2 directives before loading new schemas. Previously, this was panicing due to a missing directive.

By default, this still uses Federation 1 unless detected by aforementioned regex or set by the user to avoid breaking changes.

I have:

  • Added tests covering the bug / feature (see testing)
  • Updated any relevant documentation (see docs)

@lleadbet lleadbet marked this pull request as ready for review April 22, 2022 20:00
@lleadbet
Copy link
Contributor Author

@frederikhors - Just a small question, as I can't seem to quite understand why it's erroring out on tests/using it.

I have added a Link interface here: plugin/federation/fedruntime/runtime.go, however referencing within the federation file such as:

		builtins["link__Import"] = config.TypeMapEntry{
			Model: config.StringList{"github.com/99designs/gqlgen/fedruntime.Link"},
		}

Still doesn't find the interface.

@frederikhors
Copy link
Collaborator

@lleadbet we need to wait @StevenACoffman for this answer.

```yml
federation:
filename: graph/generated/federation.go
package: generated

Choose a reason for hiding this comment

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

Did you want to add a version: 2 key here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We can implicitly pull that from the schema, hence why I left it out; might be worthwhile, however.

@@ -11,3 +11,6 @@ type Service struct {
type Entity interface {
IsEntity()
}

// Used for the Link directive
type Link interface{}
Copy link
Collaborator

Choose a reason for hiding this comment

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

I'm idly wondering if the Link interface should have functions to introspectively answer:

  1. What version was imported (currently only "2.0" possible)
  2. What imports out of the list: ["@key","@shareable", "@provides", "@external", "@tag", "@extends", "@override", "@inaccessible"]

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hmm- I think it might be useful in the future, but since the parser also validates at time of loading, you need to load all directives just in case- the current flow just ensures that the file contains that directive using Regex, which isn't the best solution either.

Not sure if you have any recs on how to handle the pre-parsing problem, though.

@StevenACoffman
Copy link
Collaborator

StevenACoffman commented Apr 23, 2022

Applying my suggested fix removes one test failure and moves the second to:

=== Failed
=== FAIL: api TestGenerate/federation2 (7.45s)
    generate_test.go:55: Generate() error = validation failed: packages.Load: /Users/steve/Documents/git/gqlgen/api/testdata/federation2/graph/generated/generated.go:4118:17: ec.unmarshalInputlink__Import undefined (type *executionContext has no field or method unmarshalInputlink__Import)
        /Users/steve/Documents/git/gqlgen/api/testdata/federation2/graph/generated/generated.go:4126:12: ec._link__Import undefined (type *executionContext has no field or method _link__Import)
        , wantErr false
    --- FAIL: TestGenerate/federation2 (7.45s)

=== FAIL: api TestGenerate (12.63s)

This is because both the *executionContext methods mentioned unmarshalInputlink__Import and _link__Import have not been added in https://github.com/99designs/gqlgen/blob/master/plugin/federation/federation.gotpl and are not exempted from being required somehow.

@StevenACoffman
Copy link
Collaborator

StevenACoffman commented Apr 23, 2022

I modified that federation.gotpl to have this chunk to get the tests to succeed after applying the suggested fix in my other comment:


{{ reserveImport "github.com/vektah/gqlparser/v2/ast" }}

{{ reserveImport "github.com/99designs/gqlgen/plugin/federation/fedruntime" }}
{{ reserveImport "github.com/99designs/gqlgen/graphql" }}

var (
	ErrUnknownType = errors.New("unknown type")
	ErrTypeNotFound = errors.New("type not found")
)

func (ec *executionContext) __resolve__service(ctx context.Context) (fedruntime.Service, error) {
	if ec.DisableIntrospection {
		return fedruntime.Service{}, errors.New("federated introspection disabled")
	}

	var sdl []string

	for _, src := range sources {
		if src.BuiltIn {
			continue
		}
		sdl = append(sdl, src.Input)
	}

	return fedruntime.Service{
		SDL: strings.Join(sdl, "\n"),
	}, nil
}

func (ec *executionContext) unmarshalInputlink__Import(ctx context.Context, v  interface{}) (string, error) {
	fmt.Println("Yahoo-hoo-hooey")
	return "", nil
}

func (ec *executionContext) _link__Import(ctx context.Context, sel ast.SelectionSet, v  interface{}) graphql.Marshaler {
	fmt.Println("Yahoo-hoo-hooey")
	return nil
}

These are silly, but something better should go there or have them not be required.

@lleadbet
Copy link
Contributor Author

These are silly, but something better should go there or have them not be required.

Agreed- was copying Apollo's material, but since those imports are just strings, decided to convert it into [String!] instead of the custom scalar.

@coveralls
Copy link

coveralls commented Apr 25, 2022

Coverage Status

Coverage increased (+0.2%) to 74.735% when pulling 6fbe6f1 on lleadbet:main into cddbf02 on 99designs:master.

@lleadbet
Copy link
Contributor Author

https://github.com/99designs/gqlgen/runs/6159890288?check_suite_focus=true#step:6:27

I have, however it still fails; would be curious on the fix here.

@StevenACoffman
Copy link
Collaborator

You need to run cd ~/_examples/; go generate ./... i think

@StevenACoffman StevenACoffman merged commit 2a2a3dc into 99designs:master Apr 25, 2022
@StevenACoffman
Copy link
Collaborator

Thanks!

@lleadbet lleadbet deleted the main branch April 25, 2022 18:24
@lleadbet lleadbet mentioned this pull request Apr 26, 2022
2 tasks
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.

5 participants