1
0
mirror of https://github.com/SAP/jenkins-library.git synced 2025-01-30 05:59:39 +02:00

checkChangeInDevelopment (#3115)

- refactor GO implementation
This commit is contained in:
Roland Stengel 2021-10-04 13:08:34 +02:00 committed by GitHub
parent 4b7a6b1b66
commit 7612272992
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 70 additions and 70 deletions

View File

@ -1,17 +0,0 @@
package cmd
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestCheckChangeInDevelopmentCommand(t *testing.T) {
t.Parallel()
testCmd := CheckChangeInDevelopmentCommand()
// only high level testing performed - details are tested in step generation procedure
assert.Equal(t, "checkChangeInDevelopment", testCmd.Use, "command name incorrect")
}

View File

@ -9,27 +9,27 @@ import (
"strings"
)
type checkChangeInDevelopmentUtils interface {
type isChangeInDevelopmentUtils interface {
command.ExecRunner
GetExitCode() int
// Add more methods here, or embed additional interfaces, or remove/replace as required.
// The checkChangeInDevelopmentUtils interface should be descriptive of your runtime dependencies,
// The isChangeInDevelopmentUtils interface should be descriptive of your runtime dependencies,
// i.e. include everything you need to be able to mock in tests.
// Unit tests shall be executable in parallel (not depend on global state), and don't (re-)test dependencies.
}
type checkChangeInDevelopmentUtilsBundle struct {
type isChangeInDevelopmentUtilsBundle struct {
*command.Command
// Embed more structs as necessary to implement methods or interfaces you add to checkChangeInDevelopmentUtils.
// Embed more structs as necessary to implement methods or interfaces you add to isChangeInDevelopmentUtils.
// Structs embedded in this way must each have a unique set of methods attached.
// If there is no struct which implements the method you need, attach the method to
// checkChangeInDevelopmentUtilsBundle and forward to the implementation of the dependency.
// isChangeInDevelopmentUtilsBundle and forward to the implementation of the dependency.
}
func newCheckChangeInDevelopmentUtils() checkChangeInDevelopmentUtils {
utils := checkChangeInDevelopmentUtilsBundle{
func newIsChangeInDevelopmentUtils() isChangeInDevelopmentUtils {
utils := isChangeInDevelopmentUtilsBundle{
Command: &command.Command{},
}
// Reroute command output to logging framework
@ -38,10 +38,10 @@ func newCheckChangeInDevelopmentUtils() checkChangeInDevelopmentUtils {
return &utils
}
func checkChangeInDevelopment(config checkChangeInDevelopmentOptions, telemetryData *telemetry.CustomData) {
func isChangeInDevelopment(config isChangeInDevelopmentOptions, telemetryData *telemetry.CustomData) {
// Utils can be used wherever the command.ExecRunner interface is expected.
// It can also be used for example as a mavenExecRunner.
utils := newCheckChangeInDevelopmentUtils()
utils := newIsChangeInDevelopmentUtils()
// For HTTP calls import piperhttp "github.com/SAP/jenkins-library/pkg/http"
// and use a &piperhttp.Client{} in a custom system
@ -49,17 +49,17 @@ func checkChangeInDevelopment(config checkChangeInDevelopmentOptions, telemetryD
// Error situations should be bubbled up until they reach the line below which will then stop execution
// through the log.Entry().Fatal() call leading to an os.Exit(1) in the end.
err := runCheckChangeInDevelopment(&config, telemetryData, utils)
err := runIsChangeInDevelopment(&config, telemetryData, utils)
if err != nil {
log.Entry().WithError(err).Fatal("step execution failed")
}
}
func runCheckChangeInDevelopment(config *checkChangeInDevelopmentOptions, telemetryData *telemetry.CustomData, utils checkChangeInDevelopmentUtils) error {
func runIsChangeInDevelopment(config *isChangeInDevelopmentOptions, telemetryData *telemetry.CustomData, utils isChangeInDevelopmentUtils) error {
log.Entry().Infof("Checking change status for change '%s'", config.ChangeDocumentID)
isInDevelopment, err := isChangeInDevelopment(config, utils)
isInDevelopment, err := perform(config, utils)
if err != nil {
return err
}
@ -69,13 +69,13 @@ func runCheckChangeInDevelopment(config *checkChangeInDevelopmentOptions, teleme
return nil
}
if config.FailIfStatusIsNotInDevelopment {
return fmt.Errorf("Change '%s' is not in status 'in development'", config.ChangeDocumentID)
return fmt.Errorf("change '%s' is not in status 'in development'", config.ChangeDocumentID)
}
log.Entry().Warningf("Change '%s' is not in status 'in development'. Failing the step has been explicitly disabled.", config.ChangeDocumentID)
return nil
}
func isChangeInDevelopment(config *checkChangeInDevelopmentOptions, utils checkChangeInDevelopmentUtils) (bool, error) {
func perform(config *isChangeInDevelopmentOptions, utils isChangeInDevelopmentUtils) (bool, error) {
if len(config.ClientOpts) > 0 {
utils.AppendEnv([]string{fmt.Sprintf("CMCLIENT_OPTS=%s", strings.Join(config.ClientOpts, " "))})
@ -91,7 +91,7 @@ func isChangeInDevelopment(config *checkChangeInDevelopmentOptions, utils checkC
"--return-code")
if err != nil {
return false, errors.Wrap(err, "Cannot retrieve change status")
return false, errors.Wrap(err, "cannot retrieve change status")
}
exitCode := utils.GetExitCode()
@ -105,5 +105,5 @@ func isChangeInDevelopment(config *checkChangeInDevelopmentOptions, utils checkC
hint = "Invalid credentials"
}
return false, fmt.Errorf("Cannot retrieve change status: %s", hint)
return false, fmt.Errorf("cannot retrieve change status: %s", hint)
}

View File

@ -15,7 +15,7 @@ import (
"github.com/spf13/cobra"
)
type checkChangeInDevelopmentOptions struct {
type isChangeInDevelopmentOptions struct {
Endpoint string `json:"endpoint,omitempty"`
Username string `json:"username,omitempty"`
Password string `json:"password,omitempty"`
@ -24,16 +24,16 @@ type checkChangeInDevelopmentOptions struct {
ClientOpts []string `json:"clientOpts,omitempty"`
}
// CheckChangeInDevelopmentCommand Checks if a certain change is in status 'in development'
func CheckChangeInDevelopmentCommand() *cobra.Command {
const STEP_NAME = "checkChangeInDevelopment"
// IsChangeInDevelopmentCommand Checks if a certain change is in status 'in development'
func IsChangeInDevelopmentCommand() *cobra.Command {
const STEP_NAME = "isChangeInDevelopment"
metadata := checkChangeInDevelopmentMetadata()
var stepConfig checkChangeInDevelopmentOptions
metadata := isChangeInDevelopmentMetadata()
var stepConfig isChangeInDevelopmentOptions
var startTime time.Time
var logCollector *log.CollectorHook
var createCheckChangeInDevelopmentCmd = &cobra.Command{
var createIsChangeInDevelopmentCmd = &cobra.Command{
Use: STEP_NAME,
Short: "Checks if a certain change is in status 'in development'",
Long: `"Checks if a certain change is in status 'in development'"`,
@ -99,17 +99,17 @@ func CheckChangeInDevelopmentCommand() *cobra.Command {
GeneralConfig.HookConfig.SplunkConfig.Index,
GeneralConfig.HookConfig.SplunkConfig.SendLogs)
}
checkChangeInDevelopment(stepConfig, &telemetryData)
isChangeInDevelopment(stepConfig, &telemetryData)
telemetryData.ErrorCode = "0"
log.Entry().Info("SUCCESS")
},
}
addCheckChangeInDevelopmentFlags(createCheckChangeInDevelopmentCmd, &stepConfig)
return createCheckChangeInDevelopmentCmd
addIsChangeInDevelopmentFlags(createIsChangeInDevelopmentCmd, &stepConfig)
return createIsChangeInDevelopmentCmd
}
func addCheckChangeInDevelopmentFlags(cmd *cobra.Command, stepConfig *checkChangeInDevelopmentOptions) {
func addIsChangeInDevelopmentFlags(cmd *cobra.Command, stepConfig *isChangeInDevelopmentOptions) {
cmd.Flags().StringVar(&stepConfig.Endpoint, "endpoint", os.Getenv("PIPER_endpoint"), "The service endpoint")
cmd.Flags().StringVar(&stepConfig.Username, "username", os.Getenv("PIPER_username"), "The user")
cmd.Flags().StringVar(&stepConfig.Password, "password", os.Getenv("PIPER_password"), "The password")
@ -124,10 +124,10 @@ func addCheckChangeInDevelopmentFlags(cmd *cobra.Command, stepConfig *checkChang
}
// retrieve step metadata
func checkChangeInDevelopmentMetadata() config.StepData {
func isChangeInDevelopmentMetadata() config.StepData {
var theMetaData = config.StepData{
Metadata: config.StepMetadata{
Name: "checkChangeInDevelopment",
Name: "isChangeInDevelopment",
Aliases: []config.Alias{},
Description: "Checks if a certain change is in status 'in development'",
},

View File

@ -0,0 +1,17 @@
package cmd
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestIsChangeInDevelopmentCommand(t *testing.T) {
t.Parallel()
testCmd := IsChangeInDevelopmentCommand()
// only high level testing performed - details are tested in step generation procedure
assert.Equal(t, "isChangeInDevelopment", testCmd.Use, "command name incorrect")
}

View File

@ -7,22 +7,22 @@ import (
"testing"
)
type checkChangeInDevelopmentMockUtils struct {
type isChangeInDevelopmentMockUtils struct {
*mock.ExecMockRunner
}
func newCheckChangeInDevelopmentTestsUtils() checkChangeInDevelopmentMockUtils {
utils := checkChangeInDevelopmentMockUtils{
func newIsChangeInDevelopmentTestsUtils() isChangeInDevelopmentMockUtils {
utils := isChangeInDevelopmentMockUtils{
ExecMockRunner: &mock.ExecMockRunner{},
}
return utils
}
func TestRunCheckChangeInDevelopment(t *testing.T) {
func TestRunIsChangeInDevelopment(t *testing.T) {
t.Parallel()
config := checkChangeInDevelopmentOptions{
config := isChangeInDevelopmentOptions{
Endpoint: "https://example.org/cm",
Username: "me",
Password: "****",
@ -46,10 +46,10 @@ func TestRunCheckChangeInDevelopment(t *testing.T) {
t.Run("change found and in status IN_DEVELOPMENT", func(t *testing.T) {
cmd := newCheckChangeInDevelopmentTestsUtils()
cmd := newIsChangeInDevelopmentTestsUtils()
cmd.ExitCode = 0 // this exit code represents a change in status IN_DEVELOPMENT
err := runCheckChangeInDevelopment(&config, nil, cmd)
err := runIsChangeInDevelopment(&config, nil, cmd)
if assert.NoError(t, err) {
assert.Equal(t, []string{"CMCLIENT_OPTS=-Dabc=123 -Ddef=456"}, cmd.Env)
@ -59,25 +59,25 @@ func TestRunCheckChangeInDevelopment(t *testing.T) {
t.Run("change found and not in status IN_DEVELOPMENT", func(t *testing.T) {
cmd := newCheckChangeInDevelopmentTestsUtils()
cmd := newIsChangeInDevelopmentTestsUtils()
cmd.ExitCode = 3 // this exit code represents a change which is not in status IN_DEVELOPMENT
err := runCheckChangeInDevelopment(&config, nil, cmd)
err := runIsChangeInDevelopment(&config, nil, cmd)
if assert.EqualError(t, err, "Change '12345678' is not in status 'in development'") {
if assert.EqualError(t, err, "change '12345678' is not in status 'in development'") {
assert.Equal(t, []mock.ExecCall{expectedShellCall}, cmd.Calls)
}
})
t.Run("change found and not in status IN_DEVELOPMENT, but we don't fail", func(t *testing.T) {
cmd := newCheckChangeInDevelopmentTestsUtils()
cmd := newIsChangeInDevelopmentTestsUtils()
cmd.ExitCode = 3 // this exit code represents a change which is not in status IN_DEVELOPMENT
myConfig := config
myConfig.FailIfStatusIsNotInDevelopment = false // needs to be explicitly configured
err := runCheckChangeInDevelopment(&myConfig, nil, cmd)
err := runIsChangeInDevelopment(&myConfig, nil, cmd)
if assert.NoError(t, err) {
assert.Equal(t, []mock.ExecCall{expectedShellCall}, cmd.Calls)
@ -86,36 +86,36 @@ func TestRunCheckChangeInDevelopment(t *testing.T) {
t.Run("invalid credentials", func(t *testing.T) {
cmd := newCheckChangeInDevelopmentTestsUtils()
cmd := newIsChangeInDevelopmentTestsUtils()
cmd.ExitCode = 2 // this exit code represents invalid credentials
err := runCheckChangeInDevelopment(&config, nil, cmd)
err := runIsChangeInDevelopment(&config, nil, cmd)
if assert.EqualError(t, err, "Cannot retrieve change status: Invalid credentials") {
if assert.EqualError(t, err, "cannot retrieve change status: Invalid credentials") {
assert.Equal(t, []mock.ExecCall{expectedShellCall}, cmd.Calls)
}
})
t.Run("generic failure reported via exit code", func(t *testing.T) {
cmd := newCheckChangeInDevelopmentTestsUtils()
cmd := newIsChangeInDevelopmentTestsUtils()
cmd.ExitCode = 1 // this exit code indicates something went wrong
err := runCheckChangeInDevelopment(&config, nil, cmd)
err := runIsChangeInDevelopment(&config, nil, cmd)
if assert.EqualError(t, err, "Cannot retrieve change status: Check log for details") {
if assert.EqualError(t, err, "cannot retrieve change status: Check log for details") {
assert.Equal(t, []mock.ExecCall{expectedShellCall}, cmd.Calls)
}
})
t.Run("generic failure reported via error", func(t *testing.T) {
cmd := newCheckChangeInDevelopmentTestsUtils()
cmd := newIsChangeInDevelopmentTestsUtils()
cmd.ShouldFailOnCommand = map[string]error{"cm.*": fmt.Errorf("%v", "Something went wrong")}
err := runCheckChangeInDevelopment(&config, nil, cmd)
err := runIsChangeInDevelopment(&config, nil, cmd)
if assert.EqualError(t, err, "Cannot retrieve change status: Something went wrong") {
if assert.EqualError(t, err, "cannot retrieve change status: Something went wrong") {
assert.Equal(t, []mock.ExecCall{expectedShellCall}, cmd.Calls)
}
})

View File

@ -23,7 +23,6 @@ func GetAllStepMetadata() map[string]config.StepData {
"abapEnvironmentRunATCCheck": abapEnvironmentRunATCCheckMetadata(),
"abapEnvironmentRunAUnitTest": abapEnvironmentRunAUnitTestMetadata(),
"batsExecuteTests": batsExecuteTestsMetadata(),
"checkChangeInDevelopment": checkChangeInDevelopmentMetadata(),
"checkmarxExecuteScan": checkmarxExecuteScanMetadata(),
"cloudFoundryCreateService": cloudFoundryCreateServiceMetadata(),
"cloudFoundryCreateServiceKey": cloudFoundryCreateServiceKeyMetadata(),
@ -59,6 +58,7 @@ func GetAllStepMetadata() map[string]config.StepData {
"integrationArtifactUnDeploy": integrationArtifactUnDeployMetadata(),
"integrationArtifactUpdateConfiguration": integrationArtifactUpdateConfigurationMetadata(),
"integrationArtifactUpload": integrationArtifactUploadMetadata(),
"isChangeInDevelopment": isChangeInDevelopmentMetadata(),
"jsonApplyPatch": jsonApplyPatchMetadata(),
"kanikoExecute": kanikoExecuteMetadata(),
"karmaExecuteTests": karmaExecuteTestsMetadata(),

View File

@ -139,7 +139,7 @@ func Execute() {
rootCmd.AddCommand(CloudFoundryCreateSpaceCommand())
rootCmd.AddCommand(CloudFoundryDeleteSpaceCommand())
rootCmd.AddCommand(VaultRotateSecretIdCommand())
rootCmd.AddCommand(CheckChangeInDevelopmentCommand())
rootCmd.AddCommand(IsChangeInDevelopmentCommand())
rootCmd.AddCommand(TransportRequestUploadCTSCommand())
rootCmd.AddCommand(TransportRequestUploadRFCCommand())
rootCmd.AddCommand(NewmanExecuteCommand())

View File

@ -1,5 +1,5 @@
metadata:
name: checkChangeInDevelopment
name: isChangeInDevelopment
description: "Checks if a certain change is in status 'in development'"
longDescription: |
"Checks if a certain change is in status 'in development'"