Skip to content

Commit 0054578

Browse files
committed
feat: add dry run option, version option and shorthand for flags
1 parent 57653db commit 0054578

File tree

3 files changed

+65
-21
lines changed

3 files changed

+65
-21
lines changed

cmd/main.go

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -13,25 +13,23 @@ import (
1313
"github.com/spf13/cobra"
1414
)
1515

16-
type ParserArgs struct {
17-
SourceGitlabURL string
18-
SourceGitlabToken string
19-
DestinationGitlabURL string
20-
DestinationGitlabToken string
21-
MirrorMapping utils.MirrorMapping
22-
Verbose bool
23-
NoPrompt bool
24-
}
16+
var (
17+
version = "dev"
18+
)
2519

2620
func main() {
27-
var args ParserArgs
21+
var args utils.ParserArgs
2822
var mirrorMappingPath string
2923

3024
var rootCmd = &cobra.Command{
3125
Use: "gitlab-sync",
3226
Short: "Copy and enable mirroring of gitlab projects and groups",
3327
Long: "Fully customizable gitlab repositories and groups mirroring between two (or one) gitlab instances.",
3428
Run: func(cmd *cobra.Command, cmdArgs []string) {
29+
if args.Version {
30+
fmt.Printf("gitlab-sync version: %s\n", version)
31+
return
32+
}
3533

3634
utils.SetVerbose(args.Verbose)
3735
utils.LogVerbose("Verbose mode enabled")
@@ -56,8 +54,9 @@ func main() {
5654
log.Fatalf("Error opening mirror mapping file: %s", err)
5755
}
5856
utils.LogVerbose("Mirror mapping file parsed successfully")
57+
args.MirrorMapping = mapping
5958

60-
err = mirroring.MirrorGitlabs(args.SourceGitlabURL, args.SourceGitlabToken, args.DestinationGitlabURL, args.DestinationGitlabToken, mapping)
59+
err = mirroring.MirrorGitlabs(&args)
6160
if err != nil {
6261
fmt.Println("Error during mirroring process:")
6362
fmt.Println(err)
@@ -66,13 +65,15 @@ func main() {
6665
},
6766
}
6867

68+
rootCmd.Flags().BoolVarP(&args.Version, "version", "V", false, "Show version")
6969
rootCmd.Flags().StringVar(&args.SourceGitlabURL, "source-url", os.Getenv("SOURCE_GITLAB_URL"), "Source GitLab URL")
7070
rootCmd.Flags().StringVar(&args.SourceGitlabToken, "source-token", os.Getenv("SOURCE_GITLAB_TOKEN"), "Source GitLab Token")
7171
rootCmd.Flags().StringVar(&args.DestinationGitlabURL, "destination-url", os.Getenv("DESTINATION_GITLAB_URL"), "Destination GitLab URL")
7272
rootCmd.Flags().StringVar(&args.DestinationGitlabToken, "destination-token", os.Getenv("DESTINATION_GITLAB_TOKEN"), "Destination GitLab Token")
73-
rootCmd.Flags().BoolVar(&args.Verbose, "verbose", false, "Enable verbose output")
74-
rootCmd.Flags().BoolVar(&args.NoPrompt, "no-prompt", false, "Disable prompting for missing values")
73+
rootCmd.Flags().BoolVarP(&args.Verbose, "verbose", "v", false, "Enable verbose output")
74+
rootCmd.Flags().BoolVarP(&args.NoPrompt, "no-prompt", "n", strings.TrimSpace(os.Getenv("NO_PROMPT")) != "", "Disable prompting for missing values")
7575
rootCmd.Flags().StringVar(&mirrorMappingPath, "mirror-mapping", os.Getenv("MIRROR_MAPPING"), "Path to the mirror mapping file")
76+
rootCmd.Flags().BoolVar(&args.DryRun, "dry-run", false, "Perform a dry run without making any changes")
7677

7778
if err := rootCmd.Execute(); err != nil {
7879
fmt.Println(err)

mirroring/main.go

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,70 @@
11
package mirroring
22

33
import (
4+
"fmt"
5+
"log"
46
"path/filepath"
57
"sync"
68

79
"gitlab-sync/utils"
810
)
911

10-
func MirrorGitlabs(sourceGitlabURL string, sourceGitlabToken string, destinationGitlabURL string, destinationGitlabToken string, mirrorMapping *utils.MirrorMapping) error {
11-
sourceGitlabInstance, err := newGitlabInstance(sourceGitlabURL, sourceGitlabToken)
12+
func MirrorGitlabs(gitlabMirrorArgs *utils.ParserArgs) error {
13+
sourceGitlabInstance, err := newGitlabInstance(gitlabMirrorArgs.SourceGitlabURL, gitlabMirrorArgs.SourceGitlabToken)
1214
if err != nil {
1315
return err
1416
}
1517

16-
destinationGitlabInstance, err := newGitlabInstance(destinationGitlabURL, destinationGitlabToken)
18+
destinationGitlabInstance, err := newGitlabInstance(gitlabMirrorArgs.DestinationGitlabURL, gitlabMirrorArgs.DestinationGitlabToken)
1719
if err != nil {
1820
return err
1921
}
2022

21-
sourceProjectFilters, sourceGroupFilters, destinationProjectFilters, destinationGroupFilters := processFilters(mirrorMapping)
23+
sourceProjectFilters, sourceGroupFilters, destinationProjectFilters, destinationGroupFilters := processFilters(gitlabMirrorArgs.MirrorMapping)
2224

2325
wg := sync.WaitGroup{}
2426
errCh := make(chan error, 4)
2527
wg.Add(2)
2628

2729
go func() {
2830
defer wg.Done()
29-
if err := fetchAll(sourceGitlabInstance, sourceProjectFilters, sourceGroupFilters, mirrorMapping, true); err != nil {
31+
if err := fetchAll(sourceGitlabInstance, sourceProjectFilters, sourceGroupFilters, gitlabMirrorArgs.MirrorMapping, true); err != nil {
3032
errCh <- err
3133
}
3234
}()
3335
go func() {
3436
defer wg.Done()
35-
if err := fetchAll(destinationGitlabInstance, destinationProjectFilters, destinationGroupFilters, mirrorMapping, false); err != nil {
37+
if err := fetchAll(destinationGitlabInstance, destinationProjectFilters, destinationGroupFilters, gitlabMirrorArgs.MirrorMapping, false); err != nil {
3638
errCh <- err
3739
}
3840
}()
3941

4042
wg.Wait()
4143

42-
err = createGroups(sourceGitlabInstance, destinationGitlabInstance, mirrorMapping)
44+
// In case of dry run, simply print the groups and projects that would be created or updated
45+
if gitlabMirrorArgs.DryRun {
46+
log.Println("Dry run mode enabled, will not create groups or projects")
47+
fmt.Println("Groups that will be created (or updated if they already exist):")
48+
for sourceGroupPath, copyOptions := range gitlabMirrorArgs.MirrorMapping.Groups {
49+
if sourceGitlabInstance.Groups[sourceGroupPath] != nil {
50+
fmt.Printf(" - %s (source gitlab) -> %s (destination gitlab)\n", sourceGroupPath, copyOptions.DestinationPath)
51+
}
52+
}
53+
fmt.Println("Projects that will be created (or updated if they already exist):")
54+
for sourceProjectPath, copyOptions := range gitlabMirrorArgs.MirrorMapping.Projects {
55+
if sourceGitlabInstance.Projects[sourceProjectPath] != nil {
56+
fmt.Printf(" - %s (source gitlab) -> %s (destination gitlab)\n", sourceProjectPath, copyOptions.DestinationPath)
57+
}
58+
}
59+
return nil
60+
}
61+
62+
// Create groups and projects in the destination GitLab instance
63+
err = createGroups(sourceGitlabInstance, destinationGitlabInstance, gitlabMirrorArgs.MirrorMapping)
4364
if err != nil {
4465
errCh <- err
4566
}
46-
err = createProjects(sourceGitlabInstance, destinationGitlabInstance, mirrorMapping)
67+
err = createProjects(sourceGitlabInstance, destinationGitlabInstance, gitlabMirrorArgs.MirrorMapping)
4768
if err != nil {
4869
errCh <- err
4970
}

utils/types.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,28 @@ import (
1515
"sync"
1616
)
1717

18+
// ParserArgs defines the command line arguments
19+
// - source_gitlab_url: the URL of the source GitLab instance
20+
// - source_gitlab_token: the token for the source GitLab instance
21+
// - destination_gitlab_url: the URL of the destination GitLab instance
22+
// - destination_gitlab_token: the token for the destination GitLab instance
23+
// - mirror_mapping: the path to the JSON file that contains the mapping
24+
// - verbose: whether to enable verbose logging
25+
// - no_prompt: whether to disable prompts
26+
// - dry_run: whether to perform a dry run
27+
// - version: whether to show the version
28+
type ParserArgs struct {
29+
SourceGitlabURL string
30+
SourceGitlabToken string
31+
DestinationGitlabURL string
32+
DestinationGitlabToken string
33+
MirrorMapping *MirrorMapping
34+
Verbose bool
35+
NoPrompt bool
36+
DryRun bool
37+
Version bool
38+
}
39+
1840
// ProjectMirrorOptions defines how the project should be mirrored
1941
// to the destination GitLab instance
2042
// - destination_url: the URL of the destination GitLab instance

0 commit comments

Comments
 (0)