diff --git a/pkg/feeds/feed_types.go b/pkg/feeds/feed_types.go index 2de81ac3..b767c8b2 100644 --- a/pkg/feeds/feed_types.go +++ b/pkg/feeds/feed_types.go @@ -11,6 +11,7 @@ const ( FeedTypeGoogleContainerRegistry = FeedType("GoogleContainerRegistry") FeedTypeHelm = FeedType("Helm") FeedTypeMaven = FeedType("Maven") + FeedTypeNpm = FeedType("Npm") FeedTypeNuGet = FeedType("NuGet") FeedTypeOctopusProject = FeedType("OctopusProject") FeedTypeArtifactoryGeneric = FeedType("ArtifactoryGeneric") diff --git a/pkg/feeds/feed_utilities.go b/pkg/feeds/feed_utilities.go index eb8b21cc..51889759 100644 --- a/pkg/feeds/feed_utilities.go +++ b/pkg/feeds/feed_utilities.go @@ -113,6 +113,15 @@ func ToFeed(feedResource *FeedResource) (IFeed, error) { mavenFeed.DownloadRetryBackoffSeconds = feedResource.DownloadRetryBackoffSeconds mavenFeed.FeedURI = feedResource.FeedURI feed = mavenFeed + case FeedTypeNpm: + npmFeed, err := NewNpmFeed(feedResource.GetName(), feedResource.FeedURI) + if err != nil { + return nil, err + } + npmFeed.DownloadAttempts = feedResource.DownloadAttempts + npmFeed.DownloadRetryBackoffSeconds = feedResource.DownloadRetryBackoffSeconds + npmFeed.FeedURI = feedResource.FeedURI + feed = npmFeed case FeedTypeNuGet: nuGetFeed, err := NewNuGetFeed(feedResource.GetName(), feedResource.FeedURI) if err != nil { @@ -255,6 +264,11 @@ func ToFeedResource(feed IFeed) (*FeedResource, error) { feedResource.DownloadAttempts = mavenFeed.DownloadAttempts feedResource.DownloadRetryBackoffSeconds = mavenFeed.DownloadRetryBackoffSeconds feedResource.FeedURI = mavenFeed.FeedURI + case FeedTypeNpm: + npmFeed := feed.(*NpmFeed) + feedResource.DownloadAttempts = npmFeed.DownloadAttempts + feedResource.DownloadRetryBackoffSeconds = npmFeed.DownloadRetryBackoffSeconds + feedResource.FeedURI = npmFeed.FeedURI case FeedTypeNuGet: nuGetFeed := feed.(*NuGetFeed) feedResource.DownloadAttempts = nuGetFeed.DownloadAttempts diff --git a/pkg/feeds/feed_utilities_test.go b/pkg/feeds/feed_utilities_test.go index d8c6a32f..dd993195 100644 --- a/pkg/feeds/feed_utilities_test.go +++ b/pkg/feeds/feed_utilities_test.go @@ -343,6 +343,100 @@ func TestMaven(t *testing.T) { } } +func TestNpm(t *testing.T) { + feedResource := FeedResource{ + AccessKey: "", + APIVersion: "test", + DeleteUnreleasedPackagesAfterDays: 10, + DownloadAttempts: 5, + DownloadRetryBackoffSeconds: 10, + EnhancedMode: false, + FeedType: FeedTypeNpm, + FeedURI: "https://registry.npmjs.org", + IsBuiltInRepoSyncEnabled: false, + Name: "NPM Feed", + Password: nil, + PackageAcquisitionLocationOptions: nil, + Region: "", + RegistryPath: "", + SecretKey: nil, + SpaceID: "", + Username: "testuser", + LayoutRegex: "", + Repository: "", + UseMachineCredentials: false, + Resource: resources.Resource{}, + } + + feed, err := ToFeed(&feedResource) + + if err != nil { + t.Fatalf("Error should not have been returned") + } + + typedFeed := feed.(*NpmFeed) + + if typedFeed.Name != "NPM Feed" { + t.Fatalf("Name does not match") + } + + if typedFeed.DownloadAttempts != 5 { + t.Fatalf("DownloadAttempts does not match") + } + + if typedFeed.DownloadRetryBackoffSeconds != 10 { + t.Fatalf("DownloadRetryBackoffSeconds does not match") + } + + if typedFeed.FeedURI != "https://registry.npmjs.org" { + t.Fatalf("FeedURI does not match") + } + + if typedFeed.GetUsername() != "testuser" { + t.Fatalf("Username does not match") + } +} + +func TestNpmToResource(t *testing.T) { + feed := NpmFeed{ + DownloadAttempts: 5, + DownloadRetryBackoffSeconds: 10, + FeedURI: "https://registry.npmjs.org", + feed: *newFeed("NPM Feed", FeedTypeNpm), + } + feed.SetUsername("testuser") + + feedResource, err := ToFeedResource(&feed) + + if err != nil { + t.Fatalf("Error should not have been returned. %s", err) + } + + if feedResource.FeedType != FeedTypeNpm { + t.Fatalf("FeedType does not match") + } + + if feedResource.Name != "NPM Feed" { + t.Fatalf("Name does not match") + } + + if feedResource.FeedURI != "https://registry.npmjs.org" { + t.Fatalf("FeedURI does not match") + } + + if feedResource.DownloadAttempts != 5 { + t.Fatalf("DownloadAttempts does not match") + } + + if feedResource.DownloadRetryBackoffSeconds != 10 { + t.Fatalf("DownloadRetryBackoffSeconds does not match") + } + + if feedResource.Username != "testuser" { + t.Fatalf("Username does not match") + } +} + func TestNuget(t *testing.T) { feedResource := FeedResource{ AccessKey: "", diff --git a/pkg/feeds/npm_feed.go b/pkg/feeds/npm_feed.go new file mode 100644 index 00000000..b73801bb --- /dev/null +++ b/pkg/feeds/npm_feed.go @@ -0,0 +1,50 @@ +package feeds + +import ( + "github.com/OctopusDeploy/go-octopusdeploy/v2/internal" + "github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/core" + "github.com/go-playground/validator/v10" + "github.com/go-playground/validator/v10/non-standard/validators" +) + +// NpmFeed represents an NPM feed. +type NpmFeed struct { + DownloadAttempts int `json:"DownloadAttempts"` + DownloadRetryBackoffSeconds int `json:"DownloadRetryBackoffSeconds"` + FeedURI string `json:"FeedUri,omitempty"` + Username string `json:"Username,omitempty"` + Password *core.SensitiveValue `json:"Password,omitempty"` + + feed +} + +// NewNpmFeed creates and initializes an NPM feed. +func NewNpmFeed(name string, feedURI string) (*NpmFeed, error) { + if internal.IsEmpty(name) { + return nil, internal.CreateRequiredParameterIsEmptyOrNilError("name") + } + + feed := NpmFeed{ + DownloadAttempts: 5, + DownloadRetryBackoffSeconds: 10, + FeedURI: feedURI, + feed: *newFeed(name, FeedTypeNpm), + } + + // validate to ensure that all expectations are met + if err := feed.Validate(); err != nil { + return nil, err + } + + return &feed, nil +} + +// Validate checks the state of this NPM feed and returns an error if invalid. +func (n *NpmFeed) Validate() error { + v := validator.New() + err := v.RegisterValidation("notblank", validators.NotBlank) + if err != nil { + return err + } + return v.Struct(n) +}