From 0331346025e728618c37a0a92abe9042745bb6ebf81e7eafc5bc6d889ac881e0 Mon Sep 17 00:00:00 2001 From: Adam Majer Date: Thu, 28 Nov 2024 17:10:26 +0100 Subject: [PATCH] workflow-pr: maintainership parsing --- workflow-pr/maintainership.go | 53 ++++++----- workflow-pr/maintainership_test.go | 140 ++++++++++++++++++++--------- 2 files changed, 125 insertions(+), 68 deletions(-) diff --git a/workflow-pr/maintainership.go b/workflow-pr/maintainership.go index 5e7c623..4162ce1 100644 --- a/workflow-pr/maintainership.go +++ b/workflow-pr/maintainership.go @@ -2,7 +2,6 @@ package main import ( "encoding/json" - "errors" "src.opensuse.org/autogits/common" ) @@ -11,14 +10,14 @@ import ( const ProjectKey = "*" -type MaintainershipMap map[string]interface{} +type MaintainershipMap map[string][]string type GiteaMaintainershipInterface interface { FetchMaintainershipFile(org, prj, branch string) ([]byte, error) } -func MaintainerListForProject(gitea GiteaMaintainershipInterface, org, branch string) ([]string, error) { - data, err := gitea.FetchMaintainershipFile(org, common.DefaultGitPrj, branch) +func parseMaintainerhipData(gitea GiteaMaintainershipInterface, org, pkg, branch string) (MaintainershipMap, error) { + data, err := gitea.FetchMaintainershipFile(org, pkg, branch) if err != nil || data == nil { return nil, err } @@ -28,35 +27,41 @@ func MaintainerListForProject(gitea GiteaMaintainershipInterface, org, branch st return nil, err } + return maintainer, nil +} + +func MaintainerListForProject(gitea GiteaMaintainershipInterface, org, branch string) ([]string, error) { + maintainer, err := parseMaintainerhipData(gitea, org, common.DefaultGitPrj, branch) + if err != nil { + return nil, err + } + m, found := maintainer[ProjectKey] if !found { return nil, nil } - invalidTypeErr := errors.New("Invalid type") - switch m.(type) { - case []interface{}: - maintainers := make([]string, 0) - for _, v := range m.([]interface{}) { - if _, ok := v.(string); !ok { - return nil, invalidTypeErr - } - maintainers = append(maintainers, v.(string)) - } - return maintainers, nil - - case string: - return []string{m.(string)}, nil - - default: - return nil, invalidTypeErr - } + return m, nil } func MaintainerListForPackage(gitea GiteaMaintainershipInterface, org, pkg, branch string) ([]string, error) { - _, err := gitea.FetchMaintainershipFile(org, pkg, branch) + maintainer, err := parseMaintainerhipData(gitea, org, pkg, branch) if err != nil { return nil, err } - return []string{}, nil + + pkgMaintainers := maintainer[pkg] + prjMaintainers := maintainer[ProjectKey] + +prjMaintainer: + for _, prjm := range prjMaintainers { + for i := range pkgMaintainers { + if pkgMaintainers[i] == prjm { + continue prjMaintainer + } + } + pkgMaintainers = append(pkgMaintainers, prjm) + } + + return pkgMaintainers, nil } diff --git a/workflow-pr/maintainership_test.go b/workflow-pr/maintainership_test.go index 4852fc1..a00c86a 100644 --- a/workflow-pr/maintainership_test.go +++ b/workflow-pr/maintainership_test.go @@ -10,34 +10,18 @@ import ( ) func TestMaintainership(t *testing.T) { - MaintainershipFile := []byte(` - { - "*": ["user1", "user2"] - } - `) - SinglePrjMaintainershipFile := []byte(` - { - "*": "user" - } - `) - - BrokenPrjMaintainershipFile := []byte(` - { - "*": ["user", 4] - } - `) - SingleBrokenPrjMaintainershipFile := []byte(` - { - "*": 4 - } - `) - - - t.Run("No maintainer in empty package", func(t *testing.T) { + allocateMaintainershipInterface := func(t *testing.T) *mock_main.MockGiteaMaintainershipInterface { + t.Parallel() ctl := gomock.NewController(t) mi := mock_main.NewMockGiteaMaintainershipInterface(ctl) + return mi + } + + t.Run("No maintainer in empty package", func(t *testing.T) { + mi := allocateMaintainershipInterface(t) + mi.EXPECT().FetchMaintainershipFile("foo", "goo", "bar").Return(nil, nil) m, err := MaintainerListForPackage(mi, "foo", "goo", "bar") @@ -47,8 +31,7 @@ func TestMaintainership(t *testing.T) { }) t.Run("No maintainer for empty projects", func(t *testing.T) { - ctl := gomock.NewController(t) - mi := mock_main.NewMockGiteaMaintainershipInterface(ctl) + mi := allocateMaintainershipInterface(t) mi.EXPECT().FetchMaintainershipFile("foo", common.DefaultGitPrj, "bar").Return(nil, nil) @@ -66,8 +49,7 @@ func TestMaintainership(t *testing.T) { }) t.Run("Error in MaintainerListForPackage when remote has an error", func(t *testing.T) { - ctl := gomock.NewController(t) - mi := mock_main.NewMockGiteaMaintainershipInterface(ctl) + mi := allocateMaintainershipInterface(t) err := errors.New("some error here") mi.EXPECT().FetchMaintainershipFile("foo", "goo", "bar").Return(nil, err) @@ -82,9 +64,9 @@ func TestMaintainership(t *testing.T) { t.Error("Unexpected error received", err) } }) + t.Run("Error in MaintainerListForProject when remote has an error", func(t *testing.T) { - ctl := gomock.NewController(t) - mi := mock_main.NewMockGiteaMaintainershipInterface(ctl) + mi := allocateMaintainershipInterface(t) err := errors.New("some error here") mi.EXPECT().FetchMaintainershipFile("foo", common.DefaultGitPrj, "bar").Return(nil, err) @@ -101,10 +83,13 @@ func TestMaintainership(t *testing.T) { }) t.Run("Multiple project maintainers", func(t *testing.T) { - ctl := gomock.NewController(t) - mi := mock_main.NewMockGiteaMaintainershipInterface(ctl) + mi := allocateMaintainershipInterface(t) - mi.EXPECT().FetchMaintainershipFile("foo", common.DefaultGitPrj, "bar").Return(MaintainershipFile, nil) + mi.EXPECT().FetchMaintainershipFile("foo", common.DefaultGitPrj, "bar").Return([]byte(` + { + "*": ["user1", "user2"] + } + `), nil) m, err := MaintainerListForProject(mi, "foo", "bar") if len(m) != 2 || err != nil { @@ -117,10 +102,13 @@ func TestMaintainership(t *testing.T) { }) t.Run("Single project maintainer", func(t *testing.T) { - ctl := gomock.NewController(t) - mi := mock_main.NewMockGiteaMaintainershipInterface(ctl) + mi := allocateMaintainershipInterface(t) - mi.EXPECT().FetchMaintainershipFile("foo", common.DefaultGitPrj, "bar").Return(SinglePrjMaintainershipFile, nil) + mi.EXPECT().FetchMaintainershipFile("foo", common.DefaultGitPrj, "bar").Return([]byte(` + { + "*": ["user"] + } + `), nil) m, err := MaintainerListForProject(mi, "foo", "bar") if len(m) != 1 || err != nil { @@ -133,26 +121,90 @@ func TestMaintainership(t *testing.T) { }) t.Run("Invalid list of project maintainers", func(t *testing.T) { - ctl := gomock.NewController(t) - mi := mock_main.NewMockGiteaMaintainershipInterface(ctl) + mi := allocateMaintainershipInterface(t) - mi.EXPECT().FetchMaintainershipFile("foo", common.DefaultGitPrj, "bar").Return(BrokenPrjMaintainershipFile, nil) + mi.EXPECT().FetchMaintainershipFile("foo", common.DefaultGitPrj, "bar").Return([]byte(` + { + "*": ["user", 4] + } + `), nil) m, err := MaintainerListForProject(mi, "foo", "bar") - if len(m) != 0 || err.Error() != "Invalid type" { + if len(m) != 0 || err == nil { t.Error("Invalid number of maintainers for project", err) } }) t.Run("Invalid list of project maintainers", func(t *testing.T) { - ctl := gomock.NewController(t) - mi := mock_main.NewMockGiteaMaintainershipInterface(ctl) + mi := allocateMaintainershipInterface(t) - mi.EXPECT().FetchMaintainershipFile("foo", common.DefaultGitPrj, "bar").Return(SingleBrokenPrjMaintainershipFile, nil) + mi.EXPECT().FetchMaintainershipFile("foo", common.DefaultGitPrj, "bar").Return([]byte(` + { + "*": 4 + } + `), nil) _, err := MaintainerListForProject(mi, "foo", "bar") - if err.Error() != "Invalid type" { + if err == nil { t.Error("Invalid number of maintainers for project", err) } }) + + t.Run("Multiple package maintainers", func(t *testing.T) { + mi := allocateMaintainershipInterface(t) + + mi.EXPECT().FetchMaintainershipFile("foo", "pkg", "bar").Return([]byte(` + { + "pkg": ["user1", "user2"], + "*": ["user1", "user3"] + } + `), nil) + + m, err := MaintainerListForPackage(mi, "foo", "pkg", "bar") + if len(m) != 3 || err != nil { + t.Error("Invalid number of maintainers for package", m) + } + + if m[0] != "user1" || m[1] != "user2" || m[2] != "user3" { + t.Error("Can't find expected users. Found", m) + } + }) + + t.Run("No package maintainers and only project maintainer", func(t *testing.T) { + mi := allocateMaintainershipInterface(t) + + mi.EXPECT().FetchMaintainershipFile("foo", "pkg0", "bar").Return([]byte(` + { + "pkg": ["user1", "user2"], + "*": ["user1", "user3"] + } + `), nil) + + m, err := MaintainerListForPackage(mi, "foo", "pkg0", "bar") + if len(m) != 2 || err != nil { + t.Error("Invalid number of maintainers for package", m) + } + + if m[0] != "user1" || m[1] != "user3" { + t.Error("Can't find expected users. Found", m) + } + }) + + t.Run("Invalid list of package maintainers", func(t *testing.T) { + mi := allocateMaintainershipInterface(t) + + mi.EXPECT().FetchMaintainershipFile("foo", "pkg", "bar").Return([]byte(` + { + "pkg": 3, + "*": ["user", 4] + } + `), nil) + + m, err := MaintainerListForPackage(mi, "foo", "pkg", "bar") + if len(m) != 0 || err == nil { + t.Error("Invalid number of maintainers for project", err) + } + }) + + t.Parallel() }