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

Fix npm registry config (#1564)

This commit is contained in:
Florian Wilhelm
2020-05-20 13:41:23 +02:00
committed by GitHub
parent c855ae285c
commit bd1e0a1071
24 changed files with 430 additions and 163 deletions

View File

@@ -90,7 +90,7 @@ You can extract the binary using Docker means to your local filesystem:
```sh
docker create --name piper piper:latest
docker cp piper:/piper .
docker cp piper:/build/piper .
docker rm piper
```

View File

@@ -4,6 +4,7 @@ import (
"bytes"
"encoding/json"
"fmt"
"github.com/SAP/jenkins-library/pkg/npm"
"os"
"path"
"strings"
@@ -105,14 +106,11 @@ func runMtaBuild(config mtaBuildOptions,
return err
}
err = configureNpmRegistry(config.DefaultNpmRegistry, "default", "", e)
if err != nil {
return err
}
err = configureNpmRegistry(config.SapNpmRegistry, "SAP", "@sap", e)
if err != nil {
return err
}
err = npm.SetNpmRegistries(
&npm.RegistryOptions{
DefaultNpmRegistry: config.DefaultNpmRegistry,
SapNpmRegistry: config.SapNpmRegistry,
}, e)
mtaYamlFile := "mta.yaml"
mtaYamlFileExists, err := p.FileExists(mtaYamlFile)
@@ -309,26 +307,6 @@ func createMtaYamlFile(mtaYamlFile, applicationName string, p piperutils.FileUti
return nil
}
func configureNpmRegistry(registryURI string, registryName string, scope string, e execRunner) error {
if len(registryURI) == 0 {
log.Entry().Debugf("No %s npm registry provided via configuration. Leaving npm config untouched.", registryName)
return nil
}
log.Entry().Debugf("Setting %s npm registry to \"%s\"", registryName, registryURI)
key := "registry"
if len(scope) > 0 {
key = fmt.Sprintf("%s:registry", scope)
}
if err := e.RunExecutable("npm", "config", "set", key, registryURI); err != nil {
return err
}
return nil
}
func handleSettingsFiles(config mtaBuildOptions,
p piperutils.FileUtils,
httpClient piperhttp.Downloader) error {

View File

@@ -119,7 +119,7 @@ func addMtaBuildFlags(cmd *cobra.Command, stepConfig *mtaBuildOptions) {
cmd.Flags().StringVar(&stepConfig.Platform, "platform", "CF", "mtaBuildTool 'cloudMbt' only: The target platform to which the mtar can be deployed.")
cmd.Flags().StringVar(&stepConfig.ApplicationName, "applicationName", os.Getenv("PIPER_applicationName"), "The name of the application which is being built. If the parameter has been provided and no `mta.yaml` exists, the `mta.yaml` will be automatically generated using this parameter and the information (`name` and `version`) from 'package.json` before the actual build starts.")
cmd.Flags().StringVar(&stepConfig.DefaultNpmRegistry, "defaultNpmRegistry", os.Getenv("PIPER_defaultNpmRegistry"), "Url to the npm registry that should be used for installing npm dependencies.")
cmd.Flags().StringVar(&stepConfig.SapNpmRegistry, "sapNpmRegistry", os.Getenv("PIPER_sapNpmRegistry"), "Url to the sap npm registry that should be used for installing npm dependencies prefixed with @sap.")
cmd.Flags().StringVar(&stepConfig.SapNpmRegistry, "sapNpmRegistry", "https://npm.sap.com", "Url to the sap npm registry that should be used for installing npm dependencies prefixed with @sap.")
cmd.Flags().StringVar(&stepConfig.ProjectSettingsFile, "projectSettingsFile", os.Getenv("PIPER_projectSettingsFile"), "Path or url to the mvn settings file that should be used as project settings file.")
cmd.Flags().StringVar(&stepConfig.GlobalSettingsFile, "globalSettingsFile", os.Getenv("PIPER_globalSettingsFile"), "Path or url to the mvn settings file that should be used as global settings file")

View File

@@ -35,6 +35,7 @@ func TestMarBuild(t *testing.T) {
t.Run("Provide default npm registry", func(t *testing.T) {
e := mock.ExecMockRunner{}
e.StdoutReturn = map[string]string{"npm config get registry": "undefined"}
options := mtaBuildOptions{ApplicationName: "myApp", MtaBuildTool: "classic", BuildTarget: "CF", DefaultNpmRegistry: "https://example.org/npm", MtarName: "myName"}
@@ -46,15 +47,16 @@ func TestMarBuild(t *testing.T) {
assert.Nil(t, err)
if assert.Len(t, e.Calls, 2) { // the second (unchecked) entry is the mta call
assert.Equal(t, "npm", e.Calls[0].Exec)
assert.Equal(t, []string{"config", "set", "registry", "https://example.org/npm"}, e.Calls[0].Params)
if assert.Len(t, e.Calls, 4) { // the second (unchecked) entry is the mta call
assert.Equal(t, "npm", e.Calls[1].Exec)
assert.Equal(t, []string{"config", "set", "registry", "https://example.org/npm"}, e.Calls[1].Params)
}
})
t.Run("Provide SAP npm registry", func(t *testing.T) {
e := mock.ExecMockRunner{}
e.StdoutReturn = map[string]string{"npm config get @sap:registry": "undefined"}
options := mtaBuildOptions{ApplicationName: "myApp", MtaBuildTool: "classic", BuildTarget: "CF", SapNpmRegistry: "https://example.sap/npm", MtarName: "myName"}
@@ -66,9 +68,9 @@ func TestMarBuild(t *testing.T) {
assert.Nil(t, err)
if assert.Len(t, e.Calls, 2) { // the second (unchecked) entry is the mta call
assert.Equal(t, "npm", e.Calls[0].Exec)
assert.Equal(t, []string{"config", "set", "@sap:registry", "https://example.sap/npm"}, e.Calls[0].Params)
if assert.Len(t, e.Calls, 4) { // the second (unchecked) entry is the mta call
assert.Equal(t, "npm", e.Calls[2].Exec)
assert.Equal(t, []string{"config", "set", "@sap:registry", "https://example.sap/npm"}, e.Calls[2].Params)
}
})
@@ -175,9 +177,9 @@ func TestMarBuild(t *testing.T) {
assert.Nil(t, err)
if assert.Len(t, e.Calls, 1) {
assert.Equal(t, "java", e.Calls[0].Exec)
assert.Equal(t, []string{"-jar", "mta.jar", "--mtar", "myName.mtar", "--build-target=CF", "build"}, e.Calls[0].Params)
if assert.Len(t, e.Calls, 3) {
assert.Equal(t, "java", e.Calls[2].Exec)
assert.Equal(t, []string{"-jar", "mta.jar", "--mtar", "myName.mtar", "--build-target=CF", "build"}, e.Calls[2].Params)
}
assert.Equal(t, "myName.mtar", cpe.mtarFilePath)
@@ -200,9 +202,9 @@ func TestMarBuild(t *testing.T) {
assert.Nil(t, err)
if assert.Len(t, e.Calls, 1) {
assert.Equal(t, "java", e.Calls[0].Exec)
assert.Equal(t, []string{"-jar", "mta.jar", "--mtar", "myNameFromMtar.mtar", "--build-target=CF", "build"}, e.Calls[0].Params)
if assert.Len(t, e.Calls, 3) {
assert.Equal(t, "java", e.Calls[2].Exec)
assert.Equal(t, []string{"-jar", "mta.jar", "--mtar", "myNameFromMtar.mtar", "--build-target=CF", "build"}, e.Calls[2].Params)
}
})
@@ -220,9 +222,9 @@ func TestMarBuild(t *testing.T) {
assert.Nil(t, err)
if assert.Len(t, e.Calls, 1) {
assert.Equal(t, "java", e.Calls[0].Exec)
assert.Equal(t, []string{"-jar", "/opt/sap/mta/lib/mta.jar", "--mtar", "myName.mtar", "--build-target=CF", "build"}, e.Calls[0].Params)
if assert.Len(t, e.Calls, 3) {
assert.Equal(t, "java", e.Calls[2].Exec)
assert.Equal(t, []string{"-jar", "/opt/sap/mta/lib/mta.jar", "--mtar", "myName.mtar", "--build-target=CF", "build"}, e.Calls[2].Params)
}
})
@@ -242,9 +244,9 @@ func TestMarBuild(t *testing.T) {
assert.Nil(t, err)
if assert.Len(t, e.Calls, 1) {
assert.Equal(t, "mbt", e.Calls[0].Exec)
assert.Equal(t, []string{"build", "--mtar", "myName.mtar", "--platform", "CF", "--target", "./"}, e.Calls[0].Params)
if assert.Len(t, e.Calls, 3) {
assert.Equal(t, "mbt", e.Calls[2].Exec)
assert.Equal(t, []string{"build", "--mtar", "myName.mtar", "--platform", "CF", "--target", "./"}, e.Calls[2].Params)
}
assert.Equal(t, "myName.mtar", cpe.mtarFilePath)
})

View File

@@ -1,9 +1,9 @@
package cmd
import (
"bytes"
"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"
@@ -79,7 +79,12 @@ func runNpmExecuteScripts(utils npmExecuteScriptsUtilsInterface, options *npmExe
}
// set in each directory to respect existing config in rc files
err = setNpmRegistries(options, execRunner)
err = npm.SetNpmRegistries(
&npm.RegistryOptions{
DefaultNpmRegistry: options.DefaultNpmRegistry,
SapNpmRegistry: options.SapNpmRegistry,
}, execRunner)
if err != nil {
return err
}
@@ -111,39 +116,6 @@ func runNpmExecuteScripts(utils npmExecuteScriptsUtilsInterface, options *npmExe
return err
}
func setNpmRegistries(options *npmExecuteScriptsOptions, execRunner execRunner) error {
environment := []string{}
const sapRegistry = "@sap:registry"
const npmRegistry = "registry"
configurableRegistries := []string{npmRegistry, sapRegistry}
for _, registry := range configurableRegistries {
var buffer bytes.Buffer
execRunner.Stdout(&buffer)
err := execRunner.RunExecutable("npm", "config", "get", registry)
execRunner.Stdout(log.Writer())
if err != nil {
return err
}
preConfiguredRegistry := buffer.String()
log.Entry().Info("Discovered pre-configured npm registry " + preConfiguredRegistry)
if registry == npmRegistry && options.DefaultNpmRegistry != "" && (preConfiguredRegistry == "undefined" || strings.HasPrefix(preConfiguredRegistry, "https://registry.npmjs.org")) {
log.Entry().Info("npm registry " + registry + " was not configured, setting it to " + options.DefaultNpmRegistry)
environment = append(environment, "npm_config_"+registry+"="+options.DefaultNpmRegistry)
}
if registry == sapRegistry && (preConfiguredRegistry == "undefined" || strings.HasPrefix(preConfiguredRegistry, "https://npm.sap.com")) {
log.Entry().Info("npm registry " + registry + " was not configured, setting it to " + options.SapNpmRegistry)
environment = append(environment, "npm_config_"+registry+"="+options.SapNpmRegistry)
}
}
log.Entry().Info("Setting environment: " + strings.Join(environment, ", "))
execRunner.SetEnv(environment)
return nil
}
func findPackageJSONFiles(utils npmExecuteScriptsUtilsInterface) ([]string, error) {
unfilteredListOfPackageJSONFiles, err := utils.glob("**/package.json")
if err != nil {

2
go.mod
View File

@@ -24,7 +24,7 @@ require (
github.com/spf13/cobra v1.0.0
github.com/spf13/pflag v1.0.5
github.com/stretchr/testify v1.4.0
github.com/testcontainers/testcontainers-go v0.2.0
github.com/testcontainers/testcontainers-go v0.4.0
golang.org/x/crypto v0.0.0-20200414173820-0848c9571904 // indirect
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e // indirect
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d

15
go.sum
View File

@@ -157,7 +157,9 @@ github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2H
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/gin-contrib/sse v0.0.0-20190301062529-5545eab6dad3/go.mod h1:VJ0WA2NBN22VlZ2dKZQPAPnyWw5XTlK1KymzLKsr59s=
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
github.com/gin-gonic/gin v1.4.0/go.mod h1:OW2EZn3DO8Ln9oIKOvM++LBO+5UPHJJDH72/q/3rZdM=
github.com/gin-gonic/gin v1.6.2/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M=
github.com/gliderlabs/ssh v0.2.2 h1:6zsha5zo/TWhRhwqCD3+EarCAgZ2yN28ipRnGPnwkI0=
github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclKsC9YodN5RgxqK/VD9HM9JsCSh7rNhMZE98=
@@ -187,6 +189,10 @@ github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8
github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I=
github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI=
github.com/go-redis/redis v6.15.7+incompatible h1:3skhDh95XQMpnqeqNftPkQD9jL9e5e36z/1SUm6dy1U=
github.com/go-redis/redis v6.15.7+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA=
github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs=
@@ -284,6 +290,7 @@ github.com/json-iterator/go v0.0.0-20180612202835-f2b4162afba3/go.mod h1:+SdeFBv
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
@@ -316,6 +323,7 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/labstack/echo/v4 v4.1.11/go.mod h1:i541M3Fj6f76NZtHSj7TXnyM8n2gaodfvfxNnFqi74g=
github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k=
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
github.com/magiconair/properties v1.8.0 h1:LLgXmsheXeRoUOBOjtwPQCWIYqM/LU1ayDtDePerRcY=
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
@@ -328,6 +336,7 @@ github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNx
github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
@@ -453,8 +462,8 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
github.com/testcontainers/testcontainers-go v0.2.0 h1:7PED4vniZMXNkPln4zg9U9ZDp4MmD/LuX0LGYTnByE0=
github.com/testcontainers/testcontainers-go v0.2.0/go.mod h1:5aBi+1PJmFixVc3b349A7NrhyTRYkMDpZEtT5MFxCs8=
github.com/testcontainers/testcontainers-go v0.4.0 h1:BpzZG0/I4s4oAVrkYhf9K3R0AKLvhE0bX1kVSqyUVx8=
github.com/testcontainers/testcontainers-go v0.4.0/go.mod h1:BXwe1JilTOLT8cmVyPMDbIw7e+8UCGeAhxjBwguG5wQ=
github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
@@ -558,7 +567,6 @@ golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5h
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181228144115-9a3f9b0469bb/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190209173611-3b5209105503/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190221075227-b4e8571b14e0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -575,6 +583,7 @@ golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191010194322-b09406accb47/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200413165638-669c56c373c4 h1:opSr2sbRXk5X5/givKrrKj9HXxFpW2sdCiP8MJSKLQY=

View File

@@ -5,10 +5,8 @@ package main
import (
"context"
"io"
"io/ioutil"
"os"
"path"
"path/filepath"
"testing"
@@ -101,76 +99,3 @@ cd /test
assert.NoError(t, err)
assert.Equal(t, 0, code)
}
// copyDir copies a directory
func copyDir(source string, target string) error {
var err error
var fileInfo []os.FileInfo
var sourceInfo os.FileInfo
if sourceInfo, err = os.Stat(source); err != nil {
return err
}
if err = os.MkdirAll(target, sourceInfo.Mode()); err != nil {
return err
}
if fileInfo, err = ioutil.ReadDir(source); err != nil {
return err
}
for _, info := range fileInfo {
sourcePath := path.Join(source, info.Name())
targetPath := path.Join(target, info.Name())
if info.IsDir() {
if err = copyDir(sourcePath, targetPath); err != nil {
return err
}
} else {
if err = copyFile(sourcePath, targetPath); err != nil {
return err
}
}
}
return nil
}
func copyFile(source, target string) error {
var err error
var sourceFile *os.File
var targetFile *os.File
var sourceInfo os.FileInfo
if sourceFile, err = os.Open(source); err != nil {
return err
}
defer sourceFile.Close()
if targetFile, err = os.Create(target); err != nil {
return err
}
defer targetFile.Close()
if _, err = io.Copy(targetFile, sourceFile); err != nil {
return err
}
if sourceInfo, err = os.Stat(source); err != nil {
return err
}
return os.Chmod(target, sourceInfo.Mode())
}
func createTmpDir(prefix string) (string, error) {
dirName := os.TempDir()
tmpDir, err := filepath.EvalSymlinks(dirName)
if err != nil {
return "", err
}
tmpDir = filepath.Clean(tmpDir)
path, err := ioutil.TempDir(tmpDir, prefix)
if err != nil {
return "", err
}
return path, nil
}

View File

@@ -0,0 +1,169 @@
// +build integration
// can be execute with go test -tags=integration ./integration/...
package main
import (
"context"
"io/ioutil"
"os"
"path/filepath"
"testing"
"github.com/stretchr/testify/assert"
"github.com/testcontainers/testcontainers-go"
)
func TestRegistrySetInFlags(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", "registrySetInFlags"), 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 --install --runScripts=ci-build,ci-backend-unit-test --sapNpmRegistry=https://foo.bar >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 - https://foo.bar")
}
func TestRegistrySetInNpmrc(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", "registrySetInNpmrc"), 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 --install --runScripts=ci-build,ci-backend-unit-test >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 - https://example.com")
}
func TestRegistryWithTwoModules(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", "registryWithTwoModules"), 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 --install --runScripts=ci-build,ci-backend-unit-test --sapNpmRegistry=https://foo.bar >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 - https://example.com")
assert.Contains(t, output, "info npmExecuteScripts - https://foo.bar")
}

View File

@@ -7,12 +7,16 @@ import (
"bytes"
"fmt"
"github.com/SAP/jenkins-library/pkg/piperutils"
"io"
"os"
"path"
"testing"
"github.com/SAP/jenkins-library/pkg/command"
"github.com/stretchr/testify/assert"
"io/ioutil"
"path/filepath"
)
func TestPiperHelp(t *testing.T) {
@@ -46,3 +50,76 @@ func getPiperExecutable() string {
fmt.Println("Piper executable for integration test: Using 'piper' from PATH")
return "piper"
}
// copyDir copies a directory
func copyDir(source string, target string) error {
var err error
var fileInfo []os.FileInfo
var sourceInfo os.FileInfo
if sourceInfo, err = os.Stat(source); err != nil {
return err
}
if err = os.MkdirAll(target, sourceInfo.Mode()); err != nil {
return err
}
if fileInfo, err = ioutil.ReadDir(source); err != nil {
return err
}
for _, info := range fileInfo {
sourcePath := path.Join(source, info.Name())
targetPath := path.Join(target, info.Name())
if info.IsDir() {
if err = copyDir(sourcePath, targetPath); err != nil {
return err
}
} else {
if err = copyFile(sourcePath, targetPath); err != nil {
return err
}
}
}
return nil
}
func copyFile(source, target string) error {
var err error
var sourceFile *os.File
var targetFile *os.File
var sourceInfo os.FileInfo
if sourceFile, err = os.Open(source); err != nil {
return err
}
defer sourceFile.Close()
if targetFile, err = os.Create(target); err != nil {
return err
}
defer targetFile.Close()
if _, err = io.Copy(targetFile, sourceFile); err != nil {
return err
}
if sourceInfo, err = os.Stat(source); err != nil {
return err
}
return os.Chmod(target, sourceInfo.Mode())
}
func createTmpDir(prefix string) (string, error) {
dirName := os.TempDir()
tmpDir, err := filepath.EvalSymlinks(dirName)
if err != nil {
return "", err
}
tmpDir = filepath.Clean(tmpDir)
path, err := ioutil.TempDir(tmpDir, prefix)
if err != nil {
return "", err
}
return path, nil
}

6
integration/run-tests.sh Executable file
View File

@@ -0,0 +1,6 @@
#!/usr/bin/env bash
pushd ..
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -tags release -o piper
go test -tags=integration ./integration/...
popd

View File

@@ -0,0 +1,4 @@
piper
registrySetInFlags/test-log.txt
registrySetInNpmrc/test-log.txt
registryWithTwoModules/test-log.txt

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": {
"ci-build": "npm config get @sap:registry"
}
}

View File

@@ -0,0 +1 @@
@sap:registry=https://example.com

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": {
"ci-build": "npm config get @sap:registry"
}
}

View File

@@ -0,0 +1 @@
@sap:registry=https://example.com

View File

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

View File

@@ -0,0 +1,9 @@
{
"name": "db",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"ci-build": "npm config get @sap:registry"
}
}

View File

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

View File

@@ -0,0 +1,9 @@
{
"name": "srv",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"ci-build": "npm config get @sap:registry"
}
}

67
pkg/npm/npm.go Normal file
View File

@@ -0,0 +1,67 @@
package npm
import (
"bytes"
"github.com/SAP/jenkins-library/pkg/log"
"io"
"strings"
)
// RegistryOptions holds the configured urls for npm registries
type RegistryOptions struct {
DefaultNpmRegistry string
SapNpmRegistry string
}
type execRunner interface {
Stdout(out io.Writer)
RunExecutable(executable string, params ...string) error
}
// SetNpmRegistries configures the given npm registries.
// CAUTION: This will change the npm configuration in the user's home directory.
func SetNpmRegistries(options *RegistryOptions, execRunner execRunner) error {
const sapRegistry = "@sap:registry"
const npmRegistry = "registry"
configurableRegistries := []string{npmRegistry, sapRegistry}
for _, registry := range configurableRegistries {
var buffer bytes.Buffer
execRunner.Stdout(&buffer)
err := execRunner.RunExecutable("npm", "config", "get", registry)
execRunner.Stdout(log.Writer())
if err != nil {
return err
}
preConfiguredRegistry := buffer.String()
if registryIsNonEmpty(preConfiguredRegistry) {
log.Entry().Info("Discovered pre-configured npm registry " + registry + " with value " + preConfiguredRegistry)
}
if registry == npmRegistry && options.DefaultNpmRegistry != "" && registryRequiresConfiguration(preConfiguredRegistry, "https://registry.npmjs.org") {
log.Entry().Info("npm registry " + registry + " was not configured, setting it to " + options.DefaultNpmRegistry)
err = execRunner.RunExecutable("npm", "config", "set", registry, options.DefaultNpmRegistry)
if err != nil {
return err
}
}
if registry == sapRegistry && options.SapNpmRegistry != "" && registryRequiresConfiguration(preConfiguredRegistry, "https://npm.sap.com") {
log.Entry().Info("npm registry " + registry + " was not configured, setting it to " + options.SapNpmRegistry)
err = execRunner.RunExecutable("npm", "config", "set", registry, options.SapNpmRegistry)
if err != nil {
return err
}
}
}
return nil
}
func registryIsNonEmpty(preConfiguredRegistry string) bool {
return !strings.HasPrefix(preConfiguredRegistry, "undefined") && len(preConfiguredRegistry) > 0
}
func registryRequiresConfiguration(preConfiguredRegistry, url string) bool {
return strings.HasPrefix(preConfiguredRegistry, "undefined") || strings.HasPrefix(preConfiguredRegistry, url)
}

View File

@@ -99,7 +99,7 @@ spec:
- STAGES
- STEPS
mandatory: false
default:
default: https://npm.sap.com
- name: projectSettingsFile
type: string
description: "Path or url to the mvn settings file that should be used as project settings file."