Skip to content

Commit 0058fcd

Browse files
committed
feat: add a forced free tier behavior argument
add more comments & verbosity
1 parent a0b734d commit 0058fcd

File tree

5 files changed

+43
-21
lines changed

5 files changed

+43
-21
lines changed

cmd/main.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,8 @@ func main() {
7777
rootCmd.Flags().StringVar(&args.DestinationGitlabURL, "destination-url", os.Getenv("DESTINATION_GITLAB_URL"), "Destination GitLab URL")
7878
rootCmd.Flags().StringVar(&args.DestinationGitlabToken, "destination-token", os.Getenv("DESTINATION_GITLAB_TOKEN"), "Destination GitLab Token")
7979
rootCmd.Flags().BoolVar(&args.DestinationGitlabIsBig, "destination-big", strings.TrimSpace(os.Getenv("DESTINATION_GITLAB_BIG")) != "", "Destination GitLab is a big instance")
80-
rootCmd.Flags().BoolVarP(&args.DestinationGitlabForcePremium, "destination-force-premium", "p", false, "Force the destination GitLab to be treated as a premium instance")
80+
rootCmd.Flags().BoolVarP(&args.ForcePremium, "destination-force-premium", "p", false, "Force the destination GitLab to be treated as a premium instance")
81+
rootCmd.Flags().BoolVarP(&args.ForceNonPremium, "destination-force-freemium", "f", false, "Force the destination GitLab to be treated as a non premium instance")
8182
rootCmd.Flags().BoolVarP(&args.Verbose, "verbose", "v", false, "Enable verbose output")
8283
rootCmd.Flags().BoolVarP(&args.NoPrompt, "no-prompt", "n", strings.TrimSpace(os.Getenv("NO_PROMPT")) != "", "Disable prompting for missing values")
8384
rootCmd.Flags().StringVar(&mirrorMappingPath, "mirror-mapping", os.Getenv("MIRROR_MAPPING"), "Path to the mirror mapping file")

internal/mirroring/main.go

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,13 @@ import (
1919
// If the dry run flag is set, it will only print the groups and projects that would be created or updated.
2020
func MirrorGitlabs(gitlabMirrorArgs *utils.ParserArgs) []error {
2121
zap.L().Info("Starting GitLab mirroring process", zap.String(ROLE_SOURCE, gitlabMirrorArgs.SourceGitlabURL), zap.String(ROLE_DESTINATION, gitlabMirrorArgs.DestinationGitlabURL))
22+
23+
// Create source GitLab instance
2224
sourceGitlabSize := INSTANCE_SIZE_SMALL
2325
if gitlabMirrorArgs.SourceGitlabIsBig {
2426
sourceGitlabSize = INSTANCE_SIZE_BIG
2527
}
28+
2629
sourceGitlabInstance, err := newGitlabInstance(&GitlabInstanceOpts{
2730
GitlabURL: gitlabMirrorArgs.SourceGitlabURL,
2831
GitlabToken: gitlabMirrorArgs.SourceGitlabToken,
@@ -34,6 +37,7 @@ func MirrorGitlabs(gitlabMirrorArgs *utils.ParserArgs) []error {
3437
return []error{err}
3538
}
3639

40+
// Create destination GitLab instance
3741
destinationGitlabSize := INSTANCE_SIZE_SMALL
3842
if gitlabMirrorArgs.DestinationGitlabIsBig {
3943
destinationGitlabSize = INSTANCE_SIZE_BIG
@@ -48,12 +52,16 @@ func MirrorGitlabs(gitlabMirrorArgs *utils.ParserArgs) []error {
4852
if err != nil {
4953
return []error{err}
5054
}
51-
pullMirrorAvailable, err := destinationGitlabInstance.IsPullMirrorAvailable(gitlabMirrorArgs.DestinationGitlabForcePremium)
55+
pullMirrorAvailable, err := destinationGitlabInstance.IsPullMirrorAvailable(gitlabMirrorArgs.ForcePremium, gitlabMirrorArgs.ForceNonPremium)
56+
5257
if err != nil {
58+
// Could not obtain a result from the destination GitLab instance, so we cannot proceed with the mirroring process.
5359
return []error{err}
5460
} else if pullMirrorAvailable {
61+
// Proceed with the pull mirroring process
5562
zap.L().Info("GitLab instance is compatible with the pull mirroring process", zap.String(ROLE, destinationGitlabInstance.Role), zap.String(INSTANCE_SIZE, destinationGitlabInstance.InstanceSize))
5663
} else {
64+
// Use local pull/push mirroring instead
5765
zap.L().Warn("Destination GitLab instance is not compatible with the pull mirroring process (requires a >= 17.6 ; >= Premium destination GitLab instance)", zap.String(ROLE, destinationGitlabInstance.Role), zap.String(INSTANCE_SIZE, destinationGitlabInstance.InstanceSize))
5866
zap.L().Warn("Will use local pull / push mirroring instead (takes a lot longer)", zap.String(ROLE, destinationGitlabInstance.Role), zap.String(INSTANCE_SIZE, destinationGitlabInstance.InstanceSize))
5967
}
@@ -76,6 +84,8 @@ func MirrorGitlabs(gitlabMirrorArgs *utils.ParserArgs) []error {
7684

7785
wg.Wait()
7886

87+
zap.L().Debug("Fully Computed Mirror Mapping", zap.Any("MirrorMapping", gitlabMirrorArgs.MirrorMapping))
88+
7989
// In case of dry run, simply print the groups and projects that would be created or updated
8090
if gitlabMirrorArgs.DryRun {
8191
destinationGitlabInstance.DryRun(sourceGitlabInstance, gitlabMirrorArgs.MirrorMapping)
@@ -104,7 +114,7 @@ func processFilters(filters *utils.MirrorMapping) (map[string]struct{}, map[stri
104114
var wg sync.WaitGroup
105115
wg.Add(2)
106116

107-
// Process group filters concurrently.
117+
// Process group filters concurrently
108118
go func() {
109119
defer wg.Done()
110120
for group, copyOptions := range filters.Groups {
@@ -115,7 +125,7 @@ func processFilters(filters *utils.MirrorMapping) (map[string]struct{}, map[stri
115125
}
116126
}()
117127

118-
// Process project filters concurrently.
128+
// Process project filters concurrently
119129
go func() {
120130
defer wg.Done()
121131
for project, copyOptions := range filters.Projects {
@@ -178,7 +188,7 @@ func (destinationGitlabInstance *GitlabInstance) DryRunReleases(sourceGitlabInst
178188
}
179189

180190
// IsPullMirrorAvailable checks the destination GitLab instance for version and license compatibility.
181-
func (g *GitlabInstance) IsPullMirrorAvailable(forcePremium bool) (bool, error) {
191+
func (g *GitlabInstance) IsPullMirrorAvailable(forcePremium bool, forceNonPremium bool) (bool, error) {
182192
zap.L().Info("Checking destination GitLab instance")
183193
thresholdOk, err := g.IsVersionGreaterThanThreshold()
184194
if err != nil {
@@ -187,10 +197,10 @@ func (g *GitlabInstance) IsPullMirrorAvailable(forcePremium bool) (bool, error)
187197

188198
isPremium, err := g.IsLicensePremium()
189199
if err != nil {
190-
if !forcePremium {
200+
if !forcePremium && !forceNonPremium {
191201
return false, fmt.Errorf("failed to check if destination GitLab instance is premium: %w", err)
192202
}
193203
}
194204

195-
return thresholdOk && (isPremium || forcePremium), nil
205+
return !forceNonPremium && (thresholdOk && (isPremium || forcePremium)), nil
196206
}

internal/mirroring/main_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,7 @@ func TestIsPullMirrorAvailable(t *testing.T) {
257257
})
258258
}
259259

260-
pullMirrorAvailable, err := gitlabInstance.IsPullMirrorAvailable(tt.forcePremium)
260+
pullMirrorAvailable, err := gitlabInstance.IsPullMirrorAvailable(tt.forcePremium, false)
261261
if (err != nil) != tt.expectedError {
262262
t.Fatalf("CheckDestinationInstance() error = %v, expectedError %v", err, tt.expectedError)
263263
}

internal/utils/types.go

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -33,18 +33,19 @@ const (
3333
// - version: whether to show the version
3434
// - retry: the number of retries for the GitLab API requests
3535
type ParserArgs struct {
36-
SourceGitlabURL string
37-
SourceGitlabToken string
38-
SourceGitlabIsBig bool
39-
DestinationGitlabURL string
40-
DestinationGitlabToken string
41-
DestinationGitlabIsBig bool
42-
DestinationGitlabForcePremium bool
43-
MirrorMapping *MirrorMapping
44-
Verbose bool
45-
NoPrompt bool
46-
DryRun bool
47-
Retry int
36+
SourceGitlabURL string
37+
SourceGitlabToken string
38+
SourceGitlabIsBig bool
39+
DestinationGitlabURL string
40+
DestinationGitlabToken string
41+
DestinationGitlabIsBig bool
42+
ForcePremium bool
43+
ForceNonPremium bool
44+
MirrorMapping *MirrorMapping
45+
Verbose bool
46+
NoPrompt bool
47+
DryRun bool
48+
Retry int
4849
}
4950

5051
// ProjectMirrorOptions defines how the project should be mirrored

pkg/helpers/git.go

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
"github.com/go-git/go-git/v5/plumbing"
1212
"github.com/go-git/go-git/v5/plumbing/transport"
1313
"github.com/go-git/go-git/v5/plumbing/transport/http"
14+
"go.uber.org/zap"
1415
)
1516

1617
const (
@@ -35,12 +36,14 @@ func MirrorRepo(sourceURL, destinationURL string, pullAuth, pushAuth transport.A
3536
pullOpts.Auth = pullAuth
3637
}
3738

39+
zap.L().Debug("Cloning source repository", zap.String("sourceURL", sourceURL), zap.String("destinationURL", destinationURL))
3840
srcRepo, err := git.PlainClone(tmpDir, true, pullOpts)
3941
if err != nil {
4042
return fmt.Errorf("failed to clone source repository locally: %w", err)
4143
}
4244

4345
// Add destination as a remote
46+
zap.L().Debug("Adding destination remote", zap.String("destinationURL", destinationURL))
4447
_, err = srcRepo.CreateRemote(&config.RemoteConfig{
4548
Name: "destination",
4649
URLs: []string{destinationURL},
@@ -50,6 +53,7 @@ func MirrorRepo(sourceURL, destinationURL string, pullAuth, pushAuth transport.A
5053
}
5154

5255
// Push *all* refs up to it
56+
zap.L().Debug("Pushing to destination repository", zap.String("destinationURL", destinationURL))
5357
pushOpts := &git.PushOptions{
5458
RemoteName: "destination",
5559
Force: true,
@@ -61,6 +65,7 @@ func MirrorRepo(sourceURL, destinationURL string, pullAuth, pushAuth transport.A
6165
if pushAuth != nil {
6266
pushOpts.Auth = pushAuth
6367
}
68+
6469
if err := srcRepo.Push(pushOpts); err != nil {
6570
return fmt.Errorf("failed to push to destination repository: %w", err)
6671
}
@@ -97,12 +102,17 @@ func fixBareRepoHEAD(destinationURL string, srcRepo *git.Repository) error {
97102
}
98103

99104
// write a new symbolic HEAD in the bare repo
105+
zap.L().Debug("Setting HEAD in destination repository", zap.String("destinationURL", destinationURL), zap.String("branch", srcHead.Name().String()))
100106
sym := plumbing.NewSymbolicReference(plumbing.HEAD, srcHead.Name())
101107
return destRepo.Storer.SetReference(sym)
102108
}
103109

104110
// BuildHTTPAuth creates an HTTP BasicAuth object using a username and token.
105-
func BuildHTTPAuth(username, token string) transport.AuthMethod {
111+
func BuildHTTPAuth(username string, token string) transport.AuthMethod {
112+
if token == "" && username == "" {
113+
return nil
114+
}
115+
106116
if strings.TrimSpace(username) == "" {
107117
username = DEFAULT_GIT_USER
108118
}

0 commit comments

Comments
 (0)