Skip to content

Commit 6e8844e

Browse files
frjcompCopilot
andauthored
Gitlab refactor (#327)
* Refactor GitLab commands to eliminate duplicate project iteration logic - Add shared IterateProjects() and IterateGroupProjects() helpers in util package - Refactor 6 files to use callback-based iteration pattern: * cmd/gitlab/variables.go * cmd/gitlab/schedule/schedule.go * cmd/gitlab/secureFiles/secure_files.go * cmd/gitlab/scan/pipeline.go * cmd/gitlab/runners/list.go * cmd/gitlab/renovate/enum.go - Eliminate ~200+ lines of duplicated pagination code - Maintain 100% backward compatibility - All tests passing (unit + e2e) - Linter clean (0 issues) * refactor(gitlab): reorganize package structure into subdirectories Move single-file commands into their own subdirectories for better organization: - enum.go -> enum/enum.go - register.go -> register/register.go - shodan.go -> shodan/shodan.go - variables.go -> variables/variables.go - vuln.go -> vuln/vuln.go This aligns with the existing structure used by scan/, runners/, renovate/, etc. All commands now follow a consistent subdirectory pattern. Updated imports and package references in: - gitlab.go (command registration) - gitlab_unauth.go (unauthenticated commands) - gitlab_test.go (test function calls) All unit tests, e2e tests, and golangci-lint checks pass. * Remove explanatory comment from renovate enum.go (#328) * Initial plan * fix: remove comment in enum.go as per review feedback Co-authored-by: frjcomp <107982661+frjcomp@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: frjcomp <107982661+frjcomp@users.noreply.github.com> --------- Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com>
1 parent 7fcdaa3 commit 6e8844e

14 files changed

Lines changed: 183 additions & 186 deletions

File tree

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package gitlab
1+
package enum
22

33
import (
44
"net/url"
@@ -16,7 +16,12 @@ import (
1616
"resty.dev/v3"
1717
)
1818

19-
var minAccessLevel int
19+
var (
20+
gitlabApiToken string
21+
gitlabUrl string
22+
verbose bool
23+
minAccessLevel int
24+
)
2025

2126
func NewEnumCmd() *cobra.Command {
2227
enumCmd := &cobra.Command{

src/pipeleak/cmd/gitlab/gitlab.go

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,14 @@ package gitlab
22

33
import (
44
"github.com/CompassSecurity/pipeleak/cmd/gitlab/cicd"
5+
"github.com/CompassSecurity/pipeleak/cmd/gitlab/enum"
56
"github.com/CompassSecurity/pipeleak/cmd/gitlab/renovate"
67
"github.com/CompassSecurity/pipeleak/cmd/gitlab/runners"
78
"github.com/CompassSecurity/pipeleak/cmd/gitlab/scan"
89
"github.com/CompassSecurity/pipeleak/cmd/gitlab/schedule"
910
securefiles "github.com/CompassSecurity/pipeleak/cmd/gitlab/secureFiles"
11+
"github.com/CompassSecurity/pipeleak/cmd/gitlab/variables"
12+
"github.com/CompassSecurity/pipeleak/cmd/gitlab/vuln"
1013
"github.com/rs/zerolog/log"
1114
"github.com/spf13/cobra"
1215
)
@@ -39,10 +42,10 @@ For SOCKS5 proxy:
3942

4043
glCmd.AddCommand(scan.NewScanCmd())
4144
glCmd.AddCommand(runners.NewRunnersRootCmd())
42-
glCmd.AddCommand(NewVulnCmd())
43-
glCmd.AddCommand(NewVariablesCmd())
45+
glCmd.AddCommand(vuln.NewVulnCmd())
46+
glCmd.AddCommand(variables.NewVariablesCmd())
4447
glCmd.AddCommand(securefiles.NewSecureFilesCmd())
45-
glCmd.AddCommand(NewEnumCmd())
48+
glCmd.AddCommand(enum.NewEnumCmd())
4649
glCmd.AddCommand(renovate.NewRenovateRootCmd())
4750
glCmd.AddCommand(cicd.NewCiCdCmd())
4851
glCmd.AddCommand(schedule.NewScheduleCmd())

src/pipeleak/cmd/gitlab/gitlab_test.go

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,12 @@ package gitlab
22

33
import (
44
"testing"
5+
6+
"github.com/CompassSecurity/pipeleak/cmd/gitlab/enum"
7+
"github.com/CompassSecurity/pipeleak/cmd/gitlab/register"
8+
"github.com/CompassSecurity/pipeleak/cmd/gitlab/shodan"
9+
"github.com/CompassSecurity/pipeleak/cmd/gitlab/variables"
10+
"github.com/CompassSecurity/pipeleak/cmd/gitlab/vuln"
511
)
612

713
func TestNewGitLabRootCmd(t *testing.T) {
@@ -44,7 +50,7 @@ func TestNewGitLabRootCmd(t *testing.T) {
4450
}
4551

4652
func TestNewVulnCmd(t *testing.T) {
47-
cmd := NewVulnCmd()
53+
cmd := vuln.NewVulnCmd()
4854

4955
if cmd == nil {
5056
t.Fatal("Expected non-nil command")
@@ -60,7 +66,7 @@ func TestNewVulnCmd(t *testing.T) {
6066
}
6167

6268
func TestNewVariablesCmd(t *testing.T) {
63-
cmd := NewVariablesCmd()
69+
cmd := variables.NewVariablesCmd()
6470

6571
if cmd == nil {
6672
t.Fatal("Expected non-nil command")
@@ -81,7 +87,7 @@ func TestNewVariablesCmd(t *testing.T) {
8187
}
8288

8389
func TestNewEnumCmd(t *testing.T) {
84-
cmd := NewEnumCmd()
90+
cmd := enum.NewEnumCmd()
8591

8692
if cmd == nil {
8793
t.Fatal("Expected non-nil command")
@@ -97,7 +103,7 @@ func TestNewEnumCmd(t *testing.T) {
97103
}
98104

99105
func TestNewRegisterCmd(t *testing.T) {
100-
cmd := NewRegisterCmd()
106+
cmd := register.NewRegisterCmd()
101107

102108
if cmd == nil {
103109
t.Fatal("Expected non-nil command")
@@ -127,7 +133,7 @@ func TestNewRegisterCmd(t *testing.T) {
127133
}
128134

129135
func TestNewShodanCmd(t *testing.T) {
130-
cmd := NewShodanCmd()
136+
cmd := shodan.NewShodanCmd()
131137

132138
if cmd == nil {
133139
t.Fatal("Expected non-nil command")

src/pipeleak/cmd/gitlab/gitlab_unauth.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package gitlab
22

33
import (
4+
"github.com/CompassSecurity/pipeleak/cmd/gitlab/register"
5+
"github.com/CompassSecurity/pipeleak/cmd/gitlab/shodan"
46
"github.com/spf13/cobra"
57
)
68

@@ -12,8 +14,8 @@ func NewGitLabRootUnauthenticatedCmd() *cobra.Command {
1214
GroupID: "Helper",
1315
}
1416

15-
glunaCmd.AddCommand(NewShodanCmd())
16-
glunaCmd.AddCommand(NewRegisterCmd())
17+
glunaCmd.AddCommand(shodan.NewShodanCmd())
18+
glunaCmd.AddCommand(register.NewRegisterCmd())
1719

1820
glunaCmd.PersistentFlags().BoolVarP(&verbose, "verbose", "v", false, "Verbose logging")
1921

src/pipeleak/cmd/gitlab/register.go renamed to src/pipeleak/cmd/gitlab/register/register.go

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package gitlab
1+
package register
22

33
import (
44
"github.com/CompassSecurity/pipeleak/cmd/gitlab/util"
@@ -8,9 +8,11 @@ import (
88
)
99

1010
var (
11-
username string
12-
password string
13-
email string
11+
gitlabUrl string
12+
verbose bool
13+
username string
14+
password string
15+
email string
1416
)
1517

1618
func NewRegisterCmd() *cobra.Command {

src/pipeleak/cmd/gitlab/renovate/enum.go

Lines changed: 16 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import (
1010
"path/filepath"
1111
"regexp"
1212
"strings"
13-
"sync"
1413

1514
"github.com/CompassSecurity/pipeleak/cmd/gitlab/util"
1615
"github.com/CompassSecurity/pipeleak/pkg/format"
@@ -132,30 +131,14 @@ func scanNamespace(git *gitlab.Client, namespace string) {
132131
IncludeSubGroups: gitlab.Ptr(true),
133132
}
134133

135-
for {
136-
projects, resp, err := git.Groups.ListGroupProjects(group.ID, projectOpts)
137-
if err != nil {
138-
log.Error().Stack().Err(err).Int("page", page).Msg("Failed fetching projects")
139-
break
140-
}
141-
142-
var wg sync.WaitGroup
143-
for _, project := range projects {
144-
wg.Add(1)
145-
go func(proj *gitlab.Project) {
146-
defer wg.Done()
147-
log.Debug().Str("url", proj.WebURL).Msg("Check project")
148-
identifyRenovateBotJob(git, proj)
149-
}(project)
150-
}
151-
wg.Wait()
152-
153-
if resp.NextPage == 0 {
154-
break
155-
}
156-
157-
projectOpts.Page = resp.NextPage
158-
log.Info().Int("currentPage", projectOpts.Page).Msg("Fetched projects page")
134+
err = util.IterateGroupProjects(git, group.ID, projectOpts, func(project *gitlab.Project) error {
135+
log.Debug().Str("url", project.WebURL).Msg("Check project")
136+
identifyRenovateBotJob(git, project)
137+
return nil
138+
})
139+
if err != nil {
140+
log.Error().Stack().Err(err).Msg("Failed iterating group projects")
141+
return
159142
}
160143

161144
log.Info().Msg("Fetched all namespace projects")
@@ -175,30 +158,14 @@ func fetchProjects(git *gitlab.Client) {
175158
Search: gitlab.Ptr(projectSearchQuery),
176159
}
177160

178-
for {
179-
projects, resp, err := git.Projects.ListProjects(projectOpts)
180-
if err != nil {
181-
log.Error().Stack().Err(err).Int("page", page).Msg("Failed fetching projects")
182-
break
183-
}
184-
185-
var wg sync.WaitGroup
186-
for _, project := range projects {
187-
wg.Add(1)
188-
go func(proj *gitlab.Project) {
189-
defer wg.Done()
190-
log.Debug().Str("url", proj.WebURL).Msg("Check project")
191-
identifyRenovateBotJob(git, proj)
192-
}(project)
193-
}
194-
wg.Wait()
195-
196-
if resp.NextPage == 0 {
197-
break
198-
}
199-
200-
projectOpts.Page = resp.NextPage
201-
log.Info().Int("currentPage", projectOpts.Page).Msg("Fetched projects page")
161+
err := util.IterateProjects(git, projectOpts, func(project *gitlab.Project) error {
162+
log.Debug().Str("url", project.WebURL).Msg("Check project")
163+
identifyRenovateBotJob(git, project)
164+
return nil
165+
})
166+
if err != nil {
167+
log.Error().Stack().Err(err).Msg("Failed iterating projects")
168+
return
202169
}
203170

204171
log.Info().Msg("Fetched all projects")

src/pipeleak/cmd/gitlab/runners/list.go

Lines changed: 14 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -86,30 +86,22 @@ func listProjectRunners(git *gitlab.Client, runnerMap map[int]runnerResult) map[
8686
MinAccessLevel: gitlab.Ptr(gitlab.MaintainerPermissions),
8787
}
8888

89-
for {
90-
projects, resp, err := git.Projects.ListProjects(projectOpts)
91-
if err != nil {
92-
log.Error().Stack().Err(err).Msg("Failed fetching projects")
89+
err := util.IterateProjects(git, projectOpts, func(project *gitlab.Project) error {
90+
log.Debug().Str("name", project.Name).Int("id", project.ID).Msg("List runners for")
91+
runnerOpts := &gitlab.ListProjectRunnersOptions{
92+
ListOptions: gitlab.ListOptions{
93+
PerPage: 100,
94+
Page: 1,
95+
},
9396
}
94-
95-
for _, project := range projects {
96-
log.Debug().Str("name", project.Name).Int("id", project.ID).Msg("List runners for")
97-
runnerOpts := &gitlab.ListProjectRunnersOptions{
98-
ListOptions: gitlab.ListOptions{
99-
PerPage: 100,
100-
Page: 1,
101-
},
102-
}
103-
runners, _, _ := git.Runners.ListProjectRunners(project.ID, runnerOpts)
104-
for _, runner := range runners {
105-
runnerMap[runner.ID] = runnerResult{runner: runner, project: project, group: nil}
106-
}
97+
runners, _, _ := git.Runners.ListProjectRunners(project.ID, runnerOpts)
98+
for _, runner := range runners {
99+
runnerMap[runner.ID] = runnerResult{runner: runner, project: project, group: nil}
107100
}
108-
109-
if resp.NextPage == 0 {
110-
break
111-
}
112-
projectOpts.Page = resp.NextPage
101+
return nil
102+
})
103+
if err != nil {
104+
log.Error().Stack().Err(err).Msg("Failed iterating projects")
113105
}
114106

115107
return runnerMap

src/pipeleak/cmd/gitlab/scan/pipeline.go

Lines changed: 16 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -123,24 +123,14 @@ func scanNamespace(git *gitlab.Client, options *ScanOptions, wg *sync.WaitGroup)
123123
IncludeSubGroups: gitlab.Ptr(true),
124124
}
125125

126-
for {
127-
projects, resp, err := git.Groups.ListGroupProjects(group.ID, projectOpts)
128-
if err != nil {
129-
log.Error().Stack().Err(err).Msg("Failed fetching projects in namespace")
130-
break
131-
}
132-
133-
for _, project := range projects {
134-
log.Debug().Str("url", project.WebURL).Msg("Fetch project jobs")
135-
getAllJobs(git, project, options)
136-
}
137-
138-
if resp.NextPage == 0 {
139-
break
140-
}
141-
142-
projectOpts.Page = resp.NextPage
143-
log.Info().Int("currentPage", projectOpts.Page).Msg("Fetched projects page")
126+
err = util.IterateGroupProjects(git, group.ID, projectOpts, func(project *gitlab.Project) error {
127+
log.Debug().Str("url", project.WebURL).Msg("Fetch project jobs")
128+
getAllJobs(git, project, options)
129+
return nil
130+
})
131+
if err != nil {
132+
log.Error().Stack().Err(err).Msg("Failed iterating namespace projects")
133+
return
144134
}
145135

146136
log.Info().Msg("Fetched all namespace projects")
@@ -183,23 +173,14 @@ func fetchProjects(git *gitlab.Client, options *ScanOptions, wg *sync.WaitGroup)
183173
OrderBy: gitlab.Ptr("last_activity_at"),
184174
}
185175

186-
for {
187-
projects, resp, err := git.Projects.ListProjects(projectOpts)
188-
if err != nil {
189-
log.Error().Stack().Err(err).Msg("Failed fetching projects")
190-
break
191-
}
192-
193-
for _, project := range projects {
194-
log.Debug().Str("url", project.WebURL).Msg("Fetch project jobs")
195-
getAllJobs(git, project, options)
196-
}
197-
198-
if resp.NextPage == 0 {
199-
break
200-
}
201-
projectOpts.Page = resp.NextPage
202-
log.Info().Int("total", projectOpts.Page*projectOpts.PerPage).Msg("Fetched projects")
176+
err := util.IterateProjects(git, projectOpts, func(project *gitlab.Project) error {
177+
log.Debug().Str("url", project.WebURL).Msg("Fetch project jobs")
178+
getAllJobs(git, project, options)
179+
return nil
180+
})
181+
if err != nil {
182+
log.Error().Stack().Err(err).Msg("Failed iterating projects")
183+
return
203184
}
204185

205186
log.Info().Msg("Fetched all projects")

src/pipeleak/cmd/gitlab/schedule/schedule.go

Lines changed: 7 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -62,22 +62,13 @@ func FetchSchedules(cmd *cobra.Command, args []string) {
6262
OrderBy: gitlab.Ptr("last_activity_at"),
6363
}
6464

65-
for {
66-
projects, resp, err := git.Projects.ListProjects(projectOpts)
67-
if err != nil {
68-
log.Error().Stack().Err(err).Msg("Failed fetching projects")
69-
break
70-
}
71-
72-
for _, project := range projects {
73-
log.Debug().Str("project", project.WebURL).Msg("Fetch project schedules")
74-
ListPipelineSchedules(git, project)
75-
}
76-
77-
if resp.NextPage == 0 {
78-
break
79-
}
80-
projectOpts.Page = resp.NextPage
65+
err = util.IterateProjects(git, projectOpts, func(project *gitlab.Project) error {
66+
log.Debug().Str("project", project.WebURL).Msg("Fetch project schedules")
67+
ListPipelineSchedules(git, project)
68+
return nil
69+
})
70+
if err != nil {
71+
log.Fatal().Stack().Err(err).Msg("Failed iterating projects")
8172
}
8273

8374
log.Info().Msg("Fetched all schedules")

0 commit comments

Comments
 (0)