Skip to content

Commit f2360e0

Browse files
committed
refactor: major changes to logging and other of tweaks
* Reduced the use of internal/. * Replaced `go.uber.org/zap` with `log/slog`. * Fixed lint command flags.
1 parent d270d2f commit f2360e0

33 files changed

+627
-403
lines changed

cmd/lint/lint.go

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
package lint
2+
3+
import (
4+
"fmt"
5+
"os"
6+
7+
"github.com/go-git/go-git/v5"
8+
"github.com/go-git/go-git/v5/plumbing"
9+
10+
"github.com/spf13/cobra"
11+
12+
"github.com/somebadcode/commit-tool/cmd"
13+
"github.com/somebadcode/commit-tool/commitlinter"
14+
"github.com/somebadcode/commit-tool/commitlinter/defaultlinter"
15+
"github.com/somebadcode/commit-tool/revisionflag"
16+
"github.com/somebadcode/commit-tool/slogctx"
17+
)
18+
19+
const (
20+
FlagRev = "rev"
21+
FlagOtherRev = "other"
22+
FlagAllowInitialCommit = "allow-initial-commit"
23+
)
24+
25+
var linter commitlinter.CommitLinter
26+
var command = &cobra.Command{
27+
Use: "lint",
28+
Aliases: []string{"linter"},
29+
Args: cobra.MaximumNArgs(1),
30+
PreRunE: func(cmd *cobra.Command, args []string) error {
31+
var repoPath string
32+
if len(args) == 1 {
33+
repoPath = args[0]
34+
} else {
35+
wd, wdErr := os.Getwd()
36+
if wdErr != nil {
37+
return fmt.Errorf("repository path required")
38+
}
39+
40+
repoPath = wd
41+
}
42+
43+
var err error
44+
45+
linter.Repo, err = git.PlainOpen(repoPath)
46+
if err != nil {
47+
return err
48+
}
49+
50+
linter.Rev = cmd.Flags().Lookup(FlagRev).Value.(*revisionflag.Revision).Rev
51+
linter.OtherRev = cmd.Flags().Lookup(FlagOtherRev).Value.(*revisionflag.Revision).Rev
52+
linter.ReportFunc = commitlinter.SlogReporter(slogctx.L(cmd.Context()))
53+
54+
return nil
55+
},
56+
RunE: func(cmd *cobra.Command, args []string) error {
57+
return linter.Run(cmd.Context())
58+
},
59+
}
60+
61+
func init() {
62+
defaultLinter := defaultlinter.New()
63+
linter.Linter = defaultLinter
64+
65+
flagSet := command.Flags()
66+
flagSet.Var(revisionflag.New(plumbing.Revision(plumbing.HEAD)), FlagRev, "revision to start at")
67+
flagSet.Var(revisionflag.New(""), FlagOtherRev, "revision for which the merge base of this and rev should stop the linting at")
68+
flagSet.BoolVar(&defaultLinter.AllowInitialCommit, FlagAllowInitialCommit, false, "allow initial commit")
69+
70+
cmd.AddCommand(command)
71+
}

cmd/replaceattr.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package cmd
2+
3+
import (
4+
"log/slog"
5+
6+
"github.com/go-git/go-git/v5/plumbing/object"
7+
8+
"github.com/somebadcode/commit-tool/commitslogvalue"
9+
)
10+
11+
func replaceAttr(_ []string, attr slog.Attr) slog.Attr {
12+
switch attr.Value.Kind() {
13+
case slog.KindAny:
14+
switch attr.Value.Any().(type) {
15+
case *object.Commit:
16+
attr.Value = commitslogvalue.Value(attr.Value.Any().(*object.Commit))
17+
}
18+
}
19+
20+
return attr
21+
}

cmd/replaceattr_test.go

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
package cmd
2+
3+
import (
4+
"errors"
5+
"log/slog"
6+
"reflect"
7+
"testing"
8+
"time"
9+
10+
"github.com/go-git/go-git/v5/plumbing"
11+
"github.com/go-git/go-git/v5/plumbing/object"
12+
)
13+
14+
func Test_replaceAttr(t *testing.T) {
15+
type args struct {
16+
in0 []string
17+
attr slog.Attr
18+
}
19+
tests := []struct {
20+
name string
21+
args args
22+
want slog.Attr
23+
}{
24+
{
25+
name: "commit",
26+
args: args{
27+
attr: slog.Any("commit", &object.Commit{
28+
Hash: plumbing.Hash{},
29+
Author: object.Signature{
30+
Name: "Gopher",
31+
Email: "gopher@example.com",
32+
When: time.Date(2024, 02, 04, 13, 53, 00, 0, time.UTC),
33+
},
34+
Committer: object.Signature{
35+
Name: "Gopher",
36+
Email: "gopher@example.com",
37+
When: time.Date(2024, 02, 04, 13, 53, 00, 0, time.UTC),
38+
},
39+
}),
40+
},
41+
want: slog.Any("commit", slog.GroupValue(
42+
slog.String("hash", "0000000000000000000000000000000000000000"),
43+
slog.Group("author",
44+
slog.String("name", "Gopher"),
45+
slog.String("email", "gopher@example.com"),
46+
slog.Time("when", time.Date(2024, 02, 04, 13, 53, 00, 0, time.UTC)),
47+
),
48+
)),
49+
},
50+
{
51+
name: "stringer",
52+
args: args{
53+
attr: slog.Any("err",
54+
errors.New("something")),
55+
},
56+
want: slog.Any("err", errors.New("something")),
57+
},
58+
}
59+
for _, tt := range tests {
60+
t.Run(tt.name, func(t *testing.T) {
61+
if got := replaceAttr(tt.args.in0, tt.args.attr); !reflect.DeepEqual(got, tt.want) {
62+
t.Errorf("replaceAttr() = %v, want %v", got, tt.want)
63+
}
64+
})
65+
}
66+
}

cmd/root.go

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
package cmd
2+
3+
import (
4+
"context"
5+
"log/slog"
6+
"runtime/debug"
7+
8+
"github.com/spf13/cobra"
9+
10+
"github.com/somebadcode/commit-tool/slogctx"
11+
)
12+
13+
const (
14+
FlagLogLevel = "log-level"
15+
FlagLogSource = "log-source"
16+
)
17+
18+
var command = &cobra.Command{
19+
Use: "commit-tool",
20+
ValidArgsFunction: cobra.NoFileCompletions,
21+
Args: cobra.NoArgs,
22+
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
23+
levelFlagValue := cmd.Flags().Lookup(FlagLogLevel).Value.String()
24+
25+
level := &slog.LevelVar{}
26+
levelError := level.UnmarshalText([]byte(levelFlagValue))
27+
28+
addSource, _ := cmd.Flags().GetBool(FlagLogSource)
29+
30+
opts := &slog.HandlerOptions{
31+
AddSource: addSource,
32+
Level: level,
33+
ReplaceAttr: replaceAttr,
34+
}
35+
36+
handler := slog.NewJSONHandler(cmd.ErrOrStderr(), opts)
37+
logger := slog.New(handler)
38+
if levelError != nil {
39+
logger.Error("bad error level",
40+
slog.String("value", levelFlagValue),
41+
)
42+
}
43+
44+
ctx := slogctx.Context(cmd.Context(), logger)
45+
46+
cmd.SetContext(ctx)
47+
48+
return nil
49+
},
50+
PersistentPostRun: func(cmd *cobra.Command, args []string) {
51+
if syncer, ok := cmd.ErrOrStderr().(interface{ Sync() error }); ok {
52+
_ = syncer.Sync()
53+
}
54+
},
55+
TraverseChildren: true,
56+
Hidden: true,
57+
DisableSuggestions: true,
58+
}
59+
60+
func init() {
61+
buildInfo, hasBuildInfo := debug.ReadBuildInfo()
62+
if hasBuildInfo {
63+
command.Version = buildInfo.Main.Version
64+
}
65+
66+
flagSet := command.PersistentFlags()
67+
flagSet.String(FlagLogLevel, slog.LevelInfo.String(), "log level")
68+
flagSet.Bool(FlagLogSource, false, "show source in log messages")
69+
}
70+
71+
func ExecuteContext(ctx context.Context) error {
72+
return command.ExecuteContext(ctx)
73+
}
74+
75+
func AddCommand(cmds ...*cobra.Command) {
76+
command.AddCommand(cmds...)
77+
}

internal/commitlinter/defaultlinter/defaultlinter.go renamed to commitlinter/defaultlinter/defaultlinter.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ import (
66

77
"github.com/go-git/go-git/v5/plumbing/object"
88

9-
"github.com/somebadcode/commit-tool/internal/commitlinter"
10-
"github.com/somebadcode/commit-tool/internal/commitmsg"
9+
"github.com/somebadcode/commit-tool/commitlinter"
10+
"github.com/somebadcode/commit-tool/commitmsg"
1111
)
1212

1313
type Linter struct {

internal/commitlinter/defaultlinter/defaultlinter_test.go renamed to commitlinter/defaultlinter/defaultlinter_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ import (
88
"github.com/go-git/go-git/v5"
99
"github.com/go-git/go-git/v5/plumbing"
1010
"github.com/go-git/go-git/v5/plumbing/object"
11-
"github.com/somebadcode/commit-tool/internal/commitlinter"
12-
"github.com/somebadcode/commit-tool/internal/commitlinter/defaultlinter"
11+
"github.com/somebadcode/commit-tool/commitlinter"
12+
"github.com/somebadcode/commit-tool/commitlinter/defaultlinter"
1313
"github.com/somebadcode/commit-tool/internal/repobuilder"
1414
)
1515

internal/commitlinter/defaultlinter/rules.go renamed to commitlinter/defaultlinter/rules.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import (
66
"unicode"
77
"unicode/utf8"
88

9-
"github.com/somebadcode/commit-tool/internal/commitmsg"
9+
"github.com/somebadcode/commit-tool/commitmsg"
1010
)
1111

1212
type RuleFunc func(message commitmsg.CommitMessage) error

internal/commitlinter/linter.go renamed to commitlinter/linter.go

Lines changed: 27 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,14 @@ import (
44
"context"
55
"errors"
66
"fmt"
7+
"log/slog"
78

89
"github.com/go-git/go-git/v5"
910
"github.com/go-git/go-git/v5/plumbing"
1011
"github.com/go-git/go-git/v5/plumbing/object"
1112
"github.com/go-git/go-git/v5/plumbing/storer"
12-
"go.uber.org/zap"
1313

14-
"github.com/somebadcode/commit-tool/internal/zapctx"
14+
"github.com/somebadcode/commit-tool/slogctx"
1515
)
1616

1717
type ReportFunc func(err error)
@@ -46,23 +46,24 @@ var (
4646
// if any commit doesn't adhere to the linter's expectations.
4747
func NoReporting(_ error) {}
4848

49-
// ZapReporter will cause the linter to report lint errors using the specified Zap logger.
50-
func ZapReporter(logger *zap.Logger) ReportFunc {
49+
// SlogReporter will log linter errors using [log/slog].
50+
func SlogReporter(logger *slog.Logger) ReportFunc {
5151
return func(err error) {
5252
var lintError LintError
5353
if errors.As(err, &lintError) {
54-
logger.Error("bad commit message",
55-
zap.Stringer("hash", lintError.Hash),
56-
zap.Int("pos", lintError.Pos),
57-
zap.Error(errors.Unwrap(err)),
54+
logger.LogAttrs(context.Background(), slog.LevelError, "bad commit message",
55+
slog.String("hash", lintError.Hash.String()),
56+
slog.Int("pos", lintError.Pos),
57+
slog.String("err", errors.Unwrap(err).Error()),
5858
)
5959

6060
return
6161
}
6262

63-
logger.Error("bad commit message",
64-
zap.Error(err),
63+
logger.LogAttrs(context.Background(), slog.LevelError, "bad commit message",
64+
slog.String("err", errors.Unwrap(err).Error()),
6565
)
66+
6667
}
6768
}
6869

@@ -181,12 +182,12 @@ func (l *CommitLinter) Run(ctx context.Context) error {
181182
return fmt.Errorf("unable to resolve revision: %w", err)
182183
}
183184

184-
logger := zapctx.L(ctx)
185+
logger := slogctx.L(ctx)
185186

186-
if ev := logger.Check(zap.DebugLevel, "resolved starting revision"); ev != nil {
187-
ev.Write(
188-
zap.Stringer("revision", l.Rev),
189-
zap.Stringer("hash", hash),
187+
if logger.Enabled(ctx, slog.LevelDebug) {
188+
logger.LogAttrs(ctx, slog.LevelDebug, "resolved starting revision",
189+
slog.String("revision", l.Rev.String()),
190+
slog.String("hash", hash.String()),
190191
)
191192
}
192193

@@ -203,19 +204,21 @@ func (l *CommitLinter) Run(ctx context.Context) error {
203204
var errorCount uint
204205
err = iter.ForEach(func(commit *object.Commit) error {
205206
if ctx.Err() != nil {
206-
if ev := logger.Check(zap.DebugLevel, "cancelling linting"); ev != nil {
207-
ev.Write(
208-
zap.Stringer("hash", commit.Hash),
209-
zap.NamedError("cause", ctx.Err()),
207+
if logger.Enabled(ctx, slog.LevelDebug) {
208+
logger.LogAttrs(ctx, slog.LevelDebug, "cancelling linting",
209+
slog.String("hash", commit.Hash.String()),
210+
slog.String("cause", ctx.Err().Error()),
210211
)
211212
}
212213

213214
return ctx.Err()
214215
}
215216

216217
if l.StopFunc(commit) {
217-
if ev := logger.Check(zap.DebugLevel, "stopping linting"); ev != nil {
218-
ev.Write(zap.Stringer("hash", commit.Hash))
218+
if logger.Enabled(ctx, slog.LevelDebug) {
219+
logger.LogAttrs(ctx, slog.LevelDebug, "stopping linting",
220+
slog.String("hash", commit.Hash.String()),
221+
)
219222
}
220223

221224
return storer.ErrStop
@@ -230,14 +233,9 @@ func (l *CommitLinter) Run(ctx context.Context) error {
230233
return nil
231234
}
232235

233-
if ev := logger.Check(zap.DebugLevel, "commit passed"); ev != nil {
234-
ev.Write(
235-
zap.Stringer("hash", commit.Hash),
236-
zap.Dict("author",
237-
zap.String("name", commit.Author.Name),
238-
zap.String("email", commit.Author.Email),
239-
zap.Time("when", commit.Author.When),
240-
),
236+
if logger.Enabled(ctx, slog.LevelDebug) {
237+
logger.LogAttrs(ctx, slog.LevelDebug, "commit passed",
238+
slog.Any("commit", commit),
241239
)
242240
}
243241

0 commit comments

Comments
 (0)