Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitaly.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Cai <jcai@gitlab.com>2020-01-29 19:22:22 +0300
committerJohn Cai <jcai@gitlab.com>2020-01-29 19:22:22 +0300
commit81801cb1394b3f7f97c148edda3d52e2e94b07a9 (patch)
treea7ef45adc2bb5cf90e3face7297cd14dd137843e
parent98d277ed2a1d592d58e7c67c59d54fab8eb002cb (diff)
parent72995c195f206ad4d1d9ba27426ddd92510d1b77 (diff)
Merge branch 'jc-add-e2e-for-git-push-options' into 'master'
Add end to end test for git hooks including git push options See merge request gitlab-org/gitaly!1790
-rw-r--r--cmd/gitaly-hooks/hooks_test.go137
-rw-r--r--internal/git/hooks/hooks.go17
-rw-r--r--internal/git/hooks/hooks_test.go35
-rwxr-xr-xruby/git-hooks/gitlab-shell-hook8
4 files changed, 122 insertions, 75 deletions
diff --git a/cmd/gitaly-hooks/hooks_test.go b/cmd/gitaly-hooks/hooks_test.go
index c9689580f..1e2aef00f 100644
--- a/cmd/gitaly-hooks/hooks_test.go
+++ b/cmd/gitaly-hooks/hooks_test.go
@@ -18,6 +18,7 @@ import (
"github.com/stretchr/testify/require"
"gitlab.com/gitlab-org/gitaly/internal/command"
"gitlab.com/gitlab-org/gitaly/internal/config"
+ "gitlab.com/gitlab-org/gitaly/internal/git/hooks"
"gitlab.com/gitlab-org/gitaly/internal/testhelper"
"gopkg.in/yaml.v2"
)
@@ -44,28 +45,34 @@ func TestHooksPrePostReceive(t *testing.T) {
changes := "abc"
- ts := gitlabTestServer(t, "", "", secretToken, key, glRepository, changes, true)
+ gitPushOptions := []string{"gitpushoption1", "gitpushoption2"}
+
+ ts := gitlabTestServer(t, "", "", secretToken, key, glRepository, changes, true, gitPushOptions...)
defer ts.Close()
writeTemporaryConfigFile(t, tempGitlabShellDir, GitlabShellConfig{GitlabURL: ts.URL})
writeShellSecretFile(t, tempGitlabShellDir, secretToken)
for _, hook := range []string{"pre-receive", "post-receive"} {
- for envName, env := range map[string][]string{"new": env(t, glRepository, tempGitlabShellDir, key), "old": oldEnv(t, glRepository, tempGitlabShellDir, key)} {
- t.Run(hook+"."+envName, func(t *testing.T) {
- var stderr, stdout bytes.Buffer
- stdin := bytes.NewBuffer([]byte(changes))
- cmd := exec.Command(fmt.Sprintf("../../ruby/git-hooks/%s", hook))
- cmd.Stderr = &stderr
- cmd.Stdout = &stdout
- cmd.Stdin = stdin
- cmd.Env = env
-
- require.NoError(t, cmd.Run())
- require.Empty(t, stderr.String())
- require.Empty(t, stdout.String())
- })
- }
+ t.Run(hook, func(t *testing.T) {
+ var stderr, stdout bytes.Buffer
+ stdin := bytes.NewBuffer([]byte(changes))
+ cmd := exec.Command(fmt.Sprintf("../../ruby/git-hooks/%s", hook))
+ cmd.Stderr = &stderr
+ cmd.Stdout = &stdout
+ cmd.Stdin = stdin
+ cmd.Env = env(
+ t,
+ glRepository,
+ tempGitlabShellDir,
+ key,
+ gitPushOptions...,
+ )
+
+ require.NoError(t, cmd.Run())
+ require.Empty(t, stderr.String())
+ require.Empty(t, stdout.String())
+ })
}
}
@@ -82,30 +89,25 @@ func TestHooksUpdate(t *testing.T) {
require.NoError(t, os.MkdirAll(filepath.Join(tempGitlabShellDir, "hooks", "update.d"), 0755))
testhelper.MustRunCommand(t, nil, "cp", "testdata/update", filepath.Join(tempGitlabShellDir, "hooks", "update.d", "update"))
- for envName, env := range map[string][]string{"new": env(t, glRepository, tempGitlabShellDir, key), "old": oldEnv(t, glRepository, tempGitlabShellDir, key)} {
- t.Run(envName, func(t *testing.T) {
- refval, oldval, newval := "refval", "oldval", "newval"
- var stdout, stderr bytes.Buffer
+ refval, oldval, newval := "refval", "oldval", "newval"
+ var stdout, stderr bytes.Buffer
- cmd := exec.Command(fmt.Sprintf("../../ruby/git-hooks/%s", "update"), refval, oldval, newval)
- cmd.Env = env
- cmd.Stdout = &stdout
- cmd.Stderr = &stderr
+ cmd := exec.Command("../../ruby/git-hooks/update", refval, oldval, newval)
+ cmd.Env = env(t, glRepository, tempGitlabShellDir, key)
+ cmd.Stdout = &stdout
+ cmd.Stderr = &stderr
- require.NoError(t, cmd.Run())
- require.FileExists(t, "testdata/tempfile")
- require.Empty(t, stdout.String())
- require.Empty(t, stderr.String())
+ require.NoError(t, cmd.Run())
+ require.Empty(t, stdout.String())
+ require.Empty(t, stderr.String())
- var inputs []string
+ var inputs []string
- f, err := os.Open("testdata/tempfile")
- require.NoError(t, err)
- require.NoError(t, json.NewDecoder(f).Decode(&inputs))
- require.Equal(t, []string{refval, oldval, newval}, inputs)
- require.NoError(t, os.Remove("testdata/tempfile"))
- })
- }
+ f, err := os.Open("testdata/tempfile")
+ require.NoError(t, err)
+ require.NoError(t, json.NewDecoder(f).Decode(&inputs))
+ require.Equal(t, []string{refval, oldval, newval}, inputs)
+ require.NoError(t, f.Close())
}
func TestHooksPostReceiveFailed(t *testing.T) {
@@ -126,24 +128,20 @@ func TestHooksPostReceiveFailed(t *testing.T) {
writeTemporaryConfigFile(t, tempGitlabShellDir, GitlabShellConfig{GitlabURL: ts.URL})
writeShellSecretFile(t, tempGitlabShellDir, secretToken)
- for envName, env := range map[string][]string{"new": env(t, glRepository, tempGitlabShellDir, key), "old": oldEnv(t, glRepository, tempGitlabShellDir, key)} {
- t.Run(envName, func(t *testing.T) {
- var stdout, stderr bytes.Buffer
+ var stdout, stderr bytes.Buffer
- cmd := exec.Command(fmt.Sprintf("../../ruby/git-hooks/%s", "post-receive"))
- cmd.Env = env
- cmd.Stdout = &stdout
- cmd.Stderr = &stderr
+ cmd := exec.Command(fmt.Sprintf("../../ruby/git-hooks/%s", "post-receive"))
+ cmd.Env = env(t, glRepository, tempGitlabShellDir, key)
+ cmd.Stdout = &stdout
+ cmd.Stderr = &stderr
- err := cmd.Run()
- code, ok := command.ExitStatus(err)
+ err := cmd.Run()
+ code, ok := command.ExitStatus(err)
- require.True(t, ok, "expect exit status in %v", err)
- require.Equal(t, 1, code, "exit status")
- require.Empty(t, stdout.String())
- require.Empty(t, stderr.String())
- })
- }
+ require.True(t, ok, "expect exit status in %v", err)
+ require.Equal(t, 1, code, "exit status")
+ require.Empty(t, stdout.String())
+ require.Empty(t, stderr.String())
}
func TestHooksNotAllowed(t *testing.T) {
@@ -160,20 +158,16 @@ func TestHooksNotAllowed(t *testing.T) {
writeTemporaryConfigFile(t, tempGitlabShellDir, GitlabShellConfig{GitlabURL: ts.URL})
writeShellSecretFile(t, tempGitlabShellDir, "the wrong token")
- for envName, env := range map[string][]string{"new": env(t, glRepository, tempGitlabShellDir, key), "old": oldEnv(t, glRepository, tempGitlabShellDir, key)} {
- t.Run(envName, func(t *testing.T) {
- var stderr, stdout bytes.Buffer
+ var stderr, stdout bytes.Buffer
- cmd := exec.Command(fmt.Sprintf("../../ruby/git-hooks/%s", "pre-receive"))
- cmd.Stderr = &stderr
- cmd.Stdout = &stdout
- cmd.Env = env
+ cmd := exec.Command(fmt.Sprintf("../../ruby/git-hooks/%s", "pre-receive"))
+ cmd.Stderr = &stderr
+ cmd.Stdout = &stdout
+ cmd.Env = env(t, glRepository, tempGitlabShellDir, key)
- require.Error(t, cmd.Run())
- require.Equal(t, "GitLab: 401 Unauthorized\n", stderr.String())
- require.Equal(t, "", stdout.String())
- })
- }
+ require.Error(t, cmd.Run())
+ require.Equal(t, "GitLab: 401 Unauthorized\n", stderr.String())
+ require.Equal(t, "", stdout.String())
}
func TestCheckOK(t *testing.T) {
@@ -285,7 +279,7 @@ func handlePreReceive(t *testing.T, secretToken, glRepository string) func(w htt
}
}
-func handlePostReceive(t *testing.T, secretToken string, key int, glRepository, changes string, counterDecreased bool) func(w http.ResponseWriter, r *http.Request) {
+func handlePostReceive(t *testing.T, secretToken string, key int, glRepository, changes string, counterDecreased bool, gitPushOptions ...string) func(w http.ResponseWriter, r *http.Request) {
return func(w http.ResponseWriter, r *http.Request) {
require.NoError(t, r.ParseForm())
require.Equal(t, http.MethodPost, r.Method)
@@ -295,6 +289,10 @@ func handlePostReceive(t *testing.T, secretToken string, key int, glRepository,
require.Equal(t, fmt.Sprintf("key-%d", key), r.Form.Get("identifier"))
require.Equal(t, changes, r.Form.Get("changes"))
+ if len(gitPushOptions) > 0 {
+ require.Equal(t, gitPushOptions, r.Form["push_options[]"])
+ }
+
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
w.Write([]byte(fmt.Sprintf(`{"reference_counter_decreased": %v}`, counterDecreased)))
@@ -319,11 +317,12 @@ func gitlabTestServer(t *testing.T,
key int,
glRepository,
changes string,
- postReceiveCounterDecreased bool) *httptest.Server {
+ postReceiveCounterDecreased bool,
+ gitPushOptions ...string) *httptest.Server {
mux := http.NewServeMux()
mux.Handle("/api/v4/internal/allowed", http.HandlerFunc(handleAllowed(t, secretToken, key, glRepository, changes)))
mux.Handle("/api/v4/internal/pre_receive", http.HandlerFunc(handlePreReceive(t, secretToken, glRepository)))
- mux.Handle("/api/v4/internal/post_receive", http.HandlerFunc(handlePostReceive(t, secretToken, key, glRepository, changes, postReceiveCounterDecreased)))
+ mux.Handle("/api/v4/internal/post_receive", http.HandlerFunc(handlePostReceive(t, secretToken, key, glRepository, changes, postReceiveCounterDecreased, gitPushOptions...)))
mux.Handle("/api/v4/internal/check", http.HandlerFunc(handleCheck(t, user, password)))
return httptest.NewServer(mux)
@@ -360,14 +359,14 @@ func writeTemporaryGitalyConfigFile(t *testing.T, tempDir string) (string, func(
}
}
-func env(t *testing.T, glRepo, gitlabShellDir string, key int) []string {
+func env(t *testing.T, glRepo, gitlabShellDir string, key int, gitPushOptions ...string) []string {
rubyDir, err := filepath.Abs("../../ruby")
require.NoError(t, err)
- return append(oldEnv(t, glRepo, gitlabShellDir, key), []string{
+ return append(append(oldEnv(t, glRepo, gitlabShellDir, key), []string{
"GITALY_BIN_DIR=testdata/gitaly-libexec",
fmt.Sprintf("GITALY_RUBY_DIR=%s", rubyDir),
- }...)
+ }...), hooks.GitPushOptions(gitPushOptions)...)
}
func oldEnv(t *testing.T, glRepo, gitlabShellDir string, key int) []string {
diff --git a/internal/git/hooks/hooks.go b/internal/git/hooks/hooks.go
index c77c3ed1e..e8c1f325f 100644
--- a/internal/git/hooks/hooks.go
+++ b/internal/git/hooks/hooks.go
@@ -1,6 +1,7 @@
package hooks
import (
+ "fmt"
"os"
"path"
@@ -25,3 +26,19 @@ func Path() string {
return path.Join(config.Config.Ruby.Dir, "git-hooks")
}
+
+// GitPushOptions turns a slice of git push option values into a GIT_PUSH_OPTION_COUNT and individual
+// GIT_PUSH_OPTION_0, GIT_PUSH_OPTION_1 etc.
+func GitPushOptions(options []string) []string {
+ if len(options) == 0 {
+ return []string{}
+ }
+
+ envVars := []string{fmt.Sprintf("GIT_PUSH_OPTION_COUNT=%d", len(options))}
+
+ for i, pushOption := range options {
+ envVars = append(envVars, fmt.Sprintf("GIT_PUSH_OPTION_%d=%s", i, pushOption))
+ }
+
+ return envVars
+}
diff --git a/internal/git/hooks/hooks_test.go b/internal/git/hooks/hooks_test.go
index e58139953..c9d5dbe5f 100644
--- a/internal/git/hooks/hooks_test.go
+++ b/internal/git/hooks/hooks_test.go
@@ -34,3 +34,38 @@ func TestPath(t *testing.T) {
require.Equal(t, "/var/empty", Path())
})
}
+
+func TestGitPushOptions(t *testing.T) {
+ testCases := []struct {
+ desc string
+ input []string
+ expected []string
+ }{
+ {
+ desc: "empty input",
+ input: []string{},
+ expected: []string{},
+ },
+ {
+ desc: "nil input",
+ input: nil,
+ expected: []string{},
+ },
+ {
+ desc: "one option",
+ input: []string{"option1"},
+ expected: []string{"GIT_PUSH_OPTION_COUNT=1", "GIT_PUSH_OPTION_0=option1"},
+ },
+ {
+ desc: "multiple options",
+ input: []string{"option1", "option2"},
+ expected: []string{"GIT_PUSH_OPTION_COUNT=2", "GIT_PUSH_OPTION_0=option1", "GIT_PUSH_OPTION_1=option2"},
+ },
+ }
+
+ for _, tc := range testCases {
+ t.Run(tc.desc, func(t *testing.T) {
+ require.Equal(t, tc.expected, GitPushOptions(tc.input))
+ })
+ }
+}
diff --git a/ruby/git-hooks/gitlab-shell-hook b/ruby/git-hooks/gitlab-shell-hook
index 550f31d83..ae98a1b12 100755
--- a/ruby/git-hooks/gitlab-shell-hook
+++ b/ruby/git-hooks/gitlab-shell-hook
@@ -1,9 +1,5 @@
#!/bin/sh
# This is the single source of truth for where Gitaly's embedded Git hooks are.
-if [ -n "$GITALY_BIN_DIR" ]; then
- exec "$GITALY_BIN_DIR/gitaly-hooks" "$(basename $0)" "$@"
-else
- hooks_dir="$(dirname $0)/../gitlab-shell/hooks"
- exec "$hooks_dir/$(basename $0)" "$@"
-fi
+exec "$GITALY_BIN_DIR/gitaly-hooks" "$(basename $0)" "$@"
+