From 2c25dba61f469d4c654ffc7b8f0a64f8b3371c1f Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Mon, 6 May 2024 17:39:43 +0200 Subject: [PATCH] feat: codegen the context from GraphQL schema (#4) * feat: codegen the context from GraphQL schema * fix: use 'task seutp' in golangci-lint linter * fix: use 'task seutp' in govulncheck * fix: remove dependcy check * ci: test scm-engine against live gitlab project * fix: change go module name to scm-engine * fix: 'go::test' example should only trigger if Go files are changed * ci: reduce steps in ci 'build' step --- .github/workflows/build.yml | 51 ++++---- .github/workflows/dependency-review.yml | 21 ---- .github/workflows/lint.yml | 8 ++ .gitignore | 3 +- .goreleaser.yaml | 2 +- .scm-engine.example.yml | 4 +- README.md | 2 +- Taskfile.yml | 2 + cmd/cmd_evaluate.go | 6 +- cmd/shared.go | 6 +- go.mod | 11 +- go.sum | 40 ++++++- main.go | 2 +- pkg/config/config.go | 2 +- pkg/config/label.go | 8 +- pkg/scm/gitlab/client.go | 2 +- pkg/scm/gitlab/client_helpers.go | 2 +- pkg/scm/gitlab/client_label.go | 4 +- pkg/scm/gitlab/client_merge_request.go | 4 +- pkg/scm/gitlab/context.go | 27 ++--- pkg/scm/gitlab/context_commit.go | 12 -- pkg/scm/gitlab/context_group.go | 7 -- pkg/scm/gitlab/context_label.go | 12 -- pkg/scm/gitlab/context_merge_request.go | 41 ------- .../gitlab/context_merge_request_diff_stat.go | 7 -- pkg/scm/gitlab/context_project.go | 23 ---- pkg/scm/interfaces.go | 1 - pkg/scm/types.go | 2 +- schema/gitlab/generate.go | 3 + schema/gitlab/gqlgen.yml | 90 ++++++++++++++ schema/gitlab/main.go | 111 ++++++++++++++++++ schema/gitlab/schema.graphqls | 110 +++++++++++++++++ tools.go | 11 ++ 33 files changed, 447 insertions(+), 190 deletions(-) delete mode 100644 .github/workflows/dependency-review.yml delete mode 100644 pkg/scm/gitlab/context_commit.go delete mode 100644 pkg/scm/gitlab/context_group.go delete mode 100644 pkg/scm/gitlab/context_label.go delete mode 100644 pkg/scm/gitlab/context_merge_request_diff_stat.go delete mode 100644 pkg/scm/gitlab/context_project.go create mode 100644 schema/gitlab/generate.go create mode 100644 schema/gitlab/gqlgen.yml create mode 100644 schema/gitlab/main.go create mode 100644 schema/gitlab/schema.graphqls create mode 100644 tools.go diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f0bcd58..2f955fc 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -28,6 +28,14 @@ jobs: with: go-version-file: go.mod + - uses: arduino/setup-task@v2 + with: + version: 3.x + repo-token: ${{ secrets.GITHUB_TOKEN }} + + - name: setup + run: task setup + - name: install govulncheck run: go install golang.org/x/vuln/cmd/govulncheck@latest @@ -66,37 +74,22 @@ jobs: with: fetch-depth: 0 - - uses: arduino/setup-task@v2 - with: - version: 3.x - repo-token: ${{ secrets.GITHUB_TOKEN }} - - - uses: docker/setup-qemu-action@v3 + # - uses: docker/setup-qemu-action@v3 - - uses: docker/setup-buildx-action@v3 - - - name: setup-snapcraft - # FIXME: the mkdirs are a hack for https://github.com/goreleaser/goreleaser/issues/1715 - run: | - sudo apt-get update - sudo apt-get -yq --no-install-suggests --no-install-recommends install snapcraft - mkdir -p $HOME/.cache/snapcraft/download - mkdir -p $HOME/.cache/snapcraft/stage-packages + # - uses: docker/setup-buildx-action@v3 - uses: actions/setup-go@v5 with: go-version-file: go.mod - - uses: sigstore/cosign-installer@v3.5.0 - - - uses: anchore/sbom-action/download-syft@v0.15.11 - - - name: setup-validate-krew-manifest - run: go install sigs.k8s.io/krew/cmd/validate-krew-manifest@latest - - name: setup-tparse run: go install github.com/mfridman/tparse@latest + - uses: arduino/setup-task@v2 + with: + version: 3.x + repo-token: ${{ secrets.GITHUB_TOKEN }} + - name: setup run: | task setup @@ -110,6 +103,16 @@ jobs: with: token: ${{ secrets.CODECOV_TOKEN }} - - run: ./scm-engine -h + - name: Ensure scm-engine binary work + run: ./scm-engine -h + + - name: Test scm-engine against test GitLab project + run: ./scm-engine evaluate 1 + env: + SCM_ENGINE_CONFIG_FILE: ".scm-engine.example.yml" + SCM_ENGINE_TOKEN: "${{ secrets.GITLAB_INTEGRATION_TEST_API_TOKEN }}" + GITLAB_PROJECT: "jippi/scm-engine-schema-test" + GITLAB_BASEURL: https://gitlab.com/ - - run: git diff + - name: Show any diff that may be in the project + run: git diff diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml deleted file mode 100644 index 9ae2d5e..0000000 --- a/.github/workflows/dependency-review.yml +++ /dev/null @@ -1,21 +0,0 @@ -name: Dependency Review - -on: - - pull_request - -permissions: - contents: read - -jobs: - # ------------------------------ - - dependency-review: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - - uses: actions/dependency-review-action@v4 - with: - allow-licenses: BSD-2-Clause, BSD-3-Clause, MIT, Apache-2.0, MPL-2.0 - - # ------------------------------ diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index bfbf3a2..136706c 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -32,6 +32,14 @@ jobs: go-version-file: go.mod cache: false + - uses: arduino/setup-task@v2 + with: + version: 3.x + repo-token: ${{ secrets.GITHUB_TOKEN }} + + - name: setup + run: task setup + - name: golangci-lint uses: golangci/golangci-lint-action@v5 with: diff --git a/.gitignore b/.gitignore index f018aac..d650505 100644 --- a/.gitignore +++ b/.gitignore @@ -9,8 +9,9 @@ bin/ completions/ coverage.txt dist/ +/schema/*/ignore manpages/ scm-engine scm-engine.exe - +*.gen.go !.env.example diff --git a/.goreleaser.yaml b/.goreleaser.yaml index 977568c..e60cc48 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -7,7 +7,7 @@ env: before: hooks: - - go mod tidy + - task setup # - ./scripts/completions.sh # - ./scripts/manpages.sh diff --git a/.scm-engine.example.yml b/.scm-engine.example.yml index aab9630..9fcf208 100644 --- a/.scm-engine.example.yml +++ b/.scm-engine.example.yml @@ -39,13 +39,13 @@ label: color: "$red" description: "The Merge Request did NOT modify Go test files" priority: 999 - script: not merge_request.modified_files("*_test.go") + script: not merge_request.modified_files("*_test.go") && merge_request.modified_files("*.go") - name: go::tests::OK color: "$green" description: "The Merge Request modified Go test files" priority: 999 - script: merge_request.modified_files("*_test.go") + script: merge_request.modified_files("*_test.go") && merge_request.modified_files("*.go") - name: status::age::abandoned color: "$red" diff --git a/README.md b/README.md index fd6b6fb..4a79c37 100644 --- a/README.md +++ b/README.md @@ -360,7 +360,7 @@ The `skip_if` field must be a valid [Expr-lang](https://expr-lang.org/) expressi ### Attributes > [!NOTE] -> Missing an attribute? The `pkg/scm/gitlab/context_*` files are what is used to query GitLab, adding the missing `field` to the right `struct` should make it accessible. +> Missing an attribute? The `schema/gitlab/schema.graphqls` file are what is used to query GitLab, adding the missing `field` to the right `type` should make it accessible. > Please open an issue or Pull Request if something is missing. > [!IMPORTANT] diff --git a/Taskfile.yml b/Taskfile.yml index 85e1a69..fa36a93 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -16,6 +16,7 @@ tasks: desc: Install dependencies cmds: - go mod tidy + - go generate ./... build: desc: Build the binary @@ -70,6 +71,7 @@ tasks: NEXT: sh: svu n cmds: + - task: setup - git tag {{.NEXT}} - echo {{.NEXT}} - git push origin --tags diff --git a/cmd/cmd_evaluate.go b/cmd/cmd_evaluate.go index 0686d66..f66f4a0 100644 --- a/cmd/cmd_evaluate.go +++ b/cmd/cmd_evaluate.go @@ -3,9 +3,9 @@ package cmd import ( "fmt" - "github.com/jippi/gitlab-labeller/pkg/config" - "github.com/jippi/gitlab-labeller/pkg/scm/gitlab" - "github.com/jippi/gitlab-labeller/pkg/state" + "github.com/jippi/scm-engine/pkg/config" + "github.com/jippi/scm-engine/pkg/scm/gitlab" + "github.com/jippi/scm-engine/pkg/state" "github.com/urfave/cli/v2" ) diff --git a/cmd/shared.go b/cmd/shared.go index a209980..1269d1a 100644 --- a/cmd/shared.go +++ b/cmd/shared.go @@ -5,9 +5,9 @@ import ( "fmt" "net/http" - "github.com/jippi/gitlab-labeller/pkg/config" - "github.com/jippi/gitlab-labeller/pkg/scm" - "github.com/jippi/gitlab-labeller/pkg/state" + "github.com/jippi/scm-engine/pkg/config" + "github.com/jippi/scm-engine/pkg/scm" + "github.com/jippi/scm-engine/pkg/state" ) func ProcessMR(ctx context.Context, client scm.Client, cfg *config.Config, mr string) error { diff --git a/go.mod b/go.mod index e508ff9..2fce931 100644 --- a/go.mod +++ b/go.mod @@ -1,14 +1,18 @@ -module github.com/jippi/gitlab-labeller +module github.com/jippi/scm-engine go 1.22.2 require ( + github.com/99designs/gqlgen v0.17.45 github.com/davecgh/go-spew v1.1.1 github.com/expr-lang/expr v1.16.5 + github.com/fatih/structtag v1.2.0 github.com/go-playground/webhooks/v6 v6.3.0 github.com/guregu/null/v5 v5.0.0 github.com/hasura/go-graphql-client v0.12.1 + github.com/iancoleman/strcase v0.3.0 github.com/urfave/cli/v2 v2.27.2 + github.com/vektah/gqlparser/v2 v2.5.11 github.com/xanzy/go-gitlab v0.104.0 github.com/xhit/go-str2duration/v2 v2.1.0 golang.org/x/oauth2 v0.20.0 @@ -16,13 +20,18 @@ require ( ) require ( + github.com/agnivade/levenshtein v1.1.1 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect github.com/google/go-querystring v1.1.0 // indirect github.com/google/uuid v1.6.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect github.com/hashicorp/go-retryablehttp v0.7.2 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect + github.com/sosodev/duration v1.2.0 // indirect github.com/xrash/smetrics v0.0.0-20240312152122-5f08fbb34913 // indirect + golang.org/x/mod v0.16.0 // indirect + golang.org/x/text v0.14.0 // indirect golang.org/x/time v0.3.0 // indirect + golang.org/x/tools v0.19.0 // indirect nhooyr.io/websocket v1.8.11 // indirect ) diff --git a/go.sum b/go.sum index 0908720..f4c3ae7 100644 --- a/go.sum +++ b/go.sum @@ -1,10 +1,22 @@ +github.com/99designs/gqlgen v0.17.45 h1:bH0AH67vIJo8JKNKPJP+pOPpQhZeuVRQLf53dKIpDik= +github.com/99designs/gqlgen v0.17.45/go.mod h1:Bas0XQ+Jiu/Xm5E33jC8sES3G+iC2esHBMXcq0fUPs0= +github.com/agnivade/levenshtein v1.1.1 h1:QY8M92nrzkmr798gCo3kmMyqXFzdQVpxLlGPRBij0P8= +github.com/agnivade/levenshtein v1.1.1/go.mod h1:veldBMzWxcCG2ZvUTKD2kJNRdCk5hVbJomOvKkmgYbo= +github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883 h1:bvNMNQO63//z+xNgfBlViaCIJKLlCJ6/fmUseuG0wVQ= +github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= +github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0 h1:jfIu9sQUG6Ig+0+Ap1h4unLjW6YQJpKZVmUzxsD4E/Q= +github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0/go.mod h1:t2tdKJDJF9BV14lnkjHmOQgcvEKgtqs5a1N3LNdJhGE= github.com/cpuguy83/go-md2man/v2 v2.0.4 h1:wfIWP927BUkWJb2NmU/kNDYIBTh/ziUX91+lVfRxZq4= github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dgryski/trifles v0.0.0-20200323201526-dd97f9abfb48 h1:fRzb/w+pyskVMQ+UbP35JkH8yB7MYb4q/qhBarqZE6g= +github.com/dgryski/trifles v0.0.0-20200323201526-dd97f9abfb48/go.mod h1:if7Fbed8SFyPtHLHbg49SI7NAdJiC5WIA09pe59rfAA= github.com/expr-lang/expr v1.16.5 h1:m2hvtguFeVaVNTHj8L7BoAyt7O0PAIBaSVbjdHgRXMs= github.com/expr-lang/expr v1.16.5/go.mod h1:uCkhfG+x7fcZ5A5sXHKuQ07jGZRl6J0FCAaf2k4PtVQ= +github.com/fatih/structtag v1.2.0 h1:/OdNE99OxoI/PqaW/SuSK9uxxT3f/tcSZgon/ssNSx4= +github.com/fatih/structtag v1.2.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4/aAZl94= github.com/go-playground/webhooks/v6 v6.3.0 h1:zBLUxK1Scxwi97TmZt5j/B/rLlard2zY7P77FHg58FE= github.com/go-playground/webhooks/v6 v6.3.0/go.mod h1:GCocmfMtpJdkEOM1uG9p2nXzg1kY5X/LtvQgtPHUaaA= github.com/gogits/go-gogs-client v0.0.0-20200905025246-8bb8a50cb355/go.mod h1:cY2AIrMgHm6oOHmR7jY+9TtjzSjQ3iG7tURJG3Y6XH0= @@ -15,6 +27,8 @@ github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= +github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/guregu/null/v5 v5.0.0 h1:PRxjqyOekS11W+w/7Vfz6jgJE/BCwELWtgvOJzddimw= github.com/guregu/null/v5 v5.0.0/go.mod h1:SjupzNy+sCPtwQTKWhUCqjhVCO69hpsl2QsZrWHjlwU= github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= @@ -23,32 +37,54 @@ github.com/hashicorp/go-hclog v0.9.2 h1:CG6TE5H9/JXsFWJCfoIVpKFIkFe6ysEuHirp4DxC github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= github.com/hashicorp/go-retryablehttp v0.7.2 h1:AcYqCvkpalPnPF2pn0KamgwamS42TqUDDYFRKq/RAd0= github.com/hashicorp/go-retryablehttp v0.7.2/go.mod h1:Jy/gPYAdjqffZ/yFGCFV2doI5wjtH1ewM9u8iYVjtX8= +github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= +github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= github.com/hasura/go-graphql-client v0.12.1 h1:tL+BCoyubkYYyaQ+tJz+oPe/pSxYwOJHwe5SSqqi6WI= github.com/hasura/go-graphql-client v0.12.1/go.mod h1:F4N4kR6vY8amio3gEu3tjSZr8GPOXJr3zj72DKixfLE= +github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI= +github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= +github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8= +github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I= +github.com/sosodev/duration v1.2.0 h1:pqK/FLSjsAADWY74SyWDCjOcd5l7H8GSnnOGEB9A1Us= +github.com/sosodev/duration v1.2.0/go.mod h1:RQIBBX0+fMLc/D9+Jb/fwvVmo0eZvDDEERAikUR6SDg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= -github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/urfave/cli/v2 v2.27.2 h1:6e0H+AkS+zDckwPCUrZkKX38mRaau4nL2uipkJpbkcI= github.com/urfave/cli/v2 v2.27.2/go.mod h1:g0+79LmHHATl7DAcHO99smiR/T7uGLw84w8Y42x+4eM= +github.com/vektah/gqlparser/v2 v2.5.11 h1:JJxLtXIoN7+3x6MBdtIP59TP1RANnY7pXOaDnADQSf8= +github.com/vektah/gqlparser/v2 v2.5.11/go.mod h1:1rCcfwB2ekJofmluGWXMSEnPMZgbxzwj6FaZ/4OT8Cc= github.com/xanzy/go-gitlab v0.104.0 h1:YDuuaTrNdHMuBW+FagO/W4dHvAQOqpCf2pMB45ATbog= github.com/xanzy/go-gitlab v0.104.0/go.mod h1:ETg8tcj4OhrB84UEgeE8dSuV/0h4BBL1uOV/qK0vlyI= github.com/xhit/go-str2duration/v2 v2.1.0 h1:lxklc02Drh6ynqX+DdPyp5pCKLUQpRT8bp8Ydu2Bstc= github.com/xhit/go-str2duration/v2 v2.1.0/go.mod h1:ohY8p+0f07DiV6Em5LKB0s2YpLtXVyJfNt1+BlmyAsU= github.com/xrash/smetrics v0.0.0-20240312152122-5f08fbb34913 h1:+qGGcbkzsfDQNPPe9UDgpxAWQrhbbBXOYJFQDq/dtJw= github.com/xrash/smetrics v0.0.0-20240312152122-5f08fbb34913/go.mod h1:4aEEwZQutDLsQv2Deui4iYQ6DWTxR14g6m8Wv88+Xqk= +golang.org/x/mod v0.16.0 h1:QX4fJ0Rr5cPQCF7O9lh9Se4pmwfwskqZfq5moyldzic= +golang.org/x/mod v0.16.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/oauth2 v0.20.0 h1:4mQdhULixXKP1rwYBW0vAijoXnkTG0BLCDRzfe1idMo= golang.org/x/oauth2 v0.20.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= +golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.19.0 h1:tfGCXNR1OsFG+sVdLAitlpjAvD/I6dHDKnYrpEZUHkw= +golang.org/x/tools v0.19.0/go.mod h1:qoJWxmGSIBmAeriMx19ogtrEPrGtDbPK634QFIcLAhc= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/main.go b/main.go index 5995d19..14ca7af 100644 --- a/main.go +++ b/main.go @@ -6,7 +6,7 @@ import ( "os" "github.com/davecgh/go-spew/spew" - "github.com/jippi/gitlab-labeller/cmd" + "github.com/jippi/scm-engine/cmd" "github.com/urfave/cli/v2" ) diff --git a/pkg/config/config.go b/pkg/config/config.go index aa2e10e..385696d 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -4,7 +4,7 @@ import ( "errors" "fmt" - "github.com/jippi/gitlab-labeller/pkg/scm" + "github.com/jippi/scm-engine/pkg/scm" ) type Config struct { diff --git a/pkg/config/label.go b/pkg/config/label.go index b9d7b5e..0b27bcc 100644 --- a/pkg/config/label.go +++ b/pkg/config/label.go @@ -7,10 +7,10 @@ import ( "github.com/expr-lang/expr" "github.com/expr-lang/expr/vm" - "github.com/jippi/gitlab-labeller/pkg/colors" - "github.com/jippi/gitlab-labeller/pkg/scm" - "github.com/jippi/gitlab-labeller/pkg/stdlib" - "github.com/jippi/gitlab-labeller/pkg/types" + "github.com/jippi/scm-engine/pkg/colors" + "github.com/jippi/scm-engine/pkg/scm" + "github.com/jippi/scm-engine/pkg/stdlib" + "github.com/jippi/scm-engine/pkg/types" ) // labelType is a custom type for our enum diff --git a/pkg/scm/gitlab/client.go b/pkg/scm/gitlab/client.go index 3382e57..34bbb25 100644 --- a/pkg/scm/gitlab/client.go +++ b/pkg/scm/gitlab/client.go @@ -5,7 +5,7 @@ import ( "net/url" "strings" - "github.com/jippi/gitlab-labeller/pkg/scm" + "github.com/jippi/scm-engine/pkg/scm" go_gitlab "github.com/xanzy/go-gitlab" ) diff --git a/pkg/scm/gitlab/client_helpers.go b/pkg/scm/gitlab/client_helpers.go index 503fceb..a580ff8 100644 --- a/pkg/scm/gitlab/client_helpers.go +++ b/pkg/scm/gitlab/client_helpers.go @@ -4,7 +4,7 @@ import ( "fmt" "strconv" - "github.com/jippi/gitlab-labeller/pkg/scm" + "github.com/jippi/scm-engine/pkg/scm" go_gitlab "github.com/xanzy/go-gitlab" ) diff --git a/pkg/scm/gitlab/client_label.go b/pkg/scm/gitlab/client_label.go index 91de452..5456b44 100644 --- a/pkg/scm/gitlab/client_label.go +++ b/pkg/scm/gitlab/client_label.go @@ -5,8 +5,8 @@ import ( "fmt" "net/http" - "github.com/jippi/gitlab-labeller/pkg/scm" - "github.com/jippi/gitlab-labeller/pkg/state" + "github.com/jippi/scm-engine/pkg/scm" + "github.com/jippi/scm-engine/pkg/state" go_gitlab "github.com/xanzy/go-gitlab" ) diff --git a/pkg/scm/gitlab/client_merge_request.go b/pkg/scm/gitlab/client_merge_request.go index ba5f53a..babb4be 100644 --- a/pkg/scm/gitlab/client_merge_request.go +++ b/pkg/scm/gitlab/client_merge_request.go @@ -5,8 +5,8 @@ import ( "fmt" "net/http" - "github.com/jippi/gitlab-labeller/pkg/scm" - "github.com/jippi/gitlab-labeller/pkg/state" + "github.com/jippi/scm-engine/pkg/scm" + "github.com/jippi/scm-engine/pkg/state" go_gitlab "github.com/xanzy/go-gitlab" ) diff --git a/pkg/scm/gitlab/context.go b/pkg/scm/gitlab/context.go index 43d6160..937cac0 100644 --- a/pkg/scm/gitlab/context.go +++ b/pkg/scm/gitlab/context.go @@ -5,21 +5,13 @@ import ( "time" "github.com/hasura/go-graphql-client" - "github.com/jippi/gitlab-labeller/pkg/scm" - "github.com/jippi/gitlab-labeller/pkg/state" + "github.com/jippi/scm-engine/pkg/scm" + "github.com/jippi/scm-engine/pkg/state" "golang.org/x/oauth2" ) var _ scm.EvalContext = (*Context)(nil) -type Context struct { - scm.EvalContextualizer - - Project *ContextProject `expr:"project" graphql:"project(fullPath: $project_id)"` - Group *ContextGroup `expr:"group" graphql:"-"` - MergeRequest *ContextMergeRequest `expr:"merge_request" graphql:"-"` -} - func NewContext(ctx context.Context, baseURL, token string) (*Context, error) { httpClient := oauth2.NewClient( ctx, @@ -63,21 +55,26 @@ func NewContext(ctx context.Context, baseURL, token string) (*Context, error) { evalContext.Project.ResponseGroup = nil if len(evalContext.MergeRequest.ResponseFirstCommits.Nodes) > 0 { - evalContext.MergeRequest.FirstCommit = evalContext.MergeRequest.ResponseFirstCommits.Nodes[0] - evalContext.MergeRequest.TimeSinceFirstCommit = time.Since(evalContext.MergeRequest.FirstCommit.CommittedDate) + evalContext.MergeRequest.FirstCommit = &evalContext.MergeRequest.ResponseFirstCommits.Nodes[0] + + tmp := time.Since(evalContext.MergeRequest.FirstCommit.CommittedDate) + evalContext.MergeRequest.TimeSinceFirstCommit = &tmp } evalContext.MergeRequest.ResponseFirstCommits = nil if len(evalContext.MergeRequest.ResponseLastCommits.Nodes) > 0 { - evalContext.MergeRequest.LastCommit = evalContext.MergeRequest.ResponseLastCommits.Nodes[0] - evalContext.MergeRequest.TimeSinceLastCommit = time.Since(evalContext.MergeRequest.LastCommit.CommittedDate) + evalContext.MergeRequest.LastCommit = &evalContext.MergeRequest.ResponseLastCommits.Nodes[0] + + tmp := time.Since(evalContext.MergeRequest.LastCommit.CommittedDate) + evalContext.MergeRequest.TimeSinceLastCommit = &tmp } evalContext.MergeRequest.ResponseLastCommits = nil if evalContext.MergeRequest.FirstCommit != nil && evalContext.MergeRequest.LastCommit != nil { - evalContext.MergeRequest.TimeBetweenFirstAndLastCommit = evalContext.MergeRequest.FirstCommit.CommittedDate.Sub(evalContext.MergeRequest.LastCommit.CommittedDate).Round(time.Hour) + tmp := evalContext.MergeRequest.FirstCommit.CommittedDate.Sub(evalContext.MergeRequest.LastCommit.CommittedDate).Round(time.Hour) + evalContext.MergeRequest.TimeBetweenFirstAndLastCommit = &tmp } return evalContext, nil diff --git a/pkg/scm/gitlab/context_commit.go b/pkg/scm/gitlab/context_commit.go deleted file mode 100644 index 8306d83..0000000 --- a/pkg/scm/gitlab/context_commit.go +++ /dev/null @@ -1,12 +0,0 @@ -package gitlab - -import "time" - -type ContextCommit struct { - AuthorEmail string `expr:"author_email" graphql:"authorEmail"` - CommittedDate time.Time `expr:"committed_date" graphql:"committedDate"` -} - -type ContextCommitsNode struct { - Nodes []*ContextCommit `graphql:"nodes"` -} diff --git a/pkg/scm/gitlab/context_group.go b/pkg/scm/gitlab/context_group.go deleted file mode 100644 index 38612fa..0000000 --- a/pkg/scm/gitlab/context_group.go +++ /dev/null @@ -1,7 +0,0 @@ -package gitlab - -type ContextGroup struct { - ID string `expr:"id" graphql:"id"` - Name string `expr:"name" graphql:"name"` - Description string `expr:"description" graphql:"description"` -} diff --git a/pkg/scm/gitlab/context_label.go b/pkg/scm/gitlab/context_label.go deleted file mode 100644 index 3299c74..0000000 --- a/pkg/scm/gitlab/context_label.go +++ /dev/null @@ -1,12 +0,0 @@ -package gitlab - -type ContextLabel struct { - ID string `expr:"id" graphql:"id"` - Title string `expr:"title" graphql:"title"` - Color string `expr:"color" graphql:"color"` - Description string `expr:"description" graphql:"description"` -} - -type ContextLabelNodes struct { - Nodes []ContextLabel `graphql:"nodes"` -} diff --git a/pkg/scm/gitlab/context_merge_request.go b/pkg/scm/gitlab/context_merge_request.go index b942ccc..aaa9dc2 100644 --- a/pkg/scm/gitlab/context_merge_request.go +++ b/pkg/scm/gitlab/context_merge_request.go @@ -5,49 +5,8 @@ import ( "path/filepath" "regexp" "strings" - "time" ) -type ContextMergeRequest struct { - ApprovalsLeft int `expr:"approvals_left" graphql:"approvalsLeft"` - ApprovalsRequired int `expr:"approvals_required" graphql:"approvalsRequired"` - Approved bool `expr:"approved"` - AutoMergeEnabled bool `expr:"auto_merge_enabled" graphql:"autoMergeEnabled"` - AutoMergeStrategy string `expr:"auto_merge_strategy" graphql:"autoMergeStrategy"` - Conflicts bool `expr:"conflicts" graphql:"conflicts"` - CreatedAt time.Time `expr:"created_at" graphql:"createdAt"` - Description string `expr:"description"` - DiffStats []ContextMergeRequestDiffStat `expr:"diff_stats"` - DivergedFromTargetBranch bool `expr:"diverged_from_target_branch" graphql:"divergedFromTargetBranch"` - Draft bool `expr:"draft"` - FirstCommit *ContextCommit `expr:"first_commit" graphql:"-"` - ID string `expr:"id" graphql:"id"` - IID string `expr:"iid" graphql:"iid"` - Labels []ContextLabel `expr:"labels" graphql:"-"` - LastCommit *ContextCommit `expr:"last_commit" graphql:"-"` - Mergeable bool `expr:"mergeable" graphql:"mergeable"` - MergedAt *time.Time `expr:"merged_at" graphql:"mergedAt"` - MergeStatusEnum string `expr:"merge_status_enum" graphql:"mergeStatusEnum"` - SourceBranch string `expr:"source_branch" graphql:"sourceBranch"` - SourceBranchExists bool `expr:"source_branch_exists" graphql:"sourceBranchExists"` - SourceBranchProtected bool `expr:"source_branch_protected" graphql:"sourceBranchProtected"` - Squash bool `expr:"squash" graphql:"squash"` - SquashOnMerge bool `expr:"squash_on_merge" graphql:"squashOnMerge"` - State string `expr:"state"` - TargetBranch string `expr:"target_branch" graphql:"targetBranch"` - TargetBranchExists bool `expr:"target_branch_exists" graphql:"targetBranchExists"` - TimeBetweenFirstAndLastCommit time.Duration `expr:"time_between_first_and_last_commit" graphql:"-"` - TimeSinceFirstCommit time.Duration `expr:"time_since_first_commit" graphql:"-"` - TimeSinceLastCommit time.Duration `expr:"time_since_last_commit" graphql:"-"` - Title string `expr:"title"` - UpdatedAt time.Time `expr:"updated_at" graphql:"updatedAt"` - - // Internal state - ResponseLabels *ContextLabelNodes `expr:"-" graphql:"labels(first: 200)" json:"-" yaml:"-"` - ResponseFirstCommits *ContextCommitsNode `expr:"-" graphql:"first_commit: commits(first:1)"` - ResponseLastCommits *ContextCommitsNode `expr:"-" graphql:"last_commit: commits(last:1)"` -} - // Partially lifted from https://github.com/hmarr/codeowners/blob/main/match.go func (e ContextMergeRequest) ModifiedFiles(patterns ...string) bool { leftAnchoredLiteral := false diff --git a/pkg/scm/gitlab/context_merge_request_diff_stat.go b/pkg/scm/gitlab/context_merge_request_diff_stat.go deleted file mode 100644 index cb5c6a4..0000000 --- a/pkg/scm/gitlab/context_merge_request_diff_stat.go +++ /dev/null @@ -1,7 +0,0 @@ -package gitlab - -type ContextMergeRequestDiffStat struct { - Path string `expr:"path"` - Additions int `expr:"additions"` - Deletions int `expr:"deletions"` -} diff --git a/pkg/scm/gitlab/context_project.go b/pkg/scm/gitlab/context_project.go deleted file mode 100644 index b37179a..0000000 --- a/pkg/scm/gitlab/context_project.go +++ /dev/null @@ -1,23 +0,0 @@ -package gitlab - -import "time" - -type ContextProject struct { - ID string `expr:"id" graphql:"id"` - Name string `expr:"name" graphql:"name"` - NameWithNamespace string `expr:"name_with_namespace"` - Description string `expr:"description"` - Path string `expr:"path"` - FullPath string `expr:"full_path" graphql:"fullPath"` - Archived bool `expr:"archived" graphql:"archived"` - Topics []string `expr:"topics" graphql:"topics"` - Visibility string `expr:"visibility" graphql:"visibility"` - Labels []ContextLabel `expr:"labels" graphql:"-"` - LastActivityAt time.Time `expr:"last_activity_at" graphql:"lastActivityAt"` - CreatedAt time.Time `expr:"created_at" graphql:"createdAt"` - - // Internal state - MergeRequest *ContextMergeRequest `expr:"-" graphql:"mergeRequest(iid: $mr_id)"` - ResponseLabels *ContextLabelNodes `expr:"-" graphql:"labels(first: 200)" json:"-" yaml:"-"` - ResponseGroup *ContextGroup `expr:"-" graphql:"group" json:"-" yaml:"-"` -} diff --git a/pkg/scm/interfaces.go b/pkg/scm/interfaces.go index 3b7c768..a93aa69 100644 --- a/pkg/scm/interfaces.go +++ b/pkg/scm/interfaces.go @@ -22,7 +22,6 @@ type MergeRequestClient interface { type EvalContext interface { IsValid() bool - _isEvalContext() } type EvalContextualizer struct{} diff --git a/pkg/scm/types.go b/pkg/scm/types.go index c2ed45d..1154c0b 100644 --- a/pkg/scm/types.go +++ b/pkg/scm/types.go @@ -3,7 +3,7 @@ package scm import ( "net/http" - "github.com/jippi/gitlab-labeller/pkg/types" + "github.com/jippi/scm-engine/pkg/types" ) // Label represents a GitLab label. diff --git a/schema/gitlab/generate.go b/schema/gitlab/generate.go new file mode 100644 index 0000000..45b1179 --- /dev/null +++ b/schema/gitlab/generate.go @@ -0,0 +1,3 @@ +package schema + +//go:generate go run main.go diff --git a/schema/gitlab/gqlgen.yml b/schema/gitlab/gqlgen.yml new file mode 100644 index 0000000..b3d01aa --- /dev/null +++ b/schema/gitlab/gqlgen.yml @@ -0,0 +1,90 @@ +# Where are all the schema files located? globs are supported eg src/**/*.graphqls +schema: + - "*.graphqls" + +# Where should the generated server code go? +exec: + filename: ignore/generated.go + package: graph + +# Uncomment to enable federation +# federation: +# filename: graph/federation.go +# package: graph + +# Where should any generated models go? +model: + filename: ../../pkg/scm/gitlab/context.gen.go + package: gitlab + +# Where should the resolver implementations go? +resolver: + layout: follow-schema + dir: ignore/ + package: graph + filename_template: "{name}.resolvers.go" +# Optional: turn on to not generate template comments above resolvers +# omit_template_comment: false + +# Optional: turn on use ` + "`" + `gqlgen:"fieldName"` + "`" + ` tags in your models +# struct_tag: json + +# Optional: turn on to use []Thing instead of []*Thing +omit_slice_element_pointers: true + +# Optional: turn on to omit Is() methods to interface and unions +omit_interface_checks: true + +# Optional: turn on to skip generation of ComplexityRoot struct content and Complexity function +omit_complexity: true + +# Optional: turn on to not generate any file notice comments in generated files +# omit_gqlgen_file_notice: false + +# Optional: turn on to exclude the gqlgen version in the generated file notice. No effect if `omit_gqlgen_file_notice` is true. +# omit_gqlgen_version_in_file_notice: false + +# Optional: turn off to make struct-type struct fields not use pointers +# e.g. type Thing struct { FieldA OtherThing } instead of { FieldA *OtherThing } +# struct_fields_always_pointers: true + +# Optional: turn off to make resolvers return values instead of pointers for structs +# resolvers_always_return_pointers: true + +# Optional: turn on to return pointers instead of values in unmarshalInput +# return_pointers_in_unmarshalinput: false + +# Optional: wrap nullable input fields with Omittable +# nullable_input_omittable: true + +# Optional: set to speed up generation time by not performing a final validation pass. +# skip_validation: true + +# Optional: set to skip running `go mod tidy` when generating server code +skip_mod_tidy: true + +# gqlgen will search for any type names in the schema in these go packages +# if they match it will use them, otherwise it will generate them. +autobind: +# - "github.com/jippi/scm-engine/graph/model" + +# This section declares type mapping between the GraphQL and go type systems +# +# The first line in each type will be used as defaults for resolver arguments and +# modelgen, the others will be allowed when binding to fields. Configure them to +# your liking +models: + ID: + model: + - github.com/99designs/gqlgen/graphql.ID + - github.com/99designs/gqlgen/graphql.Int + - github.com/99designs/gqlgen/graphql.Int64 + - github.com/99designs/gqlgen/graphql.Int32 + Int: + model: + - github.com/99designs/gqlgen/graphql.Int + - github.com/99designs/gqlgen/graphql.Int64 + - github.com/99designs/gqlgen/graphql.Int32 + Duration: + model: + - github.com/99designs/gqlgen/graphql.Duration diff --git a/schema/gitlab/main.go b/schema/gitlab/main.go new file mode 100644 index 0000000..e81240e --- /dev/null +++ b/schema/gitlab/main.go @@ -0,0 +1,111 @@ +//go:build ignore + +package main + +import ( + "fmt" + "os" + "os/exec" + "strings" + + "github.com/99designs/gqlgen/api" + "github.com/99designs/gqlgen/codegen/config" + "github.com/99designs/gqlgen/plugin/modelgen" + "github.com/fatih/structtag" + "github.com/iancoleman/strcase" + "github.com/vektah/gqlparser/v2/ast" +) + +// Defining mutation function +func constraintFieldHook(td *ast.Definition, fd *ast.FieldDefinition, f *modelgen.Field) (*modelgen.Field, error) { + // Call default hook to proceed standard directives like goField and goTag. + // You can omit it, if you don't need. + if f, err := modelgen.DefaultFieldMutateHook(td, fd, f); err != nil { + return f, err + } + + tags, err := structtag.Parse(f.Tag) + if err != nil { + return nil, err + } + + // Remove JSON tag, we don't need it + tags.Delete("json") + + if c := fd.Directives.ForName("internal"); c != nil { + tags.Set(&structtag.Tag{Key: "expr", Name: "-"}) + } else if c := fd.Directives.ForName("expr"); c != nil { + value := c.Arguments.ForName("key") + + if value != nil { + tags.Set(&structtag.Tag{Key: "expr", Name: value.Value.Raw}) + } + } + + if c := fd.Directives.ForName("generated"); c != nil { + tags.Set(&structtag.Tag{Key: "graphql", Name: "-"}) + } else if c := fd.Directives.ForName("graphql"); c != nil { + value := c.Arguments.ForName("key") + + if value != nil { + tags.Set(&structtag.Tag{Key: "graphql", Name: value.Value.Raw}) + } + } + + f.Tag = tags.String() + + return f, nil +} + +func mutateHook(b *modelgen.ModelBuild) *modelgen.ModelBuild { + for _, model := range b.Models { + for _, field := range model.Fields { + tags, err := structtag.Parse(field.Tag) + if err != nil { + return b + } + + if !strings.Contains(field.Tag, "expr:") { + tags.Set(&structtag.Tag{Key: "expr", Name: strcase.ToSnake(field.Name)}) + } + + if !strings.Contains(field.Tag, "graphql:") { + tags.Set(&structtag.Tag{Key: "graphql", Name: strcase.ToLowerCamel(field.Name)}) + } + + field.Tag = tags.String() + } + } + + return b +} + +func main() { + cfg, err := config.LoadConfig(getRootPath() + "/schema/gitlab/gqlgen.yml") + if err != nil { + fmt.Fprintln(os.Stderr, "failed to load config", err.Error()) + + os.Exit(2) + } + + // Attaching the mutation function onto modelgen plugin + p := modelgen.Plugin{ + FieldHook: constraintFieldHook, + MutateHook: mutateHook, + } + + err = api.Generate(cfg, api.ReplacePlugin(&p)) + if err != nil { + fmt.Fprintln(os.Stderr, err.Error()) + os.Exit(3) + } +} + +func getRootPath() string { + path, err := exec.Command("git", "rev-parse", "--show-toplevel").Output() + if err != nil { + panic(err) + } + + return strings.TrimSpace(string(path)) +} diff --git a/schema/gitlab/schema.graphqls b/schema/gitlab/schema.graphqls new file mode 100644 index 0000000..67eb4e0 --- /dev/null +++ b/schema/gitlab/schema.graphqls @@ -0,0 +1,110 @@ +directive @generated on INPUT_FIELD_DEFINITION | FIELD_DEFINITION +directive @internal on INPUT_FIELD_DEFINITION | FIELD_DEFINITION +directive @expr(key: String!) on INPUT_FIELD_DEFINITION | FIELD_DEFINITION +directive @graphql(key: String!) on INPUT_FIELD_DEFINITION | FIELD_DEFINITION + +scalar Time +scalar Duration + +type Context { + Project: ContextProject @graphql(key: "project(fullPath: $project_id)") + Group: ContextGroup @generated + MergeRequest: ContextMergeRequest @generated +} + +type ContextProject { + ID: String! + Name: String! + NameWithNamespace: String! + Description: String! + Path: String! + FullPath: String! + Archived: Boolean! + Topics: [String!] + Visibility: String! + Labels: [ContextLabel!] @generated + LastActivityAt: Time! + CreatedAt: Time! + + # + # Internal state + # + + MergeRequest: ContextMergeRequest @internal @graphql(key: "mergeRequest(iid: $mr_id)") + ResponseLabels: ContextLabelNodes @internal @graphql(key: "labels(first: 200)") + ResponseGroup: ContextGroup @internal @graphql(key: "group") +} + +type ContextGroup { + ID: String! + Name: String! + Description: String! +} + +type ContextMergeRequest { + ApprovalsLeft: Int! + ApprovalsRequired: Int! + Approved: Boolean! + AutoMergeEnabled: Boolean! + AutoMergeStrategy: String! + Conflicts: Boolean! + CreatedAt: Time! + Description: String! + DiffStats: [ContextMergeRequestDiffStat!] + DivergedFromTargetBranch: Boolean! + Draft: Boolean! + FirstCommit: ContextCommit @generated() + ID: String! + IID: String! + Labels: [ContextLabel!] @generated + LastCommit: ContextCommit @generated() + Mergeable: Boolean! + MergedAt: Time + MergeStatusEnum: String! + SourceBranch: String! + SourceBranchExists: Boolean! + SourceBranchProtected: Boolean! + Squash: Boolean! + SquashOnMerge: Boolean! + State: String! + TargetBranch: String! + TargetBranchExists: Boolean! + TimeBetweenFirstAndLastCommit: Duration @generated() + TimeSinceFirstCommit: Duration @generated() + TimeSinceLastCommit: Duration @generated() + Title: String! + UpdatedAt: Time! + + # + # Internal State + # + ResponseLabels: ContextLabelNodes @internal @graphql(key: "labels(first: 200)") + ResponseFirstCommits: ContextCommitsNode @internal @graphql(key: "first_commit: commits(first:1)") + ResponseLastCommits: ContextCommitsNode @internal @graphql(key: "last_commit: commits(last:1)") +} + +type ContextCommit { + AuthorEmail: String! + CommittedDate: Time! +} + +type ContextCommitsNode { + Nodes: [ContextCommit!] @internal +} + +type ContextLabel { + ID: String! + Title: String! + Color: String! + Description: String! +} + +type ContextLabelNodes { + Nodes: [ContextLabel!] @internal +} + +type ContextMergeRequestDiffStat { + Path: String! + Additions: Int! + Deletions: Int! +} diff --git a/tools.go b/tools.go new file mode 100644 index 0000000..1bbf706 --- /dev/null +++ b/tools.go @@ -0,0 +1,11 @@ +//go:build tools +// +build tools + +package tools + +import ( + _ "github.com/99designs/gqlgen" + _ "github.com/davecgh/go-spew/spew" + _ "github.com/fatih/structtag" // needed for go:generate + _ "github.com/iancoleman/strcase" // needed for go:generate +)