1
0
mirror of https://github.com/SAP/jenkins-library.git synced 2025-07-17 01:42:43 +02:00

Refactor pkg/npm and npmExecuteScripts (#1684)

This change refactors the npm pkg and npmExecuteScripts implementations
to be reusable for future steps, e.g., npmExecuteLint.

In addition, it fixes few small bugs related to unit test execution on
Windows and the fileUtils mocking implementation.

Co-authored-by: Daniel Kurzynski <daniel.kurzynski@sap.com>
Co-authored-by: Stephan Aßmus <stephan.assmus@sap.com>
This commit is contained in:
Kevin Hudemann
2020-06-18 17:30:17 +02:00
committed by GitHub
parent be01dd3869
commit ceb3dd0a04
12 changed files with 779 additions and 343 deletions

View File

@ -1,185 +1,30 @@
package cmd
import (
"fmt"
"github.com/SAP/jenkins-library/pkg/command"
"github.com/SAP/jenkins-library/pkg/log"
"github.com/SAP/jenkins-library/pkg/npm"
FileUtils "github.com/SAP/jenkins-library/pkg/piperutils"
"github.com/SAP/jenkins-library/pkg/telemetry"
"github.com/bmatcuk/doublestar"
"os"
"path"
"strings"
)
type npmExecuteScriptsUtilsInterface interface {
fileExists(path string) (bool, error)
glob(pattern string) (matches []string, err error)
getwd() (dir string, err error)
chdir(dir string) error
getExecRunner() execRunner
}
type npmExecuteScriptsUtilsBundle struct {
projectStructure FileUtils.ProjectStructure
fileUtils FileUtils.Files
execRunner *command.Command
}
func (u *npmExecuteScriptsUtilsBundle) fileExists(path string) (bool, error) {
return u.fileUtils.FileExists(path)
}
func (u *npmExecuteScriptsUtilsBundle) glob(pattern string) (matches []string, err error) {
return doublestar.Glob(pattern)
}
func (u *npmExecuteScriptsUtilsBundle) getwd() (dir string, err error) {
return os.Getwd()
}
func (u *npmExecuteScriptsUtilsBundle) chdir(dir string) error {
return os.Chdir(dir)
}
func (u *npmExecuteScriptsUtilsBundle) getExecRunner() execRunner {
if u.execRunner == nil {
u.execRunner = &command.Command{}
u.execRunner.Stdout(log.Writer())
u.execRunner.Stderr(log.Writer())
}
return u.execRunner
}
func npmExecuteScripts(config npmExecuteScriptsOptions, telemetryData *telemetry.CustomData) {
utils := npmExecuteScriptsUtilsBundle{}
npmExecutorOptions := npm.ExecutorOptions{DefaultNpmRegistry: config.DefaultNpmRegistry, SapNpmRegistry: config.SapNpmRegistry}
npmExecutor := npm.NewExecutor(npmExecutorOptions)
err := runNpmExecuteScripts(&utils, &config)
err := runNpmExecuteScripts(npmExecutor, &config)
if err != nil {
log.Entry().WithError(err).Fatal("step execution failed")
}
}
func runNpmExecuteScripts(utils npmExecuteScriptsUtilsInterface, options *npmExecuteScriptsOptions) error {
execRunner := utils.getExecRunner()
packageJSONFiles, err := findPackageJSONFiles(utils)
if err != nil {
return err
}
oldWorkingDirectory, err := utils.getwd()
if err != nil {
return err
}
func runNpmExecuteScripts(npmExecutor npm.Executor, config *npmExecuteScriptsOptions) error {
packageJSONFiles := npmExecutor.FindPackageJSONFiles()
if options.VirtualFrameBuffer {
cmd, err := execRunner.RunExecutableInBackground("Xvfb", "-ac", ":99", "-screen", "0", "1280x1024x16")
if err != nil {
return fmt.Errorf("failed to start virtual frame buffer%w", err)
}
defer cmd.Kill()
execRunner.SetEnv([]string{"DISPLAY=:99"})
}
for _, file := range packageJSONFiles {
dir := path.Dir(file)
err = utils.chdir(dir)
if err != nil {
return err
}
// set in each directory to respect existing config in rc files
err = npm.SetNpmRegistries(
&npm.RegistryOptions{
DefaultNpmRegistry: options.DefaultNpmRegistry,
SapNpmRegistry: options.SapNpmRegistry,
}, execRunner)
if err != nil {
return err
}
packageLockExists, yarnLockExists, err := checkIfLockFilesExist(utils)
if err != nil {
return err
}
if options.Install {
err = installDependencies(dir, packageLockExists, yarnLockExists, execRunner)
if err != nil {
return err
}
}
for _, v := range options.RunScripts {
log.Entry().WithField("WorkingDirectory", dir).Info("run-script " + v)
err = execRunner.RunExecutable("npm", "run-script", v, "--if-present")
if err != nil {
return err
}
}
err = utils.chdir(oldWorkingDirectory)
if config.Install {
err := npmExecutor.InstallAllDependencies(packageJSONFiles)
if err != nil {
return err
}
}
return err
}
func findPackageJSONFiles(utils npmExecuteScriptsUtilsInterface) ([]string, error) {
unfilteredListOfPackageJSONFiles, err := utils.glob("**/package.json")
if err != nil {
return nil, err
}
var packageJSONFiles []string
for _, file := range unfilteredListOfPackageJSONFiles {
if strings.Contains(file, "node_modules") {
continue
}
if strings.HasPrefix(file, "gen/") || strings.Contains(file, "/gen/") {
continue
}
packageJSONFiles = append(packageJSONFiles, file)
log.Entry().Info("Discovered package.json file " + file)
}
return packageJSONFiles, nil
}
func checkIfLockFilesExist(utils npmExecuteScriptsUtilsInterface) (bool, bool, error) {
packageLockExists, err := utils.fileExists("package-lock.json")
if err != nil {
return false, false, err
}
yarnLockExists, err := utils.fileExists("yarn.lock")
if err != nil {
return false, false, err
}
return packageLockExists, yarnLockExists, nil
}
func installDependencies(dir string, packageLockExists bool, yarnLockExists bool, execRunner execRunner) (err error) {
log.Entry().WithField("WorkingDirectory", dir).Info("Running install")
if packageLockExists {
err = execRunner.RunExecutable("npm", "ci")
if err != nil {
return err
}
} else if yarnLockExists {
err = execRunner.RunExecutable("yarn", "install", "--frozen-lockfile")
if err != nil {
return err
}
} else {
log.Entry().Warn("No package lock file found. " +
"It is recommended to create a `package-lock.json` file by running `npm install` locally." +
" Add this file to your version control. " +
"By doing so, the builds of your application become more reliable.")
err = execRunner.RunExecutable("npm", "install")
if err != nil {
return err
}
}
return nil
return npmExecutor.RunScriptsInAllPackages(config.RunScripts, nil, config.VirtualFrameBuffer)
}