diff --git a/bots-common/git_utils.go b/bots-common/git_utils.go index 4b8acff..654ef97 100644 --- a/bots-common/git_utils.go +++ b/bots-common/git_utils.go @@ -166,6 +166,8 @@ func (e *GitHandler) GitExec(cwd string, params ...string) error { return err } +var ExtraGitParams []string + func (e *GitHandler) GitExecWithOutput(cwd string, params ...string) (string, error) { cmd := exec.Command("/usr/bin/git", params...) cmd.Env = []string{ @@ -177,6 +179,9 @@ func (e *GitHandler) GitExecWithOutput(cwd string, params ...string) (string, er "GIT_LFS_SKIP_SMUDGE=1", "GIT_SSH_COMMAND=/usr/bin/ssh -o StrictHostKeyChecking=yes", } + if len(ExtraGitParams) > 0 { + cmd.Env = append(cmd.Env, ExtraGitParams...) + } cmd.Dir = filepath.Join(e.GitPath, cwd) cmd.Stdin = nil diff --git a/bots-common/gitea_utils.go b/bots-common/gitea_utils.go index 3eb958d..3af0713 100644 --- a/bots-common/gitea_utils.go +++ b/bots-common/gitea_utils.go @@ -54,12 +54,30 @@ const ( ReviewStateUnknown models.ReviewStateType = "" ) +type Gitea interface { + GetPullRequestAndReviews(org, project string, num int64) (*models.PullRequest, []*models.PullReview, error) + GetPullNotifications(since *time.Time) ([]*models.NotificationThread, error) + SetNotificationRead(notificationId int64) error + GetOrganization(orgName string) (*models.Organization, error) + GetOrganizationRepositories(orgName string) ([]*models.Repository, error) + CreateRepositoryIfNotExist(git *GitHandler, org Organization, repoName string) (*models.Repository, error) + CreatePullRequestIfNotExist(repo *models.Repository, srcId, targetId, title, body string) (*models.PullRequest, error) + RequestReviews(pr *models.PullRequest, reviewer string) ([]*models.PullReview, error) + IsReviewed(pr *models.PullRequest) (bool, error) + AddReviewComment(pr *models.PullRequest, state models.ReviewStateType, comment string) (*models.PullReview, error) + GetAssociatedPrjGitPR(pr *PullRequestWebhookEvent) (*models.PullRequest, error) + GetRepositoryFileContent(repo *models.Repository, hash, path string) ([]byte, error) + GetPullRequestFileContent(pr *models.PullRequest, path string) ([]byte, error) + GetRecentPullRequests(org, repo string) ([]*models.PullRequest, error) + GetRecentCommits(org, repo, branch string, commitNo int64) ([]*models.Commit, error) +} + type GiteaTransport struct { transport *transport.Runtime client *apiclient.GiteaAPI } -func AllocateGiteaTransport(host string) *GiteaTransport { +func AllocateGiteaTransport(host string) Gitea { var r GiteaTransport r.transport = transport.New(host, apiclient.DefaultBasePath, [](string){"https"}) diff --git a/workflow-direct/main.go b/workflow-direct/main.go index 4fc1a6d..cd69f4f 100644 --- a/workflow-direct/main.go +++ b/workflow-direct/main.go @@ -39,7 +39,7 @@ const ( ) var configuredRepos map[string][]*common.AutogitConfig -var gitea *common.GiteaTransport +var gitea common.Gitea func isConfiguredOrg(org *common.Organization) bool { _, found := configuredRepos[org.Username] diff --git a/workflow-direct/main_test.go b/workflow-direct/main_test.go index 366a1bb..be340b9 100644 --- a/workflow-direct/main_test.go +++ b/workflow-direct/main_test.go @@ -1,6 +1,3 @@ package main // TODO, like documentation :-) -func test() -{ -} diff --git a/workflow-pr/main.go b/workflow-pr/main.go index b21eb3a..1f8d911 100644 --- a/workflow-pr/main.go +++ b/workflow-pr/main.go @@ -38,7 +38,7 @@ const ( ) var configuredRepos map[string][]*common.AutogitConfig -var gitea *common.GiteaTransport +var gitea common.Gitea /* func fetchPrGit(h *common.RequestHandler, pr *models.PullRequest) error { @@ -97,7 +97,7 @@ func updateOrCreatePRBranch(req *common.PullRequestWebhookEvent, git *common.Git common.PanicOnError(git.GitExec(path.Join(common.DefaultGitPrj, req.Repository.Name), "fetch", "--depth", "1", "origin", req.Pull_Request.Head.Sha)) common.PanicOnError(git.GitExec(path.Join(common.DefaultGitPrj, req.Repository.Name), "checkout", req.Pull_Request.Head.Sha)) common.PanicOnError(git.GitExec(common.DefaultGitPrj, "commit", "-a", "-m", commitMsg)) - common.PanicOnError(git.GitExec(common.DefaultGitPrj, "push", "-f", "origin", branchName)) + common.PanicOnError(git.GitExec(common.DefaultGitPrj, "push", "origin", "+HEAD:" + branchName)) return nil } diff --git a/workflow-pr/main_test.go b/workflow-pr/main_test.go index 36ad4b5..143e76d 100644 --- a/workflow-pr/main_test.go +++ b/workflow-pr/main_test.go @@ -1,6 +1,12 @@ package main import ( + "bytes" + "fmt" + "log" + "os/exec" + "path/filepath" + "strings" "testing" "src.opensuse.org/autogits/common" @@ -33,29 +39,154 @@ func TestProjctGitSync(t *testing.T) { } } -func setupGitForTests(dir string) error { - return nil +const LocalCMD = "---" + +func gitExecs(t *testing.T, git *common.GitHandler, cmds [][]string) { + for _, cmd := range cmds { + if cmd[0] == LocalCMD { + command := exec.Command(cmd[2], cmd[3:]...) + command.Dir = filepath.Join(git.GitPath, cmd[1]) + command.Stdin = nil + command.Env = []string{"GIT_CONFIG_COUNT=1", "GIT_CONFIG_KEY_1=protocol.file.allow", "GIT_CONFIG_VALUE_1=always"} + _, err := command.CombinedOutput() + if err != nil { + t.Errorf(" *** error: %v\n", err) + } + } else { + git.GitExecOrPanic(cmd[0], cmd[1:]...) + } + } } -func TestPkgGitSync(t *testing.T) { - req := common.PullRequestWebhookEvent{ +func commandsForPackages(dir, prefix string, startN, endN int) [][]string { + commands := make([][]string, (endN - startN + 2) * 6) + + if dir == "" { + dir = "." + } + cmdIdx := 0 + for idx := startN; idx <= endN; idx++ { + pkgDir := fmt.Sprintf("%s%d", prefix, idx) + + commands[cmdIdx+0] = []string{"", "init", "-q", "--object-format", "sha256", "-b", "testing", pkgDir} + commands[cmdIdx+1] = []string{LocalCMD, pkgDir, "/usr/bin/touch", "testFile"} + commands[cmdIdx+2] = []string{pkgDir, "add", "testFile"} + commands[cmdIdx+3] = []string{pkgDir, "commit", "-m", "added testFile"} + commands[cmdIdx+4] = []string{pkgDir, "config", "receive.denyCurrentBranch", "ignore"} + commands[cmdIdx+5] = []string{"prj", "submodule", "add", filepath.Join("..", pkgDir), filepath.Join(dir, pkgDir)} + + cmdIdx += 6 + } + + // add all the submodules to the prj + commands[cmdIdx+0] = []string{"prj", "commit", "-a", "-m", "adding subpackages"} + + return commands +} + +func setupGitForTests(t *testing.T, git *common.GitHandler) { + common.ExtraGitParams = []string{ + "GIT_CONFIG_COUNT=1", + "GIT_CONFIG_KEY_0=protocol.file.allow", + "GIT_CONFIG_VALUE_0=always", + } + + gitExecs(t, git, [][]string{ + {"", "init", "-q", "--object-format", "sha256", "-b", "testing", "prj"}, + {"", "init", "-q", "--object-format", "sha256", "-b", "testing", "foo"}, + {LocalCMD, "foo", "/usr/bin/touch", "file1"}, + {"foo", "add", "file1"}, + {"foo", "commit", "-m", "first commit"}, + {"prj", "config", "receive.denyCurrentBranch", "ignore"}, + {"prj", "submodule", "init"}, + {"prj", "submodule", "add", filepath.Join(git.GitPath, "foo"), "testRepo"}, + {"prj", "add", ".gitmodules", "testRepo"}, + {"prj", "commit", "-m", "First instance"}, + {"", "clone", "prj", common.DefaultGitPrj}, + {LocalCMD, "foo", "/usr/bin/touch", "file2"}, + {"foo", "add", "file2"}, + {"foo", "commit", "-m", "added file2"}, + }) +} + +func TestUpdatePrBranch(t *testing.T) { + var buf bytes.Buffer + origLogger := log.Writer() + log.SetOutput(&buf) + defer log.SetOutput(origLogger) + + req := &common.PullRequestWebhookEvent{ Repository: &common.Repository{ Name: "testRepo", }, + Pull_Request: &common.PullRequest { + }, } - git := common.GitHandler{ + git := &common.GitHandler{ DebugLogger: true, GitCommiter: "TestCommiter", GitEmail: "test@testing", GitPath: t.TempDir(), } - if err := setupGitForTests(git.GitPath); err != nil { - t.Fatal(err) - } + setupGitForTests(t, git) + revs := strings.Split(git.GitExecWithOutputOrPanic("foo", "rev-list", "HEAD"), "\n") + req.Pull_Request.Base.Sha = strings.TrimSpace(revs[1]) + req.Pull_Request.Head.Sha = strings.TrimSpace(revs[0]) - if err := updateOrCreatePRBranch(&req, &git, "created commit", "testing"); err != nil { + if err := updateOrCreatePRBranch(req, git, "created commit", "testing"); err != nil { t.Error(err) } + + rev := strings.TrimSpace(git.GitExecWithOutputOrPanic(filepath.Join(common.DefaultGitPrj, "testRepo"), "rev-list", "-1", "HEAD")) + if rev != req.Pull_Request.Head.Sha { + t.Error("prj/testRepo not updated to", req.Pull_Request.Head.Sha, "but is at", rev) + t.Error(buf.String()) + } } + +func TestCreatePrBranch(t *testing.T) { + var buf bytes.Buffer + origLogger := log.Writer() + log.SetOutput(&buf) + defer log.SetOutput(origLogger) + + req := &common.PullRequestWebhookEvent{ + Repository: &common.Repository{ + Name: "testRepo", + }, + Pull_Request: &common.PullRequest { + }, + } + + git := &common.GitHandler{ + DebugLogger: true, + GitCommiter: "TestCommiter", + GitEmail: "test@testing", + GitPath: t.TempDir(), + } + + setupGitForTests(t, git) + revs := strings.Split(git.GitExecWithOutputOrPanic("foo", "rev-list", "HEAD"), "\n") + req.Pull_Request.Base.Sha = strings.TrimSpace(revs[1]) + req.Pull_Request.Head.Sha = strings.TrimSpace(revs[0]) + + if err := updateOrCreatePRBranch(req, git, "created commit", "testingCreated"); err != nil { + t.Error(err) + } + + rev := strings.TrimSpace(git.GitExecWithOutputOrPanic(filepath.Join(common.DefaultGitPrj, "testRepo"), "rev-list", "-1", "HEAD")) + if rev != req.Pull_Request.Head.Sha { + t.Error("prj/testRepo not updated to", req.Pull_Request.Head.Sha, "but is at", rev) + t.Error(buf.String()) + } + + git.GitExecOrPanic("prj", "reset", "--hard", "testingCreated") + rev = strings.TrimSpace(git.GitExecWithOutputOrPanic("prj", "submodule", "status", "testRepo"))[1:len(req.Pull_Request.Head.Sha)+1] + if rev != req.Pull_Request.Head.Sha { + t.Error("prj/testRepo not updated to", req.Pull_Request.Head.Sha, "but is at", rev) + t.Error(buf.String()) + } +} +