github.com/SAP/jenkins-library@v1.362.0/cmd/isChangeInDevelopment.go (about)

     1  package cmd
     2  
     3  import (
     4  	"fmt"
     5  	"strings"
     6  
     7  	"github.com/SAP/jenkins-library/pkg/command"
     8  	"github.com/SAP/jenkins-library/pkg/log"
     9  	"github.com/SAP/jenkins-library/pkg/telemetry"
    10  )
    11  
    12  type isChangeInDevelopmentUtils interface {
    13  	command.ExecRunner
    14  	GetExitCode() int
    15  
    16  	// Add more methods here, or embed additional interfaces, or remove/replace as required.
    17  	// The isChangeInDevelopmentUtils interface should be descriptive of your runtime dependencies,
    18  	// i.e. include everything you need to be able to mock in tests.
    19  	// Unit tests shall be executable in parallel (not depend on global state), and don't (re-)test dependencies.
    20  }
    21  
    22  type isChangeInDevelopmentUtilsBundle struct {
    23  	*command.Command
    24  
    25  	// Embed more structs as necessary to implement methods or interfaces you add to isChangeInDevelopmentUtils.
    26  	// Structs embedded in this way must each have a unique set of methods attached.
    27  	// If there is no struct which implements the method you need, attach the method to
    28  	// isChangeInDevelopmentUtilsBundle and forward to the implementation of the dependency.
    29  }
    30  
    31  func newIsChangeInDevelopmentUtils() isChangeInDevelopmentUtils {
    32  	utils := isChangeInDevelopmentUtilsBundle{
    33  		Command: &command.Command{},
    34  	}
    35  	// Reroute command output to logging framework
    36  	utils.Stdout(log.Writer())
    37  	utils.Stderr(log.Writer())
    38  	return &utils
    39  }
    40  
    41  func isChangeInDevelopment(config isChangeInDevelopmentOptions,
    42  	telemetryData *telemetry.CustomData,
    43  	commonPipelineEnvironment *isChangeInDevelopmentCommonPipelineEnvironment) {
    44  	// Utils can be used wherever the command.ExecRunner interface is expected.
    45  	// It can also be used for example as a mavenExecRunner.
    46  	utils := newIsChangeInDevelopmentUtils()
    47  
    48  	// For HTTP calls import  piperhttp "github.com/SAP/jenkins-library/pkg/http"
    49  	// and use a  &piperhttp.Client{} in a custom system
    50  	// Example: step checkmarxExecuteScan.go
    51  
    52  	// Error situations should be bubbled up until they reach the line below which will then stop execution
    53  	// through the log.Entry().Fatal() call leading to an os.Exit(1) in the end.
    54  	err := runIsChangeInDevelopment(&config, telemetryData, utils, commonPipelineEnvironment)
    55  	if err != nil {
    56  		log.Entry().WithError(err).Fatal("step execution failed")
    57  	}
    58  }
    59  
    60  func runIsChangeInDevelopment(config *isChangeInDevelopmentOptions,
    61  	telemetryData *telemetry.CustomData,
    62  	utils isChangeInDevelopmentUtils,
    63  	commonPipelineEnvironment *isChangeInDevelopmentCommonPipelineEnvironment) error {
    64  
    65  	log.Entry().Infof("Checking change status for change '%s'", config.ChangeDocumentID)
    66  
    67  	isInDevelopment, err := perform(config, utils)
    68  
    69  	if err != nil {
    70  		return err
    71  	}
    72  
    73  	commonPipelineEnvironment.custom.isChangeInDevelopment = isInDevelopment
    74  
    75  	if isInDevelopment {
    76  		log.Entry().Infof("Change '%s' is in status 'in development'.", config.ChangeDocumentID)
    77  		return nil
    78  	}
    79  	if config.FailIfStatusIsNotInDevelopment {
    80  		return fmt.Errorf("change '%s' is not in status 'in development'", config.ChangeDocumentID)
    81  	}
    82  	log.Entry().Warningf("Change '%s' is not in status 'in development'. Failing the step has been explicitly disabled.", config.ChangeDocumentID)
    83  	return nil
    84  }
    85  
    86  func perform(config *isChangeInDevelopmentOptions, utils isChangeInDevelopmentUtils) (bool, error) {
    87  
    88  	if len(config.CmClientOpts) > 0 {
    89  		utils.AppendEnv([]string{fmt.Sprintf("CMCLIENT_OPTS=%s", strings.Join(config.CmClientOpts, " "))})
    90  	}
    91  
    92  	err := utils.RunExecutable("cmclient",
    93  		"--endpoint", config.Endpoint,
    94  		"--user", config.Username,
    95  		"--password", config.Password,
    96  		"is-change-in-development",
    97  		"--change-id", config.ChangeDocumentID,
    98  		"--return-code")
    99  
   100  	exitCode := utils.GetExitCode()
   101  
   102  	hint := "check log for details"
   103  	if err != nil {
   104  		hint = err.Error()
   105  	}
   106  
   107  	if exitCode == 0 {
   108  		return true, nil
   109  	} else if exitCode == 3 {
   110  		return false, nil
   111  	} else if exitCode == 2 {
   112  		hint = "invalid credentials"
   113  	}
   114  
   115  	return false, fmt.Errorf("cannot retrieve change status: %s", hint)
   116  }