mirror of
https://github.com/drone-plugins/drone-npm.git
synced 2026-06-04 18:23:52 +08:00
Updating validation to ignore default ports as well as a flag for skipping the registry validation. (#68)
* initial attempt at adding in default port agnostic configs for validation with a boolean to disable * first run at tests * more tests and fixing an error in logic in the impl file * adding in extra package.jsons for testing * adding in more tests to cover some more in depth possible variations * Changing to a cleaner code and logic for the comparisons * typo fix and a cleanup of the isNilOrStandardSchemePort logic * making the new env var and settings name be consistent with the cli flag; formatting * Adding in a README section for the new env var; as well as an example without said env var
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"name": "my-awesome-package",
|
||||
"version": "1.0.0",
|
||||
"author": "Your Name <email@example.com> (https://example.com)",
|
||||
"publishConfig": {
|
||||
"registry": "https://fakenpm.reg.org/good/path"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"name": "my-awesome-package",
|
||||
"version": "1.0.0",
|
||||
"author": "Your Name <email@example.com> (https://example.com)",
|
||||
"publishConfig": {
|
||||
"registry": "https://fakenpm.reg.org:443/good/path"
|
||||
}
|
||||
}
|
||||
+52
-12
@@ -23,16 +23,17 @@ import (
|
||||
type (
|
||||
// Settings for the Plugin.
|
||||
Settings struct {
|
||||
Username string
|
||||
Password string
|
||||
Token string
|
||||
SkipWhoami bool
|
||||
Email string
|
||||
Registry string
|
||||
Folder string
|
||||
FailOnVersionConflict bool
|
||||
Tag string
|
||||
Access string
|
||||
Username string
|
||||
Password string
|
||||
Token string
|
||||
SkipWhoami bool
|
||||
Email string
|
||||
Registry string
|
||||
Folder string
|
||||
FailOnVersionConflict bool
|
||||
Tag string
|
||||
Access string
|
||||
SkipRegistryValidation bool
|
||||
|
||||
npm *npmPackage
|
||||
}
|
||||
@@ -51,6 +52,42 @@ type (
|
||||
// globalRegistry defines the default NPM registry.
|
||||
const globalRegistry = "https://registry.npmjs.org/"
|
||||
|
||||
// May be better as an enum in order to make it a const
|
||||
var defaultPortMap = map[string]string{
|
||||
"http": "80",
|
||||
"https": "443",
|
||||
}
|
||||
|
||||
func isNilPortOrStandardSchemePort(u *url.URL) bool {
|
||||
if u.Scheme != "http" && u.Scheme != "https" {
|
||||
//invalid schemes aren't worth checking and we want http or https
|
||||
return false
|
||||
}
|
||||
// since we verify above that the scheme above is valid and this map
|
||||
// is initialized in this file. It's safe to assume the key is in the map
|
||||
return u.Port() == "" || u.Port() == defaultPortMap[u.Scheme]
|
||||
}
|
||||
|
||||
func (p *Plugin) CompareRegistries(nc npmConfig) (bool, error) {
|
||||
parsedConfigReg, err := url.Parse(nc.Registry)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("package.json registry: %s failed to parse", nc.Registry)
|
||||
}
|
||||
parsedSettingsReg, err := url.Parse(p.settings.Registry)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("drone yaml npm Registry: %s failed to parse", p.settings.Registry)
|
||||
}
|
||||
|
||||
ncDefaultOrNilPort := isNilPortOrStandardSchemePort(parsedConfigReg)
|
||||
dyDefaultOrNilPort := isNilPortOrStandardSchemePort(parsedSettingsReg)
|
||||
|
||||
matchingStatus := parsedSettingsReg.Scheme == parsedConfigReg.Scheme &&
|
||||
parsedSettingsReg.Path == parsedConfigReg.Path &&
|
||||
parsedSettingsReg.Hostname() == parsedConfigReg.Hostname() &&
|
||||
dyDefaultOrNilPort == ncDefaultOrNilPort
|
||||
return matchingStatus, nil
|
||||
}
|
||||
|
||||
// Validate handles the settings validation of the plugin.
|
||||
func (p *Plugin) Validate() error {
|
||||
// Check authentication options
|
||||
@@ -84,12 +121,15 @@ func (p *Plugin) Validate() error {
|
||||
p.settings.Registry = globalRegistry
|
||||
}
|
||||
|
||||
if strings.Compare(p.settings.Registry, npm.Config.Registry) != 0 {
|
||||
registriesMatch, err := p.CompareRegistries(npm.Config)
|
||||
if err != nil {
|
||||
return fmt.Errorf("issue comparing the registries specified in drone yaml (%s) and package.json: (%s)", p.settings.Registry, npm.Config.Registry) // if there's an error using this default to standard validation by string compare
|
||||
}
|
||||
if !registriesMatch && !p.settings.SkipRegistryValidation {
|
||||
return fmt.Errorf("registry values do not match .drone.yml: %s package.json: %s", p.settings.Registry, npm.Config.Registry)
|
||||
}
|
||||
|
||||
p.settings.npm = npm
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
+227
-2
@@ -6,11 +6,236 @@
|
||||
package plugin
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/url"
|
||||
"testing"
|
||||
|
||||
"github.com/drone-plugins/drone-plugin-lib/drone"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestValidate(t *testing.T) {
|
||||
t.Skip()
|
||||
func initFakeSettings() Settings {
|
||||
nc := npmConfig{
|
||||
// Note: this registry is the one that would come from publishConfig in package.json
|
||||
Registry: "SetByFn_readPackageFile",
|
||||
}
|
||||
np := npmPackage{
|
||||
Name: "Test Package",
|
||||
Version: "1.33.7",
|
||||
Config: nc,
|
||||
}
|
||||
return Settings{
|
||||
Username: "fakeUser",
|
||||
Password: "fakePass",
|
||||
Token: "",
|
||||
SkipWhoami: false,
|
||||
Email: "fake@user.tst",
|
||||
// Note: this registry is the one that would come from drone yaml
|
||||
Registry: "https://fakenpm.reg.org/good/path",
|
||||
Folder: "__test__",
|
||||
FailOnVersionConflict: true,
|
||||
Tag: "",
|
||||
Access: "",
|
||||
SkipRegistryValidation: false,
|
||||
npm: &np,
|
||||
}
|
||||
}
|
||||
|
||||
func initFakeNetwork() drone.Network {
|
||||
return drone.Network{
|
||||
SkipVerify: true,
|
||||
Client: nil,
|
||||
Context: context.TODO(),
|
||||
}
|
||||
}
|
||||
|
||||
func initFakePipeline() drone.Pipeline {
|
||||
return drone.Pipeline{
|
||||
Build: drone.Build{},
|
||||
Repo: drone.Repo{},
|
||||
Commit: drone.Commit{},
|
||||
Stage: drone.Stage{},
|
||||
Step: drone.Step{},
|
||||
SemVer: drone.SemVer{},
|
||||
CalVer: drone.CalVer{},
|
||||
System: drone.System{},
|
||||
}
|
||||
}
|
||||
|
||||
func initPlugin() *Plugin {
|
||||
return &Plugin{
|
||||
settings: initFakeSettings(),
|
||||
pipeline: initFakePipeline(),
|
||||
network: initFakeNetwork(),
|
||||
}
|
||||
}
|
||||
|
||||
func getParsedUri(s string) *url.URL {
|
||||
rslt, _ := url.Parse(s)
|
||||
return rslt
|
||||
}
|
||||
|
||||
func TestIsDefaultOrNilPort(t *testing.T) {
|
||||
p := initPlugin()
|
||||
|
||||
resultWithoutPort := isNilPortOrStandardSchemePort(getParsedUri(p.settings.Registry))
|
||||
assert.Equal(t, true, resultWithoutPort)
|
||||
|
||||
p.settings.Registry = "https://fakenpm.reg.org:443"
|
||||
resultWithPort := isNilPortOrStandardSchemePort(getParsedUri(p.settings.Registry))
|
||||
assert.Equal(t, true, resultWithPort)
|
||||
|
||||
p.settings.Registry = "http://fakenpm.reg.org:80"
|
||||
resultWithPortHTTP := isNilPortOrStandardSchemePort(getParsedUri(p.settings.Registry))
|
||||
assert.Equal(t, true, resultWithPortHTTP)
|
||||
|
||||
p.settings.Registry = "fakenpm.reg.org"
|
||||
resultWithoutSchemeOrPort := isNilPortOrStandardSchemePort(getParsedUri(p.settings.Registry))
|
||||
// npm requires scheme to be part of the url; so this function will return false for any missing a scheme
|
||||
assert.Equal(t, false, resultWithoutSchemeOrPort)
|
||||
|
||||
p.settings.Registry = "fakenpm.reg.org:80"
|
||||
resultWithoutScheme := isNilPortOrStandardSchemePort(getParsedUri(p.settings.Registry))
|
||||
assert.Equal(t, false, resultWithoutScheme)
|
||||
|
||||
p.settings.Registry = "https://fakenpm.reg.org:8443"
|
||||
resultWithNonStandardPort := isNilPortOrStandardSchemePort(getParsedUri(p.settings.Registry))
|
||||
assert.Equal(t, false, resultWithNonStandardPort)
|
||||
|
||||
p.settings.Registry = "https://fakenpm.reg.org:8080"
|
||||
resultWithNonStandardPortHTTP := isNilPortOrStandardSchemePort(getParsedUri(p.settings.Registry))
|
||||
assert.Equal(t, false, resultWithNonStandardPortHTTP)
|
||||
}
|
||||
|
||||
func TestCompareRegistries(t *testing.T) {
|
||||
p := initPlugin()
|
||||
goodReg := "https://fakenpm.reg.org/good/path"
|
||||
goodRegWithPort := "https://fakenpm.reg.org:443/good/path"
|
||||
goodRegWithNonStandardPort := "https://fakenpm.reg.org:8443/good/path"
|
||||
|
||||
p.settings.Registry = goodReg
|
||||
p.settings.npm.Config.Registry = goodReg
|
||||
ValidNoPorts, _ := p.CompareRegistries(p.settings.npm.Config)
|
||||
assert.Equal(t, true, ValidNoPorts)
|
||||
|
||||
p.settings.Registry = goodRegWithPort
|
||||
SameUrlOneWithPort, _ := p.CompareRegistries(p.settings.npm.Config)
|
||||
assert.Equal(t, true, SameUrlOneWithPort)
|
||||
|
||||
p.settings.Registry = goodRegWithPort
|
||||
p.settings.npm.Config.Registry = goodRegWithPort
|
||||
SameUrlBothWithPort, _ := p.CompareRegistries(p.settings.npm.Config)
|
||||
assert.Equal(t, true, SameUrlBothWithPort)
|
||||
|
||||
p.settings.Registry = "invalidUri"
|
||||
invalidUriTest, _ := p.CompareRegistries(p.settings.npm.Config)
|
||||
assert.Equal(t, false, invalidUriTest)
|
||||
|
||||
p.settings.Registry = goodRegWithNonStandardPort
|
||||
nonStandardPortTest, _ := p.CompareRegistries(p.settings.npm.Config)
|
||||
assert.Equal(t, false, nonStandardPortTest)
|
||||
}
|
||||
|
||||
func TestValidateWithInvalidFields(t *testing.T) {
|
||||
p := initPlugin()
|
||||
// Validation tests with fields missing
|
||||
p.settings.Email = ""
|
||||
noEmailErr := p.Validate()
|
||||
if assert.NotNil(t, noEmailErr) {
|
||||
assert.Contains(t, noEmailErr.Error(), "email")
|
||||
}
|
||||
|
||||
p.settings.Email = "fakeemail"
|
||||
p.settings.Username = ""
|
||||
noUserErr := p.Validate()
|
||||
if assert.NotNil(t, noUserErr) {
|
||||
assert.Contains(t, noUserErr.Error(), "username")
|
||||
}
|
||||
|
||||
p.settings.Username = "fakeuser"
|
||||
p.settings.Password = ""
|
||||
noPassErr := p.Validate()
|
||||
if assert.NotNil(t, noPassErr) {
|
||||
assert.Contains(t, noPassErr.Error(), "password")
|
||||
}
|
||||
|
||||
p.settings.Token = "fakeToken"
|
||||
p.settings.Password = ""
|
||||
p.settings.Username = ""
|
||||
p.settings.Email = ""
|
||||
tokenErr := p.Validate()
|
||||
assert.Nil(t, tokenErr)
|
||||
}
|
||||
|
||||
func TestValidateWithRegistryVariations(t *testing.T) {
|
||||
p := initPlugin()
|
||||
|
||||
// Validation Tests with Invalid Registry
|
||||
p.settings.Registry = "fakenpm.reg.org/good/path"
|
||||
missingSchemeErr := p.Validate()
|
||||
if assert.NotNil(t, missingSchemeErr) {
|
||||
assert.Contains(t, missingSchemeErr.Error(), "fakenpm.reg.org")
|
||||
}
|
||||
|
||||
p.settings.Registry = "https://fakenpm.reg.org:7894/good/path"
|
||||
weirdPortErr := p.Validate()
|
||||
if assert.NotNil(t, weirdPortErr) {
|
||||
assert.Contains(t, weirdPortErr.Error(), "7894")
|
||||
}
|
||||
|
||||
// Validation Tests with Default/NoPorts defined
|
||||
p.settings.Registry = "https://fakenpm.reg.org:443/good/path"
|
||||
defaultPortErr := p.Validate()
|
||||
assert.Nil(t, defaultPortErr)
|
||||
|
||||
// Validation Tests with Failure Conditions on Registry
|
||||
|
||||
p.settings.Registry = "https://registry.npmjs.org/good/path"
|
||||
diffRegistry := p.Validate()
|
||||
if assert.NotNil(t, diffRegistry) {
|
||||
assert.Contains(t, diffRegistry.Error(), "npmjs.org")
|
||||
}
|
||||
|
||||
p.settings.Registry = "https://registry.npmjs.org:443/good/path"
|
||||
diffRegistryWithPort := p.Validate()
|
||||
if assert.NotNil(t, diffRegistryWithPort) {
|
||||
assert.Contains(t, diffRegistryWithPort.Error(), "npmjs.org:443")
|
||||
}
|
||||
|
||||
// Validation Failures with standardPorts But DiffPaths
|
||||
p.settings.Registry = "https://registry.npmjs.org:443/bad/path"
|
||||
p.settings.Folder = "__testwithport__"
|
||||
diffRegistryWithPort = p.Validate()
|
||||
if assert.NotNil(t, diffRegistryWithPort) {
|
||||
assert.Contains(t, diffRegistryWithPort.Error(), "npmjs.org:443/bad")
|
||||
}
|
||||
|
||||
// Same path different ports
|
||||
p.settings.Registry = "https://registry.npmjs.org:8443/good/path"
|
||||
p.settings.Folder = "__testwithport__"
|
||||
diffRegistryWithPort = p.Validate()
|
||||
if assert.NotNil(t, diffRegistryWithPort) {
|
||||
assert.Contains(t, diffRegistryWithPort.Error(), "npmjs.org:8443/good")
|
||||
}
|
||||
|
||||
// Same path different ports and schemes
|
||||
p.settings.Registry = "http://registry.npmjs.org:80/good/path"
|
||||
p.settings.Folder = "__testwithport__"
|
||||
diffRegistryWithPort = p.Validate()
|
||||
if assert.NotNil(t, diffRegistryWithPort) {
|
||||
assert.Contains(t, diffRegistryWithPort.Error(), "npmjs.org:80/good")
|
||||
}
|
||||
|
||||
// Validation Tests with SkipRegistryCheck
|
||||
p.settings.SkipRegistryValidation = true
|
||||
p.settings.Registry = "fakenpm.reg.org/good/path"
|
||||
skipMissingSchemeErr := p.Validate()
|
||||
assert.Nil(t, skipMissingSchemeErr)
|
||||
|
||||
p.settings.SkipRegistryValidation = true
|
||||
p.settings.Registry = "https://fakenpm.reg.org:7894/good/path"
|
||||
skipWeirdPortErr := p.Validate()
|
||||
assert.Nil(t, skipWeirdPortErr)
|
||||
}
|
||||
|
||||
func TestExecute(t *testing.T) {
|
||||
|
||||
Reference in New Issue
Block a user