You've already forked sap-jenkins-library
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:
@@ -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)
|
||||
|
@@ -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)
|
||||
}
|
||||
|
@@ -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{},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@@ -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()
|
||||
|
@@ -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()
|
||||
|
1
integration/testdata/TestNpmIntegration/runScriptsWithOptions/main.js
vendored
Normal file
1
integration/testdata/TestNpmIntegration/runScriptsWithOptions/main.js
vendored
Normal file
@@ -0,0 +1 @@
|
||||
console.log(process.argv.slice(2));
|
5
integration/testdata/TestNpmIntegration/runScriptsWithOptions/package-lock.json
generated
vendored
Normal file
5
integration/testdata/TestNpmIntegration/runScriptsWithOptions/package-lock.json
generated
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"name": "a",
|
||||
"version": "1.0.0",
|
||||
"lockfileVersion": 1
|
||||
}
|
9
integration/testdata/TestNpmIntegration/runScriptsWithOptions/package.json
vendored
Normal file
9
integration/testdata/TestNpmIntegration/runScriptsWithOptions/package.json
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"name": "a",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"start": "node main.js"
|
||||
}
|
||||
}
|
@@ -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)
|
||||
|
@@ -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)
|
||||
|
@@ -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
|
||||
|
Reference in New Issue
Block a user