octoql

module
v0.3.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 22, 2026 License: MIT

README

Test Status Contributor Covenant

octoql

octoql generates type-safe Go clients and typed test handlers for GitHub-shaped GraphQL APIs. It validates queries and mutations against a pinned schema, then generates a self-contained Go client with typed methods for each operation.

octoql is a standalone project derived from Khan/genqlient. See THIRD_PARTY_NOTICES.md for exact source pins and attribution.

Requirements and installation

octoql requires Go 1.26 or newer. Pin octoqlgen as a Go tool dependency in the module that owns the generated client:

go get -tool github.com/willabides/octoql/cmd/octoqlgen

Run the pinned tool with go tool octoqlgen. This keeps the generator version explicit in the module that owns the generated client.

For a standalone binary, install a release archive with bindown:

bindown template-source add octoql https://github.com/WillAbides/octoql/releases/latest/download/bindown.yaml
bindown dependency add octoqlgen --source octoql

Or build a standalone binary from source with an explicit version or commit:

go install github.com/willabides/octoql/cmd/octoqlgen@<version-or-commit>

Generated clients are self-contained and use only the standard library unless configured scalar bindings add imports. Application code does not import github.com/willabides/octoql.

Generate a client

Initialize a project:

go tool octoqlgen init

GitHub authentication must be available through GH_TOKEN, GITHUB_TOKEN, or the gh CLI.

This resolves and fetches the latest GitHub Docs Free, Pro, & Team (fpt) schema, then creates a configuration containing its commit revision and SHA-256 digest. It also creates .octoql/.gitignore; the generated config uses the gitignored .octoql/schema.graphql path, graphql/**/*.graphql for operations, and internal/githubapi/generated.go for output.

Choose another GitHub Docs schema version with --schema-version:

go tool octoqlgen init --schema-version ghec
go tool octoqlgen init --schema-version ghes-3.21

All paths and globs in octoqlgen.yaml are relative to that file. See docs/octoqlgen.yaml for local schemas, other remote sources, and every configuration option.

Create graphql/repository.graphql:

query GetRepository($owner: String!, $name: String!, $first: Int!) {
  repository(owner: $owner, name: $name) {
    nameWithOwner
    issues(first: $first) {
      nodes {
        number
        title
      }
    }
  }
}

Fetch or verify the configured schema, then generate:

go tool octoqlgen schema fetch
go tool octoqlgen generate

Generation performs the same schema verification or fetch before it writes code. Query and mutation operation names become generated helper names, so use an uppercase name when the helper must be exported. octoql does not support GraphQL subscriptions, and octoqlgen rejects subscription operations.

Operations may also be embedded in Go string literals. See the directive reference for embedded operations and per-operation options.

Schema sources and updates

schema.path is always the schema used for generation. Keep it in the gitignored .octoql directory when the source is remote. A local schema needs only its path:

schema:
  path: schema/github.graphql

GitHub.com sources require a SHA-256 digest and full commit SHA. Authentication uses GH_TOKEN, GITHUB_TOKEN, or gh auth token. See the configuration reference for all schema settings.

octoqlgen init configures and fetches the latest fpt schema by default. Pass --schema-version to initialize with another GitHub Docs version.

schema fetch verifies an existing file or fetches a missing remote file:

go tool octoqlgen schema fetch

schema update fetches the latest version of the configured repository path from its default branch, validates and writes it, then updates the configuration revision and sha256. Run schema updates serially.

go tool octoqlgen schema update
git diff -- octoqlgen.yaml
go tool octoqlgen generate

The .octoql schema normally remains ignored while the reviewed pin in octoqlgen.yaml is committed. Use --config PATH with fetch, update, or generate when the config has another name or location.

Call the generated client

Configure GitHub bearer authentication directly on the client:

client := githubapi.NewClient("https://api.github.com/graphql", nil)
err := client.SetBearerToken(os.Getenv("GITHUB_TOKEN"))
if err != nil {
	return err
}

response, err := client.GetRepository(
	ctx,
	githubapi.GetRepositoryVariables{
		Owner: "octo-org",
		Name:  "octo-repo",
		First: 10,
	},
)
if err != nil {
	return err
}
fmt.Println(response.Repository.NameWithOwner)

Pass a different endpoint to githubapi.NewClient for GHES, a proxy, or an httptest.Server. Pass nil as the HTTP client to use http.DefaultClient.

For basic authentication or another authentication scheme, configure the http.Client or http.RoundTripper passed to NewClient.

Runtime responses and errors

Generated helpers return a pointer to the concrete operation response and an error. The response is nil when the error is non-nil. Sometimes GitHub returns partial data with an error. Use errors.AsType to check for partial data:

partialErr, ok := errors.AsType[*githubapi.GetRepositoryPartialDataError](err)
if ok {
	fmt.Printf("partial repository: %+v\n", partialErr.PartialData().Repository)
}

Every failure after receiving an HTTP response includes *githubapi.ResponseError. GraphQL errors, rate limits, and partial data are independent error facets, so use errors.AsType for each detail your application needs. Read the latest observed primary rate-limit state with client.RateLimit(). The client never retries automatically.

Generated types and GitHub defaults

GraphQL's built-in scalars map to ordinary Go values:

GraphQL Go
Int int
Float float64
String, ID string
Boolean bool

Nullable named values generate as pointers by default. Use @octoqlgen(pointer: false) on an argument or selected field when its zero value should represent GraphQL null. octoqlgen includes bindings for common GitHub scalars; add a binding for unknown custom scalars. See the configuration reference and directive reference for scalar bindings, abstract types, and field options.

Typed test handlers

Generate a typed http.Handler from the configured operations:

generated: internal/githubapi/generated.go
test_handler:
  generated: internal/githubapitest/generated.go
  types: client

types: client is the default and makes handler response values assignable to generated client types.

Use types: local to generate separate handler types:

test_handler:
  generated: internal/githubapitest/generated.go
  types: local

Local handler values are not assignable to client types. Test-handler configuration requires query and mutation names to begin with an uppercase letter.

After go tool octoqlgen generate, each handler operation has matching Expect<Operation>, Default<Operation>, and Reset<Operation> methods:

handler := githubapitest.NewTestHandler(t)
server := httptest.NewServer(handler)
t.Cleanup(server.Close)

variables := githubapitest.GetRepositoryVariables{
	Owner: "octo-org",
	Name:  "octo-repo",
	First: 1,
}
handler.ExpectGetRepository(variables, githubapitest.Times(2)).
	Respond(githubapitest.GetRepositoryResponse{
		Repository: githubapitest.GetRepositoryRepository{
			NameWithOwner: "octo-org/octo-repo",
		},
	})

client := githubapi.NewClient(server.URL, server.Client())
response, err := client.GetRepository(
	t.Context(),
	variables,
)
require.NoError(t, err)
require.Equal(t, "octo-org/octo-repo", response.Repository.NameWithOwner)

An expectation defaults to one call. Pass Times(n) to require exactly n, MinTimes(n) to set a minimum, or MinTimes(0) to create an unlimited stub. Default<Operation> is an unlimited fallback. Cleanup verifies unmet expectations, and expectation state is safe for concurrent requests.

Expectations can also configure partial data, errors, headers, status, and rate limits.

Reference

Directories

Path Synopsis
cmd
octoqlgen command
octoqlgen generates type-safe Go GraphQL clients.
octoqlgen generates type-safe Go GraphQL clients.
octoqlgen/internal/cli
Package cli defines the octoqlgen command-line interface.
Package cli defines the octoqlgen command-line interface.
octoqlgen/internal/config
Package config loads octoqlgen configuration files.
Package config loads octoqlgen configuration files.
octoqlgen/internal/schema
Package schema verifies and materializes pinned GraphQL schemas.
Package schema verifies and materializes pinned GraphQL schemas.
internal
generatefeatures/githubdefaults
Package githubdefaults exercises generated helpers that use GitHub's default scalar bindings.
Package githubdefaults exercises generated helpers that use GitHub's default scalar bindings.
generatefeatures/nocontext
Package nocontext exercises generated helpers configured without a context parameter.
Package nocontext exercises generated helpers configured without a context parameter.
handlertest
Package handlertest exercises generated clients and typed test handlers.
Package handlertest exercises generated clients and typed test handlers.
handlertest/localfixture
Package localfixture generates a client and handler-local types for parity tests.
Package localfixture generates a client and handler-local types for parity tests.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL