1
0
mirror of https://github.com/SAP/jenkins-library.git synced 2025-09-16 09:26:22 +02:00

NpmExecuteScripts add script options (#1780)

This commit is contained in:
Daniel Kurzynski
2020-07-09 14:57:41 +02:00
committed by GitHub
parent fb3c6b5978
commit fbf2b29a32
11 changed files with 117 additions and 11 deletions

View File

@@ -100,7 +100,7 @@ func runCiLint(npmExecutor npm.Executor, failOnError bool) error {
runScripts := []string{"ci-lint"}
runOptions := []string{"--silent"}
err := npmExecutor.RunScriptsInAllPackages(runScripts, runOptions, false)
err := npmExecutor.RunScriptsInAllPackages(runScripts, runOptions, nil, false)
if err != nil {
if failOnError {
return fmt.Errorf("ci-lint script execution failed with error: %w. This might be the result of severe linting findings, or some other issue while executing the script. Please examine the linting results in the UI, the cilint.xml file, if available, or the log above. ", err)

View File

@@ -26,5 +26,5 @@ func runNpmExecuteScripts(npmExecutor npm.Executor, config *npmExecuteScriptsOpt
}
}
return npmExecutor.RunScriptsInAllPackages(config.RunScripts, nil, config.VirtualFrameBuffer)
return npmExecutor.RunScriptsInAllPackages(config.RunScripts, nil, config.ScriptOptions, config.VirtualFrameBuffer)
}

View File

@@ -19,6 +19,7 @@ type npmExecuteScriptsOptions struct {
DefaultNpmRegistry string `json:"defaultNpmRegistry,omitempty"`
SapNpmRegistry string `json:"sapNpmRegistry,omitempty"`
VirtualFrameBuffer bool `json:"virtualFrameBuffer,omitempty"`
ScriptOptions []string `json:"scriptOptions,omitempty"`
}
// NpmExecuteScriptsCommand Execute npm run scripts on all npm packages in a project
@@ -81,6 +82,7 @@ func addNpmExecuteScriptsFlags(cmd *cobra.Command, stepConfig *npmExecuteScripts
cmd.Flags().StringVar(&stepConfig.DefaultNpmRegistry, "defaultNpmRegistry", os.Getenv("PIPER_defaultNpmRegistry"), "URL of the npm registry to use. Defaults to https://registry.npmjs.org/")
cmd.Flags().StringVar(&stepConfig.SapNpmRegistry, "sapNpmRegistry", `https://npm.sap.com`, "The default npm registry URL to be used as the remote mirror for the SAP npm packages.")
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.")
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'")
}
@@ -134,6 +136,14 @@ func npmExecuteScriptsMetadata() config.StepData {
Mandatory: false,
Aliases: []config.Alias{},
},
{
Name: "scriptOptions",
ResourceRef: []config.ResourceReference{},
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
Type: "[]string",
Mandatory: false,
Aliases: []config.Alias{},
},
},
},
},

View File

@@ -30,6 +30,7 @@ type npmConfig struct {
install bool
runScripts []string
runOptions []string
scriptOptions []string
virtualFrameBuffer bool
}
@@ -51,7 +52,7 @@ func (n *npmExecutorMock) FindPackageJSONFilesWithScript(packageJSONFiles []stri
}
// RunScriptsInAllPackages mock implementation
func (n *npmExecutorMock) RunScriptsInAllPackages(runScripts []string, runOptions []string, virtualFrameBuffer bool) error {
func (n *npmExecutorMock) RunScriptsInAllPackages(runScripts []string, runOptions []string, scriptOptions []string, virtualFrameBuffer bool) error {
if len(runScripts) != len(n.config.runScripts) {
return fmt.Errorf("RunScriptsInAllPackages was called with a different list of runScripts than config.runScripts")
}
@@ -61,6 +62,10 @@ func (n *npmExecutorMock) RunScriptsInAllPackages(runScripts []string, runOption
}
}
if len(scriptOptions) != len(n.config.scriptOptions) {
return fmt.Errorf("RunScriptsInAllPackages was called with a different list of runOptions than config.scriptOptions")
}
if len(runOptions) != len(n.config.runOptions) {
return fmt.Errorf("RunScriptsInAllPackages was called with a different list of runOptions than config.runOptions")
}
@@ -96,6 +101,18 @@ func (n *npmExecutorMock) SetNpmRegistries() error {
}
func TestNpmExecuteScripts(t *testing.T) {
t.Run("Call with scriptOptions", func(t *testing.T) {
config := npmExecuteScriptsOptions{Install: true, RunScripts: []string{"ci-build", "ci-test"}, ScriptOptions: []string{"--run"}}
utils := newNpmMockUtilsBundle()
utils.AddFile("package.json", []byte("{\"name\": \"Test\" }"))
utils.AddFile("src/package.json", []byte("{\"name\": \"Test\" }"))
npmExecutor := npmExecutorMock{utils: utils, config: npmConfig{install: config.Install, runScripts: config.RunScripts, scriptOptions: config.ScriptOptions}}
err := runNpmExecuteScripts(&npmExecutor, &config)
assert.NoError(t, err)
})
t.Run("Call with install", func(t *testing.T) {
config := npmExecuteScriptsOptions{Install: true, RunScripts: []string{"ci-build", "ci-test"}}
utils := newNpmMockUtilsBundle()

View File

@@ -14,6 +14,58 @@ import (
"github.com/testcontainers/testcontainers-go"
)
func TestRunScriptsWithOptions(t *testing.T) {
t.Parallel()
ctx := context.Background()
pwd, err := os.Getwd()
assert.NoError(t, err, "Getting current working directory failed.")
pwd = filepath.Dir(pwd)
// using custom createTmpDir function to avoid issues with symlinks on Docker for Mac
tempDir, err := createTmpDir("")
defer os.RemoveAll(tempDir) // clean up
assert.NoError(t, err, "Error when creating temp dir")
err = copyDir(filepath.Join(pwd, "integration", "testdata", "TestNpmIntegration", "runScriptsWithOptions"), tempDir)
if err != nil {
t.Fatal("Failed to copy test project.")
}
//workaround to use test script util it is possible to set workdir for Exec call
testScript := `#!/bin/sh
cd /test
/piperbin/piper npmExecuteScripts --runScripts=start --scriptOptions=--tag,tag1 >test-log.txt 2>&1
`
ioutil.WriteFile(filepath.Join(tempDir, "runPiper.sh"), []byte(testScript), 0700)
reqNode := testcontainers.ContainerRequest{
Image: "node:12-slim",
Cmd: []string{"tail", "-f"},
BindMounts: map[string]string{
pwd: "/piperbin",
tempDir: "/test",
},
}
nodeContainer, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{
ContainerRequest: reqNode,
Started: true,
})
code, err := nodeContainer.Exec(ctx, []string{"sh", "/test/runPiper.sh"})
assert.NoError(t, err)
assert.Equal(t, 0, code)
content, err := ioutil.ReadFile(filepath.Join(tempDir, "/test-log.txt"))
if err != nil {
t.Fatal("Could not read test-log.txt.", err)
}
output := string(content)
assert.Contains(t, output, "info npmExecuteScripts - running command: npm run start -- --tag tag1")
assert.Contains(t, output, "info npmExecuteScripts - [ '--tag', 'tag1' ]")
}
func TestRegistrySetInFlags(t *testing.T) {
t.Parallel()
ctx := context.Background()

View File

@@ -0,0 +1 @@
console.log(process.argv.slice(2));

View File

@@ -0,0 +1,5 @@
{
"name": "a",
"version": "1.0.0",
"lockfileVersion": 1
}

View File

@@ -0,0 +1,9 @@
{
"name": "a",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "node main.js"
}
}

View File

@@ -23,7 +23,7 @@ type Execute struct {
type Executor interface {
FindPackageJSONFiles() []string
FindPackageJSONFilesWithScript(packageJSONFiles []string, script string) ([]string, error)
RunScriptsInAllPackages(runScripts []string, runOptions []string, virtualFrameBuffer bool) error
RunScriptsInAllPackages(runScripts []string, runOptions []string, scriptOptions []string, virtualFrameBuffer bool) error
InstallAllDependencies(packageJSONFiles []string) error
SetNpmRegistries() error
}
@@ -128,7 +128,7 @@ func registryRequiresConfiguration(preConfiguredRegistry, url string) bool {
}
// RunScriptsInAllPackages runs all scripts defined in ExecuteOptions.RunScripts
func (exec *Execute) RunScriptsInAllPackages(runScripts []string, runOptions []string, virtualFrameBuffer bool) error {
func (exec *Execute) RunScriptsInAllPackages(runScripts []string, runOptions []string, scriptOptions []string, virtualFrameBuffer bool) error {
packageJSONFiles := exec.FindPackageJSONFiles()
execRunner := exec.Utils.GetExecRunner()
@@ -153,7 +153,7 @@ func (exec *Execute) RunScriptsInAllPackages(runScripts []string, runOptions []s
}
for _, packageJSON := range packagesWithScript {
err = exec.executeScript(packageJSON, script, runOptions)
err = exec.executeScript(packageJSON, script, runOptions, scriptOptions)
if err != nil {
return err
}
@@ -162,7 +162,7 @@ func (exec *Execute) RunScriptsInAllPackages(runScripts []string, runOptions []s
return nil
}
func (exec *Execute) executeScript(packageJSON string, script string, runOptions []string) error {
func (exec *Execute) executeScript(packageJSON string, script string, runOptions []string, scriptOptions []string) error {
execRunner := exec.Utils.GetExecRunner()
oldWorkingDirectory, err := exec.Utils.Getwd()
if err != nil {
@@ -188,6 +188,11 @@ func (exec *Execute) executeScript(packageJSON string, script string, runOptions
npmRunArgs = append(npmRunArgs, runOptions...)
}
if len(scriptOptions) > 0 {
npmRunArgs = append(npmRunArgs, "--")
npmRunArgs = append(npmRunArgs, scriptOptions...)
}
err = execRunner.RunExecutable("npm", npmRunArgs...)
if err != nil {
return fmt.Errorf("failed to run npm script %s: %w", script, err)

View File

@@ -210,11 +210,11 @@ func TestNpm(t *testing.T) {
Utils: &utils,
Options: options,
}
err := exec.executeScript("package.json", "ci-lint", []string{"--silent"})
err := exec.executeScript("package.json", "ci-lint", []string{"--silent"}, []string{"--tag", "tag1"})
if assert.NoError(t, err) {
if assert.Equal(t, 3, len(utils.execRunner.Calls)) {
assert.Equal(t, mock.ExecCall{Exec: "npm", Params: []string{"run", "ci-lint", "--silent"}}, utils.execRunner.Calls[2])
assert.Equal(t, mock.ExecCall{Exec: "npm", Params: []string{"run", "ci-lint", "--silent", "--", "--tag", "tag1"}}, utils.execRunner.Calls[2])
}
}
})
@@ -231,7 +231,7 @@ func TestNpm(t *testing.T) {
Utils: &utils,
Options: options,
}
err := exec.RunScriptsInAllPackages(runScripts, nil, false)
err := exec.RunScriptsInAllPackages(runScripts, nil, nil, false)
if assert.NoError(t, err) {
if assert.Equal(t, 6, len(utils.execRunner.Calls)) {
@@ -295,7 +295,7 @@ func TestNpm(t *testing.T) {
Utils: &utils,
Options: options,
}
err := exec.RunScriptsInAllPackages([]string{"foo"}, nil, true)
err := exec.RunScriptsInAllPackages([]string{"foo"}, nil, nil, true)
assert.Contains(t, utils.execRunner.Env, "DISPLAY=:99")
assert.NoError(t, err)

View File

@@ -51,6 +51,13 @@ spec:
- PARAMETERS
- STAGES
- STEPS
- name: scriptOptions
type: '[]string'
description: 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'
scope:
- PARAMETERS
- STAGES
- STEPS
containers:
- name: node
image: node:12-buster-slim