Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

[FEATURE] GraphQL mutation support (operationType, variables payload, errors-in-200 selection)

Open
#142 0 comments 0 reactions 1 assignee View on GitHub

Maintainers usually reply within 1 day

@jeffreyaven is already working on this.

Since Sep 14, 2026.

Assessment

This issue has not been assessed yet.

Description

enhancement
Summary

any-sdk currently supports GraphQL for reads only. The x-stackQL-graphQL extension is modelled by standardGraphQL (internal/anysdk/graphql.go) with id, query, url, httpVerb, cursor, and responseSelection - no operation type and no variables. The only execution path is StandardGQLReader (pkg/graphql/graphql.go), a paginating read loop (cursor strategies: cursor_after, keyset, offset, page_info) whose renderQuery() templates the cursor splice into the query string and posts { "query": "..." }. The REST mutation machinery (isMutation in public/formulation and public/providerinvokers/anysdkhttp) never consults GetGraphQL(), and the static analyzer short-circuits GraphQL methods entirely:

// public/discovery/static_analyzer.go:1448
graphQL := method.GetGraphQL()
if graphQL != nil {
    return result // TODO: GraphQL methods analysis
}

The consequence is that all GraphQL-backed providers are SELECT-only by engine constraint, not by provider choice. This issue proposes first-class GraphQL mutation support.

Motivating consumers
  • gitlab - the intended canonical reference implementation: a strictly Relay-conventional mutation surface (single input object argument, <entity>Create / <entity>Update / <entity>Destroy naming, errors: [] payloads inside HTTP 200), free full-lifecycle CI via the gitlab-ce container. A read-only provider for a DevOps platform is a visible gap (issues, MRs, labels, CI variables are write-expected resources).
  • runpod - GraphQL-only vendor whose control operations (pod deploy/start/stop/terminate) are mutations; without this feature the provider is inventory-only.
  • railway - GraphQL-only vendor; deploys/restarts/scaling are mutations.
  • Write phases of newrelic (NerdGraph: alert policies, dashboards, tagging) and buildkite.
Proposed design
  1. Model (internal/anysdk/graphql.go, loader in internal/anysdk/loader.go via ExtensionKeyGraphQL):

    • operationType (string, optional): absent or query -> existing reader behaviour; mutation -> one-shot executor. Back-compat: every existing spec is untouched.
    • variables (map, optional): a template map binding method parameters to a GraphQL variables payload, rendered with the same text/template inputs the query template receives. Present -> the request body is { "query": ..., "variables": { ... } }.
    • errorSelection (GraphQLElement, optional): a jsonPath whose resolution to a non-empty array or non-null value marks the call failed, regardless of HTTP 200. This is the GraphQL errors-in-200 convention (both the top-level errors array and payload-level userErrors/errors fields, selectable per method).
    • responseSelection retains its current meaning for the mutation payload projection.
  2. Executor (pkg/graphql/): a one-shot GQLExecutor alongside StandardGQLReader - no cursor loop, renders query + variables, single request, applies errorSelection then responseSelection. Reuse the client, logging context (ContextWithHTTPLogger), and stream_transform hooks the reader already has.

    • Note: variables support should also be made available to the read path in a follow-up, replacing the current escape-and-embed rendering in renderQuery() (pkg/graphql/graphql.go:649) for methods that declare variables - a robustness improvement independent of mutations.
  3. Invocation wiring: route GraphQL methods with operationType: mutation through the mutation path (the isMutation plumbing in public/formulation/formulation.go and public/providerinvokers/anysdkhttp/invoker.go) so INSERT/UPDATE/DELETE/EXEC verb mappings in sqlVerbs become legal for GraphQL methods.

  4. Static analysis (public/discovery/static_analyzer.go): retire the TODO at line 1448 with GraphQL method checks - query parses, template placeholders resolvable from declared parameters, operationType: mutation methods carry errorSelection (warning if absent), responseSelection present for selectable methods, cursor config forbidden on mutations.

Spec shape (target)
x-stackQL-graphQL:
  url: https://gitlab.com/api/graphql
  httpVerb: POST
  operationType: mutation
  query: >
    mutation($input: CreateIssueInput!) {
      createIssue(input: $input) {
        issue { iid title state webUrl }
        errors
      }
    }
  variables:
    input:
      projectPath: '{{ .full_path }}'
      title: '{{ .title }}'
      description: '{{ .description }}'
  responseSelection:
    jsonPath: '$.data.createIssue.issue'
  errorSelection:
    jsonPath: '$.data.createIssue.errors'
Acceptance criteria
  • Existing GraphQL read specs (including the in-repo fixture internal/anysdk/testdata/registry/src/github/v0.3.1/services/scim.yaml) load and execute byte-identically - operationType absent implies current behaviour.
  • A mutation method loads via ExtensionKeyGraphQL, executes one-shot with a variables payload, projects responseSelection on success.
  • A populated errorSelection result surfaces as a call failure (with the selected content in the error), never as rows - covered by a negative test.
  • Top-level GraphQL errors on HTTP 200 also surfaces as failure.
  • Static analyzer covers GraphQL methods per point 4; the line 1448 TODO is removed.
  • Unit tests in pkg/graphql for the executor (success, payload errors, top-level errors, template resolution failure).
Out of scope
  • GraphQL subscriptions (streaming - excluded per standing policy).
  • Automatic mutation generation from introspection (provider tooling concern - @stackql/provider-utils).
  • Cursor/pagination interaction with mutations (forbidden by analyzer rule instead).
Dominant language
Go
Stars
0
Forks
1
Avg merge
10h 40m
Merged PRs (30d)
11

Getting set up

This project ships no dev container, Dockerfile or contributing guide, so setting up is up to you: start from its README, and see our first-contribution guide for the general steps.

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from stackql/any-sdk

All issues in stackql/any-sdk

Similar issues

More Go issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.