github.com/jaylevin/jenkins-library@v1.230.4/cmd/checkIfStepActive.go (about)

     1  package cmd
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"io"
     7  	"os"
     8  
     9  	"github.com/SAP/jenkins-library/pkg/config"
    10  	"github.com/SAP/jenkins-library/pkg/log"
    11  	"github.com/SAP/jenkins-library/pkg/piperutils"
    12  	"github.com/bmatcuk/doublestar"
    13  	"github.com/pkg/errors"
    14  	"github.com/spf13/cobra"
    15  )
    16  
    17  type checkStepActiveCommandOptions struct {
    18  	openFile        func(s string, t map[string]string) (io.ReadCloser, error)
    19  	stageConfigFile string
    20  	stepName        string
    21  	stageName       string
    22  	v1Active        bool
    23  	stageOutputFile string
    24  	stepOutputFile  string
    25  }
    26  
    27  var checkStepActiveOptions checkStepActiveCommandOptions
    28  
    29  // CheckStepActiveCommand is the entry command for checking if a step is active in a defined stage
    30  func CheckStepActiveCommand() *cobra.Command {
    31  	checkStepActiveOptions.openFile = config.OpenPiperFile
    32  	var checkStepActiveCmd = &cobra.Command{
    33  		Use:   "checkIfStepActive",
    34  		Short: "Checks if a step is active in a defined stage.",
    35  		PreRun: func(cmd *cobra.Command, _ []string) {
    36  			path, _ := os.Getwd()
    37  			fatalHook := &log.FatalHook{CorrelationID: GeneralConfig.CorrelationID, Path: path}
    38  			log.RegisterHook(fatalHook)
    39  			initStageName(false)
    40  			log.SetVerbose(GeneralConfig.Verbose)
    41  			GeneralConfig.GitHubAccessTokens = ResolveAccessTokens(GeneralConfig.GitHubTokens)
    42  		},
    43  		Run: func(cmd *cobra.Command, _ []string) {
    44  			utils := &piperutils.Files{}
    45  			err := checkIfStepActive(utils)
    46  			if err != nil {
    47  				log.SetErrorCategory(log.ErrorConfiguration)
    48  				log.Entry().WithError(err).Fatal("Checking for an active step failed")
    49  			}
    50  		},
    51  	}
    52  	addCheckStepActiveFlags(checkStepActiveCmd)
    53  	return checkStepActiveCmd
    54  }
    55  
    56  func checkIfStepActive(utils piperutils.FileUtils) error {
    57  	// make the stageName the leading parameter
    58  	if len(checkStepActiveOptions.stageName) == 0 && GeneralConfig.StageName != "" {
    59  		checkStepActiveOptions.stageName = GeneralConfig.StageName
    60  	}
    61  	if checkStepActiveOptions.stageName == "" {
    62  		return errors.New("stage name must not be empty")
    63  	}
    64  	var pConfig config.Config
    65  
    66  	// load project config and defaults
    67  	projectConfig, err := initializeConfig(&pConfig)
    68  	if err != nil {
    69  		log.Entry().Errorf("Failed to load project config: %v", err)
    70  	}
    71  
    72  	stageConfigFile, err := checkStepActiveOptions.openFile(checkStepActiveOptions.stageConfigFile, GeneralConfig.GitHubAccessTokens)
    73  	if err != nil {
    74  		return errors.Wrapf(err, "config: open stage configuration file '%v' failed", checkStepActiveOptions.stageConfigFile)
    75  	}
    76  	defer stageConfigFile.Close()
    77  
    78  	runSteps := map[string]map[string]bool{}
    79  	runStages := map[string]bool{}
    80  
    81  	// load and evaluate step conditions
    82  	if checkStepActiveOptions.v1Active {
    83  		runConfig := config.RunConfig{StageConfigFile: stageConfigFile}
    84  		runConfigV1 := &config.RunConfigV1{RunConfig: runConfig}
    85  		err = runConfigV1.InitRunConfigV1(projectConfig, nil, nil, nil, nil, utils, GeneralConfig.EnvRootPath)
    86  		if err != nil {
    87  			return err
    88  		}
    89  		runSteps = runConfigV1.RunSteps
    90  		runStages = runConfigV1.RunStages
    91  	} else {
    92  		runConfig := &config.RunConfig{StageConfigFile: stageConfigFile}
    93  		err = runConfig.InitRunConfig(projectConfig, nil, nil, nil, nil, doublestar.Glob, checkStepActiveOptions.openFile)
    94  		if err != nil {
    95  			return err
    96  		}
    97  		runSteps = runConfig.RunSteps
    98  		runStages = runConfig.RunStages
    99  	}
   100  
   101  	log.Entry().Debugf("RunSteps: %v", runSteps)
   102  	log.Entry().Debugf("RunStages: %v", runStages)
   103  
   104  	if len(checkStepActiveOptions.stageOutputFile) > 0 || len(checkStepActiveOptions.stepOutputFile) > 0 {
   105  		if len(checkStepActiveOptions.stageOutputFile) > 0 {
   106  			result, err := json.Marshal(runStages)
   107  			if err != nil {
   108  				return fmt.Errorf("error marshalling json: %w", err)
   109  			}
   110  			log.Entry().Infof("Writing stage condition file %v", checkStepActiveOptions.stageOutputFile)
   111  			err = utils.FileWrite(checkStepActiveOptions.stageOutputFile, result, 0666)
   112  			if err != nil {
   113  				return fmt.Errorf("error writing file '%v': %w", checkStepActiveOptions.stageOutputFile, err)
   114  			}
   115  		}
   116  
   117  		if len(checkStepActiveOptions.stepOutputFile) > 0 {
   118  			result, err := json.Marshal(runSteps)
   119  			if err != nil {
   120  				return fmt.Errorf("error marshalling json: %w", err)
   121  			}
   122  			log.Entry().Infof("Writing step condition file %v", checkStepActiveOptions.stepOutputFile)
   123  			err = utils.FileWrite(checkStepActiveOptions.stepOutputFile, result, 0666)
   124  			if err != nil {
   125  				return fmt.Errorf("error writing file '%v': %w", checkStepActiveOptions.stepOutputFile, err)
   126  			}
   127  		}
   128  
   129  		// do not perform a check if output files are written
   130  		return nil
   131  	}
   132  
   133  	if !runSteps[checkStepActiveOptions.stageName][checkStepActiveOptions.stepName] {
   134  		return errors.Errorf("Step %s in stage %s is not active", checkStepActiveOptions.stepName, checkStepActiveOptions.stageName)
   135  	}
   136  	log.Entry().Infof("Step %s in stage %s is active", checkStepActiveOptions.stepName, checkStepActiveOptions.stageName)
   137  
   138  	return nil
   139  }
   140  
   141  func addCheckStepActiveFlags(cmd *cobra.Command) {
   142  	cmd.Flags().StringVar(&checkStepActiveOptions.stageConfigFile, "stageConfig", ".resources/piper-stage-config.yml",
   143  		"Default config of piper pipeline stages")
   144  	cmd.Flags().StringVar(&checkStepActiveOptions.stepName, "step", "", "Name of the step being checked")
   145  	cmd.Flags().StringVar(&checkStepActiveOptions.stageName, "stage", "", "Name of the stage in which contains the step being checked")
   146  	cmd.Flags().BoolVar(&checkStepActiveOptions.v1Active, "useV1", false, "Use new CRD-style stage configuration")
   147  	cmd.Flags().StringVar(&checkStepActiveOptions.stageOutputFile, "stageOutputFile", "", "Defines a file path. If set, the stage output will be written to the defined file")
   148  	cmd.Flags().StringVar(&checkStepActiveOptions.stepOutputFile, "stepOutputFile", "", "Defines a file path. If set, the step output will be written to the defined file")
   149  	cmd.MarkFlagRequired("step")
   150  }
   151  
   152  func initializeConfig(pConfig *config.Config) (*config.Config, error) {
   153  	projectConfigFile := getProjectConfigFile(GeneralConfig.CustomConfig)
   154  	customConfig, err := checkStepActiveOptions.openFile(projectConfigFile, GeneralConfig.GitHubAccessTokens)
   155  	if err != nil {
   156  		return nil, errors.Wrapf(err, "config: open configuration file '%v' failed", projectConfigFile)
   157  	}
   158  	defer customConfig.Close()
   159  
   160  	defaultConfig := []io.ReadCloser{}
   161  	for _, f := range GeneralConfig.DefaultConfig {
   162  		fc, err := checkStepActiveOptions.openFile(f, GeneralConfig.GitHubAccessTokens)
   163  		// only create error for non-default values
   164  		if err != nil && f != ".pipeline/defaults.yaml" {
   165  			return nil, errors.Wrapf(err, "config: getting defaults failed: '%v'", f)
   166  		}
   167  		if err == nil {
   168  			defaultConfig = append(defaultConfig, fc)
   169  		}
   170  	}
   171  	var flags map[string]interface{}
   172  	filter := config.StepFilters{
   173  		All:     []string{},
   174  		General: []string{},
   175  		Stages:  []string{},
   176  		Steps:   []string{},
   177  		Env:     []string{},
   178  	}
   179  
   180  	_, err = pConfig.GetStepConfig(flags, "", customConfig, defaultConfig, GeneralConfig.IgnoreCustomDefaults, filter, config.StepData{}, nil, "", "")
   181  	if err != nil {
   182  		return nil, errors.Wrap(err, "getting step config failed")
   183  	}
   184  	return pConfig, nil
   185  }