Repository: datreeio/datree (go)

Issue:
Get LocalConfiguration before publish command cobra.RunE
**Describe the solution you'd like**

Get local configuration before Run. This pattern will allow us to make sure before running the command logic it has everything that it needs. Additionally, this should make the code easier to understand and maintain. 

**“How to Implement” suggestion**

Init `localConfig` to outside of `cobra.Command` scope. Move `localConfigContent, err := ctx.LocalConfig.GetLocalConfiguration()` from `publish` command to `PreRunE`. Adjust `publish` to accept `localConfig` as an argument.

**Requirements**
Golang basic level.

Pull request:
refactor: get local configuration before Run
Closes #445 

Patch:
diff --git a/cmd/publish/main.go b/cmd/publish/main.go
index 1639c3a..da7a81c 100644
--- a/cmd/publish/main.go
+++ b/cmd/publish/main.go
@@ -36,6 +36,8 @@ type PublishCommandContext struct {
 }
 
 func New(ctx *PublishCommandContext) *cobra.Command {
+	var localConfigContent *localConfig.ConfigContent
+
 	publishCommand := &cobra.Command{
 		Use:   "publish <fileName>",
 		Short: "Publish policies configuration for given <fileName>.",
@@ -62,13 +64,18 @@ func New(ctx *PublishCommandContext) *cobra.Command {
 					ctx.Printer.PrintMessage(msg.MessageText+"\n", msg.MessageColor)
 				}
 			}
+			var err error
+			localConfigContent, err = ctx.LocalConfig.GetLocalConfiguration()
+			if err != nil {
+				return err
+			}
 			return nil
 		},
 		RunE: func(cmd *cobra.Command, args []string) error {
 			cmd.SilenceUsage = true
 			cmd.SilenceErrors = true
 
-			publishFailedResponse, err := publish(ctx, args[0])
+			publishFailedResponse, err := publish(ctx, args[0], localConfigContent)
 			if publishFailedResponse != nil {
 				ctx.Printer.PrintMessage("Publish failed:\n", "error")
 				for _, message := range publishFailedResponse.Payload {
@@ -95,12 +102,7 @@ type MessagesContext struct {
 	CliClient   *cliClient.CliClient
 }
 
-func publish(ctx *PublishCommandContext, path string) (*cliClient.PublishFailedResponse, error) {
-	localConfigContent, err := ctx.LocalConfig.GetLocalConfiguration()
-	if err != nil {
-		return nil, err
-	}
-
+func publish(ctx *PublishCommandContext, path string, localConfigContent *localConfig.ConfigContent) (*cliClient.PublishFailedResponse, error) {
 	policiesConfiguration, err := files.ExtractYamlFileToUnknownStruct(path)
 	if err != nil {
 		return nil, err


Test patch:
diff --git a/cmd/publish/main_test.go b/cmd/publish/main_test.go
index a3b77e7..0d91c30 100644
--- a/cmd/publish/main_test.go
+++ b/cmd/publish/main_test.go
@@ -77,24 +77,26 @@ func TestPublishCommand(t *testing.T) {
 		PublishCliClient: publishClientMock,
 	}
 
-	testPublishCommandSuccess(t, ctx, publishClientMock)
-	testPublishCommandFailedYaml(t, ctx)
-	testPublishCommandFailedSchema(t, ctx, publishClientMock)
+	localConfigContent, _ := ctx.LocalConfig.GetLocalConfiguration()
+
+	testPublishCommandSuccess(t, ctx, publishClientMock, localConfigContent)
+	testPublishCommandFailedYaml(t, ctx, localConfigContent)
+	testPublishCommandFailedSchema(t, ctx, publishClientMock, localConfigContent)
 }
 
-func testPublishCommandSuccess(t *testing.T, ctx *PublishCommandContext, publishClientMock *PublishClientMock) {
+func testPublishCommandSuccess(t *testing.T, ctx *PublishCommandContext, publishClientMock *PublishClientMock, localConfigContent *localConfig.ConfigContent) {
 	publishClientMock.On("PublishPolicies", mock.Anything, mock.Anything).Return(&cliClient.PublishFailedResponse{}, nil).Once()
-	_, err := publish(ctx, "../../internal/fixtures/policyAsCode/valid-schema.yaml")
+	_, err := publish(ctx, "../../internal/fixtures/policyAsCode/valid-schema.yaml", localConfigContent)
 	assert.Equal(t, nil, err)
 }
 
-func testPublishCommandFailedYaml(t *testing.T, ctx *PublishCommandContext) {
-	_, err := publish(ctx, "../../internal/fixtures/policyAsCode/invalid-yaml.yaml")
+func testPublishCommandFailedYaml(t *testing.T, ctx *PublishCommandContext, localConfigContent *localConfig.ConfigContent) {
+	_, err := publish(ctx, "../../internal/fixtures/policyAsCode/invalid-yaml.yaml", localConfigContent)
 	assert.NotEqual(t, nil, err)
 	assert.Equal(t, "yaml: line 2: did not find expected key", err.Error())
 }
 
-func testPublishCommandFailedSchema(t *testing.T, ctx *PublishCommandContext, publishClientMock *PublishClientMock) {
+func testPublishCommandFailedSchema(t *testing.T, ctx *PublishCommandContext, publishClientMock *PublishClientMock, localConfigContent *localConfig.ConfigContent) {
 	publishFailedPayloadMock := []string{"first error", "second error"}
 	errMessage := strings.Join(publishFailedPayloadMock, ",")
 	publishFailedResponseMock := &cliClient.PublishFailedResponse{
@@ -104,7 +106,7 @@ func testPublishCommandFailedSchema(t *testing.T, ctx *PublishCommandContext, pu
 	}
 
 	publishClientMock.On("PublishPolicies", mock.Anything, mock.Anything).Return(publishFailedResponseMock, errors.New(errMessage)).Once()
-	publishFailedRes, err := publish(ctx, "../../internal/fixtures/policyAsCode/invalid-schemas/duplicate-rule-id.yaml")
+	publishFailedRes, err := publish(ctx, "../../internal/fixtures/policyAsCode/invalid-schemas/duplicate-rule-id.yaml", localConfigContent)
 	assert.NotEqual(t, nil, err)
 	assert.Equal(t, errMessage, err.Error())
 	assert.Equal(t, publishFailedResponseMock, publishFailedRes)