github.com/xgoffin/jenkins-library@v1.154.0/cmd/npmExecuteScripts_generated.go (about)

     1  // Code generated by piper's step-generator. DO NOT EDIT.
     2  
     3  package cmd
     4  
     5  import (
     6  	"fmt"
     7  	"os"
     8  	"path/filepath"
     9  	"reflect"
    10  	"strings"
    11  	"time"
    12  
    13  	"github.com/SAP/jenkins-library/pkg/config"
    14  	"github.com/SAP/jenkins-library/pkg/gcs"
    15  	"github.com/SAP/jenkins-library/pkg/log"
    16  	"github.com/SAP/jenkins-library/pkg/piperenv"
    17  	"github.com/SAP/jenkins-library/pkg/splunk"
    18  	"github.com/SAP/jenkins-library/pkg/telemetry"
    19  	"github.com/SAP/jenkins-library/pkg/validation"
    20  	"github.com/bmatcuk/doublestar"
    21  	"github.com/spf13/cobra"
    22  )
    23  
    24  type npmExecuteScriptsOptions struct {
    25  	Install                    bool     `json:"install,omitempty"`
    26  	RunScripts                 []string `json:"runScripts,omitempty"`
    27  	DefaultNpmRegistry         string   `json:"defaultNpmRegistry,omitempty"`
    28  	VirtualFrameBuffer         bool     `json:"virtualFrameBuffer,omitempty"`
    29  	ScriptOptions              []string `json:"scriptOptions,omitempty"`
    30  	BuildDescriptorExcludeList []string `json:"buildDescriptorExcludeList,omitempty"`
    31  	BuildDescriptorList        []string `json:"buildDescriptorList,omitempty"`
    32  	CreateBOM                  bool     `json:"createBOM,omitempty"`
    33  	Publish                    bool     `json:"publish,omitempty"`
    34  	RepositoryURL              string   `json:"repositoryUrl,omitempty"`
    35  	RepositoryPassword         string   `json:"repositoryPassword,omitempty"`
    36  	RepositoryUsername         string   `json:"repositoryUsername,omitempty"`
    37  	BuildSettingsInfo          string   `json:"buildSettingsInfo,omitempty"`
    38  	PackBeforePublish          bool     `json:"packBeforePublish,omitempty"`
    39  }
    40  
    41  type npmExecuteScriptsCommonPipelineEnvironment struct {
    42  	custom struct {
    43  		buildSettingsInfo string
    44  	}
    45  }
    46  
    47  func (p *npmExecuteScriptsCommonPipelineEnvironment) persist(path, resourceName string) {
    48  	content := []struct {
    49  		category string
    50  		name     string
    51  		value    interface{}
    52  	}{
    53  		{category: "custom", name: "buildSettingsInfo", value: p.custom.buildSettingsInfo},
    54  	}
    55  
    56  	errCount := 0
    57  	for _, param := range content {
    58  		err := piperenv.SetResourceParameter(path, resourceName, filepath.Join(param.category, param.name), param.value)
    59  		if err != nil {
    60  			log.Entry().WithError(err).Error("Error persisting piper environment.")
    61  			errCount++
    62  		}
    63  	}
    64  	if errCount > 0 {
    65  		log.Entry().Error("failed to persist Piper environment")
    66  	}
    67  }
    68  
    69  type npmExecuteScriptsReports struct {
    70  }
    71  
    72  func (p *npmExecuteScriptsReports) persist(stepConfig npmExecuteScriptsOptions, gcpJsonKeyFilePath string, gcsBucketId string, gcsFolderPath string, gcsSubFolder string) {
    73  	if gcsBucketId == "" {
    74  		log.Entry().Info("persisting reports to GCS is disabled, because gcsBucketId is empty")
    75  		return
    76  	}
    77  	log.Entry().Info("Uploading reports to Google Cloud Storage...")
    78  	content := []gcs.ReportOutputParam{
    79  		{FilePattern: "**/bom.xml", ParamRef: "", StepResultType: "sbom"},
    80  		{FilePattern: "**/TEST-*.xml", ParamRef: "", StepResultType: "junit"},
    81  		{FilePattern: "**/cobertura-coverage.xml", ParamRef: "", StepResultType: "cobertura-coverage"},
    82  		{FilePattern: "**/e2e/*.json", ParamRef: "", StepResultType: "cucumber"},
    83  	}
    84  	envVars := []gcs.EnvVar{
    85  		{Name: "GOOGLE_APPLICATION_CREDENTIALS", Value: gcpJsonKeyFilePath, Modified: false},
    86  	}
    87  	gcsClient, err := gcs.NewClient(gcs.WithEnvVars(envVars))
    88  	if err != nil {
    89  		log.Entry().Errorf("creation of GCS client failed: %v", err)
    90  		return
    91  	}
    92  	defer gcsClient.Close()
    93  	structVal := reflect.ValueOf(&stepConfig).Elem()
    94  	inputParameters := map[string]string{}
    95  	for i := 0; i < structVal.NumField(); i++ {
    96  		field := structVal.Type().Field(i)
    97  		if field.Type.String() == "string" {
    98  			paramName := strings.Split(field.Tag.Get("json"), ",")
    99  			paramValue, _ := structVal.Field(i).Interface().(string)
   100  			inputParameters[paramName[0]] = paramValue
   101  		}
   102  	}
   103  	if err := gcs.PersistReportsToGCS(gcsClient, content, inputParameters, gcsFolderPath, gcsBucketId, gcsSubFolder, doublestar.Glob, os.Stat); err != nil {
   104  		log.Entry().Errorf("failed to persist reports: %v", err)
   105  	}
   106  }
   107  
   108  // NpmExecuteScriptsCommand Execute npm run scripts on all npm packages in a project
   109  func NpmExecuteScriptsCommand() *cobra.Command {
   110  	const STEP_NAME = "npmExecuteScripts"
   111  
   112  	metadata := npmExecuteScriptsMetadata()
   113  	var stepConfig npmExecuteScriptsOptions
   114  	var startTime time.Time
   115  	var commonPipelineEnvironment npmExecuteScriptsCommonPipelineEnvironment
   116  	var reports npmExecuteScriptsReports
   117  	var logCollector *log.CollectorHook
   118  	var splunkClient *splunk.Splunk
   119  	telemetryClient := &telemetry.Telemetry{}
   120  
   121  	var createNpmExecuteScriptsCmd = &cobra.Command{
   122  		Use:   STEP_NAME,
   123  		Short: "Execute npm run scripts on all npm packages in a project",
   124  		Long: `Execute npm run scripts in all package json files, if they implement the scripts.
   125  
   126  ### build with depedencies from a private repository
   127  if your build has scoped/unscoped dependencies from a private repository you can include a .npmrc into the source code
   128  repository as below (replace the ` + "`" + `@privateScope:registry` + "`" + ` value(s) with a valid private repo url) :
   129  
   130  ` + "`" + `` + "`" + `` + "`" + `
   131  @privateScope:registry=https://private.repository.com/
   132  //private.repository.com/:username=${PIPER_VAULTCREDENTIAL_USER}
   133  //private.repository.com/:_password=${PIPER_VAULTCREDENTIAL_PASSWORD_BASE64}
   134  //private.repository.com/:always-auth=true
   135  registry=https://registry.npmjs.org
   136  ` + "`" + `` + "`" + `` + "`" + `
   137  ` + "`" + `PIPER_VAULTCREDENTIAL_USER` + "`" + ` and ` + "`" + `PIPER_VAULTCREDENTIAL_PASSWORD_BASE64` + "`" + ` (Base64 encoded password) are the username and password for the private repository
   138  and are exposed are environment variables that must be present in the environment where the Piper step runs or alternatively can be created using :
   139  [vault general purpose credentials](../infrastructure/vault.md#using-vault-for-general-purpose-and-test-credentials)`,
   140  		PreRunE: func(cmd *cobra.Command, _ []string) error {
   141  			startTime = time.Now()
   142  			log.SetStepName(STEP_NAME)
   143  			log.SetVerbose(GeneralConfig.Verbose)
   144  
   145  			GeneralConfig.GitHubAccessTokens = ResolveAccessTokens(GeneralConfig.GitHubTokens)
   146  
   147  			path, _ := os.Getwd()
   148  			fatalHook := &log.FatalHook{CorrelationID: GeneralConfig.CorrelationID, Path: path}
   149  			log.RegisterHook(fatalHook)
   150  
   151  			err := PrepareConfig(cmd, &metadata, STEP_NAME, &stepConfig, config.OpenPiperFile)
   152  			if err != nil {
   153  				log.SetErrorCategory(log.ErrorConfiguration)
   154  				return err
   155  			}
   156  			log.RegisterSecret(stepConfig.RepositoryPassword)
   157  			log.RegisterSecret(stepConfig.RepositoryUsername)
   158  
   159  			if len(GeneralConfig.HookConfig.SentryConfig.Dsn) > 0 {
   160  				sentryHook := log.NewSentryHook(GeneralConfig.HookConfig.SentryConfig.Dsn, GeneralConfig.CorrelationID)
   161  				log.RegisterHook(&sentryHook)
   162  			}
   163  
   164  			if len(GeneralConfig.HookConfig.SplunkConfig.Dsn) > 0 {
   165  				splunkClient = &splunk.Splunk{}
   166  				logCollector = &log.CollectorHook{CorrelationID: GeneralConfig.CorrelationID}
   167  				log.RegisterHook(logCollector)
   168  			}
   169  
   170  			validation, err := validation.New(validation.WithJSONNamesForStructFields(), validation.WithPredefinedErrorMessages())
   171  			if err != nil {
   172  				return err
   173  			}
   174  			if err = validation.ValidateStruct(stepConfig); err != nil {
   175  				log.SetErrorCategory(log.ErrorConfiguration)
   176  				return err
   177  			}
   178  
   179  			return nil
   180  		},
   181  		Run: func(_ *cobra.Command, _ []string) {
   182  			stepTelemetryData := telemetry.CustomData{}
   183  			stepTelemetryData.ErrorCode = "1"
   184  			handler := func() {
   185  				commonPipelineEnvironment.persist(GeneralConfig.EnvRootPath, "commonPipelineEnvironment")
   186  				reports.persist(stepConfig, GeneralConfig.GCPJsonKeyFilePath, GeneralConfig.GCSBucketId, GeneralConfig.GCSFolderPath, GeneralConfig.GCSSubFolder)
   187  				config.RemoveVaultSecretFiles()
   188  				stepTelemetryData.Duration = fmt.Sprintf("%v", time.Since(startTime).Milliseconds())
   189  				stepTelemetryData.ErrorCategory = log.GetErrorCategory().String()
   190  				stepTelemetryData.PiperCommitHash = GitCommit
   191  				telemetryClient.SetData(&stepTelemetryData)
   192  				telemetryClient.Send()
   193  				if len(GeneralConfig.HookConfig.SplunkConfig.Dsn) > 0 {
   194  					splunkClient.Send(telemetryClient.GetData(), logCollector)
   195  				}
   196  			}
   197  			log.DeferExitHandler(handler)
   198  			defer handler()
   199  			telemetryClient.Initialize(GeneralConfig.NoTelemetry, STEP_NAME)
   200  			if len(GeneralConfig.HookConfig.SplunkConfig.Dsn) > 0 {
   201  				splunkClient.Initialize(GeneralConfig.CorrelationID,
   202  					GeneralConfig.HookConfig.SplunkConfig.Dsn,
   203  					GeneralConfig.HookConfig.SplunkConfig.Token,
   204  					GeneralConfig.HookConfig.SplunkConfig.Index,
   205  					GeneralConfig.HookConfig.SplunkConfig.SendLogs)
   206  			}
   207  			npmExecuteScripts(stepConfig, &stepTelemetryData, &commonPipelineEnvironment)
   208  			stepTelemetryData.ErrorCode = "0"
   209  			log.Entry().Info("SUCCESS")
   210  		},
   211  	}
   212  
   213  	addNpmExecuteScriptsFlags(createNpmExecuteScriptsCmd, &stepConfig)
   214  	return createNpmExecuteScriptsCmd
   215  }
   216  
   217  func addNpmExecuteScriptsFlags(cmd *cobra.Command, stepConfig *npmExecuteScriptsOptions) {
   218  	cmd.Flags().BoolVar(&stepConfig.Install, "install", true, "Run npm install or similar commands depending on the project structure.")
   219  	cmd.Flags().StringSliceVar(&stepConfig.RunScripts, "runScripts", []string{}, "List of additional run scripts to execute from package.json.")
   220  	cmd.Flags().StringVar(&stepConfig.DefaultNpmRegistry, "defaultNpmRegistry", os.Getenv("PIPER_defaultNpmRegistry"), "URL of the npm registry to use. Defaults to https://registry.npmjs.org/")
   221  	cmd.Flags().BoolVar(&stepConfig.VirtualFrameBuffer, "virtualFrameBuffer", false, "(Linux only) Start a virtual frame buffer in the background. This allows you to run a web browser without the need for an X server. Note that xvfb needs to be installed in the execution environment.")
   222  	cmd.Flags().StringSliceVar(&stepConfig.ScriptOptions, "scriptOptions", []string{}, "Options are passed to all runScripts calls separated by a '--'. './piper npmExecuteScripts --runScripts ci-e2e --scriptOptions '--tag1' will correspond to 'npm run ci-e2e -- --tag1'")
   223  	cmd.Flags().StringSliceVar(&stepConfig.BuildDescriptorExcludeList, "buildDescriptorExcludeList", []string{`deployment/**`}, "List of build descriptors and therefore modules to exclude from execution of the npm scripts. The elements can either be a path to the build descriptor or a pattern.")
   224  	cmd.Flags().StringSliceVar(&stepConfig.BuildDescriptorList, "buildDescriptorList", []string{}, "List of build descriptors and therefore modules for execution of the npm scripts. The elements have to be paths to the build descriptors. **If set, buildDescriptorExcludeList will be ignored.**")
   225  	cmd.Flags().BoolVar(&stepConfig.CreateBOM, "createBOM", false, "Create a BOM xml using CycloneDX.")
   226  	cmd.Flags().BoolVar(&stepConfig.Publish, "publish", false, "Configures npm to publish the artifact to a repository.")
   227  	cmd.Flags().StringVar(&stepConfig.RepositoryURL, "repositoryUrl", os.Getenv("PIPER_repositoryUrl"), "Url to the repository to which the project artifacts should be published.")
   228  	cmd.Flags().StringVar(&stepConfig.RepositoryPassword, "repositoryPassword", os.Getenv("PIPER_repositoryPassword"), "Password for the repository to which the project artifacts should be published.")
   229  	cmd.Flags().StringVar(&stepConfig.RepositoryUsername, "repositoryUsername", os.Getenv("PIPER_repositoryUsername"), "Username for the repository to which the project artifacts should be published.")
   230  	cmd.Flags().StringVar(&stepConfig.BuildSettingsInfo, "buildSettingsInfo", os.Getenv("PIPER_buildSettingsInfo"), "build settings info is typically filled by the step automatically to create information about the build settings that were used during the npm build . This information is typically used for compliance related processes.")
   231  	cmd.Flags().BoolVar(&stepConfig.PackBeforePublish, "packBeforePublish", false, "used for executing npm pack first, followed by npm publish. This two step maybe required when you are building a scoped packages and have npm dependencies from the same scope")
   232  
   233  }
   234  
   235  // retrieve step metadata
   236  func npmExecuteScriptsMetadata() config.StepData {
   237  	var theMetaData = config.StepData{
   238  		Metadata: config.StepMetadata{
   239  			Name:        "npmExecuteScripts",
   240  			Aliases:     []config.Alias{{Name: "executeNpm", Deprecated: false}},
   241  			Description: "Execute npm run scripts on all npm packages in a project",
   242  		},
   243  		Spec: config.StepSpec{
   244  			Inputs: config.StepInputs{
   245  				Resources: []config.StepResources{
   246  					{Name: "source", Type: "stash"},
   247  				},
   248  				Parameters: []config.StepParameters{
   249  					{
   250  						Name:        "install",
   251  						ResourceRef: []config.ResourceReference{},
   252  						Scope:       []string{"PARAMETERS", "STAGES", "STEPS"},
   253  						Type:        "bool",
   254  						Mandatory:   false,
   255  						Aliases:     []config.Alias{},
   256  						Default:     true,
   257  					},
   258  					{
   259  						Name:        "runScripts",
   260  						ResourceRef: []config.ResourceReference{},
   261  						Scope:       []string{"PARAMETERS", "STAGES", "STEPS"},
   262  						Type:        "[]string",
   263  						Mandatory:   false,
   264  						Aliases:     []config.Alias{},
   265  						Default:     []string{},
   266  					},
   267  					{
   268  						Name:        "defaultNpmRegistry",
   269  						ResourceRef: []config.ResourceReference{},
   270  						Scope:       []string{"PARAMETERS", "GENERAL", "STAGES", "STEPS"},
   271  						Type:        "string",
   272  						Mandatory:   false,
   273  						Aliases:     []config.Alias{{Name: "npm/defaultNpmRegistry"}},
   274  						Default:     os.Getenv("PIPER_defaultNpmRegistry"),
   275  					},
   276  					{
   277  						Name:        "virtualFrameBuffer",
   278  						ResourceRef: []config.ResourceReference{},
   279  						Scope:       []string{"PARAMETERS", "STAGES", "STEPS"},
   280  						Type:        "bool",
   281  						Mandatory:   false,
   282  						Aliases:     []config.Alias{},
   283  						Default:     false,
   284  					},
   285  					{
   286  						Name:        "scriptOptions",
   287  						ResourceRef: []config.ResourceReference{},
   288  						Scope:       []string{"PARAMETERS", "STAGES", "STEPS"},
   289  						Type:        "[]string",
   290  						Mandatory:   false,
   291  						Aliases:     []config.Alias{},
   292  						Default:     []string{},
   293  					},
   294  					{
   295  						Name:        "buildDescriptorExcludeList",
   296  						ResourceRef: []config.ResourceReference{},
   297  						Scope:       []string{"PARAMETERS", "STAGES", "STEPS"},
   298  						Type:        "[]string",
   299  						Mandatory:   false,
   300  						Aliases:     []config.Alias{},
   301  						Default:     []string{`deployment/**`},
   302  					},
   303  					{
   304  						Name:        "buildDescriptorList",
   305  						ResourceRef: []config.ResourceReference{},
   306  						Scope:       []string{"PARAMETERS", "STAGES", "STEPS"},
   307  						Type:        "[]string",
   308  						Mandatory:   false,
   309  						Aliases:     []config.Alias{},
   310  						Default:     []string{},
   311  					},
   312  					{
   313  						Name:        "createBOM",
   314  						ResourceRef: []config.ResourceReference{},
   315  						Scope:       []string{"GENERAL", "STEPS", "STAGES", "PARAMETERS"},
   316  						Type:        "bool",
   317  						Mandatory:   false,
   318  						Aliases:     []config.Alias{},
   319  						Default:     false,
   320  					},
   321  					{
   322  						Name:        "publish",
   323  						ResourceRef: []config.ResourceReference{},
   324  						Scope:       []string{"STEPS", "STAGES", "PARAMETERS"},
   325  						Type:        "bool",
   326  						Mandatory:   false,
   327  						Aliases:     []config.Alias{},
   328  						Default:     false,
   329  					},
   330  					{
   331  						Name: "repositoryUrl",
   332  						ResourceRef: []config.ResourceReference{
   333  							{
   334  								Name:  "commonPipelineEnvironment",
   335  								Param: "custom/npmRepositoryURL",
   336  							},
   337  
   338  							{
   339  								Name:  "commonPipelineEnvironment",
   340  								Param: "custom/repositoryUrl",
   341  							},
   342  						},
   343  						Scope:     []string{"GENERAL", "PARAMETERS", "STAGES", "STEPS"},
   344  						Type:      "string",
   345  						Mandatory: false,
   346  						Aliases:   []config.Alias{},
   347  						Default:   os.Getenv("PIPER_repositoryUrl"),
   348  					},
   349  					{
   350  						Name: "repositoryPassword",
   351  						ResourceRef: []config.ResourceReference{
   352  							{
   353  								Name:  "commonPipelineEnvironment",
   354  								Param: "custom/npmRepositoryPassword",
   355  							},
   356  
   357  							{
   358  								Name:  "commonPipelineEnvironment",
   359  								Param: "custom/repositoryPassword",
   360  							},
   361  						},
   362  						Scope:     []string{"GENERAL", "PARAMETERS", "STAGES", "STEPS"},
   363  						Type:      "string",
   364  						Mandatory: false,
   365  						Aliases:   []config.Alias{},
   366  						Default:   os.Getenv("PIPER_repositoryPassword"),
   367  					},
   368  					{
   369  						Name: "repositoryUsername",
   370  						ResourceRef: []config.ResourceReference{
   371  							{
   372  								Name:  "commonPipelineEnvironment",
   373  								Param: "custom/npmRepositoryUsername",
   374  							},
   375  
   376  							{
   377  								Name:  "commonPipelineEnvironment",
   378  								Param: "custom/repositoryUsername",
   379  							},
   380  						},
   381  						Scope:     []string{"GENERAL", "PARAMETERS", "STAGES", "STEPS"},
   382  						Type:      "string",
   383  						Mandatory: false,
   384  						Aliases:   []config.Alias{},
   385  						Default:   os.Getenv("PIPER_repositoryUsername"),
   386  					},
   387  					{
   388  						Name: "buildSettingsInfo",
   389  						ResourceRef: []config.ResourceReference{
   390  							{
   391  								Name:  "commonPipelineEnvironment",
   392  								Param: "custom/buildSettingsInfo",
   393  							},
   394  						},
   395  						Scope:     []string{"STEPS", "STAGES", "PARAMETERS"},
   396  						Type:      "string",
   397  						Mandatory: false,
   398  						Aliases:   []config.Alias{},
   399  						Default:   os.Getenv("PIPER_buildSettingsInfo"),
   400  					},
   401  					{
   402  						Name:        "packBeforePublish",
   403  						ResourceRef: []config.ResourceReference{},
   404  						Scope:       []string{"STEPS", "STAGES", "PARAMETERS"},
   405  						Type:        "bool",
   406  						Mandatory:   false,
   407  						Aliases:     []config.Alias{},
   408  						Default:     false,
   409  					},
   410  				},
   411  			},
   412  			Containers: []config.Container{
   413  				{Name: "node", Image: "node:lts-stretch"},
   414  			},
   415  			Outputs: config.StepOutputs{
   416  				Resources: []config.StepResources{
   417  					{
   418  						Name: "commonPipelineEnvironment",
   419  						Type: "piperEnvironment",
   420  						Parameters: []map[string]interface{}{
   421  							{"name": "custom/buildSettingsInfo"},
   422  						},
   423  					},
   424  					{
   425  						Name: "reports",
   426  						Type: "reports",
   427  						Parameters: []map[string]interface{}{
   428  							{"filePattern": "**/bom.xml", "type": "sbom"},
   429  							{"filePattern": "**/TEST-*.xml", "type": "junit"},
   430  							{"filePattern": "**/cobertura-coverage.xml", "type": "cobertura-coverage"},
   431  							{"filePattern": "**/e2e/*.json", "type": "cucumber"},
   432  						},
   433  					},
   434  				},
   435  			},
   436  		},
   437  	}
   438  	return theMetaData
   439  }