Skip to content

Commit c9e6857

Browse files
authored
chore: migrate cli package into the CLD engine legacy package (#340)
This is a temporary migration to get the CLI package into the CLD engine legacy package. As we determine how to best design CLI management, we will deprecate this package.
1 parent ed5dc34 commit c9e6857

File tree

9 files changed

+292
-6
lines changed

9 files changed

+292
-6
lines changed

.changeset/major-walls-stop.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"chainlink-deployments-framework": minor
3+
---
4+
5+
Adds `cli` package to `engine/cld/legacy`

engine/cld/legacy/cli/cli.go

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
// Package cli provides a base struct for creating CLI applications using Cobra. It contains common
2+
// functionality for creating CLI applications, such as providing a logger, adding commands and
3+
// running the root command.
4+
package cli
5+
6+
import (
7+
"os"
8+
9+
"github.com/smartcontractkit/chainlink-common/pkg/logger"
10+
"github.com/spf13/cobra"
11+
"go.uber.org/zap"
12+
"go.uber.org/zap/zapcore"
13+
)
14+
15+
// Base is a base struct for creating CLI applications using Cobra. This should be embedded into
16+
// a struct that contains the specific commands for the CLI application.
17+
type Base struct {
18+
Log logger.Logger
19+
20+
rootCmd *cobra.Command
21+
}
22+
23+
// NewBase creates a new CLIBase instance.
24+
func NewBase(log logger.Logger, rootCmd *cobra.Command) *Base {
25+
return &Base{
26+
Log: log,
27+
rootCmd: rootCmd,
28+
}
29+
}
30+
31+
// AddCommand adds one or more commands to the root command of the CLI application.
32+
func (base *Base) AddCommand(cmds ...*cobra.Command) {
33+
base.rootCmd.AddCommand(cmds...)
34+
}
35+
36+
// Run executes the root command of the CLI application.
37+
func (base *Base) Run() error {
38+
return base.rootCmd.Execute()
39+
}
40+
41+
// RootCmd returns the root command of the CLI application.
42+
func (base *Base) RootCmd() *cobra.Command {
43+
return base.rootCmd
44+
}
45+
46+
// NewLogger creates a new logger instance from chainlink-common. This is a helper function to
47+
// initialize a logger to provide to `NewBase`.
48+
func NewLogger(level zapcore.Level) (logger.Logger, error) {
49+
c := logger.Config{Level: level}
50+
if os.Getenv("LOG_FORMAT") == "console" || os.Getenv("LOG_FORMAT") == "human" {
51+
return logger.NewWith(func(config *zap.Config) {
52+
config.Level.SetLevel(level)
53+
config.Development = true
54+
config.DisableStacktrace = true
55+
config.Encoding = "console"
56+
config.EncoderConfig = zap.NewDevelopmentEncoderConfig()
57+
config.EncoderConfig.EncodeLevel = zapcore.CapitalColorLevelEncoder
58+
})
59+
}
60+
61+
return c.New()
62+
}

engine/cld/legacy/cli/cli_test.go

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package cli
2+
3+
import (
4+
"testing"
5+
6+
"github.com/spf13/cobra"
7+
"github.com/stretchr/testify/assert"
8+
"github.com/stretchr/testify/require"
9+
"go.uber.org/zap/zapcore"
10+
)
11+
12+
func Test_Base_AddCommand(t *testing.T) {
13+
t.Parallel()
14+
15+
base := Base{
16+
rootCmd: &cobra.Command{},
17+
}
18+
19+
give := &cobra.Command{}
20+
21+
base.AddCommand(give)
22+
23+
assert.Equal(t, []*cobra.Command{give}, base.rootCmd.Commands())
24+
}
25+
26+
func Test_Base_Run(t *testing.T) {
27+
t.Parallel()
28+
29+
var val string
30+
31+
base := Base{
32+
rootCmd: &cobra.Command{
33+
Use: "test",
34+
RunE: func(cmd *cobra.Command, args []string) error {
35+
val = "ran"
36+
37+
return nil
38+
},
39+
},
40+
}
41+
42+
err := base.Run()
43+
require.NoError(t, err)
44+
assert.Equal(t, "ran", val)
45+
}
46+
47+
func Test_NewLogger(t *testing.T) {
48+
t.Parallel()
49+
50+
log, err := NewLogger(zapcore.DebugLevel)
51+
require.NoError(t, err)
52+
assert.NotNil(t, log)
53+
}

engine/cld/legacy/cli/logger.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package cli
2+
3+
import (
4+
"github.com/smartcontractkit/chainlink-common/pkg/logger"
5+
"go.uber.org/zap"
6+
"go.uber.org/zap/zapcore"
7+
)
8+
9+
func NewCLILogger(logLevel zapcore.Level) (logger.Logger, error) {
10+
lggr, err := logger.NewWith(func(cfg *zap.Config) {
11+
*cfg = zap.NewDevelopmentConfig()
12+
cfg.Level.SetLevel(logLevel)
13+
cfg.EncoderConfig.EncodeLevel = zapcore.CapitalColorLevelEncoder
14+
})
15+
if err != nil {
16+
return nil, err
17+
}
18+
19+
return lggr, nil
20+
}

engine/cld/legacy/cli/templates.go

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package cli
2+
3+
import (
4+
"strings"
5+
)
6+
7+
const Indentation = ` `
8+
9+
// LongDesc normalizes a command's long description to follow the conventions.
10+
func LongDesc(s string) string {
11+
if len(s) == 0 {
12+
return s
13+
}
14+
15+
return normalizer{s}.trim().string
16+
}
17+
18+
// Examples normalizes a command's examples to follow the conventions.
19+
func Examples(s string) string {
20+
if len(s) == 0 {
21+
return s
22+
}
23+
24+
return normalizer{s}.trim().indent().string
25+
}
26+
27+
type normalizer struct {
28+
string
29+
}
30+
31+
func (s normalizer) trim() normalizer {
32+
s.string = strings.TrimSpace(s.string)
33+
34+
return s
35+
}
36+
37+
func (s normalizer) indent() normalizer {
38+
indentedLines := []string{}
39+
for line := range strings.SplitSeq(s.string, "\n") {
40+
trimmed := strings.TrimSpace(line)
41+
indented := Indentation + trimmed
42+
indentedLines = append(indentedLines, indented)
43+
}
44+
s.string = strings.Join(indentedLines, "\n")
45+
46+
return s
47+
}
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
package cli
2+
3+
import (
4+
"testing"
5+
6+
"github.com/stretchr/testify/assert"
7+
)
8+
9+
func Test_LongDesc(t *testing.T) {
10+
t.Parallel()
11+
12+
tests := []struct {
13+
name string
14+
give string
15+
want string
16+
}{
17+
{
18+
name: "empty string produces empty string",
19+
give: "",
20+
want: "",
21+
},
22+
{
23+
name: "single line string produces same string",
24+
give: "hello world",
25+
want: "hello world",
26+
},
27+
{
28+
name: "multi line string produces same string",
29+
give: "hello\nworld",
30+
want: "hello\nworld",
31+
},
32+
{
33+
name: "multi line string with leading/trailing whitespace trims whitespace",
34+
give: " hello\nworld ",
35+
want: "hello\nworld",
36+
},
37+
}
38+
39+
for _, tt := range tests {
40+
t.Run(tt.name, func(t *testing.T) {
41+
t.Parallel()
42+
43+
got := LongDesc(tt.give)
44+
45+
assert.Equal(t, tt.want, got)
46+
})
47+
}
48+
}
49+
50+
func Test_Examples(t *testing.T) {
51+
t.Parallel()
52+
53+
tests := []struct {
54+
name string
55+
give string
56+
want string
57+
}{
58+
{
59+
name: "empty string produces empty string",
60+
give: "",
61+
want: "",
62+
},
63+
{
64+
name: "single line string indents the line",
65+
give: "hello world",
66+
want: " hello world",
67+
},
68+
{
69+
name: "multi line string indents each line",
70+
give: "hello\nworld",
71+
want: " hello\n world",
72+
},
73+
{
74+
name: "multi line string with leading/trailing whitespace trims trailing whitespace and indents each line",
75+
give: " hello\nworld ",
76+
want: " hello\n world",
77+
},
78+
}
79+
80+
for _, tt := range tests {
81+
t.Run(tt.name, func(t *testing.T) {
82+
t.Parallel()
83+
84+
got := Examples(tt.give)
85+
86+
assert.Equal(t, tt.want, got)
87+
})
88+
}
89+
}

go.mod

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ require (
3333
github.com/smartcontractkit/chainlink-tron/relayer v0.0.11-0.20250815105909-75499abc4335
3434
github.com/smartcontractkit/freeport v0.1.2
3535
github.com/smartcontractkit/mcms v0.21.1
36+
github.com/spf13/cobra v1.8.1
3637
github.com/spf13/viper v1.20.1
3738
github.com/stretchr/testify v1.10.0
3839
github.com/testcontainers/testcontainers-go v0.38.0
@@ -147,6 +148,7 @@ require (
147148
github.com/holiman/bloomfilter/v2 v2.0.3 // indirect
148149
github.com/holiman/uint256 v1.3.2 // indirect
149150
github.com/huin/goupnp v1.3.0 // indirect
151+
github.com/inconshreveable/mousetrap v1.1.0 // indirect
150152
github.com/invopop/jsonschema v0.13.0 // indirect
151153
github.com/jackc/chunkreader/v2 v2.0.1 // indirect
152154
github.com/jackc/pgconn v1.14.3 // indirect

go.sum

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,7 @@ github.com/cosmos/go-bip39 v1.0.0 h1:pcomnQdrdH22njcAatO0yWojsUnCO3y2tNoV1cb6hHY
167167
github.com/cosmos/go-bip39 v1.0.0/go.mod h1:RNJv0H/pOIVgxw6KS7QeX2a0Uo0aKUlfhZ4xuwvCdJw=
168168
github.com/cpuguy83/dockercfg v0.3.2 h1:DlJTyZGBDlXqUZ2Dk2Q3xHs/FtnooJJVaad2S9GKorA=
169169
github.com/cpuguy83/dockercfg v0.3.2/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc=
170+
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
170171
github.com/cpuguy83/go-md2man/v2 v2.0.6 h1:XJtiaUW6dEEqVuZiMTn1ldk455QWwEIsMIJlo5vtkx0=
171172
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
172173
github.com/crate-crypto/go-ipa v0.0.0-20240724233137-53bbb0ceb27a h1:W8mUrRp6NOVl3J+MYp5kPMoUZPp7aOYHtaua31lwRHg=
@@ -371,6 +372,8 @@ github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpO
371372
github.com/huin/goupnp v1.3.0 h1:UvLUlWDNpoUdYzb2TCn+MuTWtcjXKSza2n6CBdQ0xXc=
372373
github.com/huin/goupnp v1.3.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8=
373374
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
375+
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
376+
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
374377
github.com/influxdata/influxdb-client-go/v2 v2.4.0 h1:HGBfZYStlx3Kqvsv1h2pJixbCl/jhnFtxpKFAv9Tu5k=
375378
github.com/influxdata/influxdb-client-go/v2 v2.4.0/go.mod h1:vLNHdxTJkIf2mSLvGrpj8TCcISApPoXkaxP8g9uRlW8=
376379
github.com/influxdata/influxdb1-client v0.0.0-20220302092344-a9ab5670611c h1:qSHzRbhzK8RdXOsAdfDgO49TtqC1oZ+acxPrkfTxcCs=
@@ -716,6 +719,9 @@ github.com/spf13/afero v1.12.0 h1:UcOPyRBYczmFn6yvphxkn9ZEOY65cpwGKb5mL36mrqs=
716719
github.com/spf13/afero v1.12.0/go.mod h1:ZTlWwG4/ahT8W7T0WQ5uYmjI9duaLQGy3Q2OAl4sk/4=
717720
github.com/spf13/cast v1.7.1 h1:cuNEagBQEHWN1FnbGEjCXL2szYEXqfJPbP2HNUaca9Y=
718721
github.com/spf13/cast v1.7.1/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
722+
github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM=
723+
github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y=
724+
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
719725
github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o=
720726
github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
721727
github.com/spf13/viper v1.20.1 h1:ZMi+z/lvLyPSCoNtFCpqjy0S4kPbirhpTMwl8BkW9X4=

sonar-project.properties

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,15 @@ docs/**/*,\
99
**/mocks/**/*,\
1010
**/mocks_test.go,\
1111
**/*.json, \
12-
**/*.pb.go
12+
**/*.pb.go, \
13+
engine/cld/legacy/**/*
1314

14-
# docs/**/*, # Documentation directory
15-
# **/mocks/**/* # Any generated mocks directory
16-
# **/mocks_test.go # Standard generated mocks test file
17-
# **/*.json \ # JSON files - speed up indexing
18-
# **/*.pb.go # Protobuf generated files
15+
# docs/**/*, # Documentation directory
16+
# **/mocks/**/* # Any generated mocks directory
17+
# **/mocks_test.go # Standard generated mocks test file
18+
# **/*.json \ # JSON files - speed up indexing
19+
# **/*.pb.go # Protobuf generated files
20+
# engine/cld/legacy/**/* # Legacy code that has been ported over. This will be removed in the future.
1921

2022
sonar.coverage.exclusions=\
2123
**/*_test.go, \

0 commit comments

Comments
 (0)