diff --git a/go.mod b/go.mod index ea91fe5..a71d835 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,6 @@ go 1.23.2 require ( github.com/BurntSushi/toml v1.5.0 github.com/elliotchance/pie/v2 v2.9.1 - github.com/go-git/go-git/v5 v5.16.2 github.com/google/go-github/v68 v68.0.0 github.com/rs/zerolog v1.34.0 github.com/slack-go/slack v0.17.1 @@ -17,38 +16,24 @@ require ( ) require ( - dario.cat/mergo v1.0.2 // indirect - github.com/Microsoft/go-winio v0.6.2 // indirect - github.com/ProtonMail/go-crypto v1.3.0 // indirect - github.com/cloudflare/circl v1.6.1 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.7 // indirect - github.com/cyphar/filepath-securejoin v0.4.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/emirpasic/gods v1.18.1 // indirect - github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect - github.com/go-git/go-billy/v5 v5.6.2 // indirect - github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect + github.com/google/go-cmp v0.7.0 // indirect github.com/google/go-querystring v1.1.0 // indirect github.com/gorilla/websocket v1.5.3 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect github.com/hashicorp/go-retryablehttp v0.7.8 // indirect - github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect - github.com/kevinburke/ssh_config v1.2.0 // indirect + github.com/kr/pretty v0.3.1 // indirect github.com/mattn/go-colorable v0.1.14 // indirect github.com/mattn/go-isatty v0.0.20 // indirect - github.com/pjbgf/sha1cd v0.3.2 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/rogpeppe/go-internal v1.14.1 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect - github.com/sergi/go-diff v1.4.0 // indirect - github.com/skeema/knownhosts v1.3.1 // indirect github.com/stretchr/objx v0.5.2 // indirect - github.com/xanzy/ssh-agent v0.3.3 // indirect github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 // indirect - golang.org/x/crypto v0.39.0 // indirect - golang.org/x/net v0.41.0 // indirect golang.org/x/oauth2 v0.30.0 // indirect golang.org/x/sys v0.33.0 // indirect golang.org/x/time v0.12.0 // indirect - gopkg.in/warnings.v0 v0.1.2 // indirect + gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 2f3f5f1..447ff1d 100644 --- a/go.sum +++ b/go.sum @@ -1,49 +1,18 @@ -dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8= -dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA= github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg= github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= -github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= -github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= -github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= -github.com/ProtonMail/go-crypto v1.3.0 h1:ILq8+Sf5If5DCpHQp4PbZdS1J7HDFRXz/+xKBiRGFrw= -github.com/ProtonMail/go-crypto v1.3.0/go.mod h1:9whxjD8Rbs29b4XWbB8irEcE8KHMqaR2e7GWU1R+/PE= -github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8= -github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4= -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/cloudflare/circl v1.6.1 h1:zqIqSPIndyBh1bjLVVDHMPpVKqp8Su/V+6MeDzzQBQ0= -github.com/cloudflare/circl v1.6.1/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/cpuguy83/go-md2man/v2 v2.0.7 h1:zbFlGlXEAKlwXpmvle3d8Oe3YnkKIK4xSRTd3sHPnBo= github.com/cpuguy83/go-md2man/v2 v2.0.7/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= -github.com/cyphar/filepath-securejoin v0.4.1 h1:JyxxyPEaktOD+GAnqIqTf9A8tHyAG22rowi7HkoSU1s= -github.com/cyphar/filepath-securejoin v0.4.1/go.mod h1:Sdj7gXlvMcPZsbhwhQ33GguGLDGQL7h7bg04C/+u9jI= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= 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/elazarl/goproxy v1.7.2 h1:Y2o6urb7Eule09PjlhQRGNsqRfPmYI3KKQLFpCAV3+o= -github.com/elazarl/goproxy v1.7.2/go.mod h1:82vkLNir0ALaW14Rc399OTTjyNREgmdL2cVoIbS6XaE= github.com/elliotchance/pie/v2 v2.9.1 h1:v7TdC6ZdNZJ1HACofpLXvGKHUk307AjY/bttwDPWKEQ= github.com/elliotchance/pie/v2 v2.9.1/go.mod h1:18t0dgGFH006g4eVdDtWfgFZPQEgl10IoEO8YWEq3Og= -github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= -github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= -github.com/gliderlabs/ssh v0.3.8 h1:a4YXD1V7xMF9g5nTkdfnja3Sxy1PVDCj1Zg4Wb8vY6c= -github.com/gliderlabs/ssh v0.3.8/go.mod h1:xYoytBv1sV0aL3CavoDuJIQNURXkkfPA/wxQ1pL1fAU= -github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI= -github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic= -github.com/go-git/go-billy/v5 v5.6.2 h1:6Q86EsPXMa7c3YZ3aLAQsMA0VlWmy43r6FHqa/UNbRM= -github.com/go-git/go-billy/v5 v5.6.2/go.mod h1:rcFC2rAsp/erv7CMz9GczHcuD0D32fWzH+MJAU+jaUU= -github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4= -github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII= -github.com/go-git/go-git/v5 v5.16.2 h1:fT6ZIOjE5iEnkzKyxTHK1W4HGAsPhqEqiSAssSO77hM= -github.com/go-git/go-git/v5 v5.16.2/go.mod h1:4Ge4alE/5gPs30F2H1esi2gPd69R0C39lolkucHBOp8= github.com/go-test/deep v1.1.1 h1:0r/53hagsehfO4bzD2Pgr/+RgHqhmf+k1Bpse2cTu1U= github.com/go-test/deep v1.1.1/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 h1:f+oWsMOmNPc8JmEHVZIycC7hBoQxHH9pNKQORJNozsQ= -github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8/go.mod h1:wcDNUvekVysuuOpQKo3191zZyTpiI6se1N1ULghS0sw= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= @@ -59,11 +28,7 @@ github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB1 github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= github.com/hashicorp/go-retryablehttp v0.7.8 h1:ylXZWnqa7Lhqpk0L1P1LzDtGcCR0rPVUrx/c8Unxc48= github.com/hashicorp/go-retryablehttp v0.7.8/go.mod h1:rjiScheydd+CxvumBsIrFKlx3iS0jrZ7LvzFGFmuKbw= -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/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4= -github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= @@ -77,14 +42,11 @@ github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/ github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= 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/onsi/gomega v1.34.1 h1:EUMJIKUjM8sKjYbtxQI9A4z2o+rruxnzNvpknOXie6k= -github.com/onsi/gomega v1.34.1/go.mod h1:kU1QgUvBDLXBJq618Xvm2LUX6rSAfRaFRTcdOeDLwwY= -github.com/pjbgf/sha1cd v0.3.2 h1:a9wb0bp1oC2TGwStyn0Umc/IGKQnEgF0vVaZ8QF8eo4= -github.com/pjbgf/sha1cd v0.3.2/go.mod h1:zQWigSxVmsHEZow5qaLtPYxpcKMMQpa09ixqBxuCS6A= -github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.9.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/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0= @@ -92,68 +54,34 @@ github.com/rs/zerolog v1.34.0 h1:k43nTLIwcTVQAncfCw4KZ2VY6ukYoZaBPNOE8txlOeY= github.com/rs/zerolog v1.34.0/go.mod h1:bJsvje4Z08ROH4Nhs5iH600c3IkWhwp44iRc54W6wYQ= 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.4.0 h1:n/SP9D5ad1fORl+llWyN+D6qoUETXNZARKjyY2/KVCw= -github.com/sergi/go-diff v1.4.0/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4= -github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/skeema/knownhosts v1.3.1 h1:X2osQ+RAjK76shCbvhHHHVl3ZlgDm8apHEHFqRjnBY8= -github.com/skeema/knownhosts v1.3.1/go.mod h1:r7KTdC8l4uxWRyK2TpQZ/1o5HaSzh06ePQNxPwTcfiY= github.com/slack-go/slack v0.17.1 h1:x0Mnc6biHBea5vfxLR+x4JFl/Rm3eIo0iS3xDZenX+o= github.com/slack-go/slack v0.17.1/go.mod h1:X+UqOufi3LYQHDnMG1vxf0J8asC6+WllXrVrhl8/Prk= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/urfave/cli/v2 v2.27.7 h1:bH59vdhbjLv3LAvIu6gd0usJHgoTTPhCFib8qqOwXYU= github.com/urfave/cli/v2 v2.27.7/go.mod h1:CyNAG/xg+iAOg0N4MPGZqVmv2rCoP267496AOXUZjA4= -github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM= -github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw= github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGCjxCBTO/36wtF6j2nSip77qHd4x4= github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM= gitlab.com/gitlab-org/api/client-go v0.130.1 h1:1xF5C5Zq3sFeNg3PzS2z63oqrxifne3n/OnbI7nptRc= gitlab.com/gitlab-org/api/client-go v0.130.1/go.mod h1:ZhSxLAWadqP6J9lMh40IAZOlOxBLPRh7yFOXR/bMJWM= -golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.39.0 h1:SHs+kF4LP+f+p14esP5jAoDpHU8Gu/v9lFRK6IT5imM= -golang.org/x/crypto v0.39.0/go.mod h1:L+Xg3Wf6HoL4Bn4238Z6ft6KfEpN0tJGo53AAPC632U= golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b h1:M2rDM6z3Fhozi9O7NWsxAkg/yqS/lQJ6PmkyIV3YP+o= golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b/go.mod h1:3//PLf8L/X+8b4vuAfHzxeRUl04Adcb341+IGKfnqS8= -golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.41.0 h1:vBTly1HeNPEn3wtREYfy4GZ/NECgw2Cnl+nK6Nz3uvw= -golang.org/x/net v0.41.0/go.mod h1:B/K4NNqkfmg07DQYrbwvSluqCJOOXwUjeb/5lOisjbA= golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI= golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU= golang.org/x/sync v0.15.0 h1:KWH3jNZsfyT6xfAfKiz6MRNmd46ByHDYaZ7KSkCtdW8= golang.org/x/sync v0.15.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= -golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.32.0 h1:DR4lr0TjUs3epypdhTOkMmuF5CDFJ/8pOnbzMZPQ7bg= -golang.org/x/term v0.32.0/go.mod h1:uZG1FhGx848Sqfsq4/DlJr3xGGsYMu/L5GW4abiaEPQ= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M= -golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA= golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE= golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 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-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -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.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= 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/internal/compress/extractor.go b/internal/compress/extractor.go new file mode 100644 index 0000000..7ceb3fb --- /dev/null +++ b/internal/compress/extractor.go @@ -0,0 +1,76 @@ +package compress + +import ( + "archive/tar" + "compress/gzip" + "fmt" + "io" + "os" + "path/filepath" + "strings" +) + +// ExtractTarGz extracts a tar.gz archive to the specified destination directory. +func ExtractTarGz(reader io.Reader, destDir string) error { + if _, err := os.Stat(destDir); os.IsNotExist(err) { + return fmt.Errorf("destination directory does not exist: %s", destDir) + } + + gzReader, err := gzip.NewReader(reader) + if err != nil { + return fmt.Errorf("failed to create gzip reader: %w", err) + } + defer gzReader.Close() + + tarReader := tar.NewReader(gzReader) + + for { + header, err := tarReader.Next() + if err == io.EOF { + break + } + if err != nil { + return fmt.Errorf("failed to read tar header: %w", err) + } + + // Skip the root directory (GitLab archives have a root folder) + pathParts := strings.Split(header.Name, "/") + if len(pathParts) <= 1 { + continue + } + + // Remove the first directory component (the root folder) + relativePath := strings.Join(pathParts[1:], "/") + if relativePath == "" { + continue + } + + targetPath := filepath.Join(destDir, relativePath) + if !strings.HasPrefix(targetPath, filepath.Clean(destDir)+string(os.PathSeparator)) { + return fmt.Errorf("content of tar file is trying to write outside of destination directory: %s", relativePath) + } + + switch header.Typeflag { + case tar.TypeDir: + if err := os.MkdirAll(targetPath, os.FileMode(header.Mode)); err != nil { + return fmt.Errorf("failed to create directory %s: %w", targetPath, err) + } + case tar.TypeReg: + if err := os.MkdirAll(filepath.Dir(targetPath), 0755); err != nil { + return fmt.Errorf("failed to create parent directory for %s: %w", targetPath, err) + } + + file, err := os.OpenFile(targetPath, os.O_CREATE|os.O_RDWR|os.O_TRUNC, os.FileMode(header.Mode)) + if err != nil { + return fmt.Errorf("failed to create file %s: %w", targetPath, err) + } + defer file.Close() + + if _, err := io.Copy(file, tarReader); err != nil { + return fmt.Errorf("failed to write file %s: %w", targetPath, err) + } + } + } + + return nil +} diff --git a/internal/patrol/patrol.go b/internal/patrol/patrol.go index 9743455..f81e23f 100644 --- a/internal/patrol/patrol.go +++ b/internal/patrol/patrol.go @@ -196,9 +196,9 @@ func (s *sheriffService) scanProject(project repository.Project) (report *scanne } defer os.RemoveAll(dir) - // Clone the project + // Download the project log.Info().Str("project", project.Path).Str("dir", dir).Str("url", project.RepoUrl).Msg("Cloning project") - if err := s.repoService.Provide(project.Repository).Clone(project, dir); err != nil { + if err := s.repoService.Provide(project.Repository).Download(project, dir); err != nil { return nil, errors.Join(fmt.Errorf("failed to clone project %v", project.Path), err) } diff --git a/internal/patrol/patrol_test.go b/internal/patrol/patrol_test.go index c3d21a5..878dca6 100644 --- a/internal/patrol/patrol_test.go +++ b/internal/patrol/patrol_test.go @@ -52,7 +52,7 @@ func TestScanNonVulnerableProject(t *testing.T) { mockClient := &mockClient{} mockClient.On("GetProjectList", []string{"group/to/scan"}).Return([]repository.Project{{Name: "Hello World", RepoUrl: "https://gitlab.com/group/to/scan.git", Repository: repository.Gitlab}}, nil) mockClient.On("CloseVulnerabilityIssue", mock.Anything).Return(nil) - mockClient.On("Clone", "https://gitlab.com/group/to/scan.git", mock.Anything).Return(nil) + mockClient.On("Download", "https://gitlab.com/group/to/scan.git", mock.Anything).Return(nil) mockRepoService := &mockRepoService{} mockRepoService.On("Provide", repository.Gitlab).Return(mockClient) @@ -87,7 +87,7 @@ func TestScanVulnerableProject(t *testing.T) { mockClient := &mockClient{} mockClient.On("GetProjectList", []string{"group/to/scan"}).Return([]repository.Project{{Name: "Hello World", RepoUrl: "https://gitlab.com/group/to/scan.git", Repository: repository.Gitlab}}, nil) mockClient.On("OpenVulnerabilityIssue", mock.Anything, mock.Anything).Return(&repository.Issue{}, nil) - mockClient.On("Clone", "https://gitlab.com/group/to/scan.git", mock.Anything).Return(nil) + mockClient.On("Download", "https://gitlab.com/group/to/scan.git", mock.Anything).Return(nil) mockRepoService := &mockRepoService{} mockRepoService.On("Provide", repository.Gitlab).Return(mockClient) @@ -239,7 +239,7 @@ func (c *mockClient) OpenVulnerabilityIssue(project repository.Project, report s return args.Get(0).(*repository.Issue), args.Error(1) } -func (c *mockClient) Clone(project repository.Project, dir string) error { +func (c *mockClient) Download(project repository.Project, dir string) error { args := c.Called(project.RepoUrl, dir) return args.Error(0) } diff --git a/internal/publish/to_issue_test.go b/internal/publish/to_issue_test.go index 6b1db23..ae23bbc 100644 --- a/internal/publish/to_issue_test.go +++ b/internal/publish/to_issue_test.go @@ -242,7 +242,7 @@ func (c *mockGitlabService) OpenVulnerabilityIssue(project repository.Project, r return args.Get(0).(*repository.Issue), args.Error(1) } -func (c *mockGitlabService) Clone(project repository.Project, dir string) error { +func (c *mockGitlabService) Download(project repository.Project, dir string) error { args := c.Called(project.RepoUrl, dir) return args.Error(0) } diff --git a/internal/repository/github/github.go b/internal/repository/github/github.go index 6f00b6e..532d9b0 100644 --- a/internal/repository/github/github.go +++ b/internal/repository/github/github.go @@ -1,29 +1,40 @@ package github import ( + "context" "errors" "fmt" + + "net/http" + "sheriff/internal/compress" "sheriff/internal/repository" "strings" + "time" "github.com/elliotchance/pie/v2" - "github.com/go-git/go-git/v5" - "github.com/go-git/go-git/v5/plumbing/transport/http" "github.com/google/go-github/v68/github" "github.com/rs/zerolog/log" "golang.org/x/sync/errgroup" ) type githubService struct { - client iGithubClient - token string + client iGithubClient + httpClient *http.Client + token string } // newGithubRepo creates a new GitHub repository service func New(token string) githubService { client := github.NewClient(nil) + httpClient := &http.Client{ + Timeout: 30 * time.Second, + } - s := githubService{client: &githubClient{client: client}, token: token} + s := githubService{ + client: &githubClient{client: client}, + httpClient: httpClient, + token: token, + } return s } @@ -67,17 +78,36 @@ func (s githubService) OpenVulnerabilityIssue(project repository.Project, report return nil, errors.New("OpenVulnerabilityIssue not yet implemented") // TODO #9 Add github support } -func (s githubService) Clone(project repository.Project, dir string) (err error) { - _, err = git.PlainClone(dir, false, &git.CloneOptions{ - URL: project.RepoUrl, - Auth: &http.BasicAuth{ - Username: "N/A", - Password: s.token, - }, - Depth: 1, - }) +func (s githubService) Download(project repository.Project, dir string) (err error) { + // Get archive download URL using GitHub API + archiveURL, _, err := s.client.GetArchiveLink(project.GroupOrOwner, project.Name, github.Tarball, &github.RepositoryContentGetOptions{}) + if err != nil { + return fmt.Errorf("failed to get GitHub archive link: %w", err) + } + + log.Debug().Str("archiveURL", archiveURL.String()).Msg("Got GitHub archive URL") + + // Create request with context + ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) + defer cancel() + + req, err := http.NewRequestWithContext(ctx, "GET", archiveURL.String(), nil) + if err != nil { + return fmt.Errorf("failed to create request: %w", err) + } + + // Download the archive from the URL using the shared HTTP client + resp, err := s.httpClient.Do(req) + if err != nil { + return fmt.Errorf("failed to download GitHub archive: %w", err) + } + defer resp.Body.Close() - return err + if resp.StatusCode != http.StatusOK { + return fmt.Errorf("failed to download GitHub archive, status: %s", resp.Status) + } + + return compress.ExtractTarGz(resp.Body, dir) } func (s githubService) getPathRepos(path string) (repositories []github.Repository, err error) { @@ -187,14 +217,21 @@ func derefRepoPtrs(owner string, repoPtrs []*github.Repository) (repos []github. } func mapGithubProject(r github.Repository) repository.Project { + var groupName = "" + owner := r.GetOwner() + if owner != nil { + groupName = owner.GetLogin() + } + return repository.Project{ - ID: int(valueOrEmpty(r.ID)), - Name: valueOrEmpty(r.Name), - Path: valueOrEmpty(r.FullName), - Slug: valueOrEmpty(r.Name), - WebURL: valueOrEmpty(r.HTMLURL), - RepoUrl: valueOrEmpty(r.HTMLURL), - Repository: repository.Github, + ID: int(valueOrEmpty(r.ID)), + Name: valueOrEmpty(r.Name), + GroupOrOwner: valueOrEmpty(&groupName), + Path: valueOrEmpty(r.FullName), + Slug: valueOrEmpty(r.Name), + WebURL: valueOrEmpty(r.HTMLURL), + RepoUrl: valueOrEmpty(r.HTMLURL), + Repository: repository.Github, } } diff --git a/internal/repository/github/github_client.go b/internal/repository/github/github_client.go index 9912b3e..d6af4d3 100644 --- a/internal/repository/github/github_client.go +++ b/internal/repository/github/github_client.go @@ -1,8 +1,9 @@ -// Package gitlab provides a GitLab service to interact with the GitLab API. +// Package github provides a GitHub service to interact with the GitHub API. package github import ( "context" + "net/url" "github.com/google/go-github/v68/github" ) @@ -15,6 +16,7 @@ type iGithubClient interface { GetRepository(owner string, repo string) (*github.Repository, *github.Response, error) GetOrganizationRepositories(org string, opts *github.RepositoryListByOrgOptions) ([]*github.Repository, *github.Response, error) GetUserRepositories(user string, opts *github.RepositoryListByUserOptions) ([]*github.Repository, *github.Response, error) + GetArchiveLink(owner string, repo string, archiveFormat github.ArchiveFormat, opts *github.RepositoryContentGetOptions) (*url.URL, *github.Response, error) } type githubClient struct { @@ -32,3 +34,7 @@ func (c *githubClient) GetOrganizationRepositories(org string, opts *github.Repo func (c *githubClient) GetUserRepositories(user string, opts *github.RepositoryListByUserOptions) ([]*github.Repository, *github.Response, error) { return c.client.Repositories.ListByUser(context.Background(), user, opts) } + +func (c *githubClient) GetArchiveLink(owner string, repo string, archiveFormat github.ArchiveFormat, opts *github.RepositoryContentGetOptions) (*url.URL, *github.Response, error) { + return c.client.Repositories.GetArchiveLink(context.Background(), owner, repo, archiveFormat, opts, 3) +} diff --git a/internal/repository/github/github_test.go b/internal/repository/github/github_test.go index 20c84c2..beddf57 100644 --- a/internal/repository/github/github_test.go +++ b/internal/repository/github/github_test.go @@ -2,18 +2,31 @@ package github import ( "errors" + "net/http" + "net/http/httptest" + "net/url" + "os" + "path/filepath" + "sheriff/internal/repository" "testing" + "time" "github.com/google/go-github/v68/github" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" ) func TestGetProjectListOrganizationRepos(t *testing.T) { mockService := mockService{} mockService.On("GetOrganizationRepositories", "org", mock.Anything).Return([]*github.Repository{{Name: github.Ptr("Hello World")}}, &github.Response{}, nil) - svc := githubService{client: &mockService} + svc := githubService{ + client: &mockService, + httpClient: &http.Client{ + Timeout: 30 * time.Second, + }, + } projects, err := svc.GetProjectList([]string{"org"}) @@ -28,7 +41,12 @@ func TestGetProjectListUserRepos(t *testing.T) { mockService.On("GetOrganizationRepositories", "user", mock.Anything).Return([]*github.Repository{}, &github.Response{}, errors.New("error")) mockService.On("GetUserRepositories", "user", mock.Anything).Return([]*github.Repository{{Name: github.Ptr("Hello World")}}, &github.Response{}, nil) - svc := githubService{client: &mockService} + svc := githubService{ + client: &mockService, + httpClient: &http.Client{ + Timeout: 30 * time.Second, + }, + } projects, err := svc.GetProjectList([]string{"user"}) @@ -42,7 +60,12 @@ func TestGetProjectSpecificRepo(t *testing.T) { mockService := mockService{} mockService.On("GetRepository", "owner", "repo").Return(&github.Repository{Name: github.Ptr("Hello World")}, &github.Response{}, nil) - svc := githubService{client: &mockService} + svc := githubService{ + client: &mockService, + httpClient: &http.Client{ + Timeout: 30 * time.Second, + }, + } projects, err := svc.GetProjectList([]string{"owner/repo"}) @@ -70,7 +93,12 @@ func TestGetProjectListWithNextPage(t *testing.T) { }, }, mock.Anything).Return([]*github.Repository{project2}, &github.Response{NextPage: 0}, nil) - svc := githubService{client: &mockService} + svc := githubService{ + client: &mockService, + httpClient: &http.Client{ + Timeout: 30 * time.Second, + }, + } projects, err := svc.GetProjectList([]string{"org"}) @@ -111,3 +139,75 @@ func (c *mockService) GetUserRepositories(user string, opts *github.RepositoryLi } return args.Get(0).([]*github.Repository), r, args.Error(2) } + +func (c *mockService) GetArchiveLink(owner string, repo string, archiveFormat github.ArchiveFormat, opts *github.RepositoryContentGetOptions) (*url.URL, *github.Response, error) { + args := c.Called(owner, repo, archiveFormat, opts) + var r *github.Response + if resp := args.Get(1); resp != nil { + r = args.Get(1).(*github.Response) + } + return args.Get(0).(*url.URL), r, args.Error(2) +} + +func TestDownload(t *testing.T) { + // Create temporary directory for testing + tempDir, err := os.MkdirTemp("", "sheriff-clone-test-") + require.NoError(t, err) + defer os.RemoveAll(tempDir) + + // Read the same stub archive used by GitLab tests + stubArchive, err := os.ReadFile("../testdata/sample-archive.tar.gz") + require.NoError(t, err) + + // Create a mock HTTP server to serve the archive + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/gzip") + w.WriteHeader(http.StatusOK) + if _, err := w.Write(stubArchive); err != nil { + http.Error(w, "Failed to write archive", http.StatusInternalServerError) + } + })) + defer server.Close() + + // Parse the server URL + archiveURL, err := url.Parse(server.URL + "/archive.tar.gz") + require.NoError(t, err) + + // Setup mock client + mockService := mockService{} + mockService.On("GetArchiveLink", "owner", "test-project", github.Tarball, mock.Anything).Return(archiveURL, &github.Response{}, nil) + + svc := githubService{ + client: &mockService, + httpClient: &http.Client{ + Timeout: 30 * time.Second, + }, + } + + // Create a test project + testProject := repository.Project{ + ID: 123, + Name: "test-project", + GroupOrOwner: "owner", + Path: "owner/test-project", + } + + err = svc.Download(testProject, tempDir) + + // Verify no errors + assert.NoError(t, err) + mockService.AssertExpectations(t) + + // Verify files were extracted correctly (same verification as GitLab test) + readmeContent, err := os.ReadFile(filepath.Join(tempDir, "README.md")) + assert.NoError(t, err) + assert.Equal(t, "# Test Project\n\nThis is a test project for testing GitLab archive extraction.", string(readmeContent)) + + srcContent, err := os.ReadFile(filepath.Join(tempDir, "src", "main.go")) + assert.NoError(t, err) + assert.Equal(t, "package main\n\nimport \"fmt\"\n\nfunc main() {\n\tfmt.Println(\"Hello from test project!\")\n}", string(srcContent)) + + // Verify directory structure + _, err = os.Stat(filepath.Join(tempDir, "src")) + assert.NoError(t, err, "src directory should exist") +} diff --git a/internal/repository/gitlab/gitlab.go b/internal/repository/gitlab/gitlab.go index e290245..c017dfd 100644 --- a/internal/repository/gitlab/gitlab.go +++ b/internal/repository/gitlab/gitlab.go @@ -1,16 +1,12 @@ package gitlab import ( - "archive/tar" "bytes" - "compress/gzip" "errors" "fmt" - "io" "os" - "path/filepath" + "sheriff/internal/compress" "sheriff/internal/repository" - "strings" "sync" "github.com/elliotchance/pie/v2" @@ -120,7 +116,7 @@ func (s gitlabService) OpenVulnerabilityIssue(project repository.Project, report return } -func (s gitlabService) Clone(project repository.Project, dir string) (err error) { +func (s gitlabService) Download(project repository.Project, dir string) (err error) { archiveData, _, err := s.client.Archive(project.ID, &gitlab.ArchiveOptions{}) if err != nil { return fmt.Errorf("failed to download archive: %w", err) @@ -131,8 +127,8 @@ func (s gitlabService) Clone(project repository.Project, dir string) (err error) return fmt.Errorf("failed to create directory: %w", err) } - // Extract archive to directory - return s.extractTarGz(bytes.NewReader(archiveData), dir) + // Extract archive to directory using the shared compress package + return compress.ExtractTarGz(bytes.NewReader(archiveData), dir) } // This function receives a list of paths which can be gitlab projects or groups @@ -324,14 +320,21 @@ func dereferenceProjectsPointers(projects []*gitlab.Project) (filteredProjects [ } func mapProject(p gitlab.Project) repository.Project { + group := "" + namespace := p.Namespace + if namespace != nil { + group = namespace.Name + } + return repository.Project{ - ID: p.ID, - Name: p.Name, - Slug: p.Path, - Path: p.PathWithNamespace, - WebURL: p.WebURL, - RepoUrl: p.HTTPURLToRepo, - Repository: repository.Gitlab, + ID: p.ID, + Name: p.Name, + Slug: p.Path, + GroupOrOwner: group, + Path: p.PathWithNamespace, + WebURL: p.WebURL, + RepoUrl: p.HTTPURLToRepo, + Repository: repository.Gitlab, } } @@ -351,65 +354,3 @@ func mapIssuePtr(i *gitlab.Issue) *repository.Issue { return &issue } - -// extractTarGz extracts a tar.gz archive -func (s gitlabService) extractTarGz(reader io.Reader, destDir string) error { - // TODO(#52): Move to a separate package when implementing GitHub "clone" through downloading archives - gzReader, err := gzip.NewReader(reader) - if err != nil { - return fmt.Errorf("failed to create gzip reader: %w", err) - } - defer gzReader.Close() - - tarReader := tar.NewReader(gzReader) - - for { - header, err := tarReader.Next() - if err == io.EOF { - break - } - if err != nil { - return fmt.Errorf("failed to read tar header: %w", err) - } - - // Skip the root directory (GitLab archives have a root folder) - pathParts := strings.Split(header.Name, "/") - if len(pathParts) <= 1 { - continue - } - - // Remove the first directory component (the root folder) - relativePath := strings.Join(pathParts[1:], "/") - if relativePath == "" { - continue - } - - targetPath := filepath.Join(destDir, relativePath) - if !strings.HasPrefix(targetPath, filepath.Clean(destDir)+string(os.PathSeparator)) { - return fmt.Errorf("content of tar file is trying to write outside of destination directory: %s", relativePath) - } - - switch header.Typeflag { - case tar.TypeDir: - if err := os.MkdirAll(targetPath, os.FileMode(header.Mode)); err != nil { - return fmt.Errorf("failed to create directory %s: %w", targetPath, err) - } - case tar.TypeReg: - if err := os.MkdirAll(filepath.Dir(targetPath), 0755); err != nil { - return fmt.Errorf("failed to create parent directory for %s: %w", targetPath, err) - } - - file, err := os.OpenFile(targetPath, os.O_CREATE|os.O_RDWR|os.O_TRUNC, os.FileMode(header.Mode)) - if err != nil { - return fmt.Errorf("failed to create file %s: %w", targetPath, err) - } - defer file.Close() - - if _, err := io.Copy(file, tarReader); err != nil { - return fmt.Errorf("failed to write file %s: %w", targetPath, err) - } - } - } - - return nil -} diff --git a/internal/repository/gitlab/gitlab_test.go b/internal/repository/gitlab/gitlab_test.go index 12c6e88..3c369d2 100644 --- a/internal/repository/gitlab/gitlab_test.go +++ b/internal/repository/gitlab/gitlab_test.go @@ -202,13 +202,13 @@ func TestDereferenceProjectsPointers(t *testing.T) { assert.Equal(t, 2, dereferencedProjects[1].ID) assert.Equal(t, 2, errCount) } -func TestCloneCompleteFlow(t *testing.T) { +func TestDownload(t *testing.T) { // Create temporary directory for testing tempDir, err := os.MkdirTemp("", "sheriff-clone-test-") require.NoError(t, err) defer os.RemoveAll(tempDir) - stubArchive, err := os.ReadFile("testdata/sample-archive.tar.gz") + stubArchive, err := os.ReadFile("../testdata/sample-archive.tar.gz") require.NoError(t, err) mockClient := mockClient{} @@ -218,12 +218,13 @@ func TestCloneCompleteFlow(t *testing.T) { // Create a test project testProject := repository.Project{ - ID: 123, - Name: "test-project", - Path: "group/project", + ID: 123, + Name: "test-project", + GroupOrOwner: "group", + Path: "group/project", } - err = svc.Clone(testProject, tempDir) + err = svc.Download(testProject, tempDir) // Verify no errors assert.NoError(t, err) diff --git a/internal/repository/repository.go b/internal/repository/repository.go index 13ebadbc..4c04a00 100644 --- a/internal/repository/repository.go +++ b/internal/repository/repository.go @@ -10,13 +10,14 @@ const ( ) type Project struct { - ID int - Name string - Slug string - Path string - WebURL string - RepoUrl string - Repository RepositoryType + ID int + Name string + Slug string + GroupOrOwner string + Path string + WebURL string + RepoUrl string + Repository RepositoryType } type Issue struct { @@ -30,5 +31,5 @@ type IRepositoryService interface { GetProjectList(paths []string) (projects []Project, warn error) CloseVulnerabilityIssue(project Project) error OpenVulnerabilityIssue(project Project, report string) (*Issue, error) - Clone(project Project, dir string) error + Download(project Project, dir string) error } diff --git a/internal/repository/gitlab/testdata/sample-archive.tar.gz b/internal/repository/testdata/sample-archive.tar.gz similarity index 100% rename from internal/repository/gitlab/testdata/sample-archive.tar.gz rename to internal/repository/testdata/sample-archive.tar.gz