@@ -11,82 +11,9 @@ import (
1111 "go.uber.org/zap"
1212)
1313
14- // enableProjectMirrorPull enables the pull mirror for a project in the destination GitLab instance.
15- // It sets the source project URL, enables mirroring, and configures other options like triggering builds and overwriting diverged branches.
16- func (g * GitlabInstance ) enableProjectMirrorPull (sourceProject * gitlab.Project , destinationProject * gitlab.Project , mirrorOptions * utils.MirroringOptions ) error {
17- zap .L ().Debug ("Enabling project mirror pull" , zap .String ("sourceProject" , sourceProject .HTTPURLToRepo ), zap .String ("destinationProject" , destinationProject .HTTPURLToRepo ))
18- _ , _ , err := g .Gitlab .Projects .ConfigureProjectPullMirror (destinationProject .ID , & gitlab.ConfigureProjectPullMirrorOptions {
19- URL : & sourceProject .HTTPURLToRepo ,
20- OnlyMirrorProtectedBranches : gitlab .Ptr (true ),
21- Enabled : gitlab .Ptr (true ),
22- MirrorOverwritesDivergedBranches : gitlab .Ptr (true ),
23- MirrorTriggerBuilds : gitlab .Ptr (mirrorOptions .MirrorTriggerBuilds ),
24- })
25- return err
26- }
27-
28- // copyProjectAvatar copies the avatar from the source project to the destination project.
29- // It first checks if the destination project already has an avatar set. If not, it downloads the avatar from the source project
30- // and uploads it to the destination project.
31- // The avatar is saved with a unique filename based on the current timestamp.
32- // The function returns an error if any step fails, including downloading or uploading the avatar.
33- func (sourceGitlabInstance * GitlabInstance ) copyProjectAvatar (destinationGitlabInstance * GitlabInstance , destinationProject * gitlab.Project , sourceProject * gitlab.Project ) error {
34- zap .L ().Debug ("Checking if project avatar is already set" , zap .String ("project" , destinationProject .HTTPURLToRepo ))
35-
36- // Check if the destination project already has an avatar
37- if destinationProject .AvatarURL != "" {
38- zap .L ().Debug ("Project already has an avatar set, skipping." , zap .String ("project" , destinationProject .HTTPURLToRepo ), zap .String ("path" , destinationProject .AvatarURL ))
39- return nil
40- }
41-
42- zap .L ().Debug ("Copying project avatar" , zap .String (ROLE_SOURCE , sourceProject .HTTPURLToRepo ), zap .String (ROLE_DESTINATION , destinationProject .HTTPURLToRepo ))
43-
44- // Download the source project avatar
45- sourceProjectAvatar , _ , err := sourceGitlabInstance .Gitlab .Projects .DownloadAvatar (sourceProject .ID )
46- if err != nil {
47- return fmt .Errorf ("failed to download avatar for project %s: %s" , sourceProject .HTTPURLToRepo , err )
48- }
49-
50- // Upload the avatar to the destination project
51- _ , _ , err = destinationGitlabInstance .Gitlab .Projects .UploadAvatar (destinationProject .ID , sourceProjectAvatar , fmt .Sprintf ("avatar-%d.png" , time .Now ().Unix ()))
52- if err != nil {
53- return fmt .Errorf ("failed to upload avatar for project %s: %s" , destinationProject .HTTPURLToRepo , err )
54- }
55-
56- return nil
57- }
58-
59- // copyGroupAvatar copies the avatar from the source group to the destination group.
60- // It first checks if the destination group already has an avatar set. If not, it downloads the avatar from the source group
61- // and uploads it to the destination group.
62- // The avatar is saved with a unique filename based on the current timestamp.
63- // The function returns an error if any step fails, including downloading or uploading the avatar.
64- func (sourceGitlabInstance * GitlabInstance ) copyGroupAvatar (destinationGitlabInstance * GitlabInstance , destinationGroup * gitlab.Group , sourceGroup * gitlab.Group ) error {
65- zap .L ().Debug ("Checking if group avatar is already set" , zap .String ("group" , destinationGroup .WebURL ))
66-
67- // Check if the destination group already has an avatar
68- if destinationGroup .AvatarURL != "" {
69- zap .L ().Debug ("Group avatar already set" , zap .String ("group" , destinationGroup .WebURL ), zap .String ("path" , destinationGroup .AvatarURL ))
70- return nil
71- }
72-
73- zap .L ().Debug ("Copying group avatar" , zap .String (ROLE_SOURCE , sourceGroup .WebURL ), zap .String (ROLE_DESTINATION , destinationGroup .WebURL ))
74-
75- // Download the source group avatar
76- sourceGroupAvatar , _ , err := sourceGitlabInstance .Gitlab .Groups .DownloadAvatar (sourceGroup .ID )
77- if err != nil {
78- return fmt .Errorf ("failed to download avatar for group %s: %s" , sourceGroup .WebURL , err )
79- }
80-
81- // Upload the avatar to the destination group
82- filename := fmt .Sprintf ("avatar-%d.png" , time .Now ().Unix ())
83- _ , _ , err = destinationGitlabInstance .Gitlab .Groups .UploadAvatar (destinationGroup .ID , sourceGroupAvatar , filename )
84- if err != nil {
85- return fmt .Errorf ("failed to upload avatar for group %s: %s" , destinationGroup .WebURL , err )
86- }
87-
88- return nil
89- }
14+ // ===========================================================================
15+ // PROJECTS PUT FUNCTIONS //
16+ // ===========================================================================
9017
9118// updateProjectFromSource updates the destination project with settings from the source project.
9219// It enables the project mirror pull, copies the project avatar, and optionally adds the project to the CI/CD catalog.
@@ -195,3 +122,140 @@ func (destinationGitlabInstance *GitlabInstance) syncProjectAttributes(sourcePro
195122 }
196123 return nil
197124}
125+
126+ // enableProjectMirrorPull enables the pull mirror for a project in the destination GitLab instance.
127+ // It sets the source project URL, enables mirroring, and configures other options like triggering builds and overwriting diverged branches.
128+ func (g * GitlabInstance ) enableProjectMirrorPull (sourceProject * gitlab.Project , destinationProject * gitlab.Project , mirrorOptions * utils.MirroringOptions ) error {
129+ zap .L ().Debug ("Enabling project mirror pull" , zap .String ("sourceProject" , sourceProject .HTTPURLToRepo ), zap .String ("destinationProject" , destinationProject .HTTPURLToRepo ))
130+ _ , _ , err := g .Gitlab .Projects .ConfigureProjectPullMirror (destinationProject .ID , & gitlab.ConfigureProjectPullMirrorOptions {
131+ URL : & sourceProject .HTTPURLToRepo ,
132+ OnlyMirrorProtectedBranches : gitlab .Ptr (true ),
133+ Enabled : gitlab .Ptr (true ),
134+ MirrorOverwritesDivergedBranches : gitlab .Ptr (true ),
135+ MirrorTriggerBuilds : gitlab .Ptr (mirrorOptions .MirrorTriggerBuilds ),
136+ })
137+ return err
138+ }
139+
140+ // copyProjectAvatar copies the avatar from the source project to the destination project.
141+ // It first checks if the destination project already has an avatar set. If not, it downloads the avatar from the source project
142+ // and uploads it to the destination project.
143+ // The avatar is saved with a unique filename based on the current timestamp.
144+ // The function returns an error if any step fails, including downloading or uploading the avatar.
145+ func (sourceGitlabInstance * GitlabInstance ) copyProjectAvatar (destinationGitlabInstance * GitlabInstance , destinationProject * gitlab.Project , sourceProject * gitlab.Project ) error {
146+ zap .L ().Debug ("Checking if project avatar is already set" , zap .String ("project" , destinationProject .HTTPURLToRepo ))
147+
148+ // Check if the destination project already has an avatar
149+ if destinationProject .AvatarURL != "" {
150+ zap .L ().Debug ("Project already has an avatar set, skipping." , zap .String ("project" , destinationProject .HTTPURLToRepo ), zap .String ("path" , destinationProject .AvatarURL ))
151+ return nil
152+ }
153+
154+ zap .L ().Debug ("Copying project avatar" , zap .String (ROLE_SOURCE , sourceProject .HTTPURLToRepo ), zap .String (ROLE_DESTINATION , destinationProject .HTTPURLToRepo ))
155+
156+ // Download the source project avatar
157+ sourceProjectAvatar , _ , err := sourceGitlabInstance .Gitlab .Projects .DownloadAvatar (sourceProject .ID )
158+ if err != nil {
159+ return fmt .Errorf ("failed to download avatar for project %s: %s" , sourceProject .HTTPURLToRepo , err )
160+ }
161+
162+ // Upload the avatar to the destination project
163+ _ , _ , err = destinationGitlabInstance .Gitlab .Projects .UploadAvatar (destinationProject .ID , sourceProjectAvatar , fmt .Sprintf ("avatar-%d.png" , time .Now ().Unix ()))
164+ if err != nil {
165+ return fmt .Errorf ("failed to upload avatar for project %s: %s" , destinationProject .HTTPURLToRepo , err )
166+ }
167+
168+ return nil
169+ }
170+
171+ // ===========================================================================
172+ // GROUPS PUT FUNCTIONS //
173+ // ===========================================================================
174+
175+ // updateGroupFromSource updates the destination group with settings from the source group.
176+ // It copies the group avatar and updates the group attributes.
177+ func (destinationGitlabInstance * GitlabInstance ) updateGroupFromSource (sourceGitlabInstance * GitlabInstance , sourceGroup * gitlab.Group , destinationGroup * gitlab.Group , copyOptions * utils.MirroringOptions ) []error {
178+ wg := sync.WaitGroup {}
179+ maxErrors := 2
180+ wg .Add (maxErrors )
181+ errorChan := make (chan error , maxErrors )
182+
183+ go func () {
184+ defer wg .Done ()
185+ errorChan <- destinationGitlabInstance .syncGroupAttributes (sourceGroup , destinationGroup , copyOptions )
186+ }()
187+
188+ go func () {
189+ defer wg .Done ()
190+ errorChan <- sourceGitlabInstance .copyGroupAvatar (destinationGitlabInstance , destinationGroup , sourceGroup )
191+ }()
192+
193+ wg .Wait ()
194+ close (errorChan )
195+
196+ return utils .MergeErrors (errorChan )
197+ }
198+
199+ // copyGroupAvatar copies the avatar from the source group to the destination group.
200+ // It first checks if the destination group already has an avatar set. If not, it downloads the avatar from the source group
201+ // and uploads it to the destination group.
202+ // The avatar is saved with a unique filename based on the current timestamp.
203+ // The function returns an error if any step fails, including downloading or uploading the avatar.
204+ func (sourceGitlabInstance * GitlabInstance ) copyGroupAvatar (destinationGitlabInstance * GitlabInstance , destinationGroup * gitlab.Group , sourceGroup * gitlab.Group ) error {
205+ zap .L ().Debug ("Checking if group avatar is already set" , zap .String ("group" , destinationGroup .WebURL ))
206+
207+ // Check if the destination group already has an avatar
208+ if destinationGroup .AvatarURL != "" {
209+ zap .L ().Debug ("Group avatar already set" , zap .String ("group" , destinationGroup .WebURL ), zap .String ("path" , destinationGroup .AvatarURL ))
210+ return nil
211+ }
212+
213+ zap .L ().Debug ("Copying group avatar" , zap .String (ROLE_SOURCE , sourceGroup .WebURL ), zap .String (ROLE_DESTINATION , destinationGroup .WebURL ))
214+
215+ // Download the source group avatar
216+ sourceGroupAvatar , _ , err := sourceGitlabInstance .Gitlab .Groups .DownloadAvatar (sourceGroup .ID )
217+ if err != nil {
218+ return fmt .Errorf ("failed to download avatar for group %s: %s" , sourceGroup .WebURL , err )
219+ }
220+
221+ // Upload the avatar to the destination group
222+ filename := fmt .Sprintf ("avatar-%d.png" , time .Now ().Unix ())
223+ _ , _ , err = destinationGitlabInstance .Gitlab .Groups .UploadAvatar (destinationGroup .ID , sourceGroupAvatar , filename )
224+ if err != nil {
225+ return fmt .Errorf ("failed to upload avatar for group %s: %s" , destinationGroup .WebURL , err )
226+ }
227+
228+ return nil
229+ }
230+
231+ // syncGroupAttributes updates the destination group with settings from the source group.
232+ // It checks if any diverged group data exists and if so, it overwrites it.
233+ func (destinationGitlabInstance * GitlabInstance ) syncGroupAttributes (sourceGroup * gitlab.Group , destinationGroup * gitlab.Group , copyOptions * utils.MirroringOptions ) error {
234+ zap .L ().Debug ("Checking if group requires attributes resync" , zap .String (ROLE_SOURCE , sourceGroup .FullPath ), zap .String (ROLE_DESTINATION , destinationGroup .FullPath ))
235+ gitlabEditOptions := & gitlab.UpdateGroupOptions {}
236+ missmatched := false
237+ if sourceGroup .Name != destinationGroup .Name {
238+ gitlabEditOptions .Name = & sourceGroup .Name
239+ missmatched = true
240+ }
241+ if sourceGroup .Description != destinationGroup .Description {
242+ gitlabEditOptions .Description = & sourceGroup .Description
243+ missmatched = true
244+ }
245+ if copyOptions .Visibility != string (destinationGroup .Visibility ) {
246+ visibilityValue := utils .ConvertVisibility (copyOptions .Visibility )
247+ gitlabEditOptions .Visibility = & visibilityValue
248+ missmatched = true
249+ }
250+
251+ if missmatched {
252+ destinationGroup , _ , err := destinationGitlabInstance .Gitlab .Groups .UpdateGroup (destinationGroup .ID , gitlabEditOptions )
253+ if err != nil {
254+ return fmt .Errorf ("failed to edit group %s: %s" , destinationGroup .FullPath , err )
255+ }
256+ zap .L ().Debug ("Group attributes resync completed" , zap .String (ROLE_SOURCE , sourceGroup .FullPath ), zap .String (ROLE_DESTINATION , destinationGroup .FullPath ))
257+ } else {
258+ zap .L ().Debug ("Group attributes are already in sync, skipping" , zap .String (ROLE_SOURCE , sourceGroup .FullPath ), zap .String (ROLE_DESTINATION , destinationGroup .FullPath ))
259+ }
260+ return nil
261+ }
0 commit comments