diff --git a/git/go.mod b/git/go.mod deleted file mode 100644 index 10d7f25e..00000000 --- a/git/go.mod +++ /dev/null @@ -1,32 +0,0 @@ -module github.com/fluxcd/pkg/git - -go 1.17 - -require ( - github.com/go-git/go-git/v5 v5.1.0 - github.com/google/go-github/v33 v33.0.0 - github.com/xanzy/go-gitlab v0.43.0 -) - -require ( - github.com/emirpasic/gods v1.12.0 // indirect - github.com/go-git/gcfg v1.5.0 // indirect - github.com/go-git/go-billy/v5 v5.0.0 // indirect - github.com/golang/protobuf v1.3.2 // indirect - github.com/google/go-querystring v1.0.0 // indirect - github.com/hashicorp/go-cleanhttp v0.5.1 // indirect - github.com/hashicorp/go-retryablehttp v0.6.4 // indirect - github.com/imdario/mergo v0.3.9 // indirect - github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect - github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd // indirect - github.com/mitchellh/go-homedir v1.1.0 // indirect - github.com/sergi/go-diff v1.1.0 // indirect - github.com/xanzy/ssh-agent v0.2.1 // indirect - golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073 // indirect - golang.org/x/net v0.0.0-20200301022130-244492dfa37a // indirect - golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288 // indirect - golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527 // indirect - golang.org/x/time v0.0.0-20191024005414-555d28b269f0 // indirect - google.golang.org/appengine v1.3.0 // indirect - gopkg.in/warnings.v0 v0.1.2 // indirect -) diff --git a/git/go.sum b/git/go.sum deleted file mode 100644 index b7868214..00000000 --- a/git/go.sum +++ /dev/null @@ -1,105 +0,0 @@ -github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7 h1:uSoVVbwJiQipAclBbw+8quDsfcvFjOpI5iCf4p/cqCs= -github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs= -github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA= -github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= -github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= -github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= -github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -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/emirpasic/gods v1.12.0 h1:QAUIPSaCu4G+POclxeqb3F+WPpdKqFGlw36+yOzGlrg= -github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o= -github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= -github.com/gliderlabs/ssh v0.2.2 h1:6zsha5zo/TWhRhwqCD3+EarCAgZ2yN28ipRnGPnwkI0= -github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= -github.com/go-git/gcfg v1.5.0 h1:Q5ViNfGF8zFgyJWPqYwA7qGFoMTEiBmdlkcfRmpIMa4= -github.com/go-git/gcfg v1.5.0/go.mod h1:5m20vg6GwYabIxaOonVkTdrILxQMpEShl1xiMF4ua+E= -github.com/go-git/go-billy/v5 v5.0.0 h1:7NQHvd9FVid8VL4qVUMm8XifBK+2xCoZ2lSk0agRrHM= -github.com/go-git/go-billy/v5 v5.0.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0= -github.com/go-git/go-git-fixtures/v4 v4.0.1 h1:q+IFMfLx200Q3scvt2hN79JsEzy4AmBTp/pqnefH+Bc= -github.com/go-git/go-git-fixtures/v4 v4.0.1/go.mod h1:m+ICp2rF3jDhFgEZ/8yziagdT1C+ZpZcrJjappBCDSw= -github.com/go-git/go-git/v5 v5.1.0 h1:HxJn9g/E7eYvKW3Fm7Jt4ee8LXfPOm/H1cdDu8vEssk= -github.com/go-git/go-git/v5 v5.1.0/go.mod h1:ZKfuPUoY1ZqIG4QG9BDBh3G4gLM5zvPuSJAozQrZuyM= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= -github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY= -github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-github/v33 v33.0.0 h1:qAf9yP0qc54ufQxzwv+u9H0tiVOnPJxo0lI/JXqw3ZM= -github.com/google/go-github/v33 v33.0.0/go.mod h1:GMdDnVZY/2TsWgp/lkYnpSAh6TrzhANBBwm6k6TTEXg= -github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk= -github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= -github.com/hashicorp/go-cleanhttp v0.5.1 h1:dH3aiDG9Jvb5r5+bYHsikaOUIpcM0xvgMXVoDkXMzJM= -github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= -github.com/hashicorp/go-hclog v0.9.2 h1:CG6TE5H9/JXsFWJCfoIVpKFIkFe6ysEuHirp4DxCsHI= -github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= -github.com/hashicorp/go-retryablehttp v0.6.4 h1:BbgctKO892xEyOXnGiaAwIoSq1QZ/SS4AhjoAh9DnfY= -github.com/hashicorp/go-retryablehttp v0.6.4/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY= -github.com/imdario/mergo v0.3.9 h1:UauaLniWCFHWd+Jp9oCEkTBj8VO/9DKg3PV3VCNMDIg= -github.com/imdario/mergo v0.3.9/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= -github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= -github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= -github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= -github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd h1:Coekwdh0v2wtGp9Gmz1Ze3eVRAWJMLokvN3QjdzCHLY= -github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= -github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= -github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= -github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -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/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= -github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= -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.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/xanzy/go-gitlab v0.43.0 h1:rpOZQjxVJGW/ch+Jy4j7W4o7BB1mxkXJNVGuplZ7PUs= -github.com/xanzy/go-gitlab v0.43.0/go.mod h1:sPLojNBn68fMUWSxIJtdVVIP8uSBYqesTfDUseX11Ug= -github.com/xanzy/ssh-agent v0.2.1 h1:TCbipTQL2JiiCprBWx9frJ2eJlCYT00NmctrHxVAr70= -github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0Bx9h2kr4= -golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073 h1:xMPOj6Pz6UipU1wXLkrtqpHbR0AVFnyPEQq/wRWz9lM= -golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181108082009-03003ca0c849/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20200301022130-244492dfa37a h1:GuSPYbZzB5/dcLNCwLQLsg3obCJtX9IJhpXkvY7kzk0= -golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288 h1:JIqe8uIcRBHXDQVvZtHwp80ai3Lw3IJAeJEs55Dc1W0= -golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190221075227-b4e8571b14e0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527 h1:uYVVQ9WP/Ds2ROhcaGPeIdVq0RIXVLwsHlnvJ+cT1So= -golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= -golang.org/x/time v0.0.0-20191024005414-555d28b269f0 h1:/5xXl8Y5W96D+TtHSlonuFqGHIWVuyCkGJLwGh9JJFs= -golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.3.0 h1:FBSsiFRMz3LBeXIomRnVzrQwSDj4ibvcRexLG0LZGQk= -google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= -gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= -gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I= -gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/git/provider.go b/git/provider.go deleted file mode 100644 index 8108f7da..00000000 --- a/git/provider.go +++ /dev/null @@ -1,28 +0,0 @@ -/* -Copyright 2020 The Flux authors - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package git - -import "context" - -// Provider is the interface that a git provider should implement -type Provider interface { - CreateRepository(ctx context.Context, r *Repository) (bool, error) - GetRepositoryOwner(ctx context.Context, owner string) (string, error) - DeleteRepository(ctx context.Context, r *Repository) error - AddTeam(ctx context.Context, r *Repository, name, permission string) (bool, error) - AddDeployKey(ctx context.Context, r *Repository, key, keyName string) (bool, error) -} diff --git a/git/provider_github.go b/git/provider_github.go deleted file mode 100644 index 6f04f940..00000000 --- a/git/provider_github.go +++ /dev/null @@ -1,205 +0,0 @@ -/* -Copyright 2020 The Flux authors - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package git - -import ( - "context" - "fmt" - "strings" - - "github.com/google/go-github/v33/github" -) - -// GithubProvider represents a GitHub API wrapper -type GithubProvider struct { - IsPrivate bool - IsPersonal bool -} - -const ( - GitHubTokenName = "GITHUB_TOKEN" - GitHubDefaultHostname = "github.com" -) - -func (p *GithubProvider) newClient(r *Repository) (*github.Client, error) { - auth := github.BasicAuthTransport{ - Username: "git", - Password: r.Token, - } - - gh := github.NewClient(auth.Client()) - if r.Host != GitHubDefaultHostname { - baseURL := fmt.Sprintf("https://%s/api/v3/", r.Host) - uploadURL := fmt.Sprintf("https://%s/api/uploads/", r.Host) - if g, err := github.NewEnterpriseClient(baseURL, uploadURL, auth.Client()); err == nil { - gh = g - } else { - return nil, err - } - } - - return gh, nil -} - -// CreateRepository returns false if the repository exists -func (p *GithubProvider) CreateRepository(ctx context.Context, r *Repository) (bool, error) { - gh, err := p.newClient(r) - if err != nil { - return false, fmt.Errorf("client error: %w", err) - } - org := "" - if !p.IsPersonal { - org = r.Owner - } - - if _, _, err := gh.Repositories.Get(ctx, org, r.Name); err == nil { - return false, nil - } - - autoInit := true - _, _, err = gh.Repositories.Create(ctx, org, &github.Repository{ - AutoInit: &autoInit, - Name: &r.Name, - Private: &p.IsPrivate, - }) - if err != nil { - if !strings.Contains(err.Error(), "name already exists on this account") { - return false, fmt.Errorf("failed to create repository, error: %w", err) - } - } else { - return true, nil - } - return false, nil -} - -// Deprecated, this has become obsolete due to changes in getProjects -// -// GetRepositoryOwner returns the actual path owner. This is need for Gitlab where the name of a group might differ -// from its path -func (p *GithubProvider) GetRepositoryOwner(ctx context.Context, token string, owner string) (string, error) { - return owner, nil -} - -// AddTeam returns false if the team is already assigned to the repository -func (p *GithubProvider) AddTeam(ctx context.Context, r *Repository, name, permission string) (bool, error) { - gh, err := p.newClient(r) - if err != nil { - return false, fmt.Errorf("client error: %w", err) - } - - // check team exists - _, _, err = gh.Teams.GetTeamBySlug(ctx, r.Owner, name) - if err != nil { - return false, fmt.Errorf("failed to retrieve team '%s', error: %w", name, err) - } - - // check if team is assigned to the repo - _, resp, err := gh.Teams.IsTeamRepoBySlug(ctx, r.Owner, name, r.Owner, r.Name) - if resp == nil && err != nil { - return false, fmt.Errorf("failed to determine if team '%s' is assigned to the repository, error: %w", name, err) - } - - // add team to the repo - if resp.StatusCode == 404 { - _, err = gh.Teams.AddTeamRepoBySlug(ctx, r.Owner, name, r.Owner, r.Name, &github.TeamAddTeamRepoOptions{ - Permission: permission, - }) - if err != nil { - return false, fmt.Errorf("failed to add team '%s' to the repository, error: %w", name, err) - } - return true, nil - } - - return false, nil -} - -// AddDeployKey returns false if the key exists and the content is the same -func (p *GithubProvider) AddDeployKey(ctx context.Context, r *Repository, key, keyName string) (bool, error) { - gh, err := p.newClient(r) - if err != nil { - return false, fmt.Errorf("client error: %w", err) - } - - // list deploy keys - keys, resp, err := gh.Repositories.ListKeys(ctx, r.Owner, r.Name, nil) - if err != nil { - return false, fmt.Errorf("failed to list deploy keys, error: %w", err) - } - if resp.StatusCode >= 300 { - return false, fmt.Errorf("failed to list deploy keys (status code: %s)", resp.Status) - } - - // check if the key exists - shouldCreateKey := true - var existingKey *github.Key - for _, k := range keys { - if k.Title != nil && k.Key != nil && *k.Title == keyName { - if *k.Key != key { - existingKey = k - } else { - shouldCreateKey = false - } - break - } - } - - // delete existing key if the value differs - if existingKey != nil { - resp, err := gh.Repositories.DeleteKey(ctx, r.Owner, r.Name, *existingKey.ID) - if err != nil { - return false, fmt.Errorf("failed to delete deploy key '%s', error: %w", keyName, err) - } - if resp.StatusCode >= 300 { - return false, fmt.Errorf("failed to delete deploy key '%s' (status code: %s)", keyName, resp.Status) - } - } - - // create key - if shouldCreateKey { - isReadOnly := true - _, _, err = gh.Repositories.CreateKey(ctx, r.Owner, r.Name, &github.Key{ - Title: &keyName, - Key: &key, - ReadOnly: &isReadOnly, - }) - if err != nil { - return false, fmt.Errorf("failed to create deploy key '%s', error: %w", keyName, err) - } - return true, nil - } - - return false, nil -} - -// DeleteRepository deletes the GitHub repository -func (p *GithubProvider) DeleteRepository(ctx context.Context, r *Repository) error { - gh, err := p.newClient(r) - if err != nil { - return fmt.Errorf("client error: %w", err) - } - - org := "" - if !p.IsPersonal { - org = r.Owner - } - - if _, err := gh.Repositories.Delete(ctx, org, r.Name); err != nil { - return err - } - - return nil -} diff --git a/git/provider_gitlab.go b/git/provider_gitlab.go deleted file mode 100644 index fe553302..00000000 --- a/git/provider_gitlab.go +++ /dev/null @@ -1,256 +0,0 @@ -/* -Copyright 2020 The Flux authors - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package git - -import ( - "context" - "fmt" - "strings" - - "github.com/xanzy/go-gitlab" -) - -// GitLabProvider represents a GitLab API wrapper -type GitLabProvider struct { - IsPrivate bool - IsPersonal bool -} - -const ( - GitLabTokenName = "GITLAB_TOKEN" - GitLabDefaultHostname = "gitlab.com" -) - -func (p *GitLabProvider) newClient(r *Repository) (*gitlab.Client, error) { - gl, err := gitlab.NewClient(r.Token) - if err != nil { - return nil, err - } - - if r.Host != GitLabDefaultHostname { - gl, err = gitlab.NewClient(r.Token, gitlab.WithBaseURL(fmt.Sprintf("https://%s/api/v4", r.Host))) - if err != nil { - return nil, err - } - } - return gl, nil -} - -// CreateRepository returns false if the repository already exists -func (p *GitLabProvider) CreateRepository(ctx context.Context, r *Repository) (bool, error) { - gl, err := p.newClient(r) - if err != nil { - return false, fmt.Errorf("client error: %w", err) - } - - var ( - gid *int - project *gitlab.Project - ) - if p.IsPersonal { - project, err = p.getPersonalProject(ctx, gl, r) - } else { - gid, project, err = p.getGroupProject(ctx, gl, r) - } - if err != nil { - return false, fmt.Errorf("failed to get project, error: %w", err) - } - if project != nil { - return false, nil - } - - visibility := gitlab.PublicVisibility - if p.IsPrivate { - visibility = gitlab.PrivateVisibility - } - - cpo := &gitlab.CreateProjectOptions{ - Path: gitlab.String(r.Name), - NamespaceID: gid, - Visibility: &visibility, - InitializeWithReadme: gitlab.Bool(true), - } - _, _, err = gl.Projects.CreateProject(cpo) - if err != nil { - return false, fmt.Errorf("failed to create project, error: %w", err) - } - return true, nil -} - -// AddTeam returns false if the team is already assigned to the repository -func (p *GitLabProvider) AddTeam(ctx context.Context, r *Repository, name, permission string) (bool, error) { - return false, nil -} - -// AddDeployKey returns false if the key exists and the content is the same -func (p *GitLabProvider) AddDeployKey(ctx context.Context, r *Repository, key, keyName string) (bool, error) { - gl, err := p.newClient(r) - if err != nil { - return false, fmt.Errorf("client error: %w", err) - } - - // list deploy keys - var project *gitlab.Project - if p.IsPersonal { - project, err = p.getPersonalProject(ctx, gl, r) - } else { - _, project, err = p.getGroupProject(ctx, gl, r) - } - if err != nil { - return false, fmt.Errorf("failed to get project, error: %w", err) - } - if project == nil { - return false, fmt.Errorf("no project found") - } - - // check if the key exists - keys, _, err := gl.DeployKeys.ListProjectDeployKeys(project.ID, &gitlab.ListProjectDeployKeysOptions{}) - if err != nil { - return false, fmt.Errorf("failed to list deploy keys, error: %w", err) - } - - shouldCreateKey := true - var existingKey *gitlab.DeployKey - for _, k := range keys { - if k.Title == keyName { - if k.Key != key { - existingKey = k - } else { - shouldCreateKey = false - } - break - } - } - - // delete existing key if the value differs - if existingKey != nil { - _, err := gl.DeployKeys.DeleteDeployKey(project.ID, existingKey.ID, gitlab.WithContext(ctx)) - if err != nil { - return false, fmt.Errorf("failed to delete deploy key '%s', error: %w", keyName, err) - } - } - - // create key - if shouldCreateKey { - _, _, err := gl.DeployKeys.AddDeployKey(project.ID, &gitlab.AddDeployKeyOptions{ - Title: gitlab.String(keyName), - Key: gitlab.String(key), - CanPush: gitlab.Bool(false), - }, gitlab.WithContext(ctx)) - if err != nil { - return false, fmt.Errorf("failed to create deploy key '%s', error: %w", keyName, err) - } - return true, nil - } - - return false, nil -} - -// DeleteRepository is not supported by GitLab -func (p *GitLabProvider) DeleteRepository(ctx context.Context, r *Repository) error { - return fmt.Errorf("repository deletion is not supported by the GitLab API") -} - -func (p *GitLabProvider) getPersonalProject(ctx context.Context, gl *gitlab.Client, r *Repository) (*gitlab.Project, error) { - luo := &gitlab.ListUsersOptions{ - Search: gitlab.String(r.Owner), - } - users, _, err := gl.Users.ListUsers(luo, gitlab.WithContext(ctx)) - if err != nil { - return nil, fmt.Errorf("failed to list users, error: %w", err) - } - if len(users) == 0 { - return nil, fmt.Errorf("failed to find user '%s'", r.Owner) - } - - lpo := &gitlab.ListProjectsOptions{ - Search: gitlab.String(r.Name), - Owned: gitlab.Bool(true), - } - projects, _, err := gl.Projects.ListUserProjects(users[0].ID, lpo, gitlab.WithContext(ctx)) - if err != nil { - return nil, fmt.Errorf("failed to list projects, error: %w", err) - } - if len(projects) == 0 { - return nil, nil - } - return projects[0], nil -} - -func (p *GitLabProvider) getGroupProject(ctx context.Context, gl *gitlab.Client, r *Repository) (*int, *gitlab.Project, error) { - var ( - gid *int - projects []*gitlab.Project - err error - ) - - groupAndSubGroupPaths := strings.Split(r.Owner, "/") - - lgo := &gitlab.ListGroupsOptions{ - Search: gitlab.String(groupAndSubGroupPaths[0]), - } - groups, _, err := gl.Groups.ListGroups(lgo, gitlab.WithContext(ctx)) - if err != nil { - return nil, nil, fmt.Errorf("failed to list groups, error: %w", err) - } - - group := findGroupByPath(groups, groupAndSubGroupPaths[0]) - if len(groups) == 0 || group == nil { - return nil, nil, fmt.Errorf("failed to find group named '%s'", groupAndSubGroupPaths[0]) - } - gid = &group.ID - - if len(groupAndSubGroupPaths) > 1 { - lastSubGroup := groupAndSubGroupPaths[len(groupAndSubGroupPaths)-1] - ldgo := &gitlab.ListDescendantGroupsOptions{ - Search: gitlab.String(lastSubGroup), - } - subGroups, _, err := gl.Groups.ListDescendantGroups(*gid, ldgo, gitlab.WithContext(ctx)) - if err != nil { - return nil, nil, fmt.Errorf("failed to list subgroups, error: %w", err) - } - subGroup := findGroupByPath(subGroups, lastSubGroup) - if len(subGroups) == 0 || subGroup == nil { - return nil, nil, fmt.Errorf("failed to list subgroups named '%s'", lastSubGroup) - } - gid = &subGroup.ID - } - - lpo := &gitlab.ListGroupProjectsOptions{ - Search: gitlab.String(r.Name), - } - projects, _, err = gl.Groups.ListGroupProjects(*gid, lpo, gitlab.WithContext(ctx)) - if err != nil { - return nil, nil, fmt.Errorf("failed to list projects, error: %w", err) - } - - var project *gitlab.Project - if len(projects) > 0 { - project = projects[0] - } - return gid, project, nil -} - -func findGroupByPath(groups []*gitlab.Group, path string) *gitlab.Group { - for _, group := range groups { - if group.Path == path { - return group - } - } - - return nil -} diff --git a/git/repository.go b/git/repository.go deleted file mode 100644 index 5d2fd1f3..00000000 --- a/git/repository.go +++ /dev/null @@ -1,172 +0,0 @@ -/* -Copyright 2020 The Flux authors - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package git - -import ( - "context" - "fmt" - "time" - - "github.com/go-git/go-git/v5" - "github.com/go-git/go-git/v5/plumbing" - "github.com/go-git/go-git/v5/plumbing/object" - "github.com/go-git/go-git/v5/plumbing/transport" - "github.com/go-git/go-git/v5/plumbing/transport/http" -) - -// Repository represents a git repository wrapper -type Repository struct { - Name string - Owner string - Host string - SSHHost string - Token string - AuthorName string - AuthorEmail string - - repo *git.Repository -} - -// NewRepository returns a git repository wrapper -func NewRepository(name, owner, host, token, authorName, authorEmail string) (*Repository, error) { - if name == "" { - return nil, fmt.Errorf("name required") - } - if owner == "" { - return nil, fmt.Errorf("owner required") - } - if host == "" { - return nil, fmt.Errorf("host required") - } - if token == "" { - return nil, fmt.Errorf("token required") - } - if authorName == "" { - return nil, fmt.Errorf("author name required") - } - if authorEmail == "" { - return nil, fmt.Errorf("author email required") - } - - return &Repository{ - Name: name, - Owner: owner, - Host: host, - Token: token, - AuthorName: authorName, - AuthorEmail: authorEmail, - }, nil -} - -// GetURL returns the repository HTTPS address -func (r *Repository) GetURL() string { - return fmt.Sprintf("https://%s/%s/%s", r.Host, r.Owner, r.Name) -} - -// GetSSH returns the repository SSH address -func (r *Repository) GetSSH() string { - host := r.Host - if r.SSHHost != "" { - host = r.SSHHost - } - return fmt.Sprintf("ssh://git@%s/%s/%s", host, r.Owner, r.Name) -} - -func (r *Repository) auth() transport.AuthMethod { - return &http.BasicAuth{ - Username: "git", - Password: r.Token, - } -} - -// Checkout repository branch at specified path -func (r *Repository) Checkout(ctx context.Context, branch, path string) error { - repo, err := git.PlainCloneContext(ctx, path, false, &git.CloneOptions{ - URL: r.GetURL(), - Auth: r.auth(), - RemoteName: git.DefaultRemoteName, - ReferenceName: plumbing.NewBranchReferenceName(branch), - SingleBranch: true, - NoCheckout: false, - Progress: nil, - Tags: git.NoTags, - }) - if err != nil { - return fmt.Errorf("git clone error: %w", err) - } - - _, err = repo.Head() - if err != nil { - return fmt.Errorf("git resolve HEAD error: %w", err) - } - - r.repo = repo - return nil -} - -// Commit changes for the specified path, returns false if no changes are detected -func (r *Repository) Commit(ctx context.Context, path, message string) (bool, error) { - if r.repo == nil { - return false, fmt.Errorf("repository hasn't been cloned") - } - - w, err := r.repo.Worktree() - if err != nil { - return false, err - } - - _, err = w.Add(path) - if err != nil { - return false, err - } - - status, err := w.Status() - if err != nil { - return false, err - } - - if !status.IsClean() { - if _, err := w.Commit(message, &git.CommitOptions{ - Author: &object.Signature{ - Name: r.AuthorName, - Email: r.AuthorEmail, - When: time.Now(), - }, - }); err != nil { - return false, err - } - return true, nil - } - - return false, nil -} - -// Push commits to origin -func (r *Repository) Push(ctx context.Context) error { - if r.repo == nil { - return fmt.Errorf("repository hasn't been cloned") - } - - err := r.repo.PushContext(ctx, &git.PushOptions{ - Auth: r.auth(), - Progress: nil, - }) - if err != nil { - return fmt.Errorf("git push error: %w", err) - } - return nil -}