From 6e49d65d9e5de2321da21cf8a7112b371e0a014f Mon Sep 17 00:00:00 2001 From: John Cai Date: Thu, 20 Jun 2019 08:18:41 -0700 Subject: [PATCH 1/2] Migrate hooks to use go binary --- _support/makegen.go | 2 +- cmd/hooks/hooks.go | 21 +++++++ cmd/hooks/postreceive/postceive.go | 68 +++++++++++++++++++++ cmd/hooks/prereceive/preceive.go | 70 ++++++++++++++++++++++ cmd/hooks/update/update.go | 70 ++++++++++++++++++++++ go.mod | 6 +- go.sum | 12 +++- internal/git/hooks/hooks.go | 12 ++++ internal/rubyserver/rubyserver.go | 2 +- internal/service/hook/post_receive.go | 39 ++++++++++++ internal/service/hook/pre_receive.go | 40 +++++++++++++ internal/service/hook/server.go | 10 ++++ internal/service/hook/update.go | 32 ++++++++++ internal/service/smarthttp/receive_pack.go | 3 +- internal/service/ssh/receive_pack.go | 3 +- ruby/gitlab-shell/hooks/post-receive | 3 +- ruby/gitlab-shell/hooks/pre-receive | 3 +- ruby/gitlab-shell/hooks/update | 3 +- 18 files changed, 387 insertions(+), 12 deletions(-) create mode 100644 cmd/hooks/hooks.go create mode 100644 cmd/hooks/postreceive/postceive.go create mode 100644 cmd/hooks/prereceive/preceive.go create mode 100644 cmd/hooks/update/update.go create mode 100644 internal/service/hook/post_receive.go create mode 100644 internal/service/hook/pre_receive.go create mode 100644 internal/service/hook/server.go create mode 100644 internal/service/hook/update.go diff --git a/_support/makegen.go b/_support/makegen.go index 3227f1240b2..9a16b2119b2 100644 --- a/_support/makegen.go +++ b/_support/makegen.go @@ -135,7 +135,7 @@ func (gm *gitalyMake) CommandPackages() []string { for _, dir := range entries { //Do not build gitaly-remote by default - if dir.Name() == "gitaly-remote" { + if dir.Name() == "gitaly-remote" || dir.Name() == "hooks" { continue } if !dir.IsDir() { diff --git a/cmd/hooks/hooks.go b/cmd/hooks/hooks.go new file mode 100644 index 00000000000..53a471b9f19 --- /dev/null +++ b/cmd/hooks/hooks.go @@ -0,0 +1,21 @@ +package hooks + +import ( + "bufio" + "io" +) + +func ReadRefs(r io.Reader) ([]string, error) { + s := bufio.NewScanner(r) + + var refs []string + for s.Scan() { + refs = append(refs, s.Text()) + } + + if err := s.Err(); err != nil { + return nil, err + } + + return refs, nil +} diff --git a/cmd/hooks/postreceive/postceive.go b/cmd/hooks/postreceive/postceive.go new file mode 100644 index 00000000000..41c7af5bfe1 --- /dev/null +++ b/cmd/hooks/postreceive/postceive.go @@ -0,0 +1,68 @@ +package main + +import ( + "context" + "log" + "os" + + grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware" + "gitlab.com/gitlab-org/gitaly-proto/go/gitalypb" + gitalyauth "gitlab.com/gitlab-org/gitaly/auth" + "gitlab.com/gitlab-org/gitaly/client" + "gitlab.com/gitlab-org/gitaly/cmd/hooks" + grpccorrelation "gitlab.com/gitlab-org/labkit/correlation/grpc" + grpctracing "gitlab.com/gitlab-org/labkit/tracing/grpc" + "google.golang.org/grpc" +) + +func main() { + refs, err := hooks.ReadRefs(os.Stdin) + if err != nil { + log.Fatalf("error when reading refs: %v", err) + } + keyID := os.Getenv("GL_ID") + repoPath, err := os.Getwd() + if err != nil { + log.Fatalf("error when getting pwd: %v", err) + } + glRepository := os.Getenv("GL_REPOSITORY") + url := os.Getenv("GL_URL") + + conn, err := client.Dial(url, dialOpts()) + if err != nil { + log.Fatalf("error when dialing: %v", err) + } + + c := gitalypb.NewHookServiceClient(conn) + + if _, err = c.PostReceive(context.Background(), &gitalypb.PostReceiveHookRequest{ + RepoPath: repoPath, + KeyId: keyID, + GlRepository: glRepository, + Refs: refs, + }); err != nil { + log.Fatalf("error when calling pre receive hook: %v", err) + } +} + +func dialOpts() []grpc.DialOption { + connOpts := client.DefaultDialOpts + if token := os.Getenv("GITALY_TOKEN"); token != "" { + connOpts = append(connOpts, grpc.WithPerRPCCredentials(gitalyauth.RPCCredentials(token))) + } + + // Add grpc client interceptors + connOpts = append(connOpts, grpc.WithStreamInterceptor( + grpc_middleware.ChainStreamClient( + grpctracing.StreamClientTracingInterceptor(), // Tracing + grpccorrelation.StreamClientCorrelationInterceptor(), // Correlation + )), + + grpc.WithUnaryInterceptor( + grpc_middleware.ChainUnaryClient( + grpctracing.UnaryClientTracingInterceptor(), // Tracing + grpccorrelation.UnaryClientCorrelationInterceptor(), // Correlation + ))) + + return connOpts +} diff --git a/cmd/hooks/prereceive/preceive.go b/cmd/hooks/prereceive/preceive.go new file mode 100644 index 00000000000..36dfe7c0896 --- /dev/null +++ b/cmd/hooks/prereceive/preceive.go @@ -0,0 +1,70 @@ +package main + +import ( + "context" + "log" + "os" + + grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware" + "gitlab.com/gitlab-org/gitaly-proto/go/gitalypb" + gitalyauth "gitlab.com/gitlab-org/gitaly/auth" + "gitlab.com/gitlab-org/gitaly/client" + "gitlab.com/gitlab-org/gitaly/cmd/hooks" + grpccorrelation "gitlab.com/gitlab-org/labkit/correlation/grpc" + grpctracing "gitlab.com/gitlab-org/labkit/tracing/grpc" + "google.golang.org/grpc" +) + +func main() { + refs, err := hooks.ReadRefs(os.Stdin) + if err != nil { + log.Fatalf("error when reading refs: %v", err) + } + keyID := os.Getenv("GL_ID") + protocol := os.Getenv("GL_PROTOCOL") + repoPath, err := os.Getwd() + if err != nil { + log.Fatalf("error when getting pwd: %v", err) + } + glRepository := os.Getenv("GL_REPOSITORY") + url := os.Getenv("GL_URL") + + conn, err := client.Dial(url, dialOpts()) + if err != nil { + log.Fatalf("error when dialing: %v", err) + } + + c := gitalypb.NewHookServiceClient(conn) + + if _, err = c.PreReceive(context.Background(), &gitalypb.PreReceiveHookRequest{ + GlRepository: glRepository, + RepoPath: repoPath, + KeyId: keyID, + Protocol: protocol, + Refs: refs, + }); err != nil { + log.Fatalf("error when calling pre receive hook: %v", err) + } +} + +func dialOpts() []grpc.DialOption { + connOpts := client.DefaultDialOpts + if token := os.Getenv("GITALY_TOKEN"); token != "" { + connOpts = append(connOpts, grpc.WithPerRPCCredentials(gitalyauth.RPCCredentials(token))) + } + + // Add grpc client interceptors + connOpts = append(connOpts, grpc.WithStreamInterceptor( + grpc_middleware.ChainStreamClient( + grpctracing.StreamClientTracingInterceptor(), // Tracing + grpccorrelation.StreamClientCorrelationInterceptor(), // Correlation + )), + + grpc.WithUnaryInterceptor( + grpc_middleware.ChainUnaryClient( + grpctracing.UnaryClientTracingInterceptor(), // Tracing + grpccorrelation.UnaryClientCorrelationInterceptor(), // Correlation + ))) + + return connOpts +} diff --git a/cmd/hooks/update/update.go b/cmd/hooks/update/update.go new file mode 100644 index 00000000000..49a2b8e4034 --- /dev/null +++ b/cmd/hooks/update/update.go @@ -0,0 +1,70 @@ +package main + +import ( + "context" + "log" + "os" + + grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware" + "gitlab.com/gitlab-org/gitaly-proto/go/gitalypb" + gitalyauth "gitlab.com/gitlab-org/gitaly/auth" + "gitlab.com/gitlab-org/gitaly/client" + grpccorrelation "gitlab.com/gitlab-org/labkit/correlation/grpc" + grpctracing "gitlab.com/gitlab-org/labkit/tracing/grpc" + "google.golang.org/grpc" +) + +func main() { + keyID := os.Getenv("GL_ID") + repoPath, err := os.Getwd() + if err != nil { + log.Fatalf("error when getting pwd: %v", err) + } + + if len(os.Args) < 4 { + log.Fatalf("only found %d arguments, 3 required", len(os.Args)-1) + } + + refName, oldVal, newVal := os.Args[1], os.Args[2], os.Args[3] + + url := os.Getenv("GL_URL") + + conn, err := client.Dial(url, dialOpts()) + if err != nil { + log.Fatalf("error when dialing: %v", err) + } + + c := gitalypb.NewHookServiceClient(conn) + + if _, err = c.Update(context.Background(), &gitalypb.UpdateHookRequest{ + RepoPath: repoPath, + KeyId: keyID, + Ref: refName, + OldValue: oldVal, + NewValue: newVal, + }); err != nil { + log.Fatalf("error when calling pre receive hook: %v", err) + } +} + +func dialOpts() []grpc.DialOption { + connOpts := client.DefaultDialOpts + if token := os.Getenv("GITALY_TOKEN"); token != "" { + connOpts = append(connOpts, grpc.WithPerRPCCredentials(gitalyauth.RPCCredentials(token))) + } + + // Add grpc client interceptors + connOpts = append(connOpts, grpc.WithStreamInterceptor( + grpc_middleware.ChainStreamClient( + grpctracing.StreamClientTracingInterceptor(), // Tracing + grpccorrelation.StreamClientCorrelationInterceptor(), // Correlation + )), + + grpc.WithUnaryInterceptor( + grpc_middleware.ChainUnaryClient( + grpctracing.UnaryClientTracingInterceptor(), // Tracing + grpccorrelation.UnaryClientCorrelationInterceptor(), // Correlation + ))) + + return connOpts +} diff --git a/go.mod b/go.mod index 0daf1038a7b..aafd83b186b 100644 --- a/go.mod +++ b/go.mod @@ -13,12 +13,12 @@ require ( github.com/sirupsen/logrus v1.2.0 github.com/stretchr/testify v1.2.2 github.com/tinylib/msgp v1.1.0 // indirect - gitlab.com/gitlab-org/gitaly-proto v1.32.0 + gitlab.com/gitlab-org/gitaly-proto v1.33.1-0.20190620230240-211d8c765403 gitlab.com/gitlab-org/labkit v0.0.0-20190221122536-0c3fc7cdd57c - golang.org/x/net v0.0.0-20190311183353-d8887717615a + golang.org/x/net v0.0.0-20190620200207-3b0461eec859 golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4 golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a google.golang.org/genproto v0.0.0-20181202183823-bd91e49a0898 // indirect - google.golang.org/grpc v1.16.0 + google.golang.org/grpc v1.21.1 gopkg.in/yaml.v2 v2.2.2 // indirect ) diff --git a/go.sum b/go.sum index cc56b0adbd6..0fab420f057 100644 --- a/go.sum +++ b/go.sum @@ -38,6 +38,7 @@ github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfb github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/grpc-ecosystem/go-grpc-middleware v1.0.0 h1:Iju5GlWwrvL6UBg4zJJt3btmonfrMlCDdsejg4CZE7c= github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho= @@ -102,8 +103,8 @@ github.com/uber/jaeger-client-go v2.15.0+incompatible h1:NP3qsSqNxh8VYr956ur1N/1 github.com/uber/jaeger-client-go v2.15.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= github.com/uber/jaeger-lib v1.5.0 h1:OHbgr8l656Ub3Fw5k9SWnBfIEwvoHQ+W2y+Aa9D1Uyo= github.com/uber/jaeger-lib v1.5.0/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U= -gitlab.com/gitlab-org/gitaly-proto v1.32.0 h1:TRe/iw/Gid1RNM2VzK+WICIw4/N7V5s0IdhmgiPyqNE= -gitlab.com/gitlab-org/gitaly-proto v1.32.0/go.mod h1:zNjk/86bjwLVJ4NcvInBcXcLdptdRFQ28sYrdFbrFgY= +gitlab.com/gitlab-org/gitaly-proto v1.33.1-0.20190620230240-211d8c765403 h1:uaMwn3J9CJJaAYwRozQL2VNslSz3Rnl1/tGZtDJRkWc= +gitlab.com/gitlab-org/gitaly-proto v1.33.1-0.20190620230240-211d8c765403/go.mod h1:r5s9CB3KH8viERqMaQg3eWIgk96p3eexfULUCepPU5g= gitlab.com/gitlab-org/labkit v0.0.0-20190221122536-0c3fc7cdd57c h1:xo48LcGsTCasKcJpQDBCCuZU+aP8uGaboUVvD7Lgm6g= gitlab.com/gitlab-org/labkit v0.0.0-20190221122536-0c3fc7cdd57c/go.mod h1:rYhLgfrbEcyfinG+R3EvKu6bZSsmwQqcXzLfHWSfUKM= go.uber.org/atomic v1.3.2 h1:2Oa65PReHzfn29GpvgsYwloV9AVFHPDk8tYxt2c2tr4= @@ -112,12 +113,15 @@ golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnf golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181106065722-10aee1819953/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a h1:oWX7TPOiFAMXLq8o0ikBYfCJVlRHBcsciT5bXOrH628= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859 h1:R/3boaszxrf1GEUWTVDzSKVwLmSJpwZ1yqXm8j0v2QI= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be h1:vEDujvNQGv4jgYKudGeI/+DAX4Jffq6hpD55MmoEvKs= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA= @@ -135,6 +139,7 @@ golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= google.golang.org/appengine v1.1.0 h1:igQkv0AAhEIvTEpD5LIpAfav2eeVO9HBTjvKHVJPRSs= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= @@ -142,6 +147,8 @@ google.golang.org/genproto v0.0.0-20181202183823-bd91e49a0898 h1:yvw+zsSmSM02Z5H google.golang.org/genproto v0.0.0-20181202183823-bd91e49a0898/go.mod h1:7Ep/1NZk928CDR8SjdVbjWNpdIf6nzjE3BTgJDr2Atg= google.golang.org/grpc v1.16.0 h1:dz5IJGuC2BB7qXR5AyHNwAUBhZscK2xVez7mznh72sY= google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio= +google.golang.org/grpc v1.21.1 h1:j6XxA85m/6txkUCHvzlV5f+HBNl/1r5cZ2A/3IEFOO8= +google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= gopkg.in/DataDog/dd-trace-go.v1 v1.7.0 h1:7wbMayb6JXcbAS95RN7MI42W3o1BCxCcdIzZfVWBAiE= gopkg.in/DataDog/dd-trace-go.v1 v1.7.0/go.mod h1:DVp8HmDh8PuTu2Z0fVVlBsyWaC++fzwVCaGWylTe3tg= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= @@ -155,3 +162,4 @@ gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/internal/git/hooks/hooks.go b/internal/git/hooks/hooks.go index c77c3ed1e37..05a8700cb3f 100644 --- a/internal/git/hooks/hooks.go +++ b/internal/git/hooks/hooks.go @@ -25,3 +25,15 @@ func Path() string { return path.Join(config.Config.Ruby.Dir, "git-hooks") } + +func GitPath() string { + if len(Override) > 0 { + return Override + } + + if os.Getenv("GITALY_TESTING_NO_GIT_HOOKS") == "1" { + return "/var/empty" + } + + return path.Join(config.Config.BinDir, "hooks") +} diff --git a/internal/rubyserver/rubyserver.go b/internal/rubyserver/rubyserver.go index 3b75b665ee7..cda8da076e7 100644 --- a/internal/rubyserver/rubyserver.go +++ b/internal/rubyserver/rubyserver.go @@ -111,7 +111,7 @@ func Start() (*Server, error) { "GITALY_RUBY_GITLAB_SHELL_PATH="+cfg.GitlabShell.Dir, "GITALY_RUBY_GITALY_BIN_DIR="+cfg.BinDir, "GITALY_VERSION="+version.GetVersion(), - "GITALY_GIT_HOOKS_DIR="+hooks.Path(), + "GITALY_GIT_HOOKS_DIR="+hooks.GitPath(), ) env = append(env, command.GitEnv...) diff --git a/internal/service/hook/post_receive.go b/internal/service/hook/post_receive.go new file mode 100644 index 00000000000..f72ef94fe03 --- /dev/null +++ b/internal/service/hook/post_receive.go @@ -0,0 +1,39 @@ +package hook + +import ( + "bytes" + "context" + "fmt" + "os/exec" + + "gitlab.com/gitlab-org/gitaly-proto/go/gitalypb" + "gitlab.com/gitlab-org/gitaly/internal/command" + "gitlab.com/gitlab-org/gitaly/internal/git/hooks" + "gitlab.com/gitlab-org/gitaly/internal/helper" +) + +func (s *server) PostReceive(ctx context.Context, in *gitalypb.PostReceiveHookRequest) (*gitalypb.PostReceiveHookResponse, error) { + postreceiveHook := fmt.Sprintf("%s/post-receive", hooks.Path()) + + var stdin bytes.Buffer + for _, ref := range in.GetRefs() { + stdin.WriteString(fmt.Sprintf("%s\n", ref)) + } + + env := []string{ + fmt.Sprintf("GL_REPO_PATH=%s", in.GetRepoPath()), + fmt.Sprintf("GL_ID=%s", in.GetKeyId()), + fmt.Sprintf("GL_REPOSITORY=%s", in.GetGlRepository()), + } + + cmd, err := command.New(ctx, exec.Command(postreceiveHook), &stdin, nil, nil, env...) + if err != nil { + return &gitalypb.PostReceiveHookResponse{}, helper.ErrInternal(err) + } + + if err := cmd.Wait(); err != nil { + return &gitalypb.PostReceiveHookResponse{}, helper.ErrInternal(err) + } + + return &gitalypb.PostReceiveHookResponse{}, nil +} diff --git a/internal/service/hook/pre_receive.go b/internal/service/hook/pre_receive.go new file mode 100644 index 00000000000..38d283c6cfc --- /dev/null +++ b/internal/service/hook/pre_receive.go @@ -0,0 +1,40 @@ +package hook + +import ( + "bytes" + "context" + "fmt" + "os/exec" + + "gitlab.com/gitlab-org/gitaly-proto/go/gitalypb" + "gitlab.com/gitlab-org/gitaly/internal/command" + "gitlab.com/gitlab-org/gitaly/internal/git/hooks" + "gitlab.com/gitlab-org/gitaly/internal/helper" +) + +func (s *server) PreReceive(ctx context.Context, in *gitalypb.PreReceiveHookRequest) (*gitalypb.PreReceiveHookResponse, error) { + prereceiveHook := fmt.Sprintf("%s/pre-receive", hooks.Path()) + + var stdin bytes.Buffer + for _, ref := range in.GetRefs() { + stdin.WriteString(fmt.Sprintf("%s\n", ref)) + } + + env := []string{ + fmt.Sprintf("GL_ID=%s", in.GetKeyId()), + fmt.Sprintf("GL_PROTOCOL=%s", in.GetProtocol()), + fmt.Sprintf("GL_REPO_PATH=%s", in.GetRepoPath()), + fmt.Sprintf("GL_REPOSITORY=%s", in.GetGlRepository()), + } + + cmd, err := command.New(ctx, exec.Command(prereceiveHook), &stdin, nil, nil, env...) + if err != nil { + return &gitalypb.PreReceiveHookResponse{}, helper.ErrInternal(err) + } + + if err := cmd.Wait(); err != nil { + return &gitalypb.PreReceiveHookResponse{}, helper.ErrInternal(err) + } + + return &gitalypb.PreReceiveHookResponse{}, nil +} diff --git a/internal/service/hook/server.go b/internal/service/hook/server.go new file mode 100644 index 00000000000..24473515570 --- /dev/null +++ b/internal/service/hook/server.go @@ -0,0 +1,10 @@ +package hook + +import "gitlab.com/gitlab-org/gitaly-proto/go/gitalypb" + +type server struct{} + +// NewServer creates a new instance of a gRPC namespace server +func NewServer() gitalypb.HookServiceServer { + return &server{} +} diff --git a/internal/service/hook/update.go b/internal/service/hook/update.go new file mode 100644 index 00000000000..2afe585cd9f --- /dev/null +++ b/internal/service/hook/update.go @@ -0,0 +1,32 @@ +package hook + +import ( + "context" + "fmt" + "os/exec" + + "gitlab.com/gitlab-org/gitaly-proto/go/gitalypb" + "gitlab.com/gitlab-org/gitaly/internal/command" + "gitlab.com/gitlab-org/gitaly/internal/git/hooks" + "gitlab.com/gitlab-org/gitaly/internal/helper" +) + +func (s *server) Update(ctx context.Context, in *gitalypb.UpdateHookRequest) (*gitalypb.UpdateHookResponse, error) { + updateHook := fmt.Sprintf("%s/pre-receive", hooks.Path()) + + env := []string{ + fmt.Sprintf("GL_ID=%s", in.GetKeyId()), + fmt.Sprintf("GL_REPO_PATH=%s", in.GetRepoPath()), + } + + cmd, err := command.New(ctx, exec.Command(updateHook, in.GetRef(), in.GetOldValue(), in.GetNewValue()), nil, nil, nil, env...) + if err != nil { + return &gitalypb.UpdateHookResponse{}, helper.ErrInternal(err) + } + + if err := cmd.Wait(); err != nil { + return &gitalypb.UpdateHookResponse{}, helper.ErrInternal(err) + } + + return &gitalypb.UpdateHookResponse{}, nil +} diff --git a/internal/service/smarthttp/receive_pack.go b/internal/service/smarthttp/receive_pack.go index 5ff0d584e51..c93f61ffb88 100644 --- a/internal/service/smarthttp/receive_pack.go +++ b/internal/service/smarthttp/receive_pack.go @@ -45,6 +45,7 @@ func (s *server) PostReceivePack(stream gitalypb.SmartHTTPService_PostReceivePac fmt.Sprintf("GL_ID=%s", req.GlId), "GL_PROTOCOL=http", fmt.Sprintf("GITLAB_SHELL_DIR=%s", config.Config.GitlabShell.Dir), + fmt.Sprintf("GL_URL=%s", config.Config.SocketPath), } if req.GlRepository != "" { env = append(env, fmt.Sprintf("GL_REPOSITORY=%s", req.GlRepository)) @@ -61,7 +62,7 @@ func (s *server) PostReceivePack(stream gitalypb.SmartHTTPService_PostReceivePac env = git.AddGitProtocolEnv(ctx, req, env) env = append(env, command.GitEnv...) - opts := append([]string{fmt.Sprintf("core.hooksPath=%s", hooks.Path())}, req.GitConfigOptions...) + opts := append([]string{fmt.Sprintf("core.hooksPath=%s", hooks.GitPath())}, req.GitConfigOptions...) gitOptions := git.BuildGitOptions(opts, "receive-pack", "--stateless-rpc", repoPath) cmd, err := git.BareCommand(ctx, stdin, stdout, nil, env, gitOptions...) diff --git a/internal/service/ssh/receive_pack.go b/internal/service/ssh/receive_pack.go index e952e77779a..f03e2291ff6 100644 --- a/internal/service/ssh/receive_pack.go +++ b/internal/service/ssh/receive_pack.go @@ -56,6 +56,7 @@ func sshReceivePack(stream gitalypb.SSHService_SSHReceivePackServer, req *gitaly fmt.Sprintf("GL_USERNAME=%s", req.GlUsername), "GL_PROTOCOL=ssh", fmt.Sprintf("GITLAB_SHELL_DIR=%s", config.Config.GitlabShell.Dir), + fmt.Sprintf("GL_URL=%s", config.Config.SocketPath), } if req.GlRepository != "" { env = append(env, fmt.Sprintf("GL_REPOSITORY=%s", req.GlRepository)) @@ -69,7 +70,7 @@ func sshReceivePack(stream gitalypb.SSHService_SSHReceivePackServer, req *gitaly env = git.AddGitProtocolEnv(ctx, req, env) env = append(env, command.GitEnv...) - opts := append([]string{fmt.Sprintf("core.hooksPath=%s", hooks.Path())}, req.GitConfigOptions...) + opts := append([]string{fmt.Sprintf("core.hooksPath=%s", hooks.GitPath())}, req.GitConfigOptions...) gitOptions := git.BuildGitOptions(opts, "receive-pack", repoPath) cmd, err := git.BareCommand(ctx, stdin, stdout, stderr, env, gitOptions...) diff --git a/ruby/gitlab-shell/hooks/post-receive b/ruby/gitlab-shell/hooks/post-receive index 2b6538f0323..b8b2850b22a 100755 --- a/ruby/gitlab-shell/hooks/post-receive +++ b/ruby/gitlab-shell/hooks/post-receive @@ -6,7 +6,8 @@ refs = $stdin.read key_id = ENV.delete('GL_ID') gl_repository = ENV['GL_REPOSITORY'] -repo_path = Dir.pwd +#repo_path = Dir.pwd +repo_path = ENV['GL_REPO_PATH'] require_relative '../lib/gitlab_custom_hook' require_relative '../lib/hooks_utils' diff --git a/ruby/gitlab-shell/hooks/pre-receive b/ruby/gitlab-shell/hooks/pre-receive index 6ce58795195..658a712c51e 100755 --- a/ruby/gitlab-shell/hooks/pre-receive +++ b/ruby/gitlab-shell/hooks/pre-receive @@ -6,7 +6,8 @@ refs = $stdin.read key_id = ENV.delete('GL_ID') protocol = ENV.delete('GL_PROTOCOL') -repo_path = Dir.pwd +#repo_path = Dir.pwd +repo_path = ENV.delete('GL_REPO_PATH') gl_repository = ENV['GL_REPOSITORY'] def increase_reference_counter(gl_repository, repo_path) diff --git a/ruby/gitlab-shell/hooks/update b/ruby/gitlab-shell/hooks/update index 4c2fc08b0d7..78e43d293d7 100755 --- a/ruby/gitlab-shell/hooks/update +++ b/ruby/gitlab-shell/hooks/update @@ -6,7 +6,8 @@ ref_name = ARGV[0] old_value = ARGV[1] new_value = ARGV[2] -repo_path = Dir.pwd +#repo_path = Dir.pwd +repo_path = ENV.delete('GL_REPO_PATH') key_id = ENV.delete('GL_ID') require_relative '../lib/gitlab_custom_hook' -- GitLab From 95afb45ca761db6ad49d855644992be9f184811f Mon Sep 17 00:00:00 2001 From: John Cai Date: Thu, 20 Jun 2019 16:44:20 -0700 Subject: [PATCH 2/2] Add UpdateState to testClientConn --- cmd/hooks/hooks.go | 1 + go.mod | 6 +++--- go.sum | 12 ++---------- internal/git/hooks/hooks.go | 1 + 4 files changed, 7 insertions(+), 13 deletions(-) diff --git a/cmd/hooks/hooks.go b/cmd/hooks/hooks.go index 53a471b9f19..5f00d720e77 100644 --- a/cmd/hooks/hooks.go +++ b/cmd/hooks/hooks.go @@ -5,6 +5,7 @@ import ( "io" ) +// ReadRefs reads a list of newline delimeted refs from a reader func ReadRefs(r io.Reader) ([]string, error) { s := bufio.NewScanner(r) diff --git a/go.mod b/go.mod index aafd83b186b..e89c3f76647 100644 --- a/go.mod +++ b/go.mod @@ -13,12 +13,12 @@ require ( github.com/sirupsen/logrus v1.2.0 github.com/stretchr/testify v1.2.2 github.com/tinylib/msgp v1.1.0 // indirect - gitlab.com/gitlab-org/gitaly-proto v1.33.1-0.20190620230240-211d8c765403 + gitlab.com/gitlab-org/gitaly-proto v1.33.1-0.20190620234657-0f7ad34f3faa gitlab.com/gitlab-org/labkit v0.0.0-20190221122536-0c3fc7cdd57c - golang.org/x/net v0.0.0-20190620200207-3b0461eec859 + golang.org/x/net v0.0.0-20190311183353-d8887717615a golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4 golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a google.golang.org/genproto v0.0.0-20181202183823-bd91e49a0898 // indirect - google.golang.org/grpc v1.21.1 + google.golang.org/grpc v1.16.0 gopkg.in/yaml.v2 v2.2.2 // indirect ) diff --git a/go.sum b/go.sum index 0fab420f057..17495172a1a 100644 --- a/go.sum +++ b/go.sum @@ -38,7 +38,6 @@ github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfb github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/grpc-ecosystem/go-grpc-middleware v1.0.0 h1:Iju5GlWwrvL6UBg4zJJt3btmonfrMlCDdsejg4CZE7c= github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho= @@ -103,8 +102,8 @@ github.com/uber/jaeger-client-go v2.15.0+incompatible h1:NP3qsSqNxh8VYr956ur1N/1 github.com/uber/jaeger-client-go v2.15.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= github.com/uber/jaeger-lib v1.5.0 h1:OHbgr8l656Ub3Fw5k9SWnBfIEwvoHQ+W2y+Aa9D1Uyo= github.com/uber/jaeger-lib v1.5.0/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U= -gitlab.com/gitlab-org/gitaly-proto v1.33.1-0.20190620230240-211d8c765403 h1:uaMwn3J9CJJaAYwRozQL2VNslSz3Rnl1/tGZtDJRkWc= -gitlab.com/gitlab-org/gitaly-proto v1.33.1-0.20190620230240-211d8c765403/go.mod h1:r5s9CB3KH8viERqMaQg3eWIgk96p3eexfULUCepPU5g= +gitlab.com/gitlab-org/gitaly-proto v1.33.1-0.20190620234657-0f7ad34f3faa h1:UxMg+wTfi661L7stu+guHU21YqBUTc2B36KOdlhjo6o= +gitlab.com/gitlab-org/gitaly-proto v1.33.1-0.20190620234657-0f7ad34f3faa/go.mod h1:zNjk/86bjwLVJ4NcvInBcXcLdptdRFQ28sYrdFbrFgY= gitlab.com/gitlab-org/labkit v0.0.0-20190221122536-0c3fc7cdd57c h1:xo48LcGsTCasKcJpQDBCCuZU+aP8uGaboUVvD7Lgm6g= gitlab.com/gitlab-org/labkit v0.0.0-20190221122536-0c3fc7cdd57c/go.mod h1:rYhLgfrbEcyfinG+R3EvKu6bZSsmwQqcXzLfHWSfUKM= go.uber.org/atomic v1.3.2 h1:2Oa65PReHzfn29GpvgsYwloV9AVFHPDk8tYxt2c2tr4= @@ -113,15 +112,12 @@ golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnf golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181106065722-10aee1819953/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a h1:oWX7TPOiFAMXLq8o0ikBYfCJVlRHBcsciT5bXOrH628= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859 h1:R/3boaszxrf1GEUWTVDzSKVwLmSJpwZ1yqXm8j0v2QI= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be h1:vEDujvNQGv4jgYKudGeI/+DAX4Jffq6hpD55MmoEvKs= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA= @@ -139,7 +135,6 @@ golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= google.golang.org/appengine v1.1.0 h1:igQkv0AAhEIvTEpD5LIpAfav2eeVO9HBTjvKHVJPRSs= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= @@ -147,8 +142,6 @@ google.golang.org/genproto v0.0.0-20181202183823-bd91e49a0898 h1:yvw+zsSmSM02Z5H google.golang.org/genproto v0.0.0-20181202183823-bd91e49a0898/go.mod h1:7Ep/1NZk928CDR8SjdVbjWNpdIf6nzjE3BTgJDr2Atg= google.golang.org/grpc v1.16.0 h1:dz5IJGuC2BB7qXR5AyHNwAUBhZscK2xVez7mznh72sY= google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio= -google.golang.org/grpc v1.21.1 h1:j6XxA85m/6txkUCHvzlV5f+HBNl/1r5cZ2A/3IEFOO8= -google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= gopkg.in/DataDog/dd-trace-go.v1 v1.7.0 h1:7wbMayb6JXcbAS95RN7MI42W3o1BCxCcdIzZfVWBAiE= gopkg.in/DataDog/dd-trace-go.v1 v1.7.0/go.mod h1:DVp8HmDh8PuTu2Z0fVVlBsyWaC++fzwVCaGWylTe3tg= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= @@ -162,4 +155,3 @@ gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/internal/git/hooks/hooks.go b/internal/git/hooks/hooks.go index 05a8700cb3f..94426b8bd52 100644 --- a/internal/git/hooks/hooks.go +++ b/internal/git/hooks/hooks.go @@ -26,6 +26,7 @@ func Path() string { return path.Join(config.Config.Ruby.Dir, "git-hooks") } +// GitPath returns the path where the go implemeneted global git hooks are located func GitPath() string { if len(Override) > 0 { return Override -- GitLab