package main import ( "fmt" "testing" "go.uber.org/mock/gomock" "src.opensuse.org/autogits/common" "src.opensuse.org/autogits/common/gitea-generated/models" mock_common "src.opensuse.org/autogits/common/mock" ) func TestProcessIssue_Add(t *testing.T) { ctl := gomock.NewController(t) defer ctl.Finish() gitea := mock_common.NewMockGitea(ctl) Gitea = gitea common.IsDryRun = false config := &common.AutogitConfig{ Organization: "target-org", GitProjectName: "test-org/test-prj#main", } configs := []*common.AutogitConfig{config} issue := &models.Issue{ Title: "[ADD] pkg1", Body: "src-org/pkg1#master", Index: 123, Repository: &models.RepositoryMeta{ Owner: "test-org", Name: "test-prj", }, Ref: "refs/heads/main", } t.Run("Repository does not exist - labels issue", func(t *testing.T) { mockGitGen := mock_common.NewMockGitHandlerGenerator(ctl) GitHandler = mockGitGen mockGit := mock_common.NewMockGit(ctl) mockGitGen.EXPECT().CreateGitHandler("target-org").Return(mockGit, nil) mockGit.EXPECT().Close().Return(nil) gitea.EXPECT().GetRepository("target-org", "pkg1").Return(nil, nil) gitea.EXPECT().SetLabels("test-org", "test-prj", int64(123), []string{"new/New Repository"}).Return(nil, nil) err := ProcessIssue(issue, configs) if err != nil { t.Errorf("Unexpected error: %v", err) } }) t.Run("Source is SHA - creates temp branch in target", func(t *testing.T) { mockGitGen := mock_common.NewMockGitHandlerGenerator(ctl) GitHandler = mockGitGen mockGit := mock_common.NewMockGit(ctl) mockGitGen.EXPECT().CreateGitHandler("target-org").Return(mockGit, nil) mockGit.EXPECT().GetPath().Return("/tmp/test").AnyTimes() mockGit.EXPECT().Close().Return(nil) targetRepo := &models.Repository{ Name: "pkg1", SSHURL: "target-ssh-url", Owner: &models.User{UserName: "target-org"}, } srcRepo := &models.Repository{ Name: "pkg1", SSHURL: "src-ssh-url", DefaultBranch: "master", Owner: &models.User{UserName: "src-org"}, Parent: &models.Repository{ Name: "pkg1", Owner: &models.User{UserName: "target-org"}, }, } issueSHA := &models.Issue{ Title: "[ADD] pkg1", Body: "src-org/pkg1#abcdef0123456789abcdef0123456789abcdef01", Index: 123, Repository: &models.RepositoryMeta{Owner: "test-org", Name: "test-prj"}, Ref: "refs/heads/main", } gitea.EXPECT().GetRepository("target-org", "pkg1").Return(targetRepo, nil) mockGit.EXPECT().GitClone("pkg1", "abcdef0123456789abcdef0123456789abcdef01", "target-ssh-url").Return("origin", nil) // New orphan branch logic mockGit.EXPECT().GitExec("pkg1", "checkout", "-B", "abcdef0123456789abcdef0123456789abcdef01", "origin/abcdef0123456789abcdef0123456789abcdef01").Return(fmt.Errorf("error")) mockGit.EXPECT().GitExecOrPanic("pkg1", "checkout", "--detach") mockGit.EXPECT().GitExec("pkg1", "branch", "-D", "abcdef0123456789abcdef0123456789abcdef01") mockGit.EXPECT().GitExecOrPanic("pkg1", "checkout", "-f", "--orphan", "abcdef0123456789abcdef0123456789abcdef01") mockGit.EXPECT().GitExecOrPanic("pkg1", "rm", "-rf", ".") mockGit.EXPECT().GitExecOrPanic("pkg1", "commit", "--allow-empty", "-m", "Initial empty branch") mockGit.EXPECT().GitExecOrPanic("pkg1", "push", "-f", "origin", "abcdef0123456789abcdef0123456789abcdef01") gitea.EXPECT().GetRepository("src-org", "pkg1").Return(srcRepo, nil) mockGit.EXPECT().GitExecWithOutput("pkg1", "ls-remote", "--heads", "src-ssh-url", "abcdef0123456789abcdef0123456789abcdef01").Return("", nil) // SHA source logic tempBranch := "new_package_123_pkg1" mockGit.EXPECT().GitClone("pkg1", "abcdef0123456789abcdef0123456789abcdef01", "target-ssh-url").Return("origin", nil) mockGit.EXPECT().GitExecOrPanic("pkg1", "remote", "add", "source", "src-ssh-url") mockGit.EXPECT().GitExecOrPanic("pkg1", "fetch", "source", "abcdef0123456789abcdef0123456789abcdef01") mockGit.EXPECT().GitExecOrPanic("pkg1", "checkout", "-B", tempBranch, "FETCH_HEAD") mockGit.EXPECT().GitExecOrPanic("pkg1", "push", "-f", "origin", tempBranch) // PR creation using temp branch gitea.EXPECT().CreatePullRequestIfNotExist(targetRepo, tempBranch, "main", gomock.Any(), gomock.Any()).Return(&models.PullRequest{Index: 456}, nil, false) err := ProcessIssue(issueSHA, configs) if err != nil { t.Errorf("Unexpected error: %v", err) } }) t.Run("Repository exists - continue processing and create PR", func(t *testing.T) { mockGitGen := mock_common.NewMockGitHandlerGenerator(ctl) GitHandler = mockGitGen mockGit := mock_common.NewMockGit(ctl) mockGitGen.EXPECT().CreateGitHandler("target-org").Return(mockGit, nil) mockGit.EXPECT().Close().Return(nil) targetRepo := &models.Repository{ Name: "pkg1", SSHURL: "target-ssh-url", Owner: &models.User{UserName: "target-org"}, } srcRepo := &models.Repository{ Name: "pkg1", SSHURL: "src-ssh-url", DefaultBranch: "master", Owner: &models.User{UserName: "src-org"}, Parent: &models.Repository{ Name: "pkg1", Owner: &models.User{UserName: "target-org"}, }, } gitea.EXPECT().GetRepository("target-org", "pkg1").Return(targetRepo, nil) // 4. Branch check - exists via local git mockGit.EXPECT().GitClone("pkg1", "master", "target-ssh-url").Return("origin", nil) mockGit.EXPECT().GitExec("pkg1", "checkout", "-B", "master", "origin/master").Return(nil) mockGit.EXPECT().GitDirectoryContentList("pkg1", "HEAD").Return(map[string]string{"some-file": "some-sha"}, nil) mockGit.EXPECT().GitExecOrPanic("pkg1", "checkout", "--detach") mockGit.EXPECT().GitExec("pkg1", "branch", "-D", "master") mockGit.EXPECT().GitExecOrPanic("pkg1", "checkout", "-f", "--orphan", "master") mockGit.EXPECT().GitExecOrPanic("pkg1", "rm", "-rf", ".") mockGit.EXPECT().GitExecOrPanic("pkg1", "commit", "--allow-empty", "-m", gomock.Any()) mockGit.EXPECT().GitExecOrPanic("pkg1", "push", "-f", "origin", "master") // 5. Source repo fetch gitea.EXPECT().GetRepository("src-org", "pkg1").Return(srcRepo, nil) // Check if source is a branch via ls-remote mockGit.EXPECT().GitExecWithOutput("pkg1", "ls-remote", "--heads", "src-ssh-url", "master").Return("src-sha refs/heads/master", nil) // PR creation packagePR := &models.PullRequest{ Index: 456, Base: &models.PRBranchInfo{ Ref: "main", Repo: targetRepo, Name: "main", }, Head: &models.PRBranchInfo{ Ref: "master", Repo: srcRepo, Sha: "src-sha", }, URL: "http://gitea/pr/456", } gitea.EXPECT().CreatePullRequestIfNotExist(targetRepo, "src-org:master", "main", gomock.Any(), gomock.Any()).Return(packagePR, nil, true) gitea.EXPECT().SetLabels("target-org", "pkg1", int64(456), []string{"new/New Repository"}).Return(nil, nil) err := ProcessIssue(issue, configs) if err != nil { t.Errorf("Unexpected error: %v", err) } }) t.Run("Source repository is not fork of target repository - aborts", func(t *testing.T) { mockGitGen := mock_common.NewMockGitHandlerGenerator(ctl) GitHandler = mockGitGen mockGit := mock_common.NewMockGit(ctl) mockGitGen.EXPECT().CreateGitHandler("target-org").Return(mockGit, nil) mockGit.EXPECT().Close().Return(nil) targetRepo := &models.Repository{ Name: "pkg1", SSHURL: "target-ssh-url", Owner: &models.User{UserName: "target-org"}, } srcRepo := &models.Repository{ Name: "pkg1", Owner: &models.User{UserName: "src-org"}, Parent: &models.Repository{ Name: "other-repo", Owner: &models.User{UserName: "other-org"}, }, } gitea.EXPECT().GetRepository("target-org", "pkg1").Return(targetRepo, nil) mockGit.EXPECT().GitClone("pkg1", "master", "target-ssh-url").Return("origin", nil) gitea.EXPECT().GetRepository("src-org", "pkg1").Return(srcRepo, nil) err := ProcessIssue(issue, configs) if err != nil { t.Errorf("Unexpected error: %v", err) } }) t.Run("Source repository is fork of target repository - proceeds", func(t *testing.T) { mockGitGen := mock_common.NewMockGitHandlerGenerator(ctl) GitHandler = mockGitGen mockGit := mock_common.NewMockGit(ctl) mockGitGen.EXPECT().CreateGitHandler("target-org").Return(mockGit, nil) mockGit.EXPECT().Close().Return(nil) targetRepo := &models.Repository{ Name: "pkg1", Owner: &models.User{UserName: "target-org"}, SSHURL: "target-ssh-url", } srcRepo := &models.Repository{ Name: "pkg1", Owner: &models.User{UserName: "src-org"}, SSHURL: "src-ssh-url", Parent: &models.Repository{ Name: "pkg1", Owner: &models.User{UserName: "target-org"}, }, DefaultBranch: "master", } gitea.EXPECT().GetRepository("target-org", "pkg1").Return(targetRepo, nil) mockGit.EXPECT().GitClone("pkg1", "master", "target-ssh-url").Return("origin", nil) mockGit.EXPECT().GitExec("pkg1", "checkout", "-B", "master", "origin/master").Return(nil) mockGit.EXPECT().GitDirectoryContentList("pkg1", "HEAD").Return(map[string]string{"some-file": "some-sha"}, nil) mockGit.EXPECT().GitExecOrPanic("pkg1", "checkout", "--detach") mockGit.EXPECT().GitExec("pkg1", "branch", "-D", "master") mockGit.EXPECT().GitExecOrPanic("pkg1", "checkout", "-f", "--orphan", "master") mockGit.EXPECT().GitExecOrPanic("pkg1", "rm", "-rf", ".") mockGit.EXPECT().GitExecOrPanic("pkg1", "commit", "--allow-empty", "-m", gomock.Any()) mockGit.EXPECT().GitExecOrPanic("pkg1", "push", "-f", "origin", "master") gitea.EXPECT().GetRepository("src-org", "pkg1").Return(srcRepo, nil) mockGit.EXPECT().GitExecWithOutput("pkg1", "ls-remote", "--heads", "src-ssh-url", "master").Return("src-sha refs/heads/master", nil) gitea.EXPECT().CreatePullRequestIfNotExist(targetRepo, "src-org:master", "main", gomock.Any(), gomock.Any()).Return(&models.PullRequest{Index: 456}, nil, false) err := ProcessIssue(issue, configs) if err != nil { t.Errorf("Unexpected error: %v", err) } }) t.Run("Source repository has no parent (not a fork) - aborts", func(t *testing.T) { mockGitGen := mock_common.NewMockGitHandlerGenerator(ctl) GitHandler = mockGitGen mockGit := mock_common.NewMockGit(ctl) mockGitGen.EXPECT().CreateGitHandler("target-org").Return(mockGit, nil) mockGit.EXPECT().Close().Return(nil) targetRepo := &models.Repository{ Name: "pkg1", Owner: &models.User{UserName: "target-org"}, SSHURL: "target-ssh-url", } srcRepo := &models.Repository{ Name: "pkg1", Owner: &models.User{UserName: "src-org"}, SSHURL: "src-ssh-url", Parent: nil, DefaultBranch: "master", } gitea.EXPECT().GetRepository("target-org", "pkg1").Return(targetRepo, nil) gitea.EXPECT().GetRepository("src-org", "pkg1").Return(srcRepo, nil) err := ProcessIssue(issue, configs) if err != nil { t.Errorf("Unexpected error: %v", err) } }) t.Run("Target branch missing - creates orphan branch", func(t *testing.T) { mockGitGen := mock_common.NewMockGitHandlerGenerator(ctl) GitHandler = mockGitGen mockGit := mock_common.NewMockGit(ctl) mockGitGen.EXPECT().CreateGitHandler("target-org").Return(mockGit, nil) mockGit.EXPECT().GetPath().Return("/tmp/test").AnyTimes() mockGit.EXPECT().Close().Return(nil) targetRepo := &models.Repository{ Name: "pkg1", SSHURL: "target-ssh-url", Owner: &models.User{UserName: "target-org"}, } srcRepo := &models.Repository{ Name: "pkg1", SSHURL: "src-ssh-url", DefaultBranch: "master", Owner: &models.User{UserName: "src-org"}, Parent: &models.Repository{ Name: "pkg1", Owner: &models.User{UserName: "target-org"}, }, } gitea.EXPECT().GetRepository("target-org", "pkg1").Return(targetRepo, nil) // 4. Branch check - missing mockGit.EXPECT().GitClone("pkg1", "master", "target-ssh-url").Return("origin", nil) mockGit.EXPECT().GitExec(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(fmt.Errorf("not found")) // Orphan branch creation mockGit.EXPECT().GitExecOrPanic("pkg1", "checkout", "--detach") mockGit.EXPECT().GitExec("pkg1", "branch", "-D", "master") mockGit.EXPECT().GitExecOrPanic("pkg1", "checkout", "-f", "--orphan", "master") mockGit.EXPECT().GitExecOrPanic("pkg1", "rm", "-rf", ".") mockGit.EXPECT().GitExecOrPanic("pkg1", "commit", "--allow-empty", "-m", "Initial empty branch") mockGit.EXPECT().GitExecOrPanic("pkg1", "push", "-f", "origin", "master") // 5. Source repo fetch gitea.EXPECT().GetRepository("src-org", "pkg1").Return(srcRepo, nil) mockGit.EXPECT().GitExecWithOutput("pkg1", "ls-remote", "--heads", "src-ssh-url", "master").Return("src-sha refs/heads/master", nil) // PR creation gitea.EXPECT().CreatePullRequestIfNotExist(targetRepo, "src-org:master", "main", gomock.Any(), gomock.Any()).Return(&models.PullRequest{Index: 456}, nil, false) err := ProcessIssue(issue, configs) if err != nil { t.Errorf("Unexpected error: %v", err) } }) t.Run("Config not found", func(t *testing.T) { issueNoConfig := &models.Issue{ Title: "[ADD] pkg1", Body: "src-org/pkg1#master", Index: 123, Repository: &models.RepositoryMeta{ Owner: "other-org", Name: "other-prj", }, Ref: "refs/heads/main", } err := ProcessIssue(issueNoConfig, configs) if err == nil || err.Error() != "Cannot find config for other-org/other-prj#main" { t.Errorf("Expected config not found error, got %v", err) } }) t.Run("No repos in body", func(t *testing.T) { mockGitGen := mock_common.NewMockGitHandlerGenerator(ctl) GitHandler = mockGitGen err := ProcessIssue(&models.Issue{ Title: "[ADD] pkg1", Body: "nothing here", Ref: "refs/heads/main", Repository: &models.RepositoryMeta{ Owner: "test-org", Name: "test-prj", }, }, configs) if err != nil { t.Errorf("Unexpected error: %v", err) } }) }