From 94e3757eb2c7f8923679977fb5cac2d8a63a1ea6 Mon Sep 17 00:00:00 2001 From: Valentin Kiselev Date: Sat, 21 Dec 2024 12:38:10 +0300 Subject: [PATCH 1/3] feat: add ability to specify job names to run command --- cmd/run.go | 5 +++++ internal/lefthook/run.go | 2 ++ internal/lefthook/runner/run_jobs.go | 15 +++++++++++++++ internal/lefthook/runner/runner.go | 1 + 4 files changed, 23 insertions(+) diff --git a/cmd/run.go b/cmd/run.go index 22a9b614..2f4aad04 100644 --- a/cmd/run.go +++ b/cmd/run.go @@ -94,6 +94,11 @@ func (run) New(opts *lefthook.Options) *cobra.Command { "run only specified commands", ) + runCmd.Flags().StringSliceVar( + &runArgs.RunOnlyJobs, "jobs", nil, + "run only specified jobs", + ) + err := runCmd.Flags().MarkDeprecated("files", "use --file flag instead") if err != nil { log.Warn("Unexpected error:", err) diff --git a/internal/lefthook/run.go b/internal/lefthook/run.go index 2d41798c..3331de63 100644 --- a/internal/lefthook/run.go +++ b/internal/lefthook/run.go @@ -33,6 +33,7 @@ type RunArgs struct { SkipLFS bool Files []string RunOnlyCommands []string + RunOnlyJobs []string } func Run(opts *Options, args RunArgs, hookName string, gitArgs []string) error { @@ -170,6 +171,7 @@ func (l *Lefthook) Run(hookName string, args RunArgs, gitArgs []string) error { Files: args.Files, Force: args.Force, RunOnlyCommands: args.RunOnlyCommands, + RunOnlyJobs: args.RunOnlyJobs, SourceDirs: sourceDirs, }, ) diff --git a/internal/lefthook/runner/run_jobs.go b/internal/lefthook/runner/run_jobs.go index 827eeccb..97ee68d4 100644 --- a/internal/lefthook/runner/run_jobs.go +++ b/internal/lefthook/runner/run_jobs.go @@ -4,6 +4,7 @@ import ( "context" "errors" "path/filepath" + "slices" "strconv" "sync" "sync/atomic" @@ -81,6 +82,10 @@ func (r *Runner) runJob(ctx context.Context, domain *domain, id string, job *con } if len(job.Run) != 0 || len(job.Script) != 0 { + if len(r.RunOnlyJobs) != 0 && !slices.Contains(r.RunOnlyJobs, job.Name) { + return skipped(job.PrintableName(id)) + } + return r.runSingleJob(ctx, domain, id, job) } @@ -89,6 +94,16 @@ func (r *Runner) runJob(ctx context.Context, domain *domain, id string, job *con inheritedDomain.glob = first(job.Glob, domain.glob) inheritedDomain.root = first(job.Root, domain.root) groupName := first(job.Name, "["+id+"]") + + if len(r.RunOnlyJobs) != 0 && slices.Contains(r.RunOnlyJobs, job.Name) { + children := make([]string, len(job.Group.Jobs), 0) + for _, child := range job.Group.Jobs { + children = append(children, child.Name) + } + + r.RunOnlyJobs = append(r.RunOnlyJobs, children...) + } + return r.runGroup(ctx, groupName, &inheritedDomain, job.Group) } diff --git a/internal/lefthook/runner/runner.go b/internal/lefthook/runner/runner.go index db383a3d..d545fade 100644 --- a/internal/lefthook/runner/runner.go +++ b/internal/lefthook/runner/runner.go @@ -41,6 +41,7 @@ type Options struct { Force bool Files []string RunOnlyCommands []string + RunOnlyJobs []string SourceDirs []string } From 1a9632acd93441c9a4f05ec83cf708fd92bd683f Mon Sep 17 00:00:00 2001 From: Valentin Kiselev Date: Thu, 26 Dec 2024 12:28:09 +0300 Subject: [PATCH 2/3] fix: allow running whole groups --- internal/lefthook/runner/run_jobs.go | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/internal/lefthook/runner/run_jobs.go b/internal/lefthook/runner/run_jobs.go index 97ee68d4..30ea77cc 100644 --- a/internal/lefthook/runner/run_jobs.go +++ b/internal/lefthook/runner/run_jobs.go @@ -25,8 +25,9 @@ var ( type domain struct { failed *atomic.Bool - glob string - root string + glob string + root string + onlyJobs []string } func (r *Runner) runJobs(ctx context.Context) []Result { @@ -36,7 +37,7 @@ func (r *Runner) runJobs(ctx context.Context) []Result { resultsChan := make(chan Result, len(r.Hook.Jobs)) var failed atomic.Bool - domain := &domain{failed: &failed} + domain := &domain{failed: &failed, onlyJobs: r.RunOnlyJobs} for i, job := range r.Hook.Jobs { id := strconv.Itoa(i) @@ -82,7 +83,7 @@ func (r *Runner) runJob(ctx context.Context, domain *domain, id string, job *con } if len(job.Run) != 0 || len(job.Script) != 0 { - if len(r.RunOnlyJobs) != 0 && !slices.Contains(r.RunOnlyJobs, job.Name) { + if len(domain.onlyJobs) != 0 && !slices.Contains(domain.onlyJobs, job.Name) { return skipped(job.PrintableName(id)) } @@ -95,13 +96,8 @@ func (r *Runner) runJob(ctx context.Context, domain *domain, id string, job *con inheritedDomain.root = first(job.Root, domain.root) groupName := first(job.Name, "["+id+"]") - if len(r.RunOnlyJobs) != 0 && slices.Contains(r.RunOnlyJobs, job.Name) { - children := make([]string, len(job.Group.Jobs), 0) - for _, child := range job.Group.Jobs { - children = append(children, child.Name) - } - - r.RunOnlyJobs = append(r.RunOnlyJobs, children...) + if len(domain.onlyJobs) != 0 && slices.Contains(domain.onlyJobs, job.Name) { + inheritedDomain.onlyJobs = []string{} } return r.runGroup(ctx, groupName, &inheritedDomain, job.Group) From d38e28a8a8ded477bbd6e8410fe066ea9dfd231d Mon Sep 17 00:00:00 2001 From: Valentin Kiselev Date: Thu, 26 Dec 2024 12:38:59 +0300 Subject: [PATCH 3/3] chore: add integrity test for --jobs option --- testdata/cli_run_only.txt | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 testdata/cli_run_only.txt diff --git a/testdata/cli_run_only.txt b/testdata/cli_run_only.txt new file mode 100644 index 00000000..4226df53 --- /dev/null +++ b/testdata/cli_run_only.txt @@ -0,0 +1,34 @@ +exec git init +exec git config user.email "you@example.com" +exec git config user.name "Your Name" +exec git add -A +exec lefthook install +exec lefthook run hook --jobs a --jobs c --jobs db --commands lint +stdout '\s*a\s*ca\s*cb\s*db\s*lint\s*' + +-- lefthook.yml -- +output: + - execution_out +hook: + jobs: + - name: a + run: echo a + - name: b + run: echo b + - name: c + group: + jobs: + - run: echo ca + - run: echo cb + - name: d + group: + jobs: + - name: da + run: echo da + - name: db + run: echo db + commands: + lint: + run: echo lint + test: + run: echo test