From da946903089255f7070e8a8a275738cf8af522d8 Mon Sep 17 00:00:00 2001 From: Mateo Hernandez Date: Thu, 16 Oct 2025 13:59:54 -0300 Subject: [PATCH] wrap github api errors with grpc codes --- go.sum | 72 ++++++++++++++++++++++++++++++++ pkg/connector/api_token.go | 7 +--- pkg/connector/connector.go | 21 +++------- pkg/connector/enterprise_role.go | 7 +--- pkg/connector/helpers.go | 22 ++++++++++ pkg/connector/invitation.go | 4 +- pkg/connector/org.go | 55 ++++++++++-------------- pkg/connector/org_role.go | 14 ++----- pkg/connector/repository.go | 56 +++++++++++-------------- pkg/connector/team.go | 40 +++++++----------- pkg/connector/user.go | 14 +++---- 11 files changed, 174 insertions(+), 138 deletions(-) diff --git a/go.sum b/go.sum index 5df91713..5f89aa03 100644 --- a/go.sum +++ b/go.sum @@ -1,6 +1,17 @@ c2sp.org/CCTV/age v0.0.0-20240306222714-3ec4d716e805 h1:u2qwJeEvnypw+OCPUHmoZE3IqwfuN5kgDfo5MLzpNM0= c2sp.org/CCTV/age v0.0.0-20240306222714-3ec4d716e805/go.mod h1:FomMrUJ2Lxt5jCLmZkG3FHa72zUprnhd3v/Z18Snm4w= +cel.dev/expr v0.19.1/go.mod h1:MrpN08Q+lEBs+bGYdLxxHkZoUSsCp0nSKTs0nTymJgw= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.116.0/go.mod h1:cEPSRWPzZEswwdr9BxE6ChEn01dWlTaF05LiC2Xs70U= +cloud.google.com/go/auth v0.13.0/go.mod h1:COOjD9gwfKNKz+IIduatIhYJQIc0mG3H102r/EMxX6Q= +cloud.google.com/go/auth/oauth2adapt v0.2.6/go.mod h1:AlmsELtlEBnaNTL7jCj8VQFLy6mbZv0s4Q7NGBeQ5E8= +cloud.google.com/go/compute v1.24.0/go.mod h1:kw1/T+h/+tK2LJK0wiPPx1intgdAM3j/g3hFDlscY40= +cloud.google.com/go/compute/metadata v0.6.0/go.mod h1:FjyFAW1MW0C203CEOMDTu3Dk1FlqW3Rga40jzHL4hfg= +cloud.google.com/go/firestore v1.15.0/go.mod h1:GWOxFXcv8GZUtYpWHw/w6IuYNux/BtmeVTMmjrm4yhk= +cloud.google.com/go/iam v1.2.2/go.mod h1:0Ys8ccaZHdI1dEUilwzqng/6ps2YB6vRsjIe00/+6JY= +cloud.google.com/go/longrunning v0.5.5/go.mod h1:WV2LAxD8/rg5Z1cNW6FJ/ZpX4E4VnDnoTk0yawPBB7s= +cloud.google.com/go/monitoring v1.21.2/go.mod h1:hS3pXvaG8KgWTSz+dAdyzPrGUYmi2Q+WFX8g2hqVEZU= +cloud.google.com/go/storage v1.49.0/go.mod h1:k1eHhhpLvrPjVGfo0mOUPEJ4Y2+a/Hv5PiwehZI9qGU= filippo.io/age v1.2.1 h1:X0TZjehAZylOIj4DubWYU1vWQxv9bJpo+Uu2/LGhi1o= filippo.io/age v1.2.1/go.mod h1:JL9ew2lTN+Pyft4RiNGguFfOpewKwSHm5ayKD/A4004= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= @@ -8,6 +19,11 @@ filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4 github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/DATA-DOG/go-sqlmock v1.5.0 h1:Shsta01QNfFxHCfpW6YH2STWB0MudeXXEWMr20OEh60= github.com/DATA-DOG/go-sqlmock v1.5.0/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.25.0/go.mod h1:obipzmGjfSjam60XLwGfqUkJsfiheAl+TUjG+4yzyPM= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.48.1/go.mod h1:jyqM3eLpJ3IbIFDTKVz2rF9T/xWGW0rIriGwnz8l9Tk= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.48.1/go.mod h1:viRWSEhtMZqz1rhwmOVKkWl6SwmVowfL9O2YR5gI2PE= +github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= +github.com/armon/go-metrics v0.4.1/go.mod h1:E6amYzXo6aW1tqzoZGT755KkbgrJsSdpwZ+3JqfkOG4= github.com/aws/aws-lambda-go v1.47.0 h1:0H8s0vumYx/YKs4sE7YM0ktwL2eWse+kfopsRI1sXVI= github.com/aws/aws-lambda-go v1.47.0/go.mod h1:dpMpZgvWx5vuQJfBt0zqBha60q7Dd7RfgJv23DymV8A= github.com/aws/aws-sdk-go-v2 v1.36.3 h1:mJoei2CxPutQVxaATCzDUjcZEjVRdpsiiXi2o38yqWM= @@ -53,11 +69,15 @@ github.com/aws/smithy-go v1.22.2/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxY github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/benbjohnson/clock v1.3.5 h1:VvXlSJBzZpA/zum6Sj74hxwYI2DIxRWuNIoXAzHZz5o= github.com/benbjohnson/clock v1.3.5/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= +github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/census-instrumentation/opencensus-proto v0.4.1/go.mod h1:4T9NM4+4Vw91VeyqjLS6ao50K5bOcLKN6Q42XnYaRYw= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cncf/xds/go v0.0.0-20241223141626-cff3c89139a3/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8= github.com/conductorone/baton-sdk v0.4.2 h1:hj/aXdaz850EVqnErw9DN/+3864LSdVcwa6p3vMrAfI= github.com/conductorone/baton-sdk v0.4.2/go.mod h1:Csa1C2KrI4TxJAtC3WjQqOn24u0g2f4/5FgiYqZWpN4= github.com/conductorone/dpop v0.2.3 h1:s91U3845GHQ6P6FWrdNr2SEOy1ES/jcFs1JtKSl2S+o= @@ -66,6 +86,8 @@ github.com/conductorone/dpop/integrations/dpop_grpc v0.2.3 h1:kLMCNIh0Mo2vbvvkCm github.com/conductorone/dpop/integrations/dpop_grpc v0.2.3/go.mod h1:LYNoUc1lkvozk9HBio+xI2w8YyfYy0v2cAJtIgrkj8o= github.com/conductorone/dpop/integrations/dpop_oauth2 v0.2.3 h1:KhFaxiTzj9FteI9IE2tIGdSjJKyFW5ZcUF2SrgLnA28= github.com/conductorone/dpop/integrations/dpop_oauth2 v0.2.3/go.mod h1:2eI0qv+XaEhoCw0GKFF1yH4X8Mp4KLVEVnQKRFEy4zs= +github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= 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/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -85,9 +107,14 @@ github.com/ennyjfrick/ruleguard-logfatal v0.0.2/go.mod h1:Ng4Cc8dzYEo8vzB2xd+IOx github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/go-control-plane v0.13.4/go.mod h1:kDfuBlDVsSj2MjrLEtRWtHlsWIFcGyB2RMO44Dc5GZA= +github.com/envoyproxy/go-control-plane/envoy v1.32.4/go.mod h1:Gzjc5k8JcJswLjAx1Zm+wSYE20UrLtt7JZMWiWQXQEw= +github.com/envoyproxy/go-control-plane/ratelimit v0.1.0/go.mod h1:Wk+tMFAFbCXaJPzVVHnPgRKdUdwW/KdbRt94AzgRee4= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/envoyproxy/protoc-gen-validate v1.2.1 h1:DEo3O99U8j4hBFwbJfrz9VtgcDfUKS7KJ7spH3d86P8= github.com/envoyproxy/protoc-gen-validate v1.2.1/go.mod h1:d/C80l/jxXLdfEIhX1W2TmLfsJ31lvEjwamM4DxlWXU= +github.com/fatih/color v1.14.1/go.mod h1:2oHN61fhTpgcxD3TSWCgKDiH1+x4OiDVVGH8WlgGZGg= +github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M= @@ -120,6 +147,8 @@ github.com/golang-jwt/jwt/v5 v5.2.2 h1:Rl4B7itRWVtYIHFrSNd7vhTiz9UpLdi6gZhZ3wEeD github.com/golang-jwt/jwt/v5 v5.2.2/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/glog v1.2.4/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -139,25 +168,41 @@ 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/pprof v0.0.0-20240409012703-83162a5b38cd h1:gbpYu9NMq8jhDVbvlGkMFWCjLFlqqEZjEmObmhUy6Vo= github.com/google/pprof v0.0.0-20240409012703-83162a5b38cd/go.mod h1:kf6iHlnVGwgKolg33glAes7Yg/8iWP8ukqeldJSO7jw= +github.com/google/s2a-go v0.1.8/go.mod h1:6iNWHTpQ+nfNRN5E00MSdfDwVesa8hhS32PhPO8deJA= 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/googleapis/enterprise-certificate-proxy v0.3.4/go.mod h1:YKe7cfqYXjKGpGvmSg28/fFvhNzinZQm8DGnaburhGA= +github.com/googleapis/gax-go/v2 v2.14.1/go.mod h1:Hb/NubMaVM88SrNkvl8X/o8XWwDJEPqouaLeN2IUxoA= github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 h1:UH//fgunKIs4JdUbpDl1VZCDaL56wXCB/5+wF6uHfaI= github.com/grpc-ecosystem/go-grpc-middleware v1.4.0/go.mod h1:g5qyo/la0ALbONm6Vbp88Yd8NsDy6rZz+RcrMPxvld8= github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.1 h1:e9Rjr40Z98/clHv5Yg79Is0NtosR5LXRvdr7o/6NwbA= github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.1/go.mod h1:tIxuGz/9mpox++sgp9fJjHO0+q1X9/UOWd798aAm22M= +github.com/hashicorp/consul/api v1.28.2/go.mod h1:KyzqzgMEya+IZPcD65YFoOVAgPpbfERu4I/tzG6/ueE= +github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= +github.com/hashicorp/go-hclog v1.5.0/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= +github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= +github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= +github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/hashicorp/serf v0.10.1/go.mod h1:yL2t6BqATOLGc5HF7qbFkTfXoPIY0WZdWHfEvMqbG+4= +github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/jellydator/ttlcache/v3 v3.3.0 h1:BdoC9cE81qXfrxeb9eoJi9dWrdhSuwXMAnHTbnBm4Wc= github.com/jellydator/ttlcache/v3 v3.3.0/go.mod h1:bj2/e0l4jRnQdrnSTaGTsh4GSXvMjQcy41i7th0GVGw= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo= github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= @@ -169,8 +214,10 @@ github.com/lib/pq v1.10.1 h1:6VXZrLU0jHBYyAqrSPa+MgPfnSvTPuMgK+k0o5kVFWo= github.com/lib/pq v1.10.1/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lufia/plan9stats v0.0.0-20240909124753-873cd0166683 h1:7UMa6KCCMjZEMDtTVdcGu0B1GmmC7QJKiCCjyTAWQy0= github.com/lufia/plan9stats v0.0.0-20240909124753-873cd0166683/go.mod h1:ilwx/Dta8jXAgpFYFvSWEMwxmbWXyiUHkd5FwyKhb5k= +github.com/lyft/protoc-gen-star/v2 v2.0.4-0.20230330145011-496ad1ac90a4/go.mod h1:amey7yeodaJhXSbf/TlLvWiqQfLOSpEk//mLlc+axEk= github.com/magiconair/properties v1.8.9 h1:nWcCbLq1N2v/cpNsy5WvQ37Fb+YElfq20WJ/a8RkpQM= github.com/magiconair/properties v1.8.9/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= 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-sqlite3 v1.14.7/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= @@ -180,14 +227,23 @@ github.com/maypok86/otter v1.2.4 h1:HhW1Pq6VdJkmWwcZZq19BlEQkHtI8xgsQzBVXJU0nfc= github.com/maypok86/otter v1.2.4/go.mod h1:mKLfoI7v1HOmQMwFgX4QkRk23mX6ge3RDvjdHOWG4R4= github.com/migueleliasweb/go-github-mock v1.1.0 h1:GKaOBPsrPGkAKgtfuWY8MclS1xR6MInkx1SexJucMwE= github.com/migueleliasweb/go-github-mock v1.1.0/go.mod h1:pYe/XlGs4BGMfRY4vmeixVsODHnVDDhJ9zoi0qzSMHc= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= 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/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/nats-io/nats.go v1.34.0/go.mod h1:Ubdu4Nh9exXdSz0RVWRFBbRfrbSxOYd26oF0wkWclB8= +github.com/nats-io/nkeys v0.4.7/go.mod h1:kqXRgRDPlGy7nGaEDMuYzmiJCIAAWDK0IMBtDmGD0nc= +github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4= github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M= github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/sftp v1.13.7/go.mod h1:KMKI0t3T6hfA+lTR/ssZdunHo+uwq7ghoN09/FSu3DY= +github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10/go.mod h1:t/avpk3KcrXxUnYOhZhMXJlSEyie6gQbtLq5NM3loB8= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -210,9 +266,11 @@ github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567 h1:M8mH9eK4OUR4l github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567/go.mod h1:DWNGW8A4Y+GyBgPuaQJuWiy0XYftx4Xm/y5Jqk9I6VQ= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= +github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/sagikazarmark/crypt v0.19.0/go.mod h1:c6vimRziqqERhtSe0MhIvzE1w54FrCHtrXb5NH/ja78= github.com/sagikazarmark/locafero v0.7.0 h1:5MqpDsTGNDhY8sGp0Aowyf0qKsPrhewaLSsFaodPcyo= github.com/sagikazarmark/locafero v0.7.0/go.mod h1:2za3Cg5rMaTMoG/2Ulr9AwtFaIppKXTRYnozin4aB5k= github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= @@ -264,12 +322,19 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0= github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= +go.etcd.io/etcd/api/v3 v3.5.12/go.mod h1:Ot+o0SWSyT6uHhA56al1oCED0JImsRiU9Dc26+C2a+4= +go.etcd.io/etcd/client/pkg/v3 v3.5.12/go.mod h1:seTzl2d9APP8R5Y2hFL3NVlD6qC/dOT+3kvrqPyTas4= +go.etcd.io/etcd/client/v2 v2.305.12/go.mod h1:aQ/yhsxMu+Oht1FOupSr60oBvcS9cKXHrzBpDsPTf9E= +go.etcd.io/etcd/client/v3 v3.5.12/go.mod h1:tSbBCakoWmmddL+BKVAJHa9km+O/E+bumDe9mSbPiqw= +go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= go.opentelemetry.io/contrib/bridges/otelzap v0.10.0 h1:ojdSRDvjrnm30beHOmwsSvLpoRF40MlwNCA+Oo93kXU= go.opentelemetry.io/contrib/bridges/otelzap v0.10.0/go.mod h1:oTTm4g7NEtHSV2i/0FeVdPaPgUIZPfQkFbq0vbzqnv0= +go.opentelemetry.io/contrib/detectors/gcp v1.34.0/go.mod h1:cV4BMFcscUR/ckqLkbfQmF0PRsq8w/lMGzdbCSveBHo= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.59.0 h1:rgMkmiGfix9vFJDcDi1PK8WEQP4FLQwLDfhp5ZLpFeE= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.59.0/go.mod h1:ijPqXp5P6IRRByFVVg9DY8P5HkxkHE5ARIa+86aXPf4= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0/go.mod h1:L7UH0GbB0p47T4Rri3uHjbpCFYrVrwc1I25QhNPiGK8= go.opentelemetry.io/otel v1.35.0 h1:xKWKPxrxB6OtMCbmMY021CqC45J+3Onta9MqjhnusiQ= go.opentelemetry.io/otel v1.35.0/go.mod h1:UEqy8Zp11hpkUrL73gSlELM0DupHoiq72dR+Zqel/+Y= go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.11.0 h1:HMUytBT3uGhPKYY/u/G5MR9itrlSO2SMOsSD3Tk3k7A= @@ -383,11 +448,15 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90= +google.golang.org/api v0.215.0/go.mod h1:fta3CVtuJYOEdugLNWm6WodzOS8KdFckABwN4I40hzY= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20241118233622-e639e219e697/go.mod h1:JJrvXBWRZaFMxBufik1a4RpFw4HhgVtBBWQeQgUj2cc= google.golang.org/genproto/googleapis/api v0.0.0-20250218202821-56aae31c358a h1:nwKuGPlUAt+aR+pcrkfFRrTU1BVrSmYyYMxYbUIVHr0= google.golang.org/genproto/googleapis/api v0.0.0-20250218202821-56aae31c358a/go.mod h1:3kWAYMk1I75K4vykHtKt2ycnOgpA6974V7bREqbsenU= google.golang.org/genproto/googleapis/rpc v0.0.0-20250219182151-9fdb1cabc7b2 h1:DMTIbak9GhdaSxEjvVzAeNZvyc03I61duqNbnm3SU0M= @@ -417,8 +486,11 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +lukechampine.com/uint128 v1.3.0/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk= +modernc.org/cc/v3 v3.41.0/go.mod h1:Ni4zjJYJ04CDOhG7dn640WGfwBzfE0ecX8TyMB0Fv0Y= modernc.org/cc/v4 v4.24.4 h1:TFkx1s6dCkQpd6dKurBNmpo+G8Zl4Sq/ztJ+2+DEsh0= modernc.org/cc/v4 v4.24.4/go.mod h1:uVtb5OGqUKpoLWhqwNQo/8LwvoiEBLvZXIQ/SmO6mL0= +modernc.org/ccgo/v3 v3.17.0/go.mod h1:Sg3fwVpmLvCUTaqEUjiBDAvshIaKDB0RXaf+zgqFu8I= modernc.org/ccgo/v4 v4.23.15 h1:wFDan71KnYqeHz4eF63vmGE6Q6Pc0PUGDpP0PRMYjDc= modernc.org/ccgo/v4 v4.23.15/go.mod h1:nJX30dks/IWuBOnVa7VRii9Me4/9TZ1SC9GNtmARTy0= modernc.org/fileutil v1.3.0 h1:gQ5SIzK3H9kdfai/5x41oQiKValumqNTDXMvKo62HvE= diff --git a/pkg/connector/api_token.go b/pkg/connector/api_token.go index 713e5e8b..19b48018 100644 --- a/pkg/connector/api_token.go +++ b/pkg/connector/api_token.go @@ -8,9 +8,7 @@ import ( "github.com/conductorone/baton-sdk/pkg/annotations" "github.com/conductorone/baton-sdk/pkg/pagination" resourceSdk "github.com/conductorone/baton-sdk/pkg/types/resource" - "github.com/conductorone/baton-sdk/pkg/uhttp" "github.com/google/go-github/v69/github" - "google.golang.org/grpc/codes" ) func apiTokenResource(ctx context.Context, token *github.PersonalAccessToken) (*v2.Resource, error) { @@ -94,10 +92,7 @@ func (o *apiTokenResourceType) List( }, }) if err != nil { - if isRatelimited(resp) { - return nil, "", nil, uhttp.WrapErrors(codes.Unavailable, "too many requests", err) - } - return nil, "", nil, err + return nil, "", nil, wrapGitHubError(err, resp, "github-connector: failed to list fine-grained personal access tokens") } restApiRateLimit, err := extractRateLimitData(resp) diff --git a/pkg/connector/connector.go b/pkg/connector/connector.go index 15b40e7e..0269d214 100644 --- a/pkg/connector/connector.go +++ b/pkg/connector/connector.go @@ -206,7 +206,7 @@ func (gh *GitHub) Validate(ctx context.Context) (annotations.Annotations, error) if len(gh.enterprises) > 0 { _, _, err := gh.customClient.ListEnterpriseConsumedLicenses(ctx, gh.enterprises[0], 0) if err != nil { - return nil, fmt.Errorf("can't list enterprise consumed licenses: %w", err) + return nil, uhttp.WrapErrors(codes.PermissionDenied, "github-connector: failed to access enterprise licenses", err) } } return nil, nil @@ -218,9 +218,9 @@ func (gh *GitHub) validateAppCredentials(ctx context.Context) (annotations.Annot return nil, fmt.Errorf("github-connector: only one org is allowed when using github app") } - _, _, err := findInstallation(ctx, gh.appClient, orgLogins[0]) + _, resp, err := findInstallation(ctx, gh.appClient, orgLogins[0]) if err != nil { - return nil, fmt.Errorf("github-connector: failed to retrieve org: %w", err) + return nil, wrapGitHubError(err, resp, "github-connector: failed to retrieve org installation") } return nil, nil } @@ -272,9 +272,9 @@ func New(ctx context.Context, ghc *cfg.Github, appKey string) (*GitHub, error) { if err != nil { return nil, err } - installation, _, err := findInstallation(ctx, appClient, ghc.Orgs[0]) + installation, resp, err := findInstallation(ctx, appClient, ghc.Orgs[0]) if err != nil { - return nil, err + return nil, wrapGitHubError(err, resp, "github-connector: failed to find app installation") } token, err := getInstallationToken(ctx, appClient, installation.GetID()) @@ -453,16 +453,7 @@ func getOrgs(ctx context.Context, client *github.Client, orgs []string) ([]strin for { orgs, resp, err := client.Organizations.List(ctx, "", &github.ListOptions{Page: page, PerPage: maxPageSize}) if err != nil { - if isRatelimited(resp) { - return nil, uhttp.WrapErrors(codes.Unavailable, "too many requests", err) - } - if isAuthError(resp) { - return nil, uhttp.WrapErrors(codes.Unauthenticated, "github-connector: failed to retrieve org", err) - } - if isPermissionError(resp) { - return nil, uhttp.WrapErrors(codes.PermissionDenied, "github-connector: failed to retrieve org", err) - } - return nil, fmt.Errorf("github-connector: failed to retrieve org: %w", err) + return nil, wrapGitHubError(err, resp, "github-connector: failed to retrieve organizations") } if resp.StatusCode == http.StatusUnauthorized { return nil, status.Error(codes.Unauthenticated, "github token is not authorized") diff --git a/pkg/connector/enterprise_role.go b/pkg/connector/enterprise_role.go index 5aa60ab8..81a34061 100644 --- a/pkg/connector/enterprise_role.go +++ b/pkg/connector/enterprise_role.go @@ -60,7 +60,7 @@ func (o *enterpriseRoleResourceType) fillCache(ctx context.Context) error { for continuePagination { consumedLicenses, _, err := o.customClient.ListEnterpriseConsumedLicenses(ctx, enterprise, page) if err != nil { - return fmt.Errorf("baton-github: error listing enterprise consumed licenses for %s: %w", enterprise, err) + return uhttp.WrapErrors(codes.PermissionDenied, fmt.Sprintf("baton-github: error listing enterprise consumed licenses for %s", enterprise), err) } if len(consumedLicenses.Users) == 0 { @@ -141,10 +141,7 @@ func (o *enterpriseRoleResourceType) Grants( for _, userLogin := range cache[resource.Id.Resource] { user, resp, err := o.client.Users.Get(ctx, userLogin) if err != nil { - if isRatelimited(resp) { - return nil, "", nil, uhttp.WrapErrors(codes.Unavailable, "too many requests", err) - } - return nil, "", nil, fmt.Errorf("baton-github: error getting user %s: %w", userLogin, err) + return nil, "", nil, wrapGitHubError(err, resp, fmt.Sprintf("baton-github: failed to get user %s", userLogin)) } principalId, err := resourceSdk.NewResourceID(resourceTypeUser, *user.ID) diff --git a/pkg/connector/helpers.go b/pkg/connector/helpers.go index 8c7c82da..670abaa6 100644 --- a/pkg/connector/helpers.go +++ b/pkg/connector/helpers.go @@ -11,10 +11,12 @@ import ( v2 "github.com/conductorone/baton-sdk/pb/c1/connector/v2" "github.com/conductorone/baton-sdk/pkg/annotations" "github.com/conductorone/baton-sdk/pkg/pagination" + "github.com/conductorone/baton-sdk/pkg/uhttp" "github.com/google/go-github/v69/github" "github.com/shurcooL/githubv4" "golang.org/x/text/cases" "golang.org/x/text/language" + "google.golang.org/grpc/codes" "google.golang.org/protobuf/types/known/timestamppb" ) @@ -249,3 +251,23 @@ func isPermissionError(resp *github.Response) bool { } return resp.StatusCode == http.StatusForbidden } + +// wrapGitHubError wraps GitHub API errors with appropriate gRPC status codes based on the HTTP response. +// It handles rate limiting, authentication errors, permission errors, and generic errors. +// The contextMsg parameter should describe the operation that failed (e.g., "failed to list teams"). +func wrapGitHubError(err error, resp *github.Response, contextMsg string) error { + if err == nil { + return nil + } + + if isRatelimited(resp) { + return uhttp.WrapErrors(codes.Unavailable, "too many requests", err) + } + if isAuthError(resp) { + return uhttp.WrapErrors(codes.Unauthenticated, contextMsg, err) + } + if isPermissionError(resp) { + return uhttp.WrapErrors(codes.PermissionDenied, contextMsg, err) + } + return fmt.Errorf("%s: %w", contextMsg, err) +} diff --git a/pkg/connector/invitation.go b/pkg/connector/invitation.go index d4cae673..168f4d1b 100644 --- a/pkg/connector/invitation.go +++ b/pkg/connector/invitation.go @@ -74,7 +74,7 @@ func (i *invitationResourceType) List(ctx context.Context, parentID *v2.Resource if isNotFoundError(resp) { return nil, "", nil, nil } - return nil, "", nil, fmt.Errorf("github-connector: ListPendingOrgInvitatioins failed: %w", err) + return nil, "", nil, wrapGitHubError(err, resp, "github-connector: failed to list pending org invitations") } restApiRateLimit, err := extractRateLimitData(resp) @@ -140,7 +140,7 @@ func (i *invitationResourceType) CreateAccount( Email: params.email, }) if err != nil { - return nil, nil, nil, fmt.Errorf("github-connectorv2: failed to invite user to org: %w", err) + return nil, nil, nil, wrapGitHubError(err, resp, "github-connector: failed to create org invitation") } restApiRateLimit, err := extractRateLimitData(resp) diff --git a/pkg/connector/org.go b/pkg/connector/org.go index cc2eec7e..7164d022 100644 --- a/pkg/connector/org.go +++ b/pkg/connector/org.go @@ -102,10 +102,7 @@ func (o *orgResourceType) List( orgs, resp, err := o.client.Organizations.List(ctx, "", opts) if err != nil { - if isRatelimited(resp) { - return nil, "", nil, uhttp.WrapErrors(codes.Unavailable, "too many requests", err) - } - return nil, "", nil, fmt.Errorf("github-connector: failed to fetch org: %w", err) + return nil, "", nil, wrapGitHubError(err, resp, "github-connector: failed to fetch organizations") } nextPage, reqAnnos, err := parseResp(resp) @@ -129,11 +126,7 @@ func (o *orgResourceType) List( l.Warn("insufficient access to list org membership, skipping org", zap.String("org", org.GetLogin())) continue } - - if isRatelimited(resp) { - return nil, "", nil, uhttp.WrapErrors(codes.Unavailable, "too many requests", err) - } - return nil, "", nil, err + return nil, "", nil, wrapGitHubError(err, resp, "github-connector: failed to get org membership") } // Only sync orgs that we are an admin for @@ -227,11 +220,7 @@ func (o *orgResourceType) Grants( if isNotFoundError(resp) { return nil, "", nil, uhttp.WrapErrors(codes.NotFound, fmt.Sprintf("org: %s not found", orgName)) } - errMsg := "github-connectorv2: failed to list org members" - if isRatelimited(resp) { - return nil, "", nil, uhttp.WrapErrors(codes.Unavailable, "too many requests", err) - } - return nil, "", nil, fmt.Errorf("%s: %w", errMsg, err) + return nil, "", nil, wrapGitHubError(err, resp, "github-connector: failed to list org members") } var nextPage string @@ -294,9 +283,9 @@ func (o *orgResourceType) Grant(ctx context.Context, principal *v2.Resource, en return nil, err } - user, _, err := o.client.Users.GetByID(ctx, principalID) + user, resp, err := o.client.Users.GetByID(ctx, principalID) if err != nil { - return nil, fmt.Errorf("github-connectorv2: failed to get user: %w", err) + return nil, wrapGitHubError(err, resp, "github-connector: failed to get user") } requestedRole := "" @@ -309,21 +298,21 @@ func (o *orgResourceType) Grant(ctx context.Context, principal *v2.Resource, en return nil, fmt.Errorf("github-connectorv2: invalid entitlement id: %s", en.Id) } - isMember, _, err := o.client.Organizations.IsMember(ctx, orgName, user.GetLogin()) + isMember, resp, err := o.client.Organizations.IsMember(ctx, orgName, user.GetLogin()) if err != nil { - return nil, fmt.Errorf("github-connectorv2: failed to get org membership: %w", err) + return nil, wrapGitHubError(err, resp, "github-connector: failed to check org membership") } // TODO: check existing invitations. Duplicate invitations aren't allowed, so this will fail with 4xx from github. // If user isn't a member, invite them to the org with the requested role if !isMember { - _, _, err = o.client.Organizations.CreateOrgInvitation(ctx, orgName, &github.CreateOrgInvitationOptions{ + _, resp, err = o.client.Organizations.CreateOrgInvitation(ctx, orgName, &github.CreateOrgInvitationOptions{ InviteeID: user.ID, Role: &requestedRole, }) if err != nil { - return nil, fmt.Errorf("github-connectorv2: failed to invite user to org: %w", err) + return nil, wrapGitHubError(err, resp, "github-connector: failed to invite user to org") } return nil, nil } @@ -334,9 +323,9 @@ func (o *orgResourceType) Grant(ctx context.Context, principal *v2.Resource, en } // If the user is a member, check to see what role they have - membership, _, err := o.client.Organizations.GetOrgMembership(ctx, user.GetLogin(), orgName) + membership, resp, err := o.client.Organizations.GetOrgMembership(ctx, user.GetLogin(), orgName) if err != nil { - return nil, fmt.Errorf("github-connectorv2: failed to get org membership: %w", err) + return nil, wrapGitHubError(err, resp, "github-connector: failed to get org membership") } // Skip if user already has requested role @@ -346,9 +335,9 @@ func (o *orgResourceType) Grant(ctx context.Context, principal *v2.Resource, en } // User is a member but grant is for admin, so make them an admin. - _, _, err = o.client.Organizations.EditOrgMembership(ctx, user.GetLogin(), orgName, &github.Membership{Role: github.Ptr(orgRoleAdmin)}) + _, resp, err = o.client.Organizations.EditOrgMembership(ctx, user.GetLogin(), orgName, &github.Membership{Role: github.Ptr(orgRoleAdmin)}) if err != nil { - return nil, fmt.Errorf("github-connectorv2: failed to make user an admin : %w", err) + return nil, wrapGitHubError(err, resp, "github-connector: failed to make user an admin") } return nil, nil @@ -386,14 +375,14 @@ func (o *orgResourceType) Revoke(ctx context.Context, grant *v2.Grant) (annotati return nil, err } - user, _, err := o.client.Users.GetByID(ctx, principalID) + user, resp, err := o.client.Users.GetByID(ctx, principalID) if err != nil { - return nil, fmt.Errorf("github-connectorv2: failed to get user: %w", err) + return nil, wrapGitHubError(err, resp, "github-connector: failed to get user") } - membership, _, err := o.client.Organizations.GetOrgMembership(ctx, user.GetLogin(), orgName) + membership, resp, err := o.client.Organizations.GetOrgMembership(ctx, user.GetLogin(), orgName) if err != nil { - return nil, fmt.Errorf("github-connectorv2: failed to get org membership: %w", err) + return nil, wrapGitHubError(err, resp, "github-connector: failed to get org membership") } if membership.GetState() != "active" { @@ -401,16 +390,16 @@ func (o *orgResourceType) Revoke(ctx context.Context, grant *v2.Grant) (annotati } if en.Id == memberRoleID { - _, err = o.client.Organizations.RemoveOrgMembership(ctx, user.GetLogin(), orgName) + resp, err = o.client.Organizations.RemoveOrgMembership(ctx, user.GetLogin(), orgName) if err != nil { - return nil, fmt.Errorf("github-connectorv2: failed to revoke org membership from user: %w", err) + return nil, wrapGitHubError(err, resp, "github-connector: failed to revoke org membership from user") } return nil, nil } - _, _, err = o.client.Organizations.EditOrgMembership(ctx, user.GetLogin(), orgName, &github.Membership{Role: github.Ptr(orgRoleMember)}) + _, resp, err = o.client.Organizations.EditOrgMembership(ctx, user.GetLogin(), orgName, &github.Membership{Role: github.Ptr(orgRoleMember)}) if err != nil { - return nil, fmt.Errorf("github-connectorv2: failed to revoke org admin from user: %w", err) + return nil, wrapGitHubError(err, resp, "github-connector: failed to revoke org admin from user") } return nil, nil @@ -449,7 +438,7 @@ func (o *orgResourceType) listOrganizationsFromAppInstallations( for orgName := range o.orgs { org, resp, err = o.client.Organizations.Get(ctx, orgName) if err != nil { - return nil, "", nil, fmt.Errorf("github-connector: failed to fetch organization: %w", err) + return nil, "", nil, wrapGitHubError(err, resp, "github-connector: failed to fetch organization") } } diff --git a/pkg/connector/org_role.go b/pkg/connector/org_role.go index f6450c0b..b733fc8e 100644 --- a/pkg/connector/org_role.go +++ b/pkg/connector/org_role.go @@ -13,11 +13,9 @@ import ( "github.com/conductorone/baton-sdk/pkg/types/entitlement" "github.com/conductorone/baton-sdk/pkg/types/grant" "github.com/conductorone/baton-sdk/pkg/types/resource" - "github.com/conductorone/baton-sdk/pkg/uhttp" "github.com/google/go-github/v69/github" "github.com/grpc-ecosystem/go-grpc-middleware/logging/zap/ctxzap" "go.uber.org/zap" - "google.golang.org/grpc/codes" ) type OrganizationRole struct { @@ -90,10 +88,7 @@ func (o *orgRoleResourceType) List( // Return empty list with no error to indicate we skipped this resource return nil, "", nil, nil } - if isRatelimited(resp) { - return nil, "", nil, uhttp.WrapErrors(codes.Unavailable, "too many requests", err) - } - return nil, "", nil, fmt.Errorf("failed to list organization roles: %w", err) + return nil, "", nil, wrapGitHubError(err, resp, "github-connector: failed to list organization roles") } var ret []*v2.Resource @@ -180,7 +175,7 @@ func (o *orgRoleResourceType) Grants( } return rv, pageToken, nil, nil } - return nil, "", nil, fmt.Errorf("failed to list role users: %w", err) + return nil, "", nil, wrapGitHubError(err, resp, "github-connector: failed to list users assigned to org role") } nextPage, respAnnos, err := parseResp(resp) if err != nil { @@ -227,10 +222,7 @@ func (o *orgRoleResourceType) Grants( } return nil, pageToken, nil, nil } - if isRatelimited(resp) { - return nil, "", nil, uhttp.WrapErrors(codes.Unavailable, "too many requests", err) - } - return nil, "", nil, fmt.Errorf("failed to list role teams: %w", err) + return nil, "", nil, wrapGitHubError(err, resp, "github-connector: failed to list teams assigned to org role") } nextPage, respAnnos, err := parseResp(resp) diff --git a/pkg/connector/repository.go b/pkg/connector/repository.go index 12aeaed4..2e761c88 100644 --- a/pkg/connector/repository.go +++ b/pkg/connector/repository.go @@ -90,7 +90,7 @@ func (o *repositoryResourceType) List(ctx context.Context, parentID *v2.Resource repos, resp, err := o.client.Repositories.ListByOrg(ctx, orgName, opts) if err != nil { - return nil, "", nil, fmt.Errorf("github-connector: failed to list repositories: %w", err) + return nil, "", nil, wrapGitHubError(err, resp, "github-connector: failed to list repositories") } nextPage, reqAnnos, err := parseResp(resp) @@ -181,10 +181,7 @@ func (o *repositoryResourceType) Grants( if isNotFoundError(resp) { return nil, "", nil, uhttp.WrapErrors(codes.NotFound, fmt.Sprintf("repo: %s not found", resource.DisplayName)) } - if isRatelimited(resp) { - return nil, "", nil, uhttp.WrapErrors(codes.Unavailable, "too many requests", err) - } - return nil, "", nil, fmt.Errorf("github-connector: failed to list repos: %w", err) + return nil, "", nil, wrapGitHubError(err, resp, "github-connector: failed to list collaborators") } nextPage, respAnnos, err := parseResp(resp) @@ -237,10 +234,7 @@ func (o *repositoryResourceType) Grants( return nil, "", nil, uhttp.WrapErrors(codes.NotFound, fmt.Sprintf("repo: %s not found", resource.DisplayName)) } - if isRatelimited(resp) { - return nil, "", nil, uhttp.WrapErrors(codes.Unavailable, "too many requests", err) - } - return nil, "", nil, fmt.Errorf("github-connector: failed to list repos: %w", err) + return nil, "", nil, wrapGitHubError(err, resp, "github-connector: failed to list repository teams") } nextPage, respAnnos, err := parseResp(resp) @@ -299,9 +293,9 @@ func (o *repositoryResourceType) Grant(ctx context.Context, principal *v2.Resour return nil, err } - repo, _, err := o.client.Repositories.GetByID(ctx, repoID) + repo, resp, err := o.client.Repositories.GetByID(ctx, repoID) if err != nil { - return nil, fmt.Errorf("github-connectorv2: failed to get repository: %w", err) + return nil, wrapGitHubError(err, resp, "github-connector: failed to get repository") } org := repo.GetOrganization() @@ -319,12 +313,12 @@ func (o *repositoryResourceType) Grant(ctx context.Context, principal *v2.Resour switch principal.Id.ResourceType { case resourceTypeUser.Id: - user, _, err := o.client.Users.GetByID(ctx, principalID) + user, resp, err := o.client.Users.GetByID(ctx, principalID) if err != nil { - return nil, fmt.Errorf("github-connectorv2: failed to get user: %w", err) + return nil, wrapGitHubError(err, resp, "github-connector: failed to get user") } - _, _, e := o.client.Repositories.AddCollaborator( + _, resp, er := o.client.Repositories.AddCollaborator( ctx, repo.GetOwner().GetLogin(), repo.GetName(), @@ -332,20 +326,20 @@ func (o *repositoryResourceType) Grant(ctx context.Context, principal *v2.Resour &github.RepositoryAddCollaboratorOptions{Permission: permission}, ) - if e != nil { - return nil, fmt.Errorf("github-connectorv2: failed to add user to a repository: %w", e) + if er != nil { + return nil, wrapGitHubError(er, resp, "github-connector: failed to add user to repository") } case resourceTypeTeam.Id: - team, _, err := o.client.Teams.GetTeamByID(ctx, org.GetID(), principalID) //nolint:staticcheck // TODO: migrate to GetTeamBySlug + team, resp, err := o.client.Teams.GetTeamByID(ctx, org.GetID(), principalID) //nolint:staticcheck // TODO: migrate to GetTeamBySlug if err != nil { - return nil, fmt.Errorf("github-connectorv2: failed to get team: %w", err) + return nil, wrapGitHubError(err, resp, "github-connector: failed to get team") } - _, err = o.client.Teams.AddTeamRepoBySlug(ctx, org.GetLogin(), team.GetSlug(), repo.GetOwner().GetLogin(), repo.GetName(), &github.TeamAddTeamRepoOptions{ + resp, err = o.client.Teams.AddTeamRepoBySlug(ctx, org.GetLogin(), team.GetSlug(), repo.GetOwner().GetLogin(), repo.GetName(), &github.TeamAddTeamRepoOptions{ Permission: permission, }) if err != nil { - return nil, fmt.Errorf("github-connectorv2: failed to add team to a repo: %w", err) + return nil, wrapGitHubError(err, resp, "github-connector: failed to add team to repository") } default: l.Error( @@ -370,9 +364,9 @@ func (o *repositoryResourceType) Revoke(ctx context.Context, grant *v2.Grant) (a return nil, err } - repo, _, err := o.client.Repositories.GetByID(ctx, repoID) + repo, resp, err := o.client.Repositories.GetByID(ctx, repoID) if err != nil { - return nil, fmt.Errorf("github-connectorv2: failed to get repository: %w", err) + return nil, wrapGitHubError(err, resp, "github-connector: failed to get repository") } org := repo.GetOrganization() @@ -384,24 +378,24 @@ func (o *repositoryResourceType) Revoke(ctx context.Context, grant *v2.Grant) (a switch principal.Id.ResourceType { case resourceTypeUser.Id: - user, _, err := o.client.Users.GetByID(ctx, principalID) + user, resp, err := o.client.Users.GetByID(ctx, principalID) if err != nil { - return nil, fmt.Errorf("github-connectorv2: failed to get user: %w", err) + return nil, wrapGitHubError(err, resp, "github-connector: failed to get user") } - _, e := o.client.Repositories.RemoveCollaborator(ctx, repo.GetOwner().GetLogin(), repo.GetName(), user.GetLogin()) - if e != nil { - return nil, fmt.Errorf("github-connectorv2: failed to remove user from repo: %w", e) + resp, er := o.client.Repositories.RemoveCollaborator(ctx, repo.GetOwner().GetLogin(), repo.GetName(), user.GetLogin()) + if er != nil { + return nil, wrapGitHubError(er, resp, "github-connector: failed to remove user from repository") } case resourceTypeTeam.Id: - team, _, err := o.client.Teams.GetTeamByID(ctx, org.GetID(), principalID) //nolint:staticcheck // TODO: migrate to GetTeamBySlug + team, resp, err := o.client.Teams.GetTeamByID(ctx, org.GetID(), principalID) //nolint:staticcheck // TODO: migrate to GetTeamBySlug if err != nil { - return nil, fmt.Errorf("github-connectorv2: failed to get team: %w", err) + return nil, wrapGitHubError(err, resp, "github-connector: failed to get team") } - _, err = o.client.Teams.RemoveTeamRepoBySlug(ctx, org.GetLogin(), team.GetSlug(), repo.GetOwner().GetLogin(), repo.GetName()) + resp, err = o.client.Teams.RemoveTeamRepoBySlug(ctx, org.GetLogin(), team.GetSlug(), repo.GetOwner().GetLogin(), repo.GetName()) if err != nil { - return nil, fmt.Errorf("github-connectorv2: failed to remove team from repo: %w", err) + return nil, wrapGitHubError(err, resp, "github-connector: failed to remove team from repository") } default: l.Error( diff --git a/pkg/connector/team.go b/pkg/connector/team.go index 88a13b03..194b0ba2 100644 --- a/pkg/connector/team.go +++ b/pkg/connector/team.go @@ -95,10 +95,7 @@ func (o *teamResourceType) List(ctx context.Context, parentID *v2.ResourceId, pt teams, resp, err := o.client.Teams.ListTeams(ctx, orgName, opts) if err != nil { - if isRatelimited(resp) { - return nil, "", nil, uhttp.WrapErrors(codes.Unavailable, "too many requests", err) - } - return nil, "", nil, fmt.Errorf("github-connector: failed to list teams: %w", err) + return nil, "", nil, wrapGitHubError(err, resp, "github-connector: failed to list teams") } nextPage, reqAnnos, err := parseResp(resp) @@ -109,10 +106,7 @@ func (o *teamResourceType) List(ctx context.Context, parentID *v2.ResourceId, pt for _, team := range teams { fullTeam, resp, err := o.client.Teams.GetTeamByID(ctx, orgID, team.GetID()) //nolint:staticcheck // TODO: migrate to GetTeamBySlug if err != nil { - if isRatelimited(resp) { - return nil, "", nil, uhttp.WrapErrors(codes.Unavailable, "too many requests", err) - } - return nil, "", nil, err + return nil, "", nil, wrapGitHubError(err, resp, "github-connector: failed to get team details") } tr, err := teamResource(fullTeam, &v2.ResourceId{ResourceType: resourceTypeOrg.Id, Resource: fmt.Sprintf("%d", orgID)}) @@ -172,10 +166,7 @@ func (o *teamResourceType) Grants(ctx context.Context, resource *v2.Resource, pT org, resp, err := o.client.Organizations.GetByID(ctx, orgID) if err != nil { - if isRatelimited(resp) { - return nil, "", nil, uhttp.WrapErrors(codes.Unavailable, "too many requests", err) - } - return nil, "", nil, err + return nil, "", nil, wrapGitHubError(err, resp, "github-connector: failed to get organization") } githubID, err := parseResourceToGitHub(resource.Id) @@ -211,10 +202,7 @@ func (o *teamResourceType) Grants(ctx context.Context, resource *v2.Resource, pT if isNotFoundError(resp) { return nil, "", nil, uhttp.WrapErrors(codes.NotFound, fmt.Sprintf("org: %d not found", org.GetID())) } - if isRatelimited(resp) { - return nil, "", nil, uhttp.WrapErrors(codes.Unavailable, "too many requests", err) - } - return nil, "", nil, fmt.Errorf("github-connectorv2: failed to fetch team members: %w", err) + return nil, "", nil, wrapGitHubError(err, resp, "github-connector: failed to list team members") } var nextPage string @@ -302,9 +290,9 @@ func (o *teamResourceType) Grant(ctx context.Context, principal *v2.Resource, en return nil, err } - user, _, err := o.client.Users.GetByID(ctx, userId) + user, resp, err := o.client.Users.GetByID(ctx, userId) if err != nil { - return nil, fmt.Errorf("github-connectorv2: failed to get user %d, err: %w", userId, err) + return nil, wrapGitHubError(err, resp, fmt.Sprintf("github-connector: failed to get user %d", userId)) } enIDParts := strings.Split(entitlement.Id, ":") @@ -313,7 +301,7 @@ func (o *teamResourceType) Grant(ctx context.Context, principal *v2.Resource, en } permission := enIDParts[2] - _, _, e := o.client.Teams.AddTeamMembershipByID( + _, resp, er := o.client.Teams.AddTeamMembershipByID( ctx, orgId, teamId, @@ -321,8 +309,8 @@ func (o *teamResourceType) Grant(ctx context.Context, principal *v2.Resource, en &github.TeamAddTeamMembershipOptions{Role: permission}, ) - if e != nil { - return nil, fmt.Errorf("github-connectorv2: failed to add user to a team: %w", e) + if er != nil { + return nil, wrapGitHubError(er, resp, "github-connector: failed to add user to team") } return nil, nil @@ -362,13 +350,13 @@ func (o *teamResourceType) Revoke(ctx context.Context, grant *v2.Grant) (annotat return nil, err } - user, _, err := o.client.Users.GetByID(ctx, userId) + user, resp, err := o.client.Users.GetByID(ctx, userId) if err != nil { - return nil, fmt.Errorf("github-connectorv2: failed to get user %d, err: %w", userId, err) + return nil, wrapGitHubError(err, resp, fmt.Sprintf("github-connector: failed to get user %d", userId)) } - _, e := o.client.Teams.RemoveTeamMembershipByID(ctx, orgId, teamId, user.GetLogin()) - if e != nil { - return nil, fmt.Errorf("github-connectorv2: failed to revoke user team membership: %w", e) + resp, er := o.client.Teams.RemoveTeamMembershipByID(ctx, orgId, teamId, user.GetLogin()) + if er != nil { + return nil, wrapGitHubError(er, resp, "github-connector: failed to revoke user team membership") } return nil, nil diff --git a/pkg/connector/user.go b/pkg/connector/user.go index 98d9f887..04321a84 100644 --- a/pkg/connector/user.go +++ b/pkg/connector/user.go @@ -133,10 +133,7 @@ func (o *userResourceType) List(ctx context.Context, parentID *v2.ResourceId, pt users, resp, err := o.client.Organizations.ListMembers(ctx, orgName, &opts) if err != nil { - if isRatelimited(resp) { - return nil, "", nil, uhttp.WrapErrors(codes.Unavailable, "too many requests", err) - } - return nil, "", nil, fmt.Errorf("github-connector: ListMembers failed: %w", err) + return nil, "", nil, wrapGitHubError(err, resp, "github-connector: failed to list organization members") } restApiRateLimit, err = extractRateLimitData(resp) @@ -251,24 +248,23 @@ func (o *userResourceType) Delete(ctx context.Context, resourceId *v2.ResourceId return nil, fmt.Errorf("baton-github: invalid invitation id") } - u, _, err := o.client.Users.GetByID(ctx, userID) + user, resp, err := o.client.Users.GetByID(ctx, userID) if err != nil { - return nil, fmt.Errorf("baton-github: invalid userID") + return nil, wrapGitHubError(err, resp, "baton-github: invalid userID") } var ( isRemoved = false - resp *github.Response ) for _, org := range orgs { - resp, err = o.client.Organizations.RemoveOrgMembership(ctx, u.GetLogin(), org) + resp, err = o.client.Organizations.RemoveOrgMembership(ctx, user.GetLogin(), org) if err == nil { isRemoved = true } } if !isRemoved { - return nil, fmt.Errorf("baton-github: failed to cancel user") + return nil, wrapGitHubError(err, resp, "baton-github: failed to remove user from organizations") } restApiRateLimit, err := extractRateLimitData(resp)