This repository was archived by the owner on Jan 30, 2026. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 6
Fix the failure for lint/unit/integration #3
Closed
Closed
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| approvers: | ||
| - "86254860" | ||
| - AlexVulaj | ||
| - aredenba-rh | ||
| - ciaranRoche | ||
| - crizzo71 | ||
| - jsell-rh | ||
| - mbrudnoy | ||
| - Mischulee | ||
| - rafabene | ||
| - rh-amarin | ||
| - tirthct | ||
| - vkareh | ||
| - xueli181114 | ||
| - yasun1 | ||
| - yingzhanredhat | ||
|
|
||
| reviewers: | ||
| - "86254860" | ||
| - AlexVulaj | ||
| - aredenba-rh | ||
| - ciaranRoche | ||
| - crizzo71 | ||
| - jsell-rh | ||
| - mbrudnoy | ||
| - Mischulee | ||
| - rafabene | ||
| - rh-amarin | ||
| - tirthct | ||
| - vkareh | ||
| - xueli181114 | ||
| - yasun1 | ||
| - yingzhanredhat |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,64 @@ | ||
| package config | ||
|
|
||
| import ( | ||
| "testing" | ||
|
|
||
| "github.com/spf13/pflag" | ||
| ) | ||
|
|
||
| func TestNewJobConfig(t *testing.T) { | ||
| config := NewJobConfig() | ||
|
|
||
| if config == nil { | ||
| t.Fatal("NewJobConfig() returned nil") | ||
| } | ||
|
|
||
| if !config.DryRun { | ||
| t.Errorf("Expected DryRun to be true by default, got false") | ||
| } | ||
|
|
||
| if config.WorkerCount != 1 { | ||
| t.Errorf("Expected WorkerCount to be 1 by default, got %d", config.WorkerCount) | ||
| } | ||
| } | ||
|
|
||
| func TestJobConfig_AddFlags(t *testing.T) { | ||
| config := NewJobConfig() | ||
| fs := pflag.NewFlagSet("test", pflag.ContinueOnError) | ||
|
|
||
| config.AddFlags(fs) | ||
|
|
||
| // Verify flags were added | ||
| if fs.Lookup("dry-run") == nil { | ||
| t.Error("Expected 'dry-run' flag to be registered") | ||
| } | ||
|
|
||
| if fs.Lookup("worker-count") == nil { | ||
| t.Error("Expected 'worker-count' flag to be registered") | ||
| } | ||
|
|
||
| // TODO: Add more comprehensive flag parsing tests | ||
| } | ||
|
|
||
| func TestJobConfig_FlagParsing(t *testing.T) { | ||
| config := NewJobConfig() | ||
| fs := pflag.NewFlagSet("test", pflag.ContinueOnError) | ||
|
|
||
| config.AddFlags(fs) | ||
|
|
||
| // Test parsing custom values | ||
| args := []string{"--dry-run=false", "--worker-count=5"} | ||
| if err := fs.Parse(args); err != nil { | ||
| t.Fatalf("Failed to parse flags: %v", err) | ||
| } | ||
|
|
||
| if config.DryRun { | ||
| t.Errorf("Expected DryRun to be false after parsing, got true") | ||
| } | ||
|
|
||
| if config.WorkerCount != 5 { | ||
| t.Errorf("Expected WorkerCount to be 5 after parsing, got %d", config.WorkerCount) | ||
| } | ||
|
|
||
| // TODO: Add edge case tests (negative worker count, etc.) | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,4 @@ | ||
| // Package job provides a framework for defining and executing concurrent jobs with task queues and worker pools. | ||
| package job | ||
|
|
||
| import ( | ||
|
|
@@ -43,39 +44,47 @@ type CommandBuilder struct { | |
| // panicHandler is an optional function that accepts interface and can deal with it how it wants. | ||
| // An example use can be to capture any errors and report it to sentry. Not setting panicHandler means any panics | ||
| // encountered will be silently recovered. | ||
| panicHandler func(ctx context.Context, any interface{}) | ||
| panicHandler func(ctx context.Context, panicValue interface{}) | ||
| metricsReporter MetricsReporter | ||
| } | ||
|
|
||
| // SetRegistry sets the job registry for the command builder. | ||
| func (b *CommandBuilder) SetRegistry(registry JobRegistry) *CommandBuilder { | ||
| b.registry = registry | ||
| return b | ||
| } | ||
|
|
||
| // SetContext sets the context for the command builder. | ||
| func (b *CommandBuilder) SetContext(ctx context.Context) *CommandBuilder { | ||
| b.ctx = ctx | ||
| return b | ||
| } | ||
|
|
||
| // SetBeforeJob sets the hook function to execute before job execution. | ||
| func (b *CommandBuilder) SetBeforeJob(fn func(ctx context.Context) error) *CommandBuilder { | ||
| b.beforeJob = fn | ||
| return b | ||
| } | ||
|
|
||
| // SetAfterJob sets the hook function to execute after job execution. | ||
| func (b *CommandBuilder) SetAfterJob(fn func(ctx context.Context)) *CommandBuilder { | ||
| b.afterJob = fn | ||
| return b | ||
| } | ||
|
|
||
| func (b *CommandBuilder) SetPanicHandler(fn func(ctx context.Context, any interface{})) *CommandBuilder { | ||
| // SetPanicHandler sets the panic handler function for the command builder. | ||
| func (b *CommandBuilder) SetPanicHandler(fn func(ctx context.Context, panicValue interface{})) *CommandBuilder { | ||
| b.panicHandler = fn | ||
| return b | ||
| } | ||
|
|
||
| // SetMetricsReporter sets the metrics reporter for the command builder. | ||
| func (b *CommandBuilder) SetMetricsReporter(reporter MetricsReporter) *CommandBuilder { | ||
| b.metricsReporter = reporter | ||
| return b | ||
| } | ||
|
|
||
| // Build creates and returns a Cobra command with all registered jobs as subcommands. | ||
| func (b *CommandBuilder) Build() *cobra.Command { | ||
| cmd := &cobra.Command{ | ||
| Use: "run-job", | ||
|
|
@@ -89,7 +98,7 @@ func (b *CommandBuilder) Build() *cobra.Command { | |
| Long: job.GetMetadata().Description, | ||
| // We don't need this info if job fails. | ||
| SilenceUsage: true, | ||
| RunE: func(cmd *cobra.Command, args []string) error { | ||
| RunE: func(_ *cobra.Command, _ []string) error { | ||
| err := validateJob(job) | ||
| if err != nil { | ||
| return err | ||
|
|
@@ -118,14 +127,19 @@ func validateJob(job Job) error { | |
| return nil | ||
| } | ||
|
|
||
| // JobRegistry maintains a collection of jobs that can be registered and executed. | ||
| // | ||
| //nolint:revive // JobRegistry is preferred over Registry for clarity in external usage | ||
| type JobRegistry struct { | ||
| jobs []Job | ||
| } | ||
|
|
||
| // NewJobRegistry creates a new job registry. | ||
| func NewJobRegistry() *JobRegistry { | ||
| return &JobRegistry{} | ||
| } | ||
|
|
||
| // AddJob adds a job to the registry. | ||
| func (r *JobRegistry) AddJob(job Job) { | ||
| if job == nil { | ||
| return | ||
|
|
@@ -171,7 +185,7 @@ func newTaskQueue() *taskQueue { | |
| type workerPool struct { | ||
| Queue *taskQueue | ||
| Workers int | ||
| PanicHandler func(ctx context.Context, any interface{}) | ||
| PanicHandler func(ctx context.Context, panicValue interface{}) | ||
| MetricsCollector *MetricsCollector | ||
| } | ||
|
|
||
|
|
@@ -192,11 +206,11 @@ func (wp *workerPool) Run(ctx context.Context) { | |
| return | ||
| } | ||
| func() { | ||
| taskId := ksuid.New().String() | ||
| taskID := ksuid.New().String() | ||
|
|
||
| taskCtx := AddTraceContext(ctx, "workerId", strconv.Itoa(workerId)) | ||
| taskCtx = AddTraceContext(taskCtx, "taskName", task.TaskName()) | ||
| taskCtx = AddTraceContext(taskCtx, "taskId", taskId) | ||
| taskCtx = AddTraceContext(taskCtx, "taskId", taskID) | ||
|
|
||
| defer func(taskCtx context.Context) { | ||
| if err := recover(); err != nil { | ||
|
|
@@ -208,7 +222,7 @@ func (wp *workerPool) Run(ctx context.Context) { | |
| } | ||
| }(taskCtx) | ||
|
|
||
| logger.NewOCMLogger(taskCtx).Contextual().Info("Processing task", "workerId", workerId, "taskId", taskId) | ||
| logger.NewOCMLogger(taskCtx).Contextual().Info("Processing task", "workerId", workerId, "taskId", taskID) | ||
| err := task.Process(taskCtx) | ||
| if err != nil { | ||
| wp.MetricsCollector.IncTaskFailed() | ||
|
|
@@ -235,7 +249,7 @@ var _ runner = &TestRunner{} | |
| type jobRunner struct { | ||
| BeforeJob func(ctx context.Context) error | ||
| AfterJob func(ctx context.Context) | ||
| PanicHandler func(ctx context.Context, any interface{}) | ||
| PanicHandler func(ctx context.Context, panicValue interface{}) | ||
| MetricsReporter MetricsReporter | ||
| } | ||
|
|
||
|
|
@@ -283,7 +297,7 @@ func (jr jobRunner) Run(ctx context.Context, job Job, workerCount int) error { | |
| } | ||
| for _, task := range tasks { | ||
| taskQueue.Add(task) | ||
| taskTotal += 1 | ||
| taskTotal++ | ||
| } | ||
| metricsCollector := NewMetricsCollector(job.GetMetadata().Use) | ||
| metricsCollector.SetTaskTotal(uint32(taskTotal)) | ||
|
|
@@ -320,6 +334,7 @@ func (jr jobRunner) Run(ctx context.Context, job Job, workerCount int) error { | |
| // TestRunner is a lightweight JobRunner implementation to enable for easy testing of job logic. | ||
| type TestRunner struct{} | ||
|
|
||
| // Run executes the job in test mode without lifecycle hooks. | ||
| func (tr TestRunner) Run(ctx context.Context, job Job, workerCount int) error { | ||
| taskTotal := 0 | ||
| taskQueue := newTaskQueue() | ||
|
|
@@ -331,14 +346,19 @@ func (tr TestRunner) Run(ctx context.Context, job Job, workerCount int) error { | |
| } | ||
| for _, task := range tasks { | ||
| taskQueue.Add(task) | ||
| taskTotal += 1 | ||
| taskTotal++ | ||
| } | ||
| metricsCollector := NewMetricsCollector(job.GetMetadata().Use) | ||
| metricsCollector.SetTaskTotal(uint32(taskTotal)) | ||
|
|
||
| pool := workerPool{Queue: taskQueue, Workers: workerCount, PanicHandler: nil, MetricsCollector: metricsCollector} | ||
| pool.Run(ctx) | ||
|
|
||
| if metricsCollector.taskTotal == 0 { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion | 🟠 Major Use getter methods for consistent encapsulation. Same encapsulation issue as in 🔎 Update TestRunner to use getter methods:- if metricsCollector.taskTotal == 0 {
+ if metricsCollector.GetTaskTotal() == 0 {
// No tasks to run
return nil
}
// For now return error when all tasks fail. This can be configurable for e.g. return error when 80% of tasks fail.
- if metricsCollector.taskFailed == metricsCollector.taskTotal {
+ if metricsCollector.GetTaskFailed() == metricsCollector.GetTaskTotal() {
err := errors.New("all tasks failed")
return err
}Also applies to: 362-362 🤖 Prompt for AI Agents |
||
| // No tasks to run | ||
| return nil | ||
| } | ||
| // For now return error when all tasks fail. This can be configurable for e.g. return error when 80% of tasks fail. | ||
| if metricsCollector.taskFailed == metricsCollector.taskTotal { | ||
| err := errors.New("all tasks failed") | ||
| return err | ||
|
|
||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Complete the taskId → taskID refactoring.
The context key still uses
"taskId"with lowercase 'd', but Go naming conventions prefer"taskID"with uppercase 'ID'. The AI summary indicates this refactoring was intended but appears incomplete at these locations.🔎 Apply this diff to use consistent naming:
Also applies to: 225-225
🤖 Prompt for AI Agents