Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add new output instead skip_output #637

Merged
merged 3 commits into from
Mar 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -163,8 +163,46 @@ If you want to specify a minimum version for lefthook binary (e.g. if you need s
min_version: 1.1.3
```

### `output`

You can manage verbosity using the `output` config. You can specify what to print in your output by setting these values, which you need to have

Possible values are `meta,summary,success,failure,execution,execution_out,execution_info,skips`.
By default, all output values are enabled

You can also disable all output with setting `output: false`. In this case only errors will be printed.

This config quiets all outputs except for errors.

`output` is enabled if there is no `skip_output` and `LEFTHOOK_QUIET`.

**Example**

```yml
# lefthook.yml

output:
- meta # Print lefthook version
- summary # Print summary block (successful and failed steps)
- empty_summary # Print summary heading when there are no steps to run
- success # Print successful steps
- failure # Print failed steps printing
- execution # Print any execution logs (but prints if the execution failed)
- execution_out # Print execution output (but still prints failed commands output)
- execution_info # Print `EXECUTE > ...` logging
- skips # Print "skip" (i.e. no files matched)
```

You can also *extend* this list with an environment variable `LEFTHOOK_OUTPUT`:

```bash
LEFTHOOK_OUTPUT="meta,success,summary" lefthook run pre-commit
```

### `skip_output`

> **Deprecated:** This feature is deprecated and might be removed in future versions. Please, use `[output]` instead for managing verbosity.

You can manage the verbosity using the `skip_output` config. You can set whether lefthook should print some parts of its output.

Possible values are `meta,summary,success,failure,execution,execution_out,execution_info,skips`.
Expand Down
1 change: 1 addition & 0 deletions internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ type Config struct {
SourceDirLocal string `mapstructure:"source_dir_local"`
Rc string `mapstructure:"rc,omitempty"`
SkipOutput interface{} `mapstructure:"skip_output,omitempty"`
Output interface{} `mapstructure:"output,omitempty"`
Extends []string `mapstructure:"extends,omitempty"`
NoTTY bool `mapstructure:"no_tty,omitempty"`
AssertLefthookInstalled bool `mapstructure:"assert_lefthook_installed,omitempty"`
Expand Down
35 changes: 23 additions & 12 deletions internal/lefthook/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@ import (
)

const (
envEnabled = "LEFTHOOK" // "0", "false"
envSkipOutput = "LEFTHOOK_QUIET" // "meta,success,failure,summary,skips,execution,execution_out,execution_info"
envEnabled = "LEFTHOOK" // "0", "false"
envSkipOutput = "LEFTHOOK_QUIET" // "meta,success,failure,summary,skips,execution,execution_out,execution_info"
envOutput = "LEFTHOOK_OUTPUT" // "meta,success,failure,summary,skips,execution,execution_out,execution_info"
)

type RunArgs struct {
Expand Down Expand Up @@ -75,12 +76,22 @@ func (l *Lefthook) Run(hookName string, args RunArgs, gitArgs []string) error {
log.SetLevel(log.WarnLevel)
}

tags := os.Getenv(envSkipOutput)
outputLogTags := os.Getenv(envOutput)
outputSkipTags := os.Getenv(envSkipOutput)

var logSettings log.SkipSettings
(&logSettings).ApplySettings(tags, cfg.SkipOutput)
var logSettings log.Settings

if !logSettings.SkipMeta() {
if outputSkipTags == "" && cfg.SkipOutput == nil {
logSettings = log.NewSettings()
logSettings.ApplySettings(outputLogTags, cfg.Output)
} else {
log.Warn("skip_output is deprecated, please use output option")

logSettings = log.NewSkipSettings() //nolint:staticcheck //SA1019: for temporary backward compatibility
logSettings.ApplySettings(outputSkipTags, cfg.SkipOutput)
}

if logSettings.LogMeta() {
log.Box(
log.Cyan("🥊 lefthook ")+log.Gray(fmt.Sprintf("v%s", version.Version(false))),
log.Gray("hook: ")+log.Bold(hookName),
Expand Down Expand Up @@ -176,7 +187,7 @@ Run 'lefthook install' manually.`,
return errors.New("Interrupted")
}

if !logSettings.SkipSummary() {
if logSettings.LogSummary() {
printSummary(time.Since(startTime), results, logSettings)
}

Expand All @@ -192,16 +203,16 @@ Run 'lefthook install' manually.`,
func printSummary(
duration time.Duration,
results []run.Result,
logSettings log.SkipSettings,
logSettings log.Settings,
) {
summaryPrint := log.Separate

if logSettings.SkipExecution() || (logSettings.SkipExecutionInfo() && logSettings.SkipExecutionOutput()) {
if !logSettings.LogExecution() || !(logSettings.LogExecutionInfo() && logSettings.LogExecutionOutput()) {
summaryPrint = func(s string) { log.Info(s) }
}

if len(results) == 0 {
if !logSettings.SkipEmptySummary() {
if logSettings.LogEmptySummary() {
summaryPrint(
fmt.Sprintf(
"%s %s %s",
Expand All @@ -218,7 +229,7 @@ func printSummary(
log.Cyan("summary: ") + log.Gray(fmt.Sprintf("(done in %.2f seconds)", duration.Seconds())),
)

if !logSettings.SkipSuccess() {
if logSettings.LogSuccess() {
for _, result := range results {
if result.Status != run.StatusOk {
continue
Expand All @@ -228,7 +239,7 @@ func printSummary(
}
}

if !logSettings.SkipFailure() {
if logSettings.LogFailure() {
for _, result := range results {
if result.Status != run.StatusErr {
continue
Expand Down
18 changes: 9 additions & 9 deletions internal/lefthook/run/runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ type Options struct {
HookName string
GitArgs []string
ResultChan chan Result
SkipSettings log.SkipSettings
SkipSettings log.Settings
DisableTTY bool
Force bool
Files []string
Expand Down Expand Up @@ -426,14 +426,14 @@ func (r *Runner) run(ctx context.Context, opts exec.Options, follow bool) bool {
log.SetName(opts.Name)
defer log.UnsetName(opts.Name)

if (follow || opts.Interactive) && !r.SkipSettings.SkipExecution() {
if (follow || opts.Interactive) && r.SkipSettings.LogExecution() {
r.logExecute(opts.Name, nil, nil)

var out io.Writer
if r.SkipSettings.SkipExecutionOutput() {
out = io.Discard
} else {
if r.SkipSettings.LogExecutionOutput() {
out = os.Stdout
} else {
out = io.Discard
}

err := r.executor.Execute(ctx, opts, out)
Expand Down Expand Up @@ -478,7 +478,7 @@ func intersect(a, b []string) bool {
}

func (r *Runner) logSkip(name, reason string) {
if r.SkipSettings.SkipSkips() {
if !r.SkipSettings.LogSkips() {
return
}

Expand All @@ -493,14 +493,14 @@ func (r *Runner) logSkip(name, reason string) {
}

func (r *Runner) logExecute(name string, err error, out io.Reader) {
if err == nil && r.SkipSettings.SkipExecution() {
if err == nil && !r.SkipSettings.LogExecution() {
return
}

var execLog string
var color lipgloss.TerminalColor
switch {
case r.SkipSettings.SkipExecutionInfo():
case !r.SkipSettings.LogExecutionInfo():
execLog = ""
case err != nil:
execLog = log.Red(fmt.Sprintf("%s ❯ ", name))
Expand All @@ -518,7 +518,7 @@ func (r *Runner) logExecute(name string, err error, out io.Reader) {
log.Info()
}

if err == nil && r.SkipSettings.SkipExecutionOutput() {
if err == nil && !r.SkipSettings.LogExecutionOutput() {
return
}

Expand Down
14 changes: 8 additions & 6 deletions internal/lefthook/run/runner_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
"github.com/evilmartians/lefthook/internal/config"
"github.com/evilmartians/lefthook/internal/git"
"github.com/evilmartians/lefthook/internal/lefthook/run/exec"
"github.com/evilmartians/lefthook/internal/log"
)

type TestExecutor struct{}
Expand Down Expand Up @@ -749,12 +750,13 @@ func TestRunAll(t *testing.T) {
executor := TestExecutor{}
runner := &Runner{
Options: Options{
Repo: repo,
Hook: tt.hook,
HookName: tt.hookName,
GitArgs: tt.args,
ResultChan: resultChan,
Force: tt.force,
Repo: repo,
Hook: tt.hook,
HookName: tt.hookName,
SkipSettings: log.NewSettings(),
GitArgs: tt.args,
ResultChan: resultChan,
Force: tt.force,
},
executor: executor,
}
Expand Down
140 changes: 140 additions & 0 deletions internal/log/settings.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
package log

import (
"strings"
)

const (
meta = 1 << iota
success
failure
summary
skips
execution
executionOutput
executionInfo
emptySummary
enableAll = ^0 // Set all bits as 1
)

type Settings interface {
ApplySettings(tags string, skipOutput interface{})
LogSuccess() bool
LogFailure() bool
LogSummary() bool
LogMeta() bool
LogExecution() bool
LogExecutionOutput() bool
LogExecutionInfo() bool
LogSkips() bool
LogEmptySummary() bool
}

type OutputSettings int16

func NewSettings() Settings {
var s OutputSettings
return &s
}

func (s *OutputSettings) ApplySettings(tags string, output interface{}) {
if tags == "" && (output == nil || output == "") {
s.enableAll(true)
return
}

if val, ok := output.(bool); ok {
s.enableAll(val)
return
}

if options, ok := output.([]interface{}); ok {
if len(options) == 0 {
s.enableAll(true)
return
}
for _, option := range options {
if optStr, ok := option.(string); ok {
s.applySetting(optStr)
}
}
}

if tags != "" {
for _, tag := range strings.Split(tags, ",") {
s.applySetting(tag)
}
}
}

func (s *OutputSettings) applySetting(setting string) {
switch setting {
case "meta":
*s |= meta
case "success":
*s |= success
case "failure":
*s |= failure
case "summary":
*s |= summary
case "skips":
*s |= skips
case "execution":
*s |= execution
case "execution_out":
*s |= executionOutput
case "execution_info":
*s |= executionInfo
case "empty_summary":
*s |= emptySummary
}
}

func (s *OutputSettings) enableAll(val bool) {
if val {
*s = enableAll // Enable all params
} else {
*s |= failure // Disable all params
}
}

// Checks the state of params.
func (s OutputSettings) isEnable(option int16) bool {
return int16(s)&option != 0
}

func (s OutputSettings) LogSuccess() bool {
return s.isEnable(success)
}

func (s OutputSettings) LogFailure() bool {
return s.isEnable(failure)
}

func (s OutputSettings) LogSummary() bool {
return s.isEnable(summary)
}

func (s OutputSettings) LogMeta() bool {
return s.isEnable(meta)
}

func (s OutputSettings) LogExecution() bool {
return s.isEnable(execution)
}

func (s OutputSettings) LogExecutionOutput() bool {
return s.isEnable(executionOutput)
}

func (s OutputSettings) LogExecutionInfo() bool {
return s.isEnable(executionInfo)
}

func (s OutputSettings) LogSkips() bool {
return s.isEnable(skips)
}

func (s OutputSettings) LogEmptySummary() bool {
return s.isEnable(emptySummary)
}
Loading
Loading