Skip to content

Commit

Permalink
fixup! fixup! fixup! Add an option to create draft pull requests
Browse files Browse the repository at this point in the history
  • Loading branch information
Thibault Jamet committed Mar 14, 2024
1 parent ada2686 commit 5051cbf
Show file tree
Hide file tree
Showing 5 changed files with 83 additions and 36 deletions.
17 changes: 9 additions & 8 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,6 @@ go 1.22

require (
github.com/99designs/keyring v1.2.2
// Unfortunately, there is no way, with the REST API to mark a PR as ready.
// see https://docs.github.com/en/rest/pulls/pulls?apiVersion=2022-11-28#update-a-pull-request
// Instead, we must use the graphQL client and in particular, for which there is a dedicated function in
// the official GitHub CLI client.
github.com/cli/cli/v2 v2.45.0
github.com/go-git/go-git/v5 v5.11.0
github.com/google/go-github/v55 v55.0.0
github.com/google/uuid v1.4.0
Expand All @@ -24,6 +19,15 @@ require (
golang.org/x/oauth2 v0.18.0
)

require (
// Unfortunately, there is no way, with the REST API to mark a PR as ready.
// see https://docs.github.com/en/rest/pulls/pulls?apiVersion=2022-11-28#update-a-pull-request
// Instead, we must use the graphQL client and in particular, for which there is a dedicated function in
// the official GitHub CLI client.
github.com/cli/go-gh/v2 v2.6.0
github.com/shurcooL/githubv4 v0.0.0-20230704064427-599ae7bbf278
)

require (
dario.cat/mergo v1.0.0 // indirect
github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect
Expand All @@ -36,7 +40,6 @@ require (
github.com/antchfx/xpath v1.2.0 // indirect
github.com/aymanbagabas/go-osc52 v1.0.3 // indirect
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e // indirect
github.com/cli/go-gh/v2 v2.6.0 // indirect
github.com/cli/safeexec v1.0.1 // indirect
github.com/cli/shurcooL-graphql v0.0.4 // indirect
github.com/cloudflare/circl v1.3.7 // indirect
Expand Down Expand Up @@ -69,7 +72,6 @@ require (
github.com/rivo/uniseg v0.4.4 // indirect
github.com/saintfish/chardet v0.0.0-20120816061221-3af4cd4741ca // indirect
github.com/sergi/go-diff v1.2.0 // indirect
github.com/shurcooL/githubv4 v0.0.0-20230704064427-599ae7bbf278 // indirect
github.com/shurcooL/graphql v0.0.0-20230722043721-ed46e5a46466 // indirect
github.com/skeema/knownhosts v1.2.1 // indirect
github.com/spf13/pflag v1.0.5 // indirect
Expand All @@ -78,7 +80,6 @@ require (
github.com/xanzy/ssh-agent v0.3.3 // indirect
golang.org/x/crypto v0.21.0 // indirect
golang.org/x/net v0.22.0 // indirect
golang.org/x/sync v0.5.0 // indirect
golang.org/x/sys v0.18.0 // indirect
golang.org/x/term v0.18.0 // indirect
golang.org/x/text v0.14.0 // indirect
Expand Down
14 changes: 0 additions & 14 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@ github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4/go.mod h1:hN
github.com/99designs/keyring v1.2.2 h1:pZd3neh/EmUzWONb35LxQfvuY7kiSXAq3HQd97+XBn0=
github.com/99designs/keyring v1.2.2/go.mod h1:wes/FrByc8j7lFOAGLGSNEg8f/PaI3cgTBqhFkHUrPk=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ=
github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE=
github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY=
github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow=
github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM=
Expand Down Expand Up @@ -37,8 +35,6 @@ github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPd
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
github.com/aymanbagabas/go-osc52 v1.0.3 h1:DTwqENW7X9arYimJrPeGZcV0ln14sGMt3pHZspWD+Mg=
github.com/aymanbagabas/go-osc52 v1.0.3/go.mod h1:zT8H+Rk4VSabYN90pWyugflM3ZhpTZNC7cASDfUCdT4=
github.com/briandowns/spinner v1.18.1 h1:yhQmQtM1zsqFsouh09Bk/jCjd50pC3EOGsh28gLVvwY=
github.com/briandowns/spinner v1.18.1/go.mod h1:mQak9GHqbspjC/5iUx3qMlIho8xBS/ppAL/hX5SmPJU=
github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/chzyer/logex v1.1.10 h1:Swpa1K6QvQznwJRcfTfQJmTE72DqScAa40E+fbHEXEE=
Expand All @@ -47,8 +43,6 @@ github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e h1:fY5BOSpyZCqRo5O
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1 h1:q763qf9huN11kDQavWsoZXJNW3xEE4JJyHa5Q25/sd8=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/cli/cli/v2 v2.45.0 h1:UBpGje0zISr4lPD5rBNLQ4NVAgy6k2m0eIVGFuGwt1A=
github.com/cli/cli/v2 v2.45.0/go.mod h1:mJJF+z326j4Po1qLclaVW8Cu25MFXy91J/f3b9+TYfs=
github.com/cli/go-gh/v2 v2.6.0 h1:1zXwr7mW6JDCPwXQLLtCdKnp+pNc7ZixyDeLpM1pf9I=
github.com/cli/go-gh/v2 v2.6.0/go.mod h1:h3salfqqooVpzKmHp6aUdeNx62UmxQRpLbagFSHTJGQ=
github.com/cli/safeexec v1.0.1 h1:e/C79PbXF4yYTN/wauC4tviMxEV13BwljGj0N9j+N00=
Expand All @@ -75,8 +69,6 @@ github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc
github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/gliderlabs/ssh v0.3.5 h1:OcaySEmAQJgyYcArR+gGGTHCyE7nvhEMTlYY+Dp8CpY=
github.com/gliderlabs/ssh v0.3.5/go.mod h1:8XB4KraRrX39qHhT6yxPsHedjA08I/uBVwj4xC+/+z4=
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI=
Expand Down Expand Up @@ -124,8 +116,6 @@ github.com/google/go-github/v55 v55.0.0 h1:4pp/1tNMB9X/LuAhs5i0KQAE40NmiR/y6prLN
github.com/google/go-github/v55 v55.0.0/go.mod h1:JLahOTA1DnXzhxEymmFF5PP2tSS9JVNj68mSZNDwskA=
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4=
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=
github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4=
github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c h1:6rhixN/i8ZofjG1Y75iExal34USq5p+wiN1tpie8IrU=
Expand Down Expand Up @@ -158,15 +148,11 @@ github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69
github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
github.com/manifoldco/promptui v0.9.0 h1:3V4HzJk1TtXW1MTZMP7mdlwbBpIinw3HztaIlYthEiA=
github.com/manifoldco/promptui v0.9.0/go.mod h1:ka04sppxSGFAtxX0qhlYQjISsg9mR4GWtQEhdbn6Pgg=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU=
github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d h1:5PJl274Y63IEHC+7izoQE9x6ikvDFZS2mDVS3drnohI=
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
github.com/mtibben/percent v0.2.1 h1:5gssi8Nqo8QU/r2pynCm+hBQHpkB/uNK7BJCFogWdzs=
github.com/mtibben/percent v0.2.1/go.mod h1:KG9uO+SZkUp+VkRHsCdYQV3XSZrrSpR3O9ibNBTZrns=
github.com/muesli/termenv v0.13.0 h1:wK20DRpJdDX8b7Ek2QfhvqhRQFZ237RGRO0RQ/Iqdy0=
Expand Down
45 changes: 36 additions & 9 deletions pkg/api/github.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,22 @@ import (
"context"
"errors"
"fmt"
"net/http"
"net/url"
"strconv"
"strings"

gh "github.com/adevinta/maiao/pkg/github"
"github.com/adevinta/maiao/pkg/log"
"github.com/cli/cli/v2/api"
"github.com/cli/go-gh/v2/pkg/api"
"github.com/go-git/go-git/v5/plumbing/transport"
"github.com/google/go-github/v55/github"
"github.com/shurcooL/githubv4"
"github.com/sirupsen/logrus"
)

// GitHub implements the PullRequester interface allowing to create pull requests for a given repository
type GitHub struct {
httpClient *http.Client
GraphQLClient *api.GraphQLClient
*github.Client
Host string
Owner string
Expand Down Expand Up @@ -127,10 +127,27 @@ func (g *GitHub) Update(ctx context.Context, pr *PullRequest, options PullReques
log.ForContext(ctx).Info("edit pull request")
if options.Ready {
log.ForContext(ctx).Info("marking pull request as ready")

var mutation struct {
MarkPullRequestReadyForReview struct {
PullRequest struct {
ID githubv4.ID
}
} `graphql:"markPullRequestReadyForReview(input: $input)"`
}

variables := map[string]interface{}{
"input": githubv4.MarkPullRequestReadyForReviewInput{
// https://github.blog/changelog/2018-05-30-end-jean-grey-preview/
// The NodeID seems to be the pivot between the REST API and the graphQL API
PullRequestID: p.GetNodeID(),
},
}

// Unfortunately, there is no way, with the REST API to mark a PR as ready.
// see https://docs.github.com/en/rest/pulls/pulls?apiVersion=2022-11-28#update-a-pull-request
// Instead, use the graphQL client and in particular, use the github cli implementation
err = api.PullRequestReady(api.NewClientFromHTTP(g.httpClient), g, &api.PullRequest{ID: pr.ID})
err = g.GraphQLClient.Mutate("PullRequestReadyForReview", &mutation, variables)
if err != nil {
log.ForContext(ctx).WithError(err).Error("failed to mark pull request as ready")
return nil, err
Expand Down Expand Up @@ -173,6 +190,10 @@ func NewGitHubUpserter(ctx context.Context, endpoint *transport.Endpoint) (*GitH
return nil, fmt.Errorf("invalid repository, expecting <org>/<repo>")
}
httpClient, err := gh.NewHTTPClientForDomain(ctx, endpoint.Host)
if err != nil {
log.ForContext(ctx).WithError(err).Errorf("failed to create a new http client: %s", err.Error())
return nil, err
}
client, err := gh.NewClient(httpClient, endpoint.Host)
if err != nil {
log.ForContext(ctx).WithError(err).Errorf("failed to create a new github client: %s", err.Error())
Expand All @@ -183,12 +204,18 @@ func NewGitHubUpserter(ctx context.Context, endpoint *transport.Endpoint) (*GitH
return nil, err
}

graphQLClient, err := gh.NewGraphQLClient(httpClient, endpoint.Host)
if err != nil {
log.ForContext(ctx).WithError(err).Errorf("failed to create a new github graphQL client: %s", err.Error())
return nil, err
}

gh := &GitHub{
Host: endpoint.Host,
Owner: repo.GetOwner().GetLogin(),
Repository: repo.GetName(),
Client: client,
httpClient: httpClient,
Host: endpoint.Host,
Owner: repo.GetOwner().GetLogin(),
Repository: repo.GetName(),
Client: client,
GraphQLClient: graphQLClient,
}
log.ForContext(ctx).Trace("initialized github client")
return gh, nil
Expand Down
27 changes: 23 additions & 4 deletions pkg/github/github.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,21 @@ import (
"net/url"

"github.com/adevinta/maiao/pkg/log"
"github.com/cli/go-gh/v2/pkg/api"
"github.com/google/go-github/v55/github"
"github.com/sirupsen/logrus"
"golang.org/x/oauth2"
)

func NewHTTPClientForDomain(ctx context.Context, domain string) (*http.Client, error) {
func GitHubAPIDomain(domain string) string {
if domain == "github.com" {
domain = "api.github.com"
return "api.github.com"
}
return domain
}

func NewHTTPClientForDomain(ctx context.Context, domain string) (*http.Client, error) {
domain = GitHubAPIDomain(domain)
// TODO: move this to handle unauthorized calls.
token, err := getGithubToken(domain)
if err != nil {
Expand All @@ -29,6 +35,19 @@ func NewHTTPClientForDomain(ctx context.Context, domain string) (*http.Client, e
return tc, nil
}

func NewGraphQLClient(httpClient *http.Client, domain string) (*api.GraphQLClient, error) {
opts := api.ClientOptions{
AuthToken: "overridden by Transport",
Host: GitHubAPIDomain(domain),
Transport: httpClient.Transport,
}
client, err := api.NewGraphQLClient(opts)
if err != nil {
return nil, err
}
return client, nil
}

// NewClient instanciates a new github client depending on the domain name
//
// When requesting a client for a different host than github.com,
Expand All @@ -39,11 +58,11 @@ func NewHTTPClientForDomain(ctx context.Context, domain string) (*http.Client, e
func NewClient(httpClient *http.Client, domain string) (*github.Client, error) {
c := github.NewClient(httpClient)
switch domain {
case "api.github.com", "github.com":
case "github.com", "api.github.com":
default:
GitHubURL := url.URL{
Scheme: "https",
Host: domain,
Host: GitHubAPIDomain(domain),
Path: "/api/v3/",
}
GitHubUploadURL := GitHubURL
Expand Down
16 changes: 15 additions & 1 deletion pkg/github/github_test.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
package gh

import (
"context"
"os"
"testing"

"github.com/stretchr/testify/assert"
"github.com/adevinta/maiao/pkg/credentials"
"github.com/adevinta/maiao/pkg/system"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func setCredentialStore(c credentials.CredentialGetter) {
Expand All @@ -19,6 +21,18 @@ type TestCredentialGetter struct {
Check func()
}

func TestNewGraphQLClient(t *testing.T) {
t.Setenv("GITHUB_TOKEN", "test")
ctx := context.Background()
httpClient, err := NewHTTPClientForDomain(ctx, "github.com")
require.NoError(t, err)
graphQLClient, err := NewGraphQLClient(httpClient, "github.com")

assert.NoError(t, err)
assert.NotNil(t, graphQLClient)

}

func (c *TestCredentialGetter) CredentialForHost(string) (*credentials.Credentials, error) {
if c.Check != nil {
c.Check()
Expand Down

0 comments on commit 5051cbf

Please sign in to comment.