Documentation
¶
Overview ¶
Package graphqlintrospect asks a GitLab instance for its GraphQL schema and converts the answer to SDL.
It exists because two commands need the same fetch. cmd/gen_graphql_schema pins gitlab.com's schema into the repository, and cmd/audit_graphql_documents judges every document this server sends against a schema fetched from a named instance right now. Those are the same three steps, and a second copy of them would be a second set of introspection quirks to keep in step: the canned answer every instance returns whatever is asked, the deprecation arguments that an older instance refuses, and the wrapper depth a type reference nests.
The conversion is deliberately lossy. Descriptions and deprecation reasons are dropped because validation never consults them and they would triple the file, and everything nameable is sorted so re-fetching from an instance that reorders its answer produces a diff of what changed rather than a reshuffle.
Index ¶
- Constants
- func CredentialFor(endpoint, instance, token string) (credential, withheld string)
- func InstanceVersion(ctx context.Context, target Target) (version, revision string)
- func RenderSDL(schema *Schema) string
- func TruncatedAnswer(types int) bool
- type Field
- type InputValue
- type Schema
- type Target
- type Type
- type TypeName
- type TypeRef
Constants ¶
const ( // UnknownVersion is recorded when the instance would not say what it runs, // which is what GitLab answers an anonymous caller. UnknownVersion = "unknown" // FetchTimeout bounds one whole fetch. The introspection payload is tens // of megabytes of JSON and gitlab.com takes seconds to produce it. FetchTimeout = 3 * time.Minute // MinimumTypes is the floor a GitLab schema has to clear before anything // is judged against it. gitlab.com answered with 4331 types on the day of // the pin and an unlicensed gitlab/gitlab-ee:latest with 4233, and the // figure grows release over release, so a count well under that is not a // GitLab schema: the introspection was truncated, or the instance answering // is not the GitLab this server targets. // // The consequence of accepting one is the same wherever it happens. A pin // taken from a truncated answer narrows what every later gate promises, and // a live re-probe run against one reports that every document passed a // question nobody asked, which is worse than not running at all. MinimumTypes = 4000 )
Variables ¶
This section is empty.
Functions ¶
func CredentialFor ¶
CredentialFor decides whether token may be sent to endpoint, and says why when it may not.
Both commands that introspect take their endpoint from a flag: one pins the schema of whatever `-url` names, the other re-probes whatever `-live` names. Reading GITLAB_TOKEN beside such a flag and sending it unconditionally makes every mistyped host, and every host somebody else chose, a place the operator's GitLab credential arrives. The token buys one thing here, the version string in the report, because GitLab answers introspection to anyone; so the trade is a whole credential against a line of provenance, and it is not worth making by default.
The rule is the narrowest one that is still true: a token belongs to the instance GITLAB_URL names, and goes nowhere else. Host and port must match exactly; the scheme is compared too, so a plaintext copy of an https instance is a different place. When nothing is withheld the reason is empty.
func InstanceVersion ¶
InstanceVersion asks the instance what it runs. Failure is not fatal: the schema is the artifact and the version is provenance, so an anonymous run reports UnknownVersion and the caller carries on.
func RenderSDL ¶
RenderSDL converts an introspection result into SDL.
Everything nameable is sorted, so re-fetching from an instance that reorders its answer produces a diff of what actually changed rather than a reshuffle. Order carries no meaning in SDL: a schema is a set of definitions, a type is a set of fields, and a field's arguments are matched by name.
func TruncatedAnswer ¶
TruncatedAnswer reports whether an introspection carrying this many types is too short to be a whole GitLab schema. See MinimumTypes for why the two callers share one floor rather than each picking a number.
Types ¶
type Field ¶
type Field struct {
Name string `json:"name"`
Args []InputValue `json:"args"`
Type *TypeRef `json:"type"`
}
Field is one output field with the arguments it accepts.
type InputValue ¶
type InputValue struct {
Name string `json:"name"`
Type *TypeRef `json:"type"`
DefaultValue *string `json:"defaultValue"`
}
InputValue is one argument or input-object field. DefaultValue is a pointer because introspection reports the absence of a default as null, which is not the same as a default whose literal happens to be empty.
type Schema ¶
type Schema struct {
QueryType *TypeName `json:"queryType"`
MutationType *TypeName `json:"mutationType"`
SubscriptionType *TypeName `json:"subscriptionType"`
Types []Type `json:"types"`
}
Schema is the __schema payload, holding only what the SDL renderer reads.
type Target ¶
type Target struct {
// Endpoint is the GraphQL endpoint, such as https://gitlab.com/api/graphql.
Endpoint string
// Token is sent as a bearer credential when it is not empty. GitLab answers
// introspection to anyone, so this is only needed for [InstanceVersion],
// which it refuses to tell an anonymous caller. Fill it through
// [CredentialFor] rather than from the environment directly: both commands
// take an endpoint from a flag, and a credential must not follow one to a
// host nobody said it belonged to.
Token string
// Client performs the request. A caller supplies its own so the timeout,
// and a test's transport, stay the caller's business.
Client *http.Client
}
Target is the instance to ask and how to ask it.
type Type ¶
type Type struct {
Kind string `json:"kind"`
Name string `json:"name"`
Fields []Field `json:"fields"`
InputFields []InputValue `json:"inputFields"`
Interfaces []TypeName `json:"interfaces"`
EnumValues []TypeName `json:"enumValues"`
PossibleTypes []TypeName `json:"possibleTypes"`
}
Type is one introspected type in any of the six kinds.