From 3c3b6c2d9496548f4f8c79499270dc4aa4db6c6c Mon Sep 17 00:00:00 2001 From: Sam Coe Date: Tue, 16 Nov 2021 12:44:15 -0800 Subject: [PATCH 1/3] Make repo go gettable --- .github/CODE-OF-CONDUCT.md | 133 ++++++++++++++++++++++++++ .github/CONTRIBUTING.md | 48 ++++++++++ .github/workflows/codeql-analysis.yml | 70 ++++++++++++++ .github/workflows/lint.yml | 18 ++++ .github/workflows/test.yml | 22 +++++ .golangci.yml | 11 +++ .travis.yml | 16 ---- LICENSE | 1 + README.md | 19 +--- SECURITY.md | 3 + doc.go | 8 -- example/graphqldev/main.go | 105 -------------------- go.mod | 5 + go.sum | 7 ++ graphql.go | 34 +++++-- graphql_test.go | 6 +- ident/ident_test.go | 2 +- internal/jsonutil/benchmark_test.go | 4 +- internal/jsonutil/graphql.go | 2 +- internal/jsonutil/graphql_test.go | 6 +- query.go | 47 +++++---- query_test.go | 4 +- scalar_test.go | 2 +- 23 files changed, 386 insertions(+), 187 deletions(-) create mode 100644 .github/CODE-OF-CONDUCT.md create mode 100644 .github/CONTRIBUTING.md create mode 100644 .github/workflows/codeql-analysis.yml create mode 100644 .github/workflows/lint.yml create mode 100644 .github/workflows/test.yml create mode 100644 .golangci.yml delete mode 100644 .travis.yml create mode 100644 SECURITY.md delete mode 100644 doc.go delete mode 100644 example/graphqldev/main.go create mode 100644 go.mod create mode 100644 go.sum diff --git a/.github/CODE-OF-CONDUCT.md b/.github/CODE-OF-CONDUCT.md new file mode 100644 index 0000000..322065b --- /dev/null +++ b/.github/CODE-OF-CONDUCT.md @@ -0,0 +1,133 @@ + +# Contributor Covenant Code of Conduct + +## Our Pledge + +We as members, contributors, and leaders pledge to make participation in our +community a harassment-free experience for everyone, regardless of age, body +size, visible or invisible disability, ethnicity, sex characteristics, gender +identity and expression, level of experience, education, socio-economic status, +nationality, personal appearance, race, caste, color, religion, or sexual identity +and orientation. + +We pledge to act and interact in ways that contribute to an open, welcoming, +diverse, inclusive, and healthy community. + +## Our Standards + +Examples of behavior that contributes to a positive environment for our +community include: + +* Demonstrating empathy and kindness toward other people +* Being respectful of differing opinions, viewpoints, and experiences +* Giving and gracefully accepting constructive feedback +* Accepting responsibility and apologizing to those affected by our mistakes, + and learning from the experience +* Focusing on what is best not just for us as individuals, but for the + overall community + +Examples of unacceptable behavior include: + +* The use of sexualized language or imagery, and sexual attention or + advances of any kind +* Trolling, insulting or derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or email + address, without their explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Enforcement Responsibilities + +Community leaders are responsible for clarifying and enforcing our standards of +acceptable behavior and will take appropriate and fair corrective action in +response to any behavior that they deem inappropriate, threatening, offensive, +or harmful. + +Community leaders have the right and responsibility to remove, edit, or reject +comments, commits, code, wiki edits, issues, and other contributions that are +not aligned to this Code of Conduct, and will communicate reasons for moderation +decisions when appropriate. + +## Scope + +This Code of Conduct applies within all community spaces, and also applies when +an individual is officially representing the community in public spaces. +Examples of representing our community include using an official e-mail address, +posting via an official social media account, or acting as an appointed +representative at an online or offline event. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported to the community leaders responsible for enforcement at +opensource@github.com. +All complaints will be reviewed and investigated promptly and fairly. + +All community leaders are obligated to respect the privacy and security of the +reporter of any incident. + +## Enforcement Guidelines + +Community leaders will follow these Community Impact Guidelines in determining +the consequences for any action they deem in violation of this Code of Conduct: + +### 1. Correction + +**Community Impact**: Use of inappropriate language or other behavior deemed +unprofessional or unwelcome in the community. + +**Consequence**: A private, written warning from community leaders, providing +clarity around the nature of the violation and an explanation of why the +behavior was inappropriate. A public apology may be requested. + +### 2. Warning + +**Community Impact**: A violation through a single incident or series +of actions. + +**Consequence**: A warning with consequences for continued behavior. No +interaction with the people involved, including unsolicited interaction with +those enforcing the Code of Conduct, for a specified period of time. This +includes avoiding interactions in community spaces as well as external channels +like social media. Violating these terms may lead to a temporary or +permanent ban. + +### 3. Temporary Ban + +**Community Impact**: A serious violation of community standards, including +sustained inappropriate behavior. + +**Consequence**: A temporary ban from any sort of interaction or public +communication with the community for a specified period of time. No public or +private interaction with the people involved, including unsolicited interaction +with those enforcing the Code of Conduct, is allowed during this period. +Violating these terms may lead to a permanent ban. + +### 4. Permanent Ban + +**Community Impact**: Demonstrating a pattern of violation of community +standards, including sustained inappropriate behavior, harassment of an +individual, or aggression toward or disparagement of classes of individuals. + +**Consequence**: A permanent ban from any sort of public interaction within +the community. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], +version 2.1, available at +[https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1]. + +Community Impact Guidelines were inspired by +[Mozilla's code of conduct enforcement ladder][Mozilla CoC]. + +For answers to common questions about this code of conduct, see the FAQ at +[https://www.contributor-covenant.org/faq][FAQ]. Translations are available +at [https://www.contributor-covenant.org/translations][translations]. + +[homepage]: https://www.contributor-covenant.org +[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html +[Mozilla CoC]: https://github.com/mozilla/diversity +[FAQ]: https://www.contributor-covenant.org/faq +[translations]: https://www.contributor-covenant.org/translations diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md new file mode 100644 index 0000000..a4336f6 --- /dev/null +++ b/.github/CONTRIBUTING.md @@ -0,0 +1,48 @@ +## Contributing + +Hi! Thanks for your interest in contributing to the GitHub GraphQL Client Module! + +We accept pull requests for bug fixes and features where we've discussed the approach in an issue and given the go-ahead for a community member to work on it. We'd also love to hear about ideas for new features as issues. + +Please do: + +* Check existing issues to verify that the [bug][bug issues] or [feature request][feature request issues] has not already been submitted. +* Open an issue if things aren't working as expected. +* Open an issue to propose a significant change. +* Open a pull request to fix a bug. +* Open a pull request to fix documentation. +* Open a pull request for any issue labelled [`help wanted`][hw] or [`good first issue`][gfi]. + +Please avoid: + +* Opening pull requests for issues marked `needs-design`, `needs-investigation`, or `blocked`. +* Opening pull requests for any issue marked `core`. These issues require additional context from + the core CLI team at GitHub and any external pull requests will not be accepted. + +## Submitting a pull request + +1. Create a new branch: `git checkout -b my-branch-name` +1. Make your change, add tests, and ensure tests pass +1. Submit a pull request: `gh pr create --web` + +Contributions to this project are [released][legal] to the public under the [project's open source license][license]. + +Please note that this project adheres to a [Contributor Code of Conduct][code-of-conduct]. By participating in this project you agree to abide by its terms. + +## Resources + +- [How to Contribute to Open Source][] +- [Using Pull Requests][] +- [GitHub Help][] + + +[bug issues]: https://github.com/cli/shurcooL-graphql/issues?q=is%3Aopen+is%3Aissue+label%3Abug +[feature request issues]: https://github.com/cli/shurcooL-graphql/issues?q=is%3Aopen+is%3Aissue+label%3Aenhancement +[hw]: https://github.com/cli/shurcooL-graphql/labels/help%20wanted +[gfi]: https://github.com/cli/shurcooL-graphql/labels/good%20first%20issue +[legal]: https://docs.github.com/en/free-pro-team@latest/github/site-policy/github-terms-of-service#6-contributions-under-repository-license +[license]: ../LICENSE +[code-of-conduct]: ./CODE-OF-CONDUCT.md +[How to Contribute to Open Source]: https://opensource.guide/how-to-contribute/ +[Using Pull Requests]: https://docs.github.com/en/free-pro-team@latest/github/collaborating-with-issues-and-pull-requests/about-pull-requests +[GitHub Help]: https://docs.github.com/ diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml new file mode 100644 index 0000000..cfaa562 --- /dev/null +++ b/.github/workflows/codeql-analysis.yml @@ -0,0 +1,70 @@ +# For most projects, this workflow file will not need changing; you simply need +# to commit it to your repository. +# +# You may wish to alter this file to override the set of languages analyzed, +# or to provide custom queries or build logic. +# +# ******** NOTE ******** +# We have attempted to detect the languages in your repository. Please check +# the `language` matrix defined below to confirm you have the correct set of +# supported CodeQL languages. +# +name: "CodeQL" + +on: + push: + branches: [ trunk ] + pull_request: + # The branches below must be a subset of the branches above + branches: [ trunk ] + schedule: + - cron: '32 4 * * 3' + +jobs: + analyze: + name: Analyze + runs-on: ubuntu-latest + permissions: + actions: read + contents: read + security-events: write + + strategy: + fail-fast: false + matrix: + language: [ 'go' ] + # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] + # Learn more about CodeQL language support at https://git.io/codeql-language-support + + steps: + - name: Checkout repository + uses: actions/checkout@v2 + + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v1 + with: + languages: ${{ matrix.language }} + # If you wish to specify custom queries, you can do so here or in a config file. + # By default, queries listed here will override any specified in a config file. + # Prefix the list here with "+" to use these queries and those in the config file. + # queries: ./path/to/local/query, your-org/your-repo/queries@main + + # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). + # If this step fails, then you should remove it and run the build manually (see below) + - name: Autobuild + uses: github/codeql-action/autobuild@v1 + + # ℹī¸ Command-line programs to run using the OS shell. + # 📚 https://git.io/JvXDl + + # ✏ī¸ If the Autobuild fails above, remove it and uncomment the following three lines + # and modify them (or add more) to build your code if your project + # uses a compiled language + + #- run: | + # make bootstrap + # make release + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v1 diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 0000000..6c13706 --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,18 @@ +name: Lint +on: [push, pull_request] +jobs: + lint: + strategy: + matrix: + os: [ubuntu-latest] + go: [1.16] + runs-on: ${{ matrix.os }} + + steps: + - name: Checkout code + uses: actions/checkout@v2 + + - name: Lint + uses: golangci/golangci-lint-action@v2 + with: + version: latest diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..000f7da --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,22 @@ +name: Test +on: [push, pull_request] +jobs: + test: + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, windows-latest, macos-latest] + go: [1.16] + runs-on: ${{ matrix.os }} + + steps: + - name: Set up Go + uses: actions/setup-go@v1 + with: + go-version: ${{ matrix.go }} + + - name: Checkout code + uses: actions/checkout@v2 + + - name: Run tests + run: go test -v ./... diff --git a/.golangci.yml b/.golangci.yml new file mode 100644 index 0000000..2d5cc27 --- /dev/null +++ b/.golangci.yml @@ -0,0 +1,11 @@ +linters: + enable: + - gofmt + - godot + +linters-settings: + godot: + # comments to be checked: `declarations`, `toplevel`, or `all` + scope: declarations + # check that each sentence starts with a capital letter + capital: true diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 6452acb..0000000 --- a/.travis.yml +++ /dev/null @@ -1,16 +0,0 @@ -sudo: false -language: go -go: - - 1.x - - master -matrix: - allow_failures: - - go: master - fast_finish: true -install: - - # Do nothing. This is needed to prevent default install action "go get -t -v ./..." from happening here (we want it to happen inside script step). -script: - - go get -t -v ./... - - diff -n <(echo -n) <(gofmt -d -s .) - - go vet ./... - - go test -v -race ./... diff --git a/LICENSE b/LICENSE index ca4c776..c3f4bb7 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,7 @@ MIT License Copyright (c) 2017 Dmitri Shuralyov +Copyright (c) 2021 GitHub Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 3353795..40e8de9 100644 --- a/README.md +++ b/README.md @@ -1,19 +1,15 @@ graphql ======= -[![Build Status](https://travis-ci.org/shurcooL/graphql.svg?branch=master)](https://travis-ci.org/shurcooL/graphql) [![GoDoc](https://godoc.org/github.com/shurcooL/graphql?status.svg)](https://godoc.org/github.com/shurcooL/graphql) - -Package `graphql` provides a GraphQL client implementation. - -For more information, see package [`github.com/shurcooL/githubv4`](https://github.com/shurcooL/githubv4), which is a specialized version targeting GitHub GraphQL API v4. That package is driving the feature development. +Package `graphql` provides a GraphQL client implementation, and is forked from `https://github.com/shurcooL/graphql`. Installation ------------ -`graphql` requires Go version 1.8 or later. +`graphql` requires Go version 1.16 or later. ```bash -go get -u github.com/shurcooL/graphql +go get -u github.com/cli/shurcooL-graphql ``` Usage @@ -276,15 +272,6 @@ fmt.Printf("Created a %v star review: %v\n", m.CreateReview.Stars, m.CreateRevie // Created a 5 star review: This is a great movie! ``` -Directories ------------ - -| Path | Synopsis | -|----------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------| -| [example/graphqldev](https://godoc.org/github.com/shurcooL/graphql/example/graphqldev) | graphqldev is a test program currently being used for developing graphql package. | -| [ident](https://godoc.org/github.com/shurcooL/graphql/ident) | Package ident provides functions for parsing and converting identifier names between various naming convention. | -| [internal/jsonutil](https://godoc.org/github.com/shurcooL/graphql/internal/jsonutil) | Package jsonutil provides a function for decoding JSON into a GraphQL query data structure. | - License ------- diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..27170f5 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,3 @@ +If you discover a security issue in this repository, please submit it through the [GitHub Security Bug Bounty](https://hackerone.com/github). + +Thanks for helping make GitHub safe for everyone. diff --git a/doc.go b/doc.go deleted file mode 100644 index 870e3d4..0000000 --- a/doc.go +++ /dev/null @@ -1,8 +0,0 @@ -// Package graphql provides a GraphQL client implementation. -// -// For more information, see package github.com/shurcooL/githubv4, -// which is a specialized version targeting GitHub GraphQL API v4. -// That package is driving the feature development. -// -// For now, see README for more details. -package graphql // import "github.com/shurcooL/graphql" diff --git a/example/graphqldev/main.go b/example/graphqldev/main.go deleted file mode 100644 index ffc8302..0000000 --- a/example/graphqldev/main.go +++ /dev/null @@ -1,105 +0,0 @@ -// graphqldev is a test program currently being used for developing graphql package. -// It performs queries against a local test GraphQL server instance. -// -// It's not meant to be a clean or readable example. But it's functional. -// Better, actual examples will be created in the future. -package main - -import ( - "context" - "encoding/json" - "flag" - "log" - "net/http" - "net/http/httptest" - "os" - - graphqlserver "github.com/graph-gophers/graphql-go" - "github.com/graph-gophers/graphql-go/example/starwars" - "github.com/graph-gophers/graphql-go/relay" - "github.com/shurcooL/graphql" -) - -func main() { - flag.Parse() - - err := run() - if err != nil { - log.Println(err) - } -} - -func run() error { - // Set up a GraphQL server. - schema, err := graphqlserver.ParseSchema(starwars.Schema, &starwars.Resolver{}) - if err != nil { - return err - } - mux := http.NewServeMux() - mux.Handle("/query", &relay.Handler{Schema: schema}) - - client := graphql.NewClient("/query", &http.Client{Transport: localRoundTripper{handler: mux}}) - - /* - query { - hero { - id - name - } - character(id: "1003") { - name - friends { - name - __typename - } - appearsIn - } - } - */ - var q struct { - Hero struct { - ID graphql.ID - Name graphql.String - } - Character struct { - Name graphql.String - Friends []struct { - Name graphql.String - Typename graphql.String `graphql:"__typename"` - } - AppearsIn []graphql.String - } `graphql:"character(id: $characterID)"` - } - variables := map[string]interface{}{ - "characterID": graphql.ID("1003"), - } - err = client.Query(context.Background(), &q, variables) - if err != nil { - return err - } - print(q) - - return nil -} - -// print pretty prints v to stdout. It panics on any error. -func print(v interface{}) { - w := json.NewEncoder(os.Stdout) - w.SetIndent("", "\t") - err := w.Encode(v) - if err != nil { - panic(err) - } -} - -// localRoundTripper is an http.RoundTripper that executes HTTP transactions -// by using handler directly, instead of going over an HTTP connection. -type localRoundTripper struct { - handler http.Handler -} - -func (l localRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) { - w := httptest.NewRecorder() - l.handler.ServeHTTP(w, req) - return w.Result(), nil -} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..1d5df24 --- /dev/null +++ b/go.mod @@ -0,0 +1,5 @@ +module github.com/cli/shurcooL-graphql + +go 1.16 + +require golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..cccd595 --- /dev/null +++ b/go.sum @@ -0,0 +1,7 @@ +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 h1:CIJ76btIcR3eFI5EgSo6k1qKw9KJexJuRLI9G7Hp5wE= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/graphql.go b/graphql.go index 8520956..ecfadfb 100644 --- a/graphql.go +++ b/graphql.go @@ -7,8 +7,9 @@ import ( "fmt" "io/ioutil" "net/http" + "strings" - "github.com/shurcooL/graphql/internal/jsonutil" + "github.com/cli/shurcooL-graphql/internal/jsonutil" "golang.org/x/net/context/ctxhttp" ) @@ -32,26 +33,36 @@ func NewClient(url string, httpClient *http.Client) *Client { // Query executes a single GraphQL query request, // with a query derived from q, populating the response into it. -// q should be a pointer to struct that corresponds to the GraphQL schema. +// Argument q should be a pointer to struct that corresponds to the GraphQL schema. func (c *Client) Query(ctx context.Context, q interface{}, variables map[string]interface{}) error { - return c.do(ctx, queryOperation, q, variables) + return c.do(ctx, queryOperation, q, variables, "") +} + +// QueryNamed is the same as Query but allows a name to be specified for the query. +func (c *Client) QueryNamed(ctx context.Context, queryName string, q interface{}, variables map[string]interface{}) error { + return c.do(ctx, queryOperation, q, variables, queryName) } // Mutate executes a single GraphQL mutation request, // with a mutation derived from m, populating the response into it. -// m should be a pointer to struct that corresponds to the GraphQL schema. +// Argument m should be a pointer to struct that corresponds to the GraphQL schema. func (c *Client) Mutate(ctx context.Context, m interface{}, variables map[string]interface{}) error { - return c.do(ctx, mutationOperation, m, variables) + return c.do(ctx, mutationOperation, m, variables, "") +} + +// MutateNamed is the same as Mutate but allows a name to be specified for the mutation. +func (c *Client) MutateNamed(ctx context.Context, queryName string, m interface{}, variables map[string]interface{}) error { + return c.do(ctx, mutationOperation, m, variables, queryName) } // do executes a single GraphQL operation. -func (c *Client) do(ctx context.Context, op operationType, v interface{}, variables map[string]interface{}) error { +func (c *Client) do(ctx context.Context, op operationType, v interface{}, variables map[string]interface{}, queryName string) error { var query string switch op { case queryOperation: - query = constructQuery(v, variables) + query = constructQuery(v, variables, queryName) case mutationOperation: - query = constructMutation(v, variables) + query = constructMutation(v, variables, queryName) } in := struct { Query string `json:"query"` @@ -111,7 +122,11 @@ type errors []struct { // Error implements error interface. func (e errors) Error() string { - return e[0].Message + b := strings.Builder{} + for _, err := range e { + b.WriteString(fmt.Sprintf("Message: %s, Locations: %+v", err.Message, err.Locations)) + } + return b.String() } type operationType uint8 @@ -119,5 +134,4 @@ type operationType uint8 const ( queryOperation operationType = iota mutationOperation - //subscriptionOperation // Unused. ) diff --git a/graphql_test.go b/graphql_test.go index e09dcc9..2fb7722 100644 --- a/graphql_test.go +++ b/graphql_test.go @@ -8,7 +8,7 @@ import ( "net/http/httptest" "testing" - "github.com/shurcooL/graphql" + graphql "github.com/cli/shurcooL-graphql" ) func TestClient_Query_partialDataWithErrorResponse(t *testing.T) { @@ -53,7 +53,7 @@ func TestClient_Query_partialDataWithErrorResponse(t *testing.T) { if err == nil { t.Fatal("got error: nil, want: non-nil") } - if got, want := err.Error(), "Could not resolve to a node with the global id of 'NotExist'"; got != want { + if got, want := err.Error(), "Message: Could not resolve to a node with the global id of 'NotExist', Locations: [{Line:10 Column:4}]"; got != want { t.Errorf("got error: %v, want: %v", got, want) } if q.Node1 == nil || q.Node1.ID != "MDEyOklzc3VlQ29tbWVudDE2OTQwNzk0Ng==" { @@ -93,7 +93,7 @@ func TestClient_Query_noDataWithErrorResponse(t *testing.T) { if err == nil { t.Fatal("got error: nil, want: non-nil") } - if got, want := err.Error(), "Field 'user' is missing required arguments: login"; got != want { + if got, want := err.Error(), "Message: Field 'user' is missing required arguments: login, Locations: [{Line:7 Column:3}]"; got != want { t.Errorf("got error: %v, want: %v", got, want) } if q.User.Name != "" { diff --git a/ident/ident_test.go b/ident/ident_test.go index 9ee1b47..b6487a8 100644 --- a/ident/ident_test.go +++ b/ident/ident_test.go @@ -5,7 +5,7 @@ import ( "reflect" "testing" - "github.com/shurcooL/graphql/ident" + "github.com/cli/shurcooL-graphql/ident" ) func Example_lowerCamelCaseToMixedCaps() { diff --git a/internal/jsonutil/benchmark_test.go b/internal/jsonutil/benchmark_test.go index f8788b1..c803530 100644 --- a/internal/jsonutil/benchmark_test.go +++ b/internal/jsonutil/benchmark_test.go @@ -8,8 +8,8 @@ import ( "testing" "time" - "github.com/shurcooL/graphql" - "github.com/shurcooL/graphql/internal/jsonutil" + "github.com/cli/shurcooL-graphql" + "github.com/cli/shurcooL-graphql/internal/jsonutil" ) func TestUnmarshalGraphQL_benchmark(t *testing.T) { diff --git a/internal/jsonutil/graphql.go b/internal/jsonutil/graphql.go index 15bae24..1f165fd 100644 --- a/internal/jsonutil/graphql.go +++ b/internal/jsonutil/graphql.go @@ -300,7 +300,7 @@ func isGraphQLFragment(f reflect.StructField) bool { } // unmarshalValue unmarshals JSON value into v. -// v must be addressable and not obtained by the use of unexported +// Argument v must be addressable and not obtained by the use of unexported // struct fields, otherwise unmarshalValue will panic. func unmarshalValue(value json.Token, v reflect.Value) error { b, err := json.Marshal(value) // TODO: Short-circuit (if profiling says it's worth it). diff --git a/internal/jsonutil/graphql_test.go b/internal/jsonutil/graphql_test.go index 6329ed8..1c92965 100644 --- a/internal/jsonutil/graphql_test.go +++ b/internal/jsonutil/graphql_test.go @@ -5,8 +5,8 @@ import ( "testing" "time" - "github.com/shurcooL/graphql" - "github.com/shurcooL/graphql/internal/jsonutil" + "github.com/cli/shurcooL-graphql" + "github.com/cli/shurcooL-graphql/internal/jsonutil" ) func TestUnmarshalGraphQL(t *testing.T) { @@ -243,7 +243,7 @@ func TestUnmarshalGraphQL_pointerWithInlineFragment(t *testing.T) { func TestUnmarshalGraphQL_unexportedField(t *testing.T) { type query struct { - foo graphql.String + foo graphql.String //nolint } err := jsonutil.UnmarshalGraphQL([]byte(`{"foo": "bar"}`), new(query)) if err == nil { diff --git a/query.go b/query.go index e10b771..0d04b04 100644 --- a/query.go +++ b/query.go @@ -7,23 +7,32 @@ import ( "reflect" "sort" - "github.com/shurcooL/graphql/ident" + "github.com/cli/shurcooL-graphql/ident" ) -func constructQuery(v interface{}, variables map[string]interface{}) string { +func constructQuery(v interface{}, variables map[string]interface{}, queryName string) string { query := query(v) if len(variables) > 0 { - return "query(" + queryArguments(variables) + ")" + query + return "query" + queryNameFormat(queryName) + "(" + queryArguments(variables) + ")" + query + } else if queryName != "" { + return "query" + queryNameFormat(queryName) + query } return query } -func constructMutation(v interface{}, variables map[string]interface{}) string { +func constructMutation(v interface{}, variables map[string]interface{}, queryName string) string { query := query(v) if len(variables) > 0 { - return "mutation(" + queryArguments(variables) + ")" + query + return "mutation" + queryNameFormat(queryName) + "(" + queryArguments(variables) + ")" + query } - return "mutation" + query + return "mutation" + queryNameFormat(queryName) + query +} + +func queryNameFormat(n string) string { + if n != "" { + return " " + n + } + return n } // queryArguments constructs a minified arguments string for variables. @@ -40,9 +49,9 @@ func queryArguments(variables map[string]interface{}) string { var buf bytes.Buffer for _, k := range keys { - io.WriteString(&buf, "$") - io.WriteString(&buf, k) - io.WriteString(&buf, ":") + _, _ = io.WriteString(&buf, "$") + _, _ = io.WriteString(&buf, k) + _, _ = io.WriteString(&buf, ":") writeArgumentType(&buf, reflect.TypeOf(variables[k]), true) // Don't insert a comma here. // Commas in GraphQL are insignificant, and we want minified output. @@ -52,7 +61,7 @@ func queryArguments(variables map[string]interface{}) string { } // writeArgumentType writes a minified GraphQL type for t to w. -// value indicates whether t is a value (required) type or pointer (optional) type. +// Argument value indicates whether t is a value (required) type or pointer (optional) type. // If value is true, then "!" is written at the end of t. func writeArgumentType(w io.Writer, t reflect.Type, value bool) { if t.Kind() == reflect.Ptr { @@ -64,21 +73,21 @@ func writeArgumentType(w io.Writer, t reflect.Type, value bool) { switch t.Kind() { case reflect.Slice, reflect.Array: // List. E.g., "[Int]". - io.WriteString(w, "[") + _, _ = io.WriteString(w, "[") writeArgumentType(w, t.Elem(), true) - io.WriteString(w, "]") + _, _ = io.WriteString(w, "]") default: // Named type. E.g., "Int". name := t.Name() if name == "string" { // HACK: Workaround for https://github.com/shurcooL/githubv4/issues/12. name = "ID" } - io.WriteString(w, name) + _, _ = io.WriteString(w, name) } if value { // Value is a required type, so add "!" to the end. - io.WriteString(w, "!") + _, _ = io.WriteString(w, "!") } } @@ -104,26 +113,26 @@ func writeQuery(w io.Writer, t reflect.Type, inline bool) { return } if !inline { - io.WriteString(w, "{") + _, _ = io.WriteString(w, "{") } for i := 0; i < t.NumField(); i++ { if i != 0 { - io.WriteString(w, ",") + _, _ = io.WriteString(w, ",") } f := t.Field(i) value, ok := f.Tag.Lookup("graphql") inlineField := f.Anonymous && !ok if !inlineField { if ok { - io.WriteString(w, value) + _, _ = io.WriteString(w, value) } else { - io.WriteString(w, ident.ParseMixedCaps(f.Name).ToLowerCamelCase()) + _, _ = io.WriteString(w, ident.ParseMixedCaps(f.Name).ToLowerCamelCase()) } } writeQuery(w, f.Type, inlineField) } if !inline { - io.WriteString(w, "}") + _, _ = io.WriteString(w, "}") } } } diff --git a/query_test.go b/query_test.go index 4de8cb5..c290d91 100644 --- a/query_test.go +++ b/query_test.go @@ -229,7 +229,7 @@ func TestConstructQuery(t *testing.T) { }, } for _, tc := range tests { - got := constructQuery(tc.inV, tc.inVariables) + got := constructQuery(tc.inV, tc.inVariables, "") if got != tc.want { t.Errorf("\ngot: %q\nwant: %q\n", got, tc.want) } @@ -264,7 +264,7 @@ func TestConstructMutation(t *testing.T) { }, } for _, tc := range tests { - got := constructMutation(tc.inV, tc.inVariables) + got := constructMutation(tc.inV, tc.inVariables, "") if got != tc.want { t.Errorf("\ngot: %q\nwant: %q\n", got, tc.want) } diff --git a/scalar_test.go b/scalar_test.go index 8334b96..b91fcf5 100644 --- a/scalar_test.go +++ b/scalar_test.go @@ -3,7 +3,7 @@ package graphql_test import ( "testing" - "github.com/shurcooL/graphql" + "github.com/cli/shurcooL-graphql" ) func TestNewScalars(t *testing.T) { From 80d14c0896a6245803d8f183b865badb683482c9 Mon Sep 17 00:00:00 2001 From: Sam Coe Date: Wed, 17 Nov 2021 09:03:42 -0800 Subject: [PATCH 2/3] Address PR comments --- .github/CODE-OF-CONDUCT.md | 133 ------------------------------------- .github/CONTRIBUTING.md | 48 ------------- .github/workflows/lint.yml | 6 +- LICENSE | 1 - SECURITY.md | 3 - 5 files changed, 1 insertion(+), 190 deletions(-) delete mode 100644 .github/CODE-OF-CONDUCT.md delete mode 100644 .github/CONTRIBUTING.md delete mode 100644 SECURITY.md diff --git a/.github/CODE-OF-CONDUCT.md b/.github/CODE-OF-CONDUCT.md deleted file mode 100644 index 322065b..0000000 --- a/.github/CODE-OF-CONDUCT.md +++ /dev/null @@ -1,133 +0,0 @@ - -# Contributor Covenant Code of Conduct - -## Our Pledge - -We as members, contributors, and leaders pledge to make participation in our -community a harassment-free experience for everyone, regardless of age, body -size, visible or invisible disability, ethnicity, sex characteristics, gender -identity and expression, level of experience, education, socio-economic status, -nationality, personal appearance, race, caste, color, religion, or sexual identity -and orientation. - -We pledge to act and interact in ways that contribute to an open, welcoming, -diverse, inclusive, and healthy community. - -## Our Standards - -Examples of behavior that contributes to a positive environment for our -community include: - -* Demonstrating empathy and kindness toward other people -* Being respectful of differing opinions, viewpoints, and experiences -* Giving and gracefully accepting constructive feedback -* Accepting responsibility and apologizing to those affected by our mistakes, - and learning from the experience -* Focusing on what is best not just for us as individuals, but for the - overall community - -Examples of unacceptable behavior include: - -* The use of sexualized language or imagery, and sexual attention or - advances of any kind -* Trolling, insulting or derogatory comments, and personal or political attacks -* Public or private harassment -* Publishing others' private information, such as a physical or email - address, without their explicit permission -* Other conduct which could reasonably be considered inappropriate in a - professional setting - -## Enforcement Responsibilities - -Community leaders are responsible for clarifying and enforcing our standards of -acceptable behavior and will take appropriate and fair corrective action in -response to any behavior that they deem inappropriate, threatening, offensive, -or harmful. - -Community leaders have the right and responsibility to remove, edit, or reject -comments, commits, code, wiki edits, issues, and other contributions that are -not aligned to this Code of Conduct, and will communicate reasons for moderation -decisions when appropriate. - -## Scope - -This Code of Conduct applies within all community spaces, and also applies when -an individual is officially representing the community in public spaces. -Examples of representing our community include using an official e-mail address, -posting via an official social media account, or acting as an appointed -representative at an online or offline event. - -## Enforcement - -Instances of abusive, harassing, or otherwise unacceptable behavior may be -reported to the community leaders responsible for enforcement at -opensource@github.com. -All complaints will be reviewed and investigated promptly and fairly. - -All community leaders are obligated to respect the privacy and security of the -reporter of any incident. - -## Enforcement Guidelines - -Community leaders will follow these Community Impact Guidelines in determining -the consequences for any action they deem in violation of this Code of Conduct: - -### 1. Correction - -**Community Impact**: Use of inappropriate language or other behavior deemed -unprofessional or unwelcome in the community. - -**Consequence**: A private, written warning from community leaders, providing -clarity around the nature of the violation and an explanation of why the -behavior was inappropriate. A public apology may be requested. - -### 2. Warning - -**Community Impact**: A violation through a single incident or series -of actions. - -**Consequence**: A warning with consequences for continued behavior. No -interaction with the people involved, including unsolicited interaction with -those enforcing the Code of Conduct, for a specified period of time. This -includes avoiding interactions in community spaces as well as external channels -like social media. Violating these terms may lead to a temporary or -permanent ban. - -### 3. Temporary Ban - -**Community Impact**: A serious violation of community standards, including -sustained inappropriate behavior. - -**Consequence**: A temporary ban from any sort of interaction or public -communication with the community for a specified period of time. No public or -private interaction with the people involved, including unsolicited interaction -with those enforcing the Code of Conduct, is allowed during this period. -Violating these terms may lead to a permanent ban. - -### 4. Permanent Ban - -**Community Impact**: Demonstrating a pattern of violation of community -standards, including sustained inappropriate behavior, harassment of an -individual, or aggression toward or disparagement of classes of individuals. - -**Consequence**: A permanent ban from any sort of public interaction within -the community. - -## Attribution - -This Code of Conduct is adapted from the [Contributor Covenant][homepage], -version 2.1, available at -[https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1]. - -Community Impact Guidelines were inspired by -[Mozilla's code of conduct enforcement ladder][Mozilla CoC]. - -For answers to common questions about this code of conduct, see the FAQ at -[https://www.contributor-covenant.org/faq][FAQ]. Translations are available -at [https://www.contributor-covenant.org/translations][translations]. - -[homepage]: https://www.contributor-covenant.org -[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html -[Mozilla CoC]: https://github.com/mozilla/diversity -[FAQ]: https://www.contributor-covenant.org/faq -[translations]: https://www.contributor-covenant.org/translations diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md deleted file mode 100644 index a4336f6..0000000 --- a/.github/CONTRIBUTING.md +++ /dev/null @@ -1,48 +0,0 @@ -## Contributing - -Hi! Thanks for your interest in contributing to the GitHub GraphQL Client Module! - -We accept pull requests for bug fixes and features where we've discussed the approach in an issue and given the go-ahead for a community member to work on it. We'd also love to hear about ideas for new features as issues. - -Please do: - -* Check existing issues to verify that the [bug][bug issues] or [feature request][feature request issues] has not already been submitted. -* Open an issue if things aren't working as expected. -* Open an issue to propose a significant change. -* Open a pull request to fix a bug. -* Open a pull request to fix documentation. -* Open a pull request for any issue labelled [`help wanted`][hw] or [`good first issue`][gfi]. - -Please avoid: - -* Opening pull requests for issues marked `needs-design`, `needs-investigation`, or `blocked`. -* Opening pull requests for any issue marked `core`. These issues require additional context from - the core CLI team at GitHub and any external pull requests will not be accepted. - -## Submitting a pull request - -1. Create a new branch: `git checkout -b my-branch-name` -1. Make your change, add tests, and ensure tests pass -1. Submit a pull request: `gh pr create --web` - -Contributions to this project are [released][legal] to the public under the [project's open source license][license]. - -Please note that this project adheres to a [Contributor Code of Conduct][code-of-conduct]. By participating in this project you agree to abide by its terms. - -## Resources - -- [How to Contribute to Open Source][] -- [Using Pull Requests][] -- [GitHub Help][] - - -[bug issues]: https://github.com/cli/shurcooL-graphql/issues?q=is%3Aopen+is%3Aissue+label%3Abug -[feature request issues]: https://github.com/cli/shurcooL-graphql/issues?q=is%3Aopen+is%3Aissue+label%3Aenhancement -[hw]: https://github.com/cli/shurcooL-graphql/labels/help%20wanted -[gfi]: https://github.com/cli/shurcooL-graphql/labels/good%20first%20issue -[legal]: https://docs.github.com/en/free-pro-team@latest/github/site-policy/github-terms-of-service#6-contributions-under-repository-license -[license]: ../LICENSE -[code-of-conduct]: ./CODE-OF-CONDUCT.md -[How to Contribute to Open Source]: https://opensource.guide/how-to-contribute/ -[Using Pull Requests]: https://docs.github.com/en/free-pro-team@latest/github/collaborating-with-issues-and-pull-requests/about-pull-requests -[GitHub Help]: https://docs.github.com/ diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 6c13706..3c84b5e 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -2,11 +2,7 @@ name: Lint on: [push, pull_request] jobs: lint: - strategy: - matrix: - os: [ubuntu-latest] - go: [1.16] - runs-on: ${{ matrix.os }} + runs-on: ubuntu-latest steps: - name: Checkout code diff --git a/LICENSE b/LICENSE index c3f4bb7..ca4c776 100644 --- a/LICENSE +++ b/LICENSE @@ -1,7 +1,6 @@ MIT License Copyright (c) 2017 Dmitri Shuralyov -Copyright (c) 2021 GitHub Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/SECURITY.md b/SECURITY.md deleted file mode 100644 index 27170f5..0000000 --- a/SECURITY.md +++ /dev/null @@ -1,3 +0,0 @@ -If you discover a security issue in this repository, please submit it through the [GitHub Security Bug Bounty](https://hackerone.com/github). - -Thanks for helping make GitHub safe for everyone. From 641d414e31085b475814db4b83e5227ab7e5c77b Mon Sep 17 00:00:00 2001 From: Sam Coe Date: Wed, 17 Nov 2021 09:47:01 -0800 Subject: [PATCH 3/3] Separate errors with new line --- graphql.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/graphql.go b/graphql.go index ecfadfb..06ca511 100644 --- a/graphql.go +++ b/graphql.go @@ -123,8 +123,12 @@ type errors []struct { // Error implements error interface. func (e errors) Error() string { b := strings.Builder{} - for _, err := range e { + l := len(e) + for i, err := range e { b.WriteString(fmt.Sprintf("Message: %s, Locations: %+v", err.Message, err.Locations)) + if i != l-1 { + b.WriteString("\n") + } } return b.String() }