Skip to content

Commit 9cefb2b

Browse files
authored
Merge pull request #2 from mona-actions/parallel-processing
2 parents f4f8c19 + 52bfc9a commit 9cefb2b

3 files changed

Lines changed: 613 additions & 57 deletions

File tree

go.mod

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ require (
1212
github.com/shurcooL/githubv4 v0.0.0-20240727222349-48295856cce7
1313
github.com/spf13/cobra v1.9.1
1414
github.com/spf13/viper v1.19.0
15+
github.com/stretchr/testify v1.9.0
1516
golang.org/x/oauth2 v0.27.0
1617
)
1718

@@ -20,6 +21,7 @@ require (
2021
atomicgo.dev/keyboard v0.2.9 // indirect
2122
atomicgo.dev/schedule v0.1.0 // indirect
2223
github.com/containerd/console v1.0.5 // indirect
24+
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
2325
github.com/fsnotify/fsnotify v1.7.0 // indirect
2426
github.com/golang-jwt/jwt/v5 v5.2.1 // indirect
2527
github.com/google/go-github/v64 v64.0.0 // indirect
@@ -32,6 +34,7 @@ require (
3234
github.com/mattn/go-runewidth v0.0.16 // indirect
3335
github.com/mitchellh/mapstructure v1.5.0 // indirect
3436
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
37+
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
3538
github.com/rivo/uniseg v0.4.7 // indirect
3639
github.com/sagikazarmark/locafero v0.4.0 // indirect
3740
github.com/sagikazarmark/slog-shim v0.1.0 // indirect

internal/validator/validator.go

Lines changed: 85 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ package validator
33
import (
44
"fmt"
55
"mona-actions/gh-migration-validator/internal/api"
6+
"sync"
7+
"time"
68

79
"github.com/pterm/pterm"
810
"github.com/spf13/viper"
@@ -48,169 +50,195 @@ func New(githubAPI *api.GitHubAPI) *MigrationValidator {
4850
// ValidateMigration performs the migration validation logic and returns results
4951
func (mv *MigrationValidator) ValidateMigration(sourceOwner, sourceRepo, targetOwner, targetRepo string) ([]ValidationResult, error) {
5052
fmt.Println("Starting migration validation...")
53+
fmt.Printf("Source: %s/%s | Target: %s/%s\n", sourceOwner, sourceRepo, targetOwner, targetRepo)
5154

52-
// Retrieve source repository data
53-
if err := mv.RetrieveSource(sourceOwner, sourceRepo); err != nil {
54-
return nil, fmt.Errorf("failed to retrieve source data: %w", err)
55-
}
55+
// Create a multi printer. This allows multiple spinners to print simultaneously.
56+
multi := pterm.DefaultMultiPrinter
57+
58+
// Create spinners for source and target with separate writers from the multi printer
59+
sourceSpinner, _ := pterm.DefaultSpinner.WithWriter(multi.NewWriter()).Start(fmt.Sprintf("Preparing to retrieve data from %s/%s...", sourceOwner, sourceRepo))
60+
targetSpinner, _ := pterm.DefaultSpinner.WithWriter(multi.NewWriter()).Start(fmt.Sprintf("Preparing to retrieve data from %s/%s...", targetOwner, targetRepo))
61+
62+
// Start the multi printer
63+
multi.Start()
64+
65+
// Use WaitGroup to wait for both goroutines to complete
66+
var wg sync.WaitGroup
67+
var sourceErr, targetErr error
68+
69+
// Channel to synchronize goroutines
70+
wg.Add(2)
71+
72+
// Retrieve source repository data in a goroutine
73+
go func() {
74+
defer wg.Done()
75+
sourceErr = mv.retrieveSource(sourceOwner, sourceRepo, sourceSpinner)
76+
}()
5677

57-
// Retrieve target repository data
58-
if err := mv.RetrieveTarget(targetOwner, targetRepo); err != nil {
59-
return nil, fmt.Errorf("failed to retrieve target data: %w", err)
78+
// Retrieve target repository data in a goroutine
79+
go func() {
80+
defer wg.Done()
81+
targetErr = mv.retrieveTarget(targetOwner, targetRepo, targetSpinner)
82+
}()
83+
84+
// Wait for both goroutines to complete
85+
wg.Wait()
86+
87+
// Stop the multi printer
88+
multi.Stop()
89+
90+
// Check for errors from both operations
91+
if sourceErr != nil {
92+
return nil, fmt.Errorf("failed to retrieve source data: %w", sourceErr)
93+
}
94+
if targetErr != nil {
95+
return nil, fmt.Errorf("failed to retrieve target data: %w", targetErr)
6096
}
6197

6298
// Compare and validate the data
6399
fmt.Println("\nValidating migration data...")
64-
results := mv.ValidateRepositoryData()
100+
results := mv.validateRepositoryData()
65101

66102
fmt.Println("Migration validation completed!")
67103
return results, nil
68104
}
69105

70-
// RetrieveSource retrieves all repository data from the source repository
71-
func (mv *MigrationValidator) RetrieveSource(owner, name string) error {
72-
fmt.Printf("Retrieving data from source repository: %s/%s\n", owner, name)
106+
// retrieveSource retrieves all repository data from the source repository
107+
func (mv *MigrationValidator) retrieveSource(owner, name string, spinner *pterm.SpinnerPrinter) error {
108+
startTime := time.Now()
73109

74110
mv.SourceData.Owner = owner
75111
mv.SourceData.Name = name
76112

77113
// Get issue count
78-
spinner, _ := pterm.DefaultSpinner.Start("Fetching issues...")
114+
spinner.UpdateText(fmt.Sprintf("Fetching issues from %s/%s...", owner, name))
79115
issues, err := mv.api.GetIssueCount(api.SourceClient, owner, name)
80116
if err != nil {
81-
spinner.Fail("Failed to fetch issues")
117+
spinner.Fail(fmt.Sprintf("Failed to fetch issues from %s/%s", owner, name))
82118
return fmt.Errorf("failed to get source issue count: %w", err)
83119
}
84120
mv.SourceData.Issues = issues
85-
spinner.Success("Issues fetched successfully")
86121

87122
// Get PR counts
88-
spinner, _ = pterm.DefaultSpinner.Start("Fetching pull requests...")
123+
spinner.UpdateText(fmt.Sprintf("Fetching pull requests from %s/%s...", owner, name))
89124
prCounts, err := mv.api.GetPRCounts(api.SourceClient, owner, name)
90125
if err != nil {
91-
spinner.Fail("Failed to fetch pull requests")
126+
spinner.Fail(fmt.Sprintf("Failed to fetch pull requests from %s/%s", owner, name))
92127
return fmt.Errorf("failed to get source PR counts: %w", err)
93128
}
94129
mv.SourceData.PRs = prCounts
95-
spinner.Success("Pull requests fetched successfully")
96130

97131
// Get tag count
98-
spinner, _ = pterm.DefaultSpinner.Start("Fetching tags...")
132+
spinner.UpdateText(fmt.Sprintf("Fetching tags from %s/%s...", owner, name))
99133
tags, err := mv.api.GetTagCount(api.SourceClient, owner, name)
100134
if err != nil {
101-
spinner.Fail("Failed to fetch tags")
135+
spinner.Fail(fmt.Sprintf("Failed to fetch tags from %s/%s", owner, name))
102136
return fmt.Errorf("failed to get source tag count: %w", err)
103137
}
104138
mv.SourceData.Tags = tags
105-
spinner.Success("Tags fetched successfully")
106139

107140
// Get release count
108-
spinner, _ = pterm.DefaultSpinner.Start("Fetching releases...")
141+
spinner.UpdateText(fmt.Sprintf("Fetching releases from %s/%s...", owner, name))
109142
releases, err := mv.api.GetReleaseCount(api.SourceClient, owner, name)
110143
if err != nil {
111-
spinner.Fail("Failed to fetch releases")
144+
spinner.Fail(fmt.Sprintf("Failed to fetch releases from %s/%s", owner, name))
112145
return fmt.Errorf("failed to get source release count: %w", err)
113146
}
114147
mv.SourceData.Releases = releases
115-
spinner.Success("Releases fetched successfully")
116148

117149
// Get commit count
118-
spinner, _ = pterm.DefaultSpinner.Start("Fetching commit count...")
150+
spinner.UpdateText(fmt.Sprintf("Fetching commit count from %s/%s...", owner, name))
119151
commitCount, err := mv.api.GetCommitCount(api.SourceClient, owner, name)
120152
if err != nil {
121-
spinner.Fail("Failed to fetch commit count")
153+
spinner.Fail(fmt.Sprintf("Failed to fetch commit count from %s/%s", owner, name))
122154
return fmt.Errorf("failed to get source commit count: %w", err)
123155
}
124156
mv.SourceData.CommitCount = commitCount
125-
spinner.Success("Commit count fetched successfully")
126157

127158
// Get latest commit hash
128-
spinner, _ = pterm.DefaultSpinner.Start("Fetching latest commit hash...")
159+
spinner.UpdateText(fmt.Sprintf("Fetching latest commit hash from %s/%s...", owner, name))
129160
latestCommitSHA, err := mv.api.GetLatestCommitHash(api.SourceClient, owner, name)
130161
if err != nil {
131-
spinner.Fail("Failed to fetch latest commit hash")
162+
spinner.Fail(fmt.Sprintf("Failed to fetch latest commit hash from %s/%s", owner, name))
132163
return fmt.Errorf("failed to get source latest commit hash: %w", err)
133164
}
134165
mv.SourceData.LatestCommitSHA = latestCommitSHA
135-
spinner.Success("Latest commit hash fetched successfully")
136166

137-
fmt.Printf("Source data retrieved successfully!\n")
167+
duration := time.Since(startTime)
168+
spinner.Success(fmt.Sprintf("%s/%s retrieved successfully (%v)", owner, name, duration))
169+
138170
return nil
139171
}
140172

141-
// RetrieveTarget retrieves all repository data from the target repository
142-
func (mv *MigrationValidator) RetrieveTarget(owner, name string) error {
143-
fmt.Printf("Retrieving data from target repository: %s/%s\n", owner, name)
173+
// retrieveTarget retrieves all repository data from the target repository
174+
func (mv *MigrationValidator) retrieveTarget(owner, name string, spinner *pterm.SpinnerPrinter) error {
175+
startTime := time.Now()
144176

145177
mv.TargetData.Owner = owner
146178
mv.TargetData.Name = name
147179

148180
// Get issue count
149-
spinner, _ := pterm.DefaultSpinner.Start("Fetching issues...")
181+
spinner.UpdateText(fmt.Sprintf("Fetching issues from %s/%s...", owner, name))
150182
issues, err := mv.api.GetIssueCount(api.TargetClient, owner, name)
151183
if err != nil {
152-
spinner.Fail("Failed to fetch issues")
184+
spinner.Fail(fmt.Sprintf("Failed to fetch issues from %s/%s", owner, name))
153185
return fmt.Errorf("failed to get target issue count: %w", err)
154186
}
155187
mv.TargetData.Issues = issues
156-
spinner.Success("Issues fetched successfully")
157188

158189
// Get PR counts
159-
spinner, _ = pterm.DefaultSpinner.Start("Fetching pull requests...")
190+
spinner.UpdateText(fmt.Sprintf("Fetching pull requests from %s/%s...", owner, name))
160191
prCounts, err := mv.api.GetPRCounts(api.TargetClient, owner, name)
161192
if err != nil {
162-
spinner.Fail("Failed to fetch pull requests")
193+
spinner.Fail(fmt.Sprintf("Failed to fetch pull requests from %s/%s", owner, name))
163194
return fmt.Errorf("failed to get target PR counts: %w", err)
164195
}
165196
mv.TargetData.PRs = prCounts
166-
spinner.Success("Pull requests fetched successfully")
167197

168198
// Get tag count
169-
spinner, _ = pterm.DefaultSpinner.Start("Fetching tags...")
199+
spinner.UpdateText(fmt.Sprintf("Fetching tags from %s/%s...", owner, name))
170200
tags, err := mv.api.GetTagCount(api.TargetClient, owner, name)
171201
if err != nil {
172-
spinner.Fail("Failed to fetch tags")
202+
spinner.Fail(fmt.Sprintf("Failed to fetch tags from %s/%s", owner, name))
173203
return fmt.Errorf("failed to get target tag count: %w", err)
174204
}
175205
mv.TargetData.Tags = tags
176-
spinner.Success("Tags fetched successfully")
177206

178207
// Get release count
179-
spinner, _ = pterm.DefaultSpinner.Start("Fetching releases...")
208+
spinner.UpdateText(fmt.Sprintf("Fetching releases from %s/%s...", owner, name))
180209
releases, err := mv.api.GetReleaseCount(api.TargetClient, owner, name)
181210
if err != nil {
182-
spinner.Fail("Failed to fetch releases")
211+
spinner.Fail(fmt.Sprintf("Failed to fetch releases from %s/%s", owner, name))
183212
return fmt.Errorf("failed to get target release count: %w", err)
184213
}
185214
mv.TargetData.Releases = releases
186-
spinner.Success("Releases fetched successfully")
187215

188216
// Get commit count
189-
spinner, _ = pterm.DefaultSpinner.Start("Fetching commit count...")
217+
spinner.UpdateText(fmt.Sprintf("Fetching commit count from %s/%s...", owner, name))
190218
commitCount, err := mv.api.GetCommitCount(api.TargetClient, owner, name)
191219
if err != nil {
192-
spinner.Fail("Failed to fetch commit count")
220+
spinner.Fail(fmt.Sprintf("Failed to fetch commit count from %s/%s", owner, name))
193221
return fmt.Errorf("failed to get target commit count: %w", err)
194222
}
195223
mv.TargetData.CommitCount = commitCount
196-
spinner.Success("Commit count fetched successfully")
197224

198225
// Get latest commit hash
199-
spinner, _ = pterm.DefaultSpinner.Start("Fetching latest commit hash...")
226+
spinner.UpdateText(fmt.Sprintf("Fetching latest commit hash from %s/%s...", owner, name))
200227
latestCommitSHA, err := mv.api.GetLatestCommitHash(api.TargetClient, owner, name)
201228
if err != nil {
202-
spinner.Fail("Failed to fetch latest commit hash")
229+
spinner.Fail(fmt.Sprintf("Failed to fetch latest commit hash from %s/%s", owner, name))
203230
return fmt.Errorf("failed to get target latest commit hash: %w", err)
204231
}
205232
mv.TargetData.LatestCommitSHA = latestCommitSHA
206-
spinner.Success("Latest commit hash fetched successfully")
207233

208-
fmt.Printf("Target data retrieved successfully!\n")
234+
duration := time.Since(startTime)
235+
spinner.Success(fmt.Sprintf("%s/%s retrieved successfully (%v)", owner, name, duration))
236+
209237
return nil
210238
}
211239

212-
// ValidateRepositoryData compares source and target repository data and returns validation results
213-
func (mv *MigrationValidator) ValidateRepositoryData() []ValidationResult {
240+
// validateRepositoryData compares source and target repository data and returns validation results
241+
func (mv *MigrationValidator) validateRepositoryData() []ValidationResult {
214242
fmt.Println("Comparing repository data...")
215243

216244
var results []ValidationResult
@@ -437,12 +465,12 @@ func (mv *MigrationValidator) PrintValidationResults(results []ValidationResult)
437465

438466
fmt.Println() // Add spacing
439467
if viper.GetBool("MARKDOWN_TABLE") {
440-
mv.PrintMarkdownTable(results)
468+
mv.printMarkdownTable(results)
441469
}
442470
}
443471

444-
// PrintMarkdownTable prints a markdown-formatted table for easy copy/paste
445-
func (mv *MigrationValidator) PrintMarkdownTable(results []ValidationResult) {
472+
// printMarkdownTable prints a markdown-formatted table for easy copy/paste
473+
func (mv *MigrationValidator) printMarkdownTable(results []ValidationResult) {
446474
pterm.DefaultSection.Println("📋 Markdown Table (Copy-Paste Ready)")
447475

448476
fmt.Println("```markdown")

0 commit comments

Comments
 (0)