Skip to content

Commit 22593a5

Browse files
authored
CON-1738 mt commands (#80)
Added mt detect and mt translate commands Implemented resolving values hierarchy from flag, file config, env variable or flag default value Used humble object pattern and separated CLI framework command with running logic Separated service logic from CLI framework and UI logic Moved UI to output dir Used CLI UI framework for outputs Implemented dynamic and static output mode rendering depends on flag value Used github.com/charmbracelet/bubbletea for dynamic output rendering Used github.com/charmbracelet/lipgloss for static output rendering Dynamic mode use bubbletea and lipgloss Static mode use lipgloss only Added UIError for outputs Added tests and mocks
1 parent 590fc3f commit 22593a5

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

65 files changed

+3089
-247
lines changed

.mockery.yml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,11 @@ packages:
2020
Service:
2121
config:
2222
dir: services/init/mocks
23+
github.com/Smartling/smartling-cli/services/mt:
24+
interfaces:
25+
Service:
26+
config:
27+
dir: services/mt/mocks
2328
github.com/Smartling/smartling-cli/cmd/files:
2429
interfaces:
2530
SrvInitializer:
@@ -35,3 +40,8 @@ packages:
3540
SrvInitializer:
3641
config:
3742
dir: cmd/init/mocks
43+
github.com/Smartling/smartling-cli/cmd/mt:
44+
interfaces:
45+
SrvInitializer:
46+
config:
47+
dir: cmd/mt/mocks

Jenkinsfile

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,19 @@ pipeline {
1515
}
1616
}
1717

18-
stage('Deploy') {
18+
stage('Release?') {
19+
agent none
20+
when {
21+
branch env.TARGET_BRANCH
22+
}
23+
steps {
24+
timeout(time: 1, unit: 'HOURS') {
25+
input 'Release to PROD?'
26+
}
27+
}
28+
}
29+
30+
stage('Upload to public S3') {
1931
when {
2032
branch env.TARGET_BRANCH
2133
}
@@ -25,6 +37,9 @@ pipeline {
2537
}
2638

2739
stage('Generate Packages') {
40+
when {
41+
branch env.TARGET_BRANCH
42+
}
2843
steps {
2944
sh "docker run -t --rm -v ${WORKSPACE}:/go/src/cli -w /go/src/cli gvangool/rpmbuilder:centos7 bash -c 'make rpm'"
3045
// TODO : Replace with special docker image

cmd/cmd_root.go

Lines changed: 23 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,23 @@
11
package cmd
22

33
import (
4-
"os"
54
"strings"
65

7-
"github.com/Smartling/smartling-cli/services/helpers/client"
8-
"github.com/Smartling/smartling-cli/services/helpers/config"
9-
"github.com/Smartling/smartling-cli/services/helpers/rlog"
10-
11-
sdk "github.com/Smartling/api-sdk-go"
12-
"github.com/kovetskiy/lorg"
136
"github.com/spf13/cobra"
147
)
158

169
var (
17-
smartlingURL string
18-
configFile string
19-
project string
20-
account string
21-
user string
22-
secret string
23-
directory string
24-
threads uint32
25-
insecure bool
26-
proxy string
27-
verbose int
10+
smartlingURL string
11+
configFile string
12+
project string
13+
account string
14+
user string
15+
secret string
16+
operationDirectory string
17+
threads uint32
18+
insecure bool
19+
proxy string
20+
verbose int
2821

2922
isInit bool
3023
isFiles bool
@@ -33,30 +26,30 @@ var (
3326
)
3427

3528
// NewRootCmd creates a new root command.
36-
func NewRootCmd() (*cobra.Command, error) {
29+
func NewRootCmd() *cobra.Command {
3730
rootCmd := &cobra.Command{
3831
Use: "smartling-cli",
3932
Short: "Manage translation files using Smartling CLI.",
40-
Version: "2.0",
33+
Version: "2.1",
4134
Long: `Manage translation files using Smartling CLI.
4235
Complete documentation is available at https://www.smartling.com`,
4336
PersistentPreRun: func(cmd *cobra.Command, _ []string) {
4437
configureLoggerVerbose()
4538

4639
path := cmd.CommandPath()
47-
isInit = strings.HasPrefix(path, "my-cli init")
48-
isFiles = strings.HasPrefix(path, "my-cli files")
49-
isProjects = strings.HasPrefix(path, "my-cli projects")
50-
isList = strings.HasPrefix(path, "my-cli list")
40+
isInit = strings.HasPrefix(path, "smartling-cli init")
41+
isFiles = strings.HasPrefix(path, "smartling-cli files")
42+
isProjects = strings.HasPrefix(path, "smartling-cli projects")
43+
isList = strings.HasPrefix(path, "smartling-cli list")
5144
},
52-
Run: func(cmd *cobra.Command, args []string) {
45+
RunE: func(cmd *cobra.Command, args []string) error {
5346
if len(args) == 0 && cmd.Flags().NFlag() == 0 {
5447
if err := cmd.Help(); err != nil {
55-
rlog.Error(err.Error())
56-
os.Exit(1)
48+
return err
5749
}
58-
return
50+
return nil
5951
}
52+
return nil
6053
},
6154
}
6255

@@ -72,7 +65,7 @@ This option overrides config value "account_id".`)
7265
This option overrides config value "user_id".`)
7366
rootCmd.PersistentFlags().StringVar(&secret, "secret", "", `Token Secret which will be used for authentication.
7467
This option overrides config value "secret".`)
75-
rootCmd.PersistentFlags().StringVarP(&directory, "directory", "d", ".", `Sets directory to operate on, usually, to store or to
68+
rootCmd.PersistentFlags().StringVar(&operationDirectory, "operation-directory", ".", `Sets directory to operate on, usually, to store or to
7669
read files. Depends on command.`)
7770
rootCmd.PersistentFlags().Uint32Var(&threads, "threads", 4, `If command can be executed concurrently, it will be
7871
executed for at most <number> of threads.`)
@@ -82,79 +75,5 @@ executed for at most <number> of threads.`)
8275
purposes.`)
8376
rootCmd.PersistentFlags().CountVarP(&verbose, "verbose", "v", "Verbose logging")
8477

85-
return rootCmd, nil
86-
}
87-
88-
// ConfigureLogger initializes the logger with default settings.
89-
func ConfigureLogger() {
90-
rlog.Init()
91-
rlog.ToggleRedact(true)
92-
rlog.SetFormat(lorg.NewFormat("* ${time} ${level:[%s]:right} %s"))
93-
rlog.SetIndentLines(true)
94-
}
95-
96-
// CLIClientConfig returns a client.Config based on the CLI flags.
97-
func CLIClientConfig() client.Config {
98-
return client.Config{
99-
Insecure: insecure,
100-
Proxy: proxy,
101-
SmartlingURL: smartlingURL,
102-
}
103-
}
104-
105-
// Config returns a config.Config based on the CLI flags.
106-
func Config() (config.Config, error) {
107-
params := config.Params{
108-
Directory: directory,
109-
File: configFile,
110-
User: user,
111-
Secret: secret,
112-
Account: account,
113-
Project: project,
114-
Threads: threads,
115-
IsInit: isInit,
116-
IsFiles: isFiles,
117-
IsProjects: isProjects,
118-
IsList: isList,
119-
}
120-
cnf, err := config.BuildConfigFromFlags(params)
121-
if err != nil {
122-
return config.Config{}, err
123-
}
124-
return cnf, nil
125-
}
126-
127-
// Client creates a new Smartling API client based on the configuration and CLI params.
128-
func Client() (sdk.Client, error) {
129-
cnf, err := Config()
130-
if err != nil {
131-
return sdk.Client{}, err
132-
}
133-
client, err := client.CreateClient(CLIClientConfig(), cnf, uint8(verbose))
134-
if err != nil {
135-
return sdk.Client{}, err
136-
}
137-
return *client, nil
138-
}
139-
140-
// ConfigFile returns the path to the configuration file.
141-
func ConfigFile() string {
142-
return configFile
143-
}
144-
145-
func configureLoggerVerbose() {
146-
switch verbose {
147-
case 0:
148-
// nothing do to
149-
150-
case 1:
151-
rlog.SetLevel(lorg.LevelInfo)
152-
153-
case 2:
154-
rlog.SetLevel(lorg.LevelDebug)
155-
156-
default:
157-
rlog.ToggleRedact(false)
158-
rlog.SetLevel(lorg.LevelDebug)
159-
}
78+
return rootCmd
16079
}

cmd/config.go

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
package cmd
2+
3+
import (
4+
"github.com/Smartling/smartling-cli/services/helpers/client"
5+
"github.com/Smartling/smartling-cli/services/helpers/config"
6+
"github.com/Smartling/smartling-cli/services/helpers/rlog"
7+
8+
sdk "github.com/Smartling/api-sdk-go"
9+
"github.com/kovetskiy/lorg"
10+
)
11+
12+
// ConfigureLogger initializes the logger with default settings.
13+
func ConfigureLogger() {
14+
rlog.Init()
15+
rlog.ToggleRedact(true)
16+
rlog.SetFormat(lorg.NewFormat("* ${time} ${level:[%s]:right} %s"))
17+
rlog.SetIndentLines(true)
18+
}
19+
20+
// CLIClientConfig returns a client.Config based on the CLI flags.
21+
func CLIClientConfig() client.Config {
22+
return client.Config{
23+
Insecure: insecure,
24+
Proxy: proxy,
25+
SmartlingURL: smartlingURL,
26+
}
27+
}
28+
29+
// Config returns a config.Config based on the CLI flags.
30+
func Config() (config.Config, error) {
31+
rlog.Debugf("resolving configs")
32+
params := config.Params{
33+
Directory: operationDirectory,
34+
File: configFile,
35+
User: user,
36+
Secret: secret,
37+
Account: account,
38+
Project: project,
39+
Threads: threads,
40+
IsInit: isInit,
41+
IsFiles: isFiles,
42+
IsProjects: isProjects,
43+
IsList: isList,
44+
}
45+
cnf, err := config.BuildConfigFromFlags(params)
46+
if err != nil {
47+
return config.Config{}, err
48+
}
49+
return cnf, nil
50+
}
51+
52+
// Client creates a new Smartling API client based on the configuration and CLI params.
53+
func Client() (sdk.HttpAPIClient, error) {
54+
cnf, err := Config()
55+
if err != nil {
56+
return sdk.HttpAPIClient{}, err
57+
}
58+
client, err := client.CreateClient(CLIClientConfig(), cnf, uint8(verbose))
59+
if err != nil {
60+
return sdk.HttpAPIClient{}, err
61+
}
62+
return client, nil
63+
}
64+
65+
// ConfigFile returns the path to the configuration file.
66+
func ConfigFile() string {
67+
return configFile
68+
}
69+
70+
func configureLoggerVerbose() {
71+
switch verbose {
72+
case 0:
73+
// nothing do to
74+
75+
case 1:
76+
rlog.SetLevel(lorg.LevelInfo)
77+
78+
case 2:
79+
rlog.SetLevel(lorg.LevelDebug)
80+
81+
default:
82+
rlog.ToggleRedact(false)
83+
rlog.SetLevel(lorg.LevelDebug)
84+
}
85+
}

cmd/files/import/cmd_import.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ func NewImportCmd(initializer filescmd.SrvInitializer) *cobra.Command {
2323
importCmd := &cobra.Command{
2424
Use: "import <uri> <file> <locale>",
2525
Short: "Imports translations for given original file URI with.",
26-
Long: `smartling-cli import — import file translations.
26+
Long: `smartling-cli files import — import file translations.
2727
2828
Import pre-existent file translations into Smartling. Note, that
2929
original file should be pushed prior file translations are imported.

cmd/helpers/resolve/resolve.go

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
package resolve
2+
3+
import (
4+
"os"
5+
6+
"github.com/Smartling/smartling-cli/services/helpers/env"
7+
8+
"github.com/spf13/pflag"
9+
)
10+
11+
// StringParam defines resolve string param
12+
type StringParam struct {
13+
FlagName string
14+
Config *string
15+
}
16+
17+
// BoolParam defines resolve bool param
18+
type BoolParam struct {
19+
FlagName string
20+
Config *bool
21+
}
22+
23+
// FallbackString resolve string value from hierarchy of fallbacks
24+
func FallbackString(flag *pflag.Flag, param StringParam) string {
25+
// return flag value if it was changed
26+
if flag != nil && flag.Changed {
27+
return flag.Value.String()
28+
}
29+
// return env value if it is available
30+
envVarName := env.VarNameFromCLIFlagName(param.FlagName)
31+
if val, isSet := os.LookupEnv(envVarName); isSet {
32+
return val
33+
}
34+
// return config value if it is available
35+
if param.Config != nil {
36+
return *param.Config
37+
}
38+
// return zero value if no flag
39+
if flag == nil {
40+
return ""
41+
}
42+
// return default flag value
43+
return flag.DefValue
44+
}
45+
46+
// FallbackBool resolve bool value from hierarchy of fallbacks
47+
func FallbackBool(flag *pflag.Flag, param BoolParam) bool {
48+
// return flag value if it was changed
49+
if flag != nil && flag.Changed {
50+
return true
51+
}
52+
// return env value if it is available
53+
envVarName := env.VarNameFromCLIFlagName(param.FlagName)
54+
if _, isSet := os.LookupEnv(envVarName); isSet {
55+
return true
56+
}
57+
// return config value if it is available
58+
if param.Config != nil {
59+
return *param.Config
60+
}
61+
// return zero value if no flag
62+
if flag == nil {
63+
return false
64+
}
65+
// return default flag value
66+
return true
67+
}

0 commit comments

Comments
 (0)